about summary refs log tree commit diff
path: root/pkgs
diff options
context:
space:
mode:
authorEelco Dolstra <eelco.dolstra@logicblox.com>2009-01-16 10:59:27 +0000
committerEelco Dolstra <eelco.dolstra@logicblox.com>2009-01-16 10:59:27 +0000
commitc1579d2e78f76e7ad3b30cc2961fafe7b8a24a74 (patch)
tree904516c8b572724b240f93e7901d324caf12daa3 /pkgs
parent821de7706a4a44d919c95f0e990ac01840788c94 (diff)
parent4eedf7dae894a40f6c70cc80735f1500ded9bff3 (diff)
* stdenv branch: synced with the trunk.
svn path=/nixpkgs/branches/stdenv-updates/; revision=13785
Diffstat (limited to 'pkgs')
-rw-r--r--pkgs/applications/editors/vim/configurable.nix130
-rw-r--r--pkgs/applications/graphics/exrdisplay/default.nix2
-rw-r--r--pkgs/applications/graphics/pqiv/default.nix6
-rw-r--r--pkgs/applications/misc/audio/sox/default.nix81
-rw-r--r--pkgs/applications/misc/gv/default.nix7
-rw-r--r--pkgs/applications/misc/mrxvt/default.nix19
-rw-r--r--pkgs/applications/misc/qgis/0.11.0.nix45
-rw-r--r--pkgs/applications/misc/qgis_svn/default.nix74
-rw-r--r--pkgs/applications/misc/truecrypt/builder.sh18
-rw-r--r--pkgs/applications/misc/truecrypt/default.nix34
-rw-r--r--pkgs/applications/misc/xneur/0.8.nix26
-rw-r--r--pkgs/applications/misc/xneur/default.nix13
-rw-r--r--pkgs/applications/misc/xpdf/default.nix6
-rw-r--r--pkgs/applications/networking/browsers/firefox-2/default.nix6
-rw-r--r--pkgs/applications/networking/browsers/firefox-3/3.1.nix84
-rw-r--r--pkgs/applications/networking/browsers/firefox-3/default.nix7
-rw-r--r--pkgs/applications/networking/browsers/firefox-3/xulrunner-3.1.nix96
-rw-r--r--pkgs/applications/networking/browsers/firefox-3/xulrunner.nix6
-rw-r--r--pkgs/applications/networking/browsers/icecat-3/default.nix6
-rw-r--r--pkgs/applications/networking/browsers/mozilla-plugins/flashplayer-10/default.nix2
-rw-r--r--pkgs/applications/networking/instant-messengers/mcabber/default.nix19
-rw-r--r--pkgs/applications/networking/instant-messengers/psi/0.12.nix20
-rw-r--r--pkgs/applications/networking/mailreaders/thunderbird-2.x/default.nix6
-rw-r--r--pkgs/applications/networking/p2p/mldonkey/default.nix18
-rw-r--r--pkgs/applications/networking/skype/default.nix8
-rw-r--r--pkgs/applications/science/math/maxima/default.nix11
-rw-r--r--pkgs/applications/version-management/bazaar/default.nix7
-rw-r--r--pkgs/applications/version-management/git/default.nix2
-rw-r--r--pkgs/applications/video/MPlayer/newconfig.nix255
-rw-r--r--pkgs/applications/video/dvdauthor/default.nix17
-rw-r--r--pkgs/applications/virtualization/qemu/linux-img/0.2.nix4
-rw-r--r--pkgs/applications/window-managers/compiz-fusion/compiz-manager/0.6.0.nix4
-rw-r--r--pkgs/applications/window-managers/compiz-fusion/default.nix2
-rw-r--r--pkgs/applications/window-managers/compiz-fusion/general-dependencies.nix1
-rw-r--r--pkgs/applications/window-managers/dwm/default.nix1
-rw-r--r--pkgs/build-support/release/debian-build.nix11
-rw-r--r--pkgs/build-support/release/default.nix2
-rw-r--r--pkgs/data/documentation/man-pages/default.nix4
-rw-r--r--pkgs/data/fonts/freefont-ttf/default.nix7
-rw-r--r--pkgs/data/misc/themes/green.nix5
-rw-r--r--pkgs/data/misc/themes/theme-gnu.nix5
-rw-r--r--pkgs/data/misc/xkeyboard-config/eo.patch83
-rw-r--r--pkgs/development/compilers/bigloo/default.nix4
-rw-r--r--pkgs/development/compilers/ghc/boot610.nix51
-rw-r--r--pkgs/development/compilers/hugs/default.nix101
-rw-r--r--pkgs/development/compilers/roadsend/default.nix54
-rw-r--r--pkgs/development/interpreters/php_configurable/default.nix205
-rw-r--r--pkgs/development/interpreters/python-new/2.5/default.nix21
-rw-r--r--pkgs/development/libraries/aterm/2.4.2-fixes.nix2
-rw-r--r--pkgs/development/libraries/avahi/0.6.21.nix2
-rw-r--r--pkgs/development/libraries/avahi/0.6.22.nix2
-rw-r--r--pkgs/development/libraries/avahi/default.nix (renamed from pkgs/development/libraries/avahi/common.nix)13
-rw-r--r--pkgs/development/libraries/dbus/default.nix20
-rw-r--r--pkgs/development/libraries/fltk/default.nix60
-rw-r--r--pkgs/development/libraries/freeimage/default.nix22
-rw-r--r--pkgs/development/libraries/geos/default.nix66
-rw-r--r--pkgs/development/libraries/gnutls/default.nix4
-rw-r--r--pkgs/development/libraries/gsl/default.nix33
-rw-r--r--pkgs/development/libraries/haskell/wxHaskell/default.nix14
-rw-r--r--pkgs/development/libraries/kerberos/heimdal.nix3
-rw-r--r--pkgs/development/libraries/libassuan/default.nix34
-rw-r--r--pkgs/development/libraries/libdv/default.nix37
-rw-r--r--pkgs/development/libraries/libgpg-error/default.nix24
-rw-r--r--pkgs/development/libraries/libsamplerate/default.nix54
-rw-r--r--pkgs/development/libraries/popt/popt-1.10.6.nix13
-rw-r--r--pkgs/development/libraries/pthread-stubs/default.nix8
-rw-r--r--pkgs/development/libraries/vxl/default.nix17
-rw-r--r--pkgs/development/tools/analysis/valgrind/callgrind_annotate.patch8
-rw-r--r--pkgs/development/tools/analysis/valgrind/default.nix8
-rw-r--r--pkgs/development/tools/build-managers/cmake/default.nix9
-rw-r--r--pkgs/development/tools/haskell/uuagc/default.nix4
-rw-r--r--pkgs/development/tools/misc/autoconf/2.13.nix37
-rw-r--r--pkgs/development/tools/misc/avrdude/default.nix48
-rw-r--r--pkgs/development/tools/misc/gdb/default.nix6
-rw-r--r--pkgs/development/tools/misc/gnum4/default.nix5
-rw-r--r--pkgs/development/tools/misc/strace/default.nix6
-rw-r--r--pkgs/development/tools/misc/yodl/default.nix23
-rw-r--r--pkgs/development/tools/parsing/bison/bison-2.4.nix4
-rw-r--r--pkgs/games/keen4/default.nix2
-rw-r--r--pkgs/games/quake3/demo/default.nix4
-rw-r--r--pkgs/games/sgt-puzzles/default.nix34
-rw-r--r--pkgs/games/teeworlds/default.nix81
-rw-r--r--pkgs/games/xsokoban/default.nix48
-rw-r--r--pkgs/lib/composable-derivation.nix46
-rw-r--r--pkgs/lib/default.nix249
-rw-r--r--pkgs/misc/bleeding-edge-fetch-infos.nix4
-rw-r--r--pkgs/misc/emulators/wine/default.nix6
-rw-r--r--pkgs/misc/gxemul/default.nix55
-rw-r--r--pkgs/misc/jackaudio/default.nix104
-rw-r--r--pkgs/misc/tex/nix/run-latex.sh19
-rw-r--r--pkgs/os-specific/linux/cpufrequtils/default.nix19
-rw-r--r--pkgs/os-specific/linux/e2fsprogs/default.nix23
-rw-r--r--pkgs/os-specific/linux/firmware/iwlwifi-3945-ucode/default.nix6
-rw-r--r--pkgs/os-specific/linux/firmware/iwlwifi-4965-ucode/default.nix4
-rw-r--r--pkgs/os-specific/linux/htop/default.nix24
-rw-r--r--pkgs/os-specific/linux/iproute/default.nix27
-rw-r--r--pkgs/os-specific/linux/kernel-headers/2.6.26.2.nix24
-rw-r--r--pkgs/os-specific/linux/kernel-headers/2.6.28.nix44
-rw-r--r--pkgs/os-specific/linux/kernel/builder-custom.sh127
-rw-r--r--pkgs/os-specific/linux/kernel/builder.sh13
-rw-r--r--pkgs/os-specific/linux/kernel/config-2.6.28-i686-smp4227
-rw-r--r--pkgs/os-specific/linux/kernel/config-2.6.28-x86_64-smp4002
-rw-r--r--pkgs/os-specific/linux/kernel/generic.nix (renamed from pkgs/os-specific/linux/kernel/linux-2.6.21_ck.nix)53
-rw-r--r--pkgs/os-specific/linux/kernel/linux-2.6.20.3-ext3cow.patch18494
-rw-r--r--pkgs/os-specific/linux/kernel/linux-2.6.20.nix92
-rw-r--r--pkgs/os-specific/linux/kernel/linux-2.6.21.nix91
-rw-r--r--pkgs/os-specific/linux/kernel/linux-2.6.22.nix99
-rw-r--r--pkgs/os-specific/linux/kernel/linux-2.6.23.nix106
-rw-r--r--pkgs/os-specific/linux/kernel/linux-2.6.25.nix114
-rw-r--r--pkgs/os-specific/linux/kernel/linux-2.6.26.nix113
-rw-r--r--pkgs/os-specific/linux/kernel/linux-2.6.27.nix113
-rw-r--r--pkgs/os-specific/linux/kernel/linux-2.6.28.nix26
-rw-r--r--pkgs/os-specific/linux/kernel/linux.nix101
-rw-r--r--pkgs/os-specific/linux/kernel/patch-2.6.21-ck15040
-rw-r--r--pkgs/os-specific/linux/kernel/patch-2.6.22-ck15167
-rw-r--r--pkgs/os-specific/linux/kvm/82.nix38
-rw-r--r--pkgs/os-specific/linux/kvm/readonly-kernel-r3.patch14
-rw-r--r--pkgs/os-specific/linux/kvm/smbd-path-r2.patch50
-rw-r--r--pkgs/os-specific/linux/mkinitrd/builder.sh5
-rw-r--r--pkgs/os-specific/linux/mkinitrd/default.nix14
-rwxr-xr-xpkgs/os-specific/linux/nvidia/builder.sh2
-rw-r--r--pkgs/os-specific/linux/nvidia/default.nix6
-rw-r--r--pkgs/os-specific/linux/splashutils/1.5.nix6
-rw-r--r--pkgs/os-specific/linux/upstart/default.nix11
-rw-r--r--pkgs/os-specific/linux/util-linux-ng/default.nix54
-rw-r--r--pkgs/servers/http/apache-httpd/default.nix6
-rw-r--r--pkgs/servers/http/tomcat/6.0.nix6
-rw-r--r--pkgs/servers/pulseaudio/default.nix42
-rw-r--r--pkgs/servers/squid/3.head.nix24
-rw-r--r--pkgs/servers/squid/default.nix24
-rw-r--r--pkgs/servers/squid/squids.nix44
-rw-r--r--pkgs/servers/x11/xorg/default.nix20
-rw-r--r--pkgs/shells/zsh/cvs.nix19
-rw-r--r--pkgs/tools/archivers/cromfs/default.nix28
-rw-r--r--pkgs/tools/archivers/dar/default.nix16
-rw-r--r--pkgs/tools/cd-dvd/cdrkit/default.nix22
-rw-r--r--pkgs/tools/misc/grub/default.nix8
-rw-r--r--pkgs/tools/networking/proxychains/default.nix16
-rw-r--r--pkgs/tools/package-management/checkinstall/default.nix16
-rw-r--r--pkgs/tools/package-management/checkinstall/readlink.patch40
-rw-r--r--pkgs/tools/package-management/nix/unstable.nix8
-rw-r--r--pkgs/tools/security/aefs/default.nix7
-rw-r--r--pkgs/tools/security/ccrypt/default.nix13
-rw-r--r--pkgs/tools/security/gnupg2/default.nix33
-rw-r--r--pkgs/tools/system/ts/default.nix8
-rw-r--r--pkgs/tools/text/groff/default.nix35
-rw-r--r--pkgs/tools/text/namazu/default.nix37
-rw-r--r--pkgs/top-level/all-packages.nix479
-rw-r--r--pkgs/top-level/build-for-release.nix14
-rw-r--r--pkgs/top-level/builder-defs.nix30
150 files changed, 10978 insertions, 31200 deletions
diff --git a/pkgs/applications/editors/vim/configurable.nix b/pkgs/applications/editors/vim/configurable.nix
index b27bb157f75ad..0eac7ea5979f4 100644
--- a/pkgs/applications/editors/vim/configurable.nix
+++ b/pkgs/applications/editors/vim/configurable.nix
@@ -1,72 +1,78 @@
 # TODO tidy up eg The patchelf code is patching gvim even if you don't build it..
 # but I have gvim with python support now :) - Marc
-args:
-let edf = args.lib.enableDisableFeature; in
-( args.mkDerivationByConfiguration {
-    # most interpreters aren't tested yet.. (see python for example how to do it)
-    flagConfig = { 
-      mandatory = { cfgOption = "--enable-gui=auto --with-features=${args.features}"; 
-                    buildInputs = ["ncurses" "pkgconfig"];
-                  };
-      X11 = { buildInputs = [ "libX11" "libXext" "libSM" "libXpm" "libXt" "libXaw" "libXau" "libXmu" ]; };
+args: with args;
+let inherit (args.composableDerivation) composableDerivation edf; in
+composableDerivation {
+  initial = {
 
-    } // edf "darwin" "darwin" { } #Disable Darwin (Mac OS X) support.
-      // edf "xsmp" "xsmp" { } #Disable XSMP session management
-      // edf "xsmp_interact" "xsmp_interact" {  } #Disable XSMP interaction
-      // edf "mzscheme" "mzschemeinterp" { } #Include MzScheme interpreter.
-      // edf "perl" "perlinterp" { } #Include Perl interpreter.
-      // edf "python" "pythoninterp" { pass = "python"; } #Include Python interpreter.
-      // edf "tcl" "tclinterp" { } #Include Tcl interpreter.
-      // edf "ruby" "rubyinterp" { } #Include Ruby interpreter.
-      // edf "cscope" "cscope" { } #Include cscope interface.
-      // edf "workshop" "workshop" { } #Include Sun Visual Workshop support.
-      // edf "netbeans" "netbeans" { } #Disable NetBeans integration support.
-      // edf "sniff" "sniff" { } #Include Sniff interface.
-      // edf "multibyte" "multibyte" { } #Include multibyte editing support.
-      // edf "hangulinput" "hangulinput" { } #Include Hangul input support.
-      // edf "xim" "xim" { pass = "xim"; } #Include XIM input support.
-      // edf "fontset" "fontset" { } #Include X fontset output support.
+      name = "vim_configurable-7.1";
 
-  #--enable-gui=OPTS     X11 GUI default=auto OPTS=auto/no/gtk/gtk2/gnome/gnome2/motif/athena/neXtaw/photon/carbon
-    /*
-      // edf "gtk_check" "gtk_check" { } #If auto-select GUI, check for GTK default=yes
-      // edf "gtk2_check" "gtk2_check" { } #If GTK GUI, check for GTK+ 2 default=yes
-      // edf "gnome_check" "gnome_check" { } #If GTK GUI, check for GNOME default=no
-      // edf "motif_check" "motif_check" { } #If auto-select GUI, check for Motif default=yes
-      // edf "athena_check" "athena_check" { } #If auto-select GUI, check for Athena default=yes
-      // edf "nextaw_check" "nextaw_check" { } #If auto-select GUI, check for neXtaw default=yes
-      // edf "carbon_check" "carbon_check" { } #If auto-select GUI, check for Carbon default=yes
-      // edf "gtktest" "gtktest" { } #Do not try to compile and run a test GTK program
-    */
-      // edf "acl" "acl" { } #Don't check for ACL support.
-      // edf "gpm" "gpm" { } #Don't use gpm (Linux mouse daemon).
-      // edf "nls" "nls" { } #Don't support NLS (gettext()).
-    ; 
+      src = args.fetchurl {
+        url = ftp://ftp.vim.org/pub/vim/unix/vim-7.2.tar.bz2;
+        sha256 = "11hxkb6r2550c4n13nwr0d8afvh30qjyr5c2hw16zgay43rb0kci";
+      };
 
-  optionals = ["python"];
+      cfgOption = "--enable-gui=auto --with-features=${args.features}";
 
-  extraAttrs = co : {
-    name = "vim_configurable-7.1";
+      buildInputs = [ncurses pkgconfig]
+        ++ [ libX11 libXext libSM libXpm libXt libXaw libXau libXmu ];
 
-  src = args.fetchurl {
-    url = ftp://ftp.nluug.nl/pub/editors/vim/unix/vim-7.1.tar.bz2;
-    sha256 = "0w6gy49gdbw7hby5rjkjpa7cdvc0z5iajsm4j1h8108rvfam22kz";
-  };
+      # most interpreters aren't tested yet.. (see python for example how to do it)
+      flags = {}
+        // edf { name = "darwin"; } #Disable Darwin (Mac OS X) support.
+        // edf { name = "xsmp"; } #Disable XSMP session management
+        // edf { name = "xsmp_interact"; } #Disable XSMP interaction
+        // edf { name = "mzscheme"; } #Include MzScheme interpreter.
+        // edf { name = "perl"; } #Include Perl interpreter.
+        // edf { name = "python"; feat = "pythoninterp"; enable = { buildInputs = [python]; }; } #Include Python interpreter.
+        // edf { name = "tcl"; } #Include Tcl interpreter.
+        // edf { name = "ruby"; } #Include Ruby interpreter.
+        // edf { name = "cscope"; } #Include cscope interface.
+        // edf { name = "workshop"; } #Include Sun Visual Workshop support.
+        // edf { name = "netbeans"; } #Disable NetBeans integration support.
+        // edf { name = "sniff"; } #Include Sniff interface.
+        // edf { name = "multibyte"; } #Include multibyte editing support.
+        // edf { name = "hangulinput"; } #Include Hangul input support.
+        # // edf { name = "xim"; enable = { buildInputs = [xim]; }; } #Include XIM input support.
+        // edf { name = "fontset"; } #Include X fontset output support.
+        // edf { name = "acl"; } #Don't check for ACL support.
+        // edf { name = "gpm"; } #Don't use gpm (Linux mouse daemon).
+        // edf { name = "nls"; } #Don't support NLS (gettext()).
+        ;
+
+    cfg = {
+      pythonSupport = true;
+    };
+
+    #--enable-gui=OPTS     X11 GUI default=auto OPTS=auto/no/gtk/gtk2/gnome/gnome2/motif/athena/neXtaw/photon/carbon
+      /*
+        // edf "gtk_check" "gtk_check" { } #If auto-select GUI, check for GTK default=yes
+        // edf "gtk2_check" "gtk2_check" { } #If GTK GUI, check for GTK+ 2 default=yes
+        // edf "gnome_check" "gnome_check" { } #If GTK GUI, check for GNOME default=no
+        // edf "motif_check" "motif_check" { } #If auto-select GUI, check for Motif default=yes
+        // edf "athena_check" "athena_check" { } #If auto-select GUI, check for Athena default=yes
+        // edf "nextaw_check" "nextaw_check" { } #If auto-select GUI, check for neXtaw default=yes
+        // edf "carbon_check" "carbon_check" { } #If auto-select GUI, check for Carbon default=yes
+        // edf "gtktest" "gtktest" { } #Do not try to compile and run a test GTK program
+      */
 
-  postInstall = "
-    rpath=`patchelf --print-rpath \$out/bin/vim`;
-    for i in $\buildInputs; do
-      echo adding \$i/lib
-      rpath=\$rpath:\$i/lib
-    done
-    echo \$buildInputs
-    echo \$rpath
-    patchelf --set-rpath \$rpath \$out/bin/{vim,gvim}
-  ";
+    postInstall = "
+      rpath=`patchelf --print-rpath \$out/bin/vim`;
+      for i in $\buildInputs; do
+        echo adding \$i/lib
+        rpath=\$rpath:\$i/lib
+      done
+      echo \$buildInputs
+      echo \$rpath
+      patchelf --set-rpath \$rpath \$out/bin/{vim,gvim}
+    ";
+    dontStrip =1;
+
+    meta = {
+      description = "The most popular clone of the VI editor";
+      homepage = "www.vim.org";
+    };
 
-  meta = {
-    description = "The most popular clone of the VI editor";
-    homepage = "www.vim.org";
   };
-};
-} ) args
+
+}
diff --git a/pkgs/applications/graphics/exrdisplay/default.nix b/pkgs/applications/graphics/exrdisplay/default.nix
index f82f07602f8c5..6a8b3d6499bd9 100644
--- a/pkgs/applications/graphics/exrdisplay/default.nix
+++ b/pkgs/applications/graphics/exrdisplay/default.nix
@@ -1,6 +1,6 @@
 args: with args;
 
-assert fltk.flag_set_gl;
+assert fltk.glSupport;
 stdenv.mkDerivation {
 
   name ="openexr_viewers-1.0.1";
diff --git a/pkgs/applications/graphics/pqiv/default.nix b/pkgs/applications/graphics/pqiv/default.nix
index 72f338dcfeb9e..dbb2ce6ed737f 100644
--- a/pkgs/applications/graphics/pqiv/default.nix
+++ b/pkgs/applications/graphics/pqiv/default.nix
@@ -1,11 +1,11 @@
 { stdenv, fetchurl, getopt, which, pkgconfig, gtk } :
 
 stdenv.mkDerivation (rec {
-  name = "pqiv-0.7.1";
+  name = "pqiv-0.8";
 
   src = fetchurl {
-    url = "http://www.pberndt.com/raw//Programme/Linux/pqiv/_download/pqiv-0.7.1.tbz";
-    sha256 = "659c5d1d12c080dff5152325a2391e01a2c9a6ea225d1f755a98e8766f318eef";
+    url = "http://www.pberndt.com/raw//Programme/Linux/pqiv/_download/pqiv-0.8.tbz";
+    sha256 = "365332bab4b13ca56da6935e7155af20658e67d323808942dce23e880466f66d";
   };
 
   buildInputs = [ getopt which pkgconfig gtk ];
diff --git a/pkgs/applications/misc/audio/sox/default.nix b/pkgs/applications/misc/audio/sox/default.nix
index c0cf9d91b7303..1655457b40491 100644
--- a/pkgs/applications/misc/audio/sox/default.nix
+++ b/pkgs/applications/misc/audio/sox/default.nix
@@ -1,43 +1,9 @@
-args:
-( args.mkDerivationByConfiguration {
-    flagConfig = {
-    mandatory = { implies = [ "no_oss" "no_sun_audio" ]; };
-    # are these options of interest? We'll see
-    #--disable-fftw          disable usage of FFTW
-    #--enable-debug          enable debugging
-    #--disable-cpu-clip      disable tricky cpu specific clipper
-    alsa =              { cfgOption = "--enable-alsa"; buildInputs = "alsa"; };
-    no_alsa = { cfgOption = "--disable-alsa"; };
-    libao =             { cfgOption = "--enable-libao"; buildInputs = "libao"; };
-    no_libao = { cfgOption = "--disable-libao"; };
-    #oss =               { cfgOption = "--enable-oss"; buildInputs = "oss"; };
-    no_oss = { cfgOption = "--disable-oss"; };
-    #sun_audio =         { cfgOption = "--enable-sun-audio"; buildInputs = "sun_audio"; };
-    no_sun_audio = { cfgOption = "--disable-sun_audio"; };
-
-    # These options should be autodetected by the configure script 
-    /*
-    --without-sndfile       Don't try to use libsndfile
-    --without-ogg           Don't try to use Ogg Vorbis
-    --without-flac          Don't try to use FLAC
-    --without-ffmpeg        Don't try to use ffmpeg
-    --without-mad           Don't try to use MAD (MP3 Audio Decoder)
-    --without-lame          Don't try to use LAME (LAME Ain't an MP3 Encoder)
-    --without-amr-wb        Don't try to use amr-wb
-    --without-amr-nb        Don't try to use amr-nb
-    --without-samplerate    Don't try to use libsamplerate (aka Secret Rabbit
-                            Code)
-    --without-ladspa        Don't try to use LADSPA
-    --with-ladspa-path      Default search path for LADSPA plugins
-    */
-  };
-
-  optionals = [ "libsndfile" "libogg" "flac" "ffmpeg" "libmad" "lame" 
-                 /* "amr-wb" "amr-nb" */ 
-                "libsamplerate" /* "ladspa" */ ];
+args: with args;
+let inherit (args.composableDerivation) composableDerivation edf; in
+composableDerivation {
 
+  initial = {
 
-    extraAttrs = co : {
       name = "sox-14.0.0";
 
       src = args.fetchurl {
@@ -45,6 +11,43 @@ args:
         sha256 = "1l7v04nlvb96y0w9crvm6nq8g50yxp3bkv6nb1c205s982inlalc";
       };
 
+      flags =
+      # are these options of interest? We'll see
+      #--disable-fftw          disable usage of FFTW
+      #--enable-debug          enable debugging
+      #--disable-cpu-clip      disable tricky cpu specific clipper
+      edf { name = "alsa"; enable = { buildInputs = [alsaLib]; }; }
+      // edf { name = "libao"; enable = { buildInputs = [libao]; }; }
+      // edf { name = "oss"; }
+      // edf { name = "sun_audio"; };
+      # These options should be autodetected by the configure script
+      /*
+      --without-sndfile       Don't try to use libsndfile
+      --without-ogg           Don't try to use Ogg Vorbis
+      --without-flac          Don't try to use FLAC
+      --without-ffmpeg        Don't try to use ffmpeg
+      --without-mad           Don't try to use MAD (MP3 Audio Decoder)
+      --without-lame          Don't try to use LAME (LAME Ain't an MP3 Encoder)
+      --without-amr-wb        Don't try to use amr-wb
+      --without-amr-nb        Don't try to use amr-nb
+      --without-samplerate    Don't try to use libsamplerate (aka Secret Rabbit
+                              Code)
+      --without-ladspa        Don't try to use LADSPA
+      --with-ladspa-path      Default search path for LADSPA plugins
+      */
+
+
+    cfg = {
+      ossSupport = false;
+      sun_audioSupport = false;
+    };
+
+
+    optionals = [ "libsndfile" "libogg" "flac" "ffmpeg" "libmad" "lame"
+                   /* "amr-wb" "amr-nb" */
+                  "libsamplerate" /* "ladspa" */ ];
+
+
     meta = {
       description = "Sample Rate Converter for audio";
       homepage = http://www.mega-nerd.com/SRC/index.html;
@@ -55,4 +58,4 @@ args:
                   } ];
     };
   };
-} ) args
+}
diff --git a/pkgs/applications/misc/gv/default.nix b/pkgs/applications/misc/gv/default.nix
index 4f1b415e90669..109c3d8102f93 100644
--- a/pkgs/applications/misc/gv/default.nix
+++ b/pkgs/applications/misc/gv/default.nix
@@ -10,13 +10,16 @@ stdenv.mkDerivation rec {
 
   buildInputs = [ Xaw3d ghostscriptX ];
   
-  postConfigure = [ "sed 's|\\<gs\\>|${ghostscriptX}/bin/gs|g' -i src/*.am" ];
+  postConfigure = ''
+    sed 's|\<gs\>|${ghostscriptX}/bin/gs|g' -i src/*.in
+    sed 's|"gs"|"${ghostscriptX}/bin/gs"|g' -i src/*.c
+  '';
 
   doCheck = true;
 
   meta = {
     homepage = http://www.gnu.org/software/gv/;
     description = "GNU gv, a PostScript/PDF document viewer";
-    license = "GPLv2+";
+    license = "GPLv3+";
   };
 }
diff --git a/pkgs/applications/misc/mrxvt/default.nix b/pkgs/applications/misc/mrxvt/default.nix
index f58fff56bc084..346ae2b50cd4a 100644
--- a/pkgs/applications/misc/mrxvt/default.nix
+++ b/pkgs/applications/misc/mrxvt/default.nix
@@ -1,26 +1,17 @@
-args: with args.lib; with args;
+args: with args;
+stdenv.mkDerivation {
 
-let
-  co = chooseOptionsByFlags {
-    inherit args;
-    flagDescr = {
-      mandatory = { buildInputs = [ "libX11" ]; cfgOption = "--with-x"; };
-      # many options to add here ... :)
-      # many of them can be set by configuration file I think..
-    };
-};
+  name = "mrxvt-0.5.3";
 
-in stdenv.mkDerivation {
+  buildInputs = [libX11];
 
-  inherit (co) buildInputs configureFlags;
+  configureFlags="--with-x";
 
   src = fetchurl {
     url = mirror://sourceforge/materm/mrxvt-0.5.3.tar.gz;
     sha256 = "04flnn58hp4qvvk6jzyipsj13v1qyrjabgbw5laz5cqxvxzpncp2";
   };
 
-  name = "mrxvt-0.5.3";
-
   meta = { 
     description = "multitabbed lightweight terminal emulator basd on rxvt supporting transparency, backgroundimages, freetype fonts,..";
     homepage = http://sourceforge.net/projects/materm;
diff --git a/pkgs/applications/misc/qgis/0.11.0.nix b/pkgs/applications/misc/qgis/0.11.0.nix
new file mode 100644
index 0000000000000..127675b358d5c
--- /dev/null
+++ b/pkgs/applications/misc/qgis/0.11.0.nix
@@ -0,0 +1,45 @@
+args: with args;
+let edf = composableDerivation.edf;
+    optionIncLib = name : attr : " -D${name}_INCLUDE_DIR=${__getAttr attr args}/incclude"
+                               + " -D${name}_LIBRARY=${__getAttr attr args}/lib "; # lib 64?
+in
+composableDerivation.composableDerivation {
+  initial = {
+
+    buildInputs = [ gdal cmake qt flex bison proj geos x11 sqlite gsl];
+      cfgOption = [
+                    # without this option it can't find sqlite libs yet (missing symbols..) (TODO)
+                    "-DWITH_INTERNAL_SQLITE3=TRUE"
+                  ];
+
+    name = "qgis-${version}";
+
+    # src = args.fetchsvn { url=https://svn.qgis.org/repos/qgis/trunk/qgis;
+    #                md5="ac0560e0a2d4e6258c8639f1e9b56df3"; rev="7704"; };
+    src = fetchurl {
+      url = "http://download.osgeo.org/qgis/src/qgis_${version}.tar.gz";
+      sha256 = "17vqbld4wr9jyn1s5n0bkpaminsgc2dzcgdfk8ic168xydnwa7b3";
+    };
+
+    meta = {
+      description = "user friendly Open Source Geographic Information System";
+      homepage = http://www.qgis.org;
+      # you can choose one of the following licenses:
+      license = [ "GPL" ];
+    };
+
+    phases = "unpackPhase buildPhase installPhase";
+    buildPhase = ''pwd;echo XXXXXXXXX; VERBOSE=1 cmake -DCMAKE_INSTALL_PREFIX=$out ''${cfgOption} ..'';
+
+    postUnpack = ''
+      export CMAKE_SYSTEM_LIBRARY_PATH=
+      for i in $buildInputs $propagatedBuildInputs; do
+        CMAKE_SYSTEM_LIBRARY_PATH=$i/lib:$CMAKE_SYSTEM_LIBRARY_PATH
+      done
+    '';
+
+    #configurePhase="./autogen.sh --prefix=\$out --with-gdal=\$gdal/bin/gdal-config --with-qtdir=\$qt";
+    # buildPhases="unpackPhase buildPhase";
+
+  };
+}
diff --git a/pkgs/applications/misc/qgis_svn/default.nix b/pkgs/applications/misc/qgis_svn/default.nix
deleted file mode 100644
index 547e941ecac8f..0000000000000
--- a/pkgs/applications/misc/qgis_svn/default.nix
+++ /dev/null
@@ -1,74 +0,0 @@
-args:
-let optionIncLib = name : attr : " -D${name}_INCLUDE_DIR=${__getAttr attr args}/inc"
-                               + " -D${name}_LIBRARY=${__getAttr attr args}/lib "; # lib 64?
-in
-( args.mkDerivationByConfiguration {
-
-    flagConfig = {
-      mandatory = { 
-        buildInputs = [ "gdal" "cmake" "qt" "flex" "bison" "proj" "geos" "x11" "sqlite" "gsl"]; 
-        cfgOption = [ (optionIncLib "GEOS" "geos") 
-                         (optionIncLib "PROJ" "proj")
-                         (optionIncLib "QT_X11_X11" "qt")
-                         (optionIncLib "QT_X11_Xext" "qt")
-                         (optionIncLib "QT_X11_m" "glibc")
-                         (optionIncLib "SQLITE3" "sqlite")
-
-"-DQT_FONTCONFIG_LIBRARY=${args.fontconfig}/lib"
-"-DQT_FREETYPE_LIBRARY=${args.freetype}/lib"
-"-DQT_PNG_LIBRARY=${args.libpng}/lib"
-"-DQT_X11_ICE_LIBRARY=${args.libICE}/lib"
-"-DQT_X11_SM_LIBRARY=${args.libSM}/lib"
-"-DQT_XCURSOR_LIBRARY=${args.libXcursor}/lib"
-"-DQT_XINERAMA_LIBRARY=${args.libXinerama}/lib"
-"-DQT_XRANDR_LIBRARY=${args.libXrandr}/lib"
-"-DQT_XRENDER_LIBRARY=${args.libXrender}/lib"
-"-DQT_ZLIB_LIBRARY=${args.zlib}/lib"
-                         ];
-
-/* advanced options - feel free to add them if you have time to
-"-DPROJ_INCLUDE_DIR"
-"-DPROJ_LIBRARY"
-"-DQT_X11_X11_LIBRARY"
-"-DQT_X11_Xext_LIBRARY"
-"-DQT_X11_m_LIBRARY"
-"-DSQLITE3_INCLUDE_DIR"
-"-DSQLITE3_LIBRARY"
--DQT_FONTCONFIG_LIBRARY (ADVANCED)
--DQT_FREETYPE_LIBRARY (ADVANCED)
--DQT_PNG_LIBRARY (ADVANCED)
--DQT_X11_ICE_LIBRARY (ADVANCED)
--DQT_X11_SM_LIBRARY (ADVANCED)
--DQT_XCURSOR_LIBRARY (ADVANCED)
--DQT_XINERAMA_LIBRARY (ADVANCED)
--DQT_XRANDR_LIBRARY (ADVANCED)
--DQT_XRENDER_LIBRARY (ADVANCED)
--DQT_ZLIB_LIBRARY (ADVANCED)
-*/
-      };
-    }; 
-
-    #inherit geos proj x11 libXext;
-
-    extraAttrs = co : {
-
-    name = "qgis-svn";
-
-    src = args.fetchsvn { url=https://svn.qgis.org/repos/qgis/trunk/qgis; 
-                    md5="ac0560e0a2d4e6258c8639f1e9b56df3"; rev="7704"; };
-
-    meta = { 
-      description = "user friendly Open Source Geographic Information System";
-      homepage = http://www.qgis.org;
-      # you can choose one of the following licenses: 
-      license = [ "GPL" ];
-    };
-
-    phases = "unpackPhase buildPhase installPhase";
-    buildPhase = "cmake -DCMAKE_INSTALL_PREFIX=\$out ${co.configureFlags} .";
-
-    #configurePhase="./autogen.sh --prefix=\$out --with-gdal=\$gdal/bin/gdal-config --with-qtdir=\$qt";
-    # buildPhases="unpackPhase buildPhase";
-  };
-
-} ) args
diff --git a/pkgs/applications/misc/truecrypt/builder.sh b/pkgs/applications/misc/truecrypt/builder.sh
index 71fcc0f94e2a1..88820d4cad21d 100644
--- a/pkgs/applications/misc/truecrypt/builder.sh
+++ b/pkgs/applications/misc/truecrypt/builder.sh
@@ -1,15 +1,15 @@
 source $stdenv/setup
 
-# PATH=$perl/bin:$PATH
-
-tar zxvf $wxWidgets
-
-# we need the absolute path, relative will not work
-wxwdir=$(pwd)/wxX11-*
-
 tar xvfz $src
 cd truecrypt-*
 
-make WX_ROOT=$wxwdir wxbuild
-make
+cp $pkcs11h pkcs11.h
+cp $pkcs11th pkcs11t.h
+cp $pkcs11fh pkcs11f.h
+
+make PKCS11_INC="`pwd`"
 
+mkdir -p $out/bin
+cp Main/truecrypt $out/bin
+mkdir -p $out/share/$name
+cp License.txt $out/share/$name/LICENSE
diff --git a/pkgs/applications/misc/truecrypt/default.nix b/pkgs/applications/misc/truecrypt/default.nix
index e1ac3dd350664..1cd7eb2c237c3 100644
--- a/pkgs/applications/misc/truecrypt/default.nix
+++ b/pkgs/applications/misc/truecrypt/default.nix
@@ -40,24 +40,38 @@ library, use the 'NOGUI' parameter:
    $ make NOGUI=1
 */
 
-{ fetchurl, stdenv, pkgconfig, fuse, gtk, libSM, glibc
+{ fetchurl, stdenv, pkgconfig, fuse, wxGTK, devicemapper
 }:
 
 stdenv.mkDerivation {
-  name = "trueCrypt-6.0a";
+  name = "trueCrypt-6.1a";
   builder = ./builder.sh;
 
   src = fetchurl {
-    url = http://www.sfr-fresh.com/unix/misc/TrueCrypt-6.0a-Source.tar.gz;
-    sha256 = "dea0ac2f1f6964d7e88f6751fa9f0a89d0dbfb957e9a557e8dee48492d0b4fac";
+    url = http://www.sfr-fresh.com/unix/misc/TrueCrypt-6.1a-Source.tar.gz;
+    sha256 = "a2bb8273edcb3c3d10d9819daac853f940033deb1f9726986311356bd5b88c4a";
   };
 
-  wxWidgets = fetchurl {
-    url = mirror://sourceforge/wxwindows/wxX11-2.8.8.tar.gz;
-    sha256 = "85e1a458fd9523c68b22af0a51eb507b792894e9ba58a560f9dbe7b6faa6f625";
+  pkcs11h = fetchurl {
+    url = ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-11/v2-20/pkcs11.h;
+    sha256 = "1563d877b6f8868b8eb8687358162bfb7f868104ed694beb35ae1c5cf1a58b9b";
   };
 
-  buildInputs = [pkgconfig fuse gtk libSM glibc];
-  #configureFlags =
-  #postInstall = "
+  pkcs11th = fetchurl {
+    url = ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-11/v2-20/pkcs11t.h;
+    sha256 = "8ce68616304684f92a7e267bcc8f486441e92a5cbdfcfd97e69ac9a0b436fb7b";
+  };
+
+  pkcs11fh = fetchurl {
+    url = ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-11/v2-20/pkcs11f.h;
+    sha256 = "5ae6a4f32ca737e02def3bf314c9842fb89be82bf00b6f4022a97d8d565522b8";
+  };
+
+  buildInputs = [pkgconfig fuse wxGTK devicemapper];
+
+  meta = {
+    description = "Free Open-Source filesystem on-the-fly encryption";
+    homepage = http://www.truecrypt.org/;
+    license = "TrueCrypt License Version 2.6";
+  };
 }
diff --git a/pkgs/applications/misc/xneur/0.8.nix b/pkgs/applications/misc/xneur/0.8.nix
new file mode 100644
index 0000000000000..9010c36a5a8ba
--- /dev/null
+++ b/pkgs/applications/misc/xneur/0.8.nix
@@ -0,0 +1,26 @@
+args: with args;
+
+stdenv.mkDerivation {
+  name="xneur";
+  src = fetchurl {
+    url = http://dists.xneur.ru/release-0.8.0/tgz/xneur-0.8.0.tar.bz2;
+    sha256 = "1f05bm4vqdrlm8rxwgqv89k5lhc236xg841aw4snw514g0hi2sl8";
+  };
+
+  buildInputs = [libX11 pkgconfig pcre GStreamer glib libxml2 aspell
+    libXpm imlib2 xosd libXt libXext];
+
+  inherit aspell imlib2 xosd;
+
+  preConfigure = ''
+    sed -e 's/-Werror//' -i configure
+    sed -e 's/for aspell_dir in/for aspell_dir in $aspell /' -i configure
+    sed -e 's/for imlib2_dir in/for imlib2_dir in $imlib2 /' -i configure
+    sed -e 's/for xosd_dir in/for xosd_dir in $xosd /' -i configure
+  '';
+
+  meta = {
+    description = "xneur is the keyboard layout switcher.";
+  };
+
+}
diff --git a/pkgs/applications/misc/xneur/default.nix b/pkgs/applications/misc/xneur/default.nix
index d69a8334d43d1..7e5fad64c0153 100644
--- a/pkgs/applications/misc/xneur/default.nix
+++ b/pkgs/applications/misc/xneur/default.nix
@@ -3,18 +3,20 @@ args: with args;
 stdenv.mkDerivation {
   name="xneur";
   src = fetchurl {
-    url = "http://dists.xneur.ru/release-0.9.2/tgz/xneur-0.9.2.tar.bz2";
-    sha256 = "1zk13ixd82nq8a2rzmmk53xy2iphydf57mfb2ndfil21rkffr0jq";
+    url = http://dists.xneur.ru/release-0.9.3/tgz/xneur-0.9.3.tar.bz2;
+    sha256 = "14pjsxajbibjl70yrvina3kk2114h3i7bgyqlxpjkfcz2778qq12";
   };
 
   buildInputs = [libX11 pkgconfig pcre GStreamer glib libxml2 aspell
-    libXpm];
+    libXpm imlib2 xosd libXt libXext];
 
-  inherit aspell;
+  inherit aspell imlib2 xosd;
 
   preConfigure = ''
     sed -e 's/-Werror//' -i configure
     sed -e 's/for aspell_dir in/for aspell_dir in $aspell /' -i configure
+    sed -e 's/for imlib2_dir in/for imlib2_dir in $imlib2 /' -i configure
+    sed -e 's/for xosd_dir in/for xosd_dir in $xosd /' -i configure
   '';
 
   meta = {
@@ -22,6 +24,3 @@ stdenv.mkDerivation {
   };
 
 }
-
-
-
diff --git a/pkgs/applications/misc/xpdf/default.nix b/pkgs/applications/misc/xpdf/default.nix
index fc79703d87704..ae8da855cd7b5 100644
--- a/pkgs/applications/misc/xpdf/default.nix
+++ b/pkgs/applications/misc/xpdf/default.nix
@@ -8,7 +8,7 @@ assert enablePDFtoPPM -> freetype != null;
 assert useT1Lib -> t1lib != null;
 
 stdenv.mkDerivation {
-  name = "xpdf-3.02pl1";
+  name = "xpdf-3.02pl2";
 
   src = fetchurl {
     url = ftp://ftp.foolabs.com/pub/xpdf/xpdf-3.02.tar.gz;
@@ -24,6 +24,10 @@ stdenv.mkDerivation {
       url = ftp://ftp.foolabs.com/pub/xpdf/xpdf-3.02pl1.patch;
       sha256 = "1wxv9l0d2kkwi961ihpdwi75whdvk7cgqxkbfym8cjj11fq17xjq";
     })
+    (fetchurl {
+      url = ftp://ftp.foolabs.com/pub/xpdf/xpdf-3.02pl2.patch;
+      sha256 = "1nfrgsh9xj0vryd8h65myzd94bjz117y89gq0hzji9dqn23xihfi";
+    })
     ./xpdf-3.02-protection.patch
   ];
     
diff --git a/pkgs/applications/networking/browsers/firefox-2/default.nix b/pkgs/applications/networking/browsers/firefox-2/default.nix
index 31da6ea2b4650..e557743aacad9 100644
--- a/pkgs/applications/networking/browsers/firefox-2/default.nix
+++ b/pkgs/applications/networking/browsers/firefox-2/default.nix
@@ -10,12 +10,12 @@
 }:
 
 stdenv.mkDerivation {
-  name = "firefox-2.0.0.17";
+  name = "firefox-2.0.0.20";
 
   builder = ./builder.sh;
   src = fetchurl {
-    url = http://releases.mozilla.org/pub/mozilla.org/firefox/releases/2.0.0.17/source/firefox-2.0.0.17-source.tar.bz2;
-    sha1 = "ba95d9f64f2307b109dbce25d7a17af7e68298ed";
+    url = http://releases.mozilla.org/pub/mozilla.org/firefox/releases/2.0.0.20/source/firefox-2.0.0.20-source.tar.bz2;
+    sha1 = "16601fdbbb0a83b85fd053e76350f7da397f525e";
   };
 
   buildInputs = [
diff --git a/pkgs/applications/networking/browsers/firefox-3/3.1.nix b/pkgs/applications/networking/browsers/firefox-3/3.1.nix
new file mode 100644
index 0000000000000..ef40ac0c7d3e5
--- /dev/null
+++ b/pkgs/applications/networking/browsers/firefox-3/3.1.nix
@@ -0,0 +1,84 @@
+{ stdenv, fetchurl, pkgconfig, gtk, pango, perl, python, zip, libIDL
+, libjpeg, zlib, cairo, dbus, dbus_glib, bzip2
+, freetype, fontconfig, xulrunner, alsaLib, autoconf
+
+, # If you want the resulting program to call itself "Firefox" instead
+  # of "Deer Park", enable this option.  However, those binaries may
+  # not be distributed without permission from the Mozilla Foundation,
+  # see http://www.mozilla.org/foundation/trademarks/.
+  enableOfficialBranding ? false
+    
+}:
+
+stdenv.mkDerivation {
+  name = "firefox-3.1b2";
+
+  src = fetchurl {
+    url = ftp://ftp.mozilla.org/pub/firefox/releases/3.1b2/source/firefox-3.1b2-source.tar.bz2;
+    sha256 = "1mqy7q4bfw8iphlmzvymqfki8r4zzynyyy6z6gws4qqx9ry42jqs";
+  };
+
+  buildInputs = [
+    pkgconfig gtk perl zip libIDL libjpeg zlib cairo bzip2
+    python dbus dbus_glib pango freetype fontconfig alsaLib
+    autoconf
+  ];
+
+  propagatedBuildInputs = [xulrunner];
+
+  preConfigure = ''
+    export PREFIX=$out
+    export LIBXUL_DIST=$out
+    autoconf
+    cd js/src
+    autoconf
+    cd ../..
+  '';
+
+  preBuild = ''
+    cd nsprpub
+    autoconf 
+    ./configure
+    make
+    cd ..
+  '';
+
+  configureFlags = [
+    "--enable-application=browser"
+    "--enable-optimize"
+    "--disable-debug"
+    "--enable-strip"
+    "--with-system-jpeg"
+    "--with-system-zlib"
+    "--with-system-bz2"
+    # "--with-system-png" # <-- "--with-system-png won't work because the system's libpng doesn't have APNG support"
+    "--enable-system-cairo"
+    #"--enable-system-sqlite" # <-- this seems to be discouraged
+    "--disable-crashreporter"
+    "--with-libxul-sdk=${xulrunner}/lib/xulrunner-devel-${xulrunner.version}"
+  ];
+
+  postInstall = ''
+    # Strip some more stuff.
+    strip -S $out/lib/*/* || true
+
+    libDir=$(cd $out/lib && ls -d firefox-[0-9]*)
+    test -n "$libDir"
+    
+    ln -s ${xulrunner}/lib/xulrunner-${xulrunner.version} $out/lib/$libDir/xulrunner
+
+    # Register extensions etc. !!! is this needed anymore?
+    echo "running firefox -register..."
+    $out/bin/firefox -register
+  ''; # */
+
+  meta = {
+    description = "Mozilla Firefox - the browser, reloaded";
+    homepage = http://www.mozilla.com/en-US/firefox/;
+  };
+
+  passthru = {
+    inherit gtk;
+    isFirefox3Like = true;
+  };
+}
diff --git a/pkgs/applications/networking/browsers/firefox-3/default.nix b/pkgs/applications/networking/browsers/firefox-3/default.nix
index 9874b6df7d1df..4c89505bb94d4 100644
--- a/pkgs/applications/networking/browsers/firefox-3/default.nix
+++ b/pkgs/applications/networking/browsers/firefox-3/default.nix
@@ -11,11 +11,12 @@
 }:
 
 stdenv.mkDerivation {
-  name = "firefox-3.0.4";
+  name = "firefox-3.0.5";
 
   src = fetchurl {
-    url = http://releases.mozilla.org/pub/mozilla.org/firefox/releases/3.0.4/source/firefox-3.0.4-source.tar.bz2;
-    sha1 = "16715b4af7ca2bad6baa8d450a3fd9cb375ad6d6";
+    # Don't forget to update xulrunner.nix as well!
+    url = http://releases.mozilla.org/pub/mozilla.org/firefox/releases/3.0.5/source/firefox-3.0.5-source.tar.bz2;
+    sha1 = "f934e073efaad3d4dde847c8491fa9529564d5d2";
   };
 
   buildInputs = [
diff --git a/pkgs/applications/networking/browsers/firefox-3/xulrunner-3.1.nix b/pkgs/applications/networking/browsers/firefox-3/xulrunner-3.1.nix
new file mode 100644
index 0000000000000..0fb5027e31ee1
--- /dev/null
+++ b/pkgs/applications/networking/browsers/firefox-3/xulrunner-3.1.nix
@@ -0,0 +1,96 @@
+{ stdenv, fetchurl, pkgconfig, gtk, pango, perl, python, zip, libIDL
+, libjpeg, libpng, zlib, cairo, dbus, dbus_glib, bzip2, xlibs
+, freetype, fontconfig, file, alsaLib, autoconf
+
+, # If you want the resulting program to call itself "Firefox" instead
+  # of "Deer Park", enable this option.  However, those binaries may
+  # not be distributed without permission from the Mozilla Foundation,
+  # see http://www.mozilla.org/foundation/trademarks/.
+  enableOfficialBranding ? false
+}:
+
+let
+
+  version = "1.9.1b2"; # this attribute is used by other packages
+
+in  
+
+stdenv.mkDerivation {
+  name = "xulrunner-${version}";
+
+  src = fetchurl {
+    url = ftp://ftp.mozilla.org/pub/firefox/releases/3.1b2/source/firefox-3.1b2-source.tar.bz2;
+    sha256 = "1mqy7q4bfw8iphlmzvymqfki8r4zzynyyy6z6gws4qqx9ry42jqs";
+  };
+
+  buildInputs = [
+    pkgconfig gtk perl zip libIDL libjpeg libpng zlib cairo bzip2
+    python dbus dbus_glib pango freetype fontconfig
+    xlibs.libXi xlibs.libX11 xlibs.libXrender xlibs.libXft xlibs.libXt
+    file alsaLib autoconf
+  ];
+
+  preConfigure = ''
+    export PREFIX=$out
+    export LIBXUL_DIST=$out
+    autoconf
+    cd js/src
+    autoconf
+    cd ../..
+  '';
+
+  configureFlags = [
+    "--enable-application=xulrunner"
+    "--disable-javaxpcom"
+    "--enable-optimize"
+    "--disable-debug"
+    "--enable-strip"
+    "--with-system-jpeg"
+    "--with-system-zlib"
+    "--with-system-bz2"
+    # "--with-system-png" # <-- "--with-system-png won't work because the system's libpng doesn't have APNG support"
+    "--enable-system-cairo"
+    #"--enable-system-sqlite" # <-- this seems to be discouraged
+    "--disable-crashreporter"
+  ];
+
+  installFlags = [
+    "SKIP_GRE_REGISTRATION=1"
+  ];
+
+  postInstall = ''
+    export dontPatchELF=1;
+
+    # Strip some more stuff
+    strip -S $out/lib/*/* || true
+
+    # Fix some references to /bin paths in the Firefox shell script.
+    substituteInPlace $out/bin/xulrunner \
+        --replace /bin/pwd "$(type -tP pwd)" \
+        --replace /bin/ls "$(type -tP ls)"
+    
+    # Fix run-mozilla.sh search
+    libDir=$(cd $out/lib && ls -d xulrunner-[0-9]*)
+    echo libDir: $libDir
+    test -n "$libDir"
+    cd $out/bin
+    mv xulrunner ../lib/$libDir/
+
+    for i in $out/lib/$libDir/*; do 
+        file $i;
+        if file $i | grep executable &>/dev/null; then 
+	    ln -s $i $out/bin
+        fi;
+    done;
+    rm $out/bin/run-mozilla.sh || true
+  ''; # */
+
+  meta = {
+    description = "Mozilla Firefox XUL runner";
+    homepage = http://www.mozilla.com/en-US/firefox/;
+  };
+
+  passthru = { inherit gtk version; };
+}
+
+
diff --git a/pkgs/applications/networking/browsers/firefox-3/xulrunner.nix b/pkgs/applications/networking/browsers/firefox-3/xulrunner.nix
index 09798ce02ddc2..5dede1b723f86 100644
--- a/pkgs/applications/networking/browsers/firefox-3/xulrunner.nix
+++ b/pkgs/applications/networking/browsers/firefox-3/xulrunner.nix
@@ -11,7 +11,7 @@
 
 let
 
-  version = "1.9.0.4"; # this attribute is used by other packages
+  version = "1.9.0.5"; # this attribute is used by other packages
 
 in  
 
@@ -19,8 +19,8 @@ stdenv.mkDerivation {
   name = "xulrunner-${version}";
 
   src = fetchurl {
-    url = http://releases.mozilla.org/pub/mozilla.org/firefox/releases/3.0.4/source/firefox-3.0.4-source.tar.bz2;
-    sha1 = "16715b4af7ca2bad6baa8d450a3fd9cb375ad6d6";
+    url = http://releases.mozilla.org/pub/mozilla.org/firefox/releases/3.0.5/source/firefox-3.0.5-source.tar.bz2;
+    sha1 = "f934e073efaad3d4dde847c8491fa9529564d5d2";
   };
 
   buildInputs = [
diff --git a/pkgs/applications/networking/browsers/icecat-3/default.nix b/pkgs/applications/networking/browsers/icecat-3/default.nix
index b22fe9b6d8026..cd786c2b014c5 100644
--- a/pkgs/applications/networking/browsers/icecat-3/default.nix
+++ b/pkgs/applications/networking/browsers/icecat-3/default.nix
@@ -4,13 +4,13 @@
 , freetype, fontconfig
 , application ? "browser" }:
 
-let version = "3.0.3-g1"; in
+let version = "3.0.5-g1"; in
 stdenv.mkDerivation {
   name = "icecat-${version}";
 
   src = fetchurl {
     url = "mirror://gnu/gnuzilla/${version}/icecat-${version}.tar.lzma";
-    sha256 = "189rfgcsp98hd8ix8mc294xg0iw3qwmn2nyb2495hx84zli09n5m";
+    sha256 = "15s71zjwiqpaqsmjzk5kxwamxzkb3p7172dbazqyxmgvca9yw8bs";
   };
 
   buildInputs = [
@@ -104,7 +104,7 @@ stdenv.mkDerivation {
   };
 
   passthru = {
-    inherit gtk;
+    inherit gtk version;
     isFirefox3Like = true;
   };
 }
diff --git a/pkgs/applications/networking/browsers/mozilla-plugins/flashplayer-10/default.nix b/pkgs/applications/networking/browsers/mozilla-plugins/flashplayer-10/default.nix
index 9cb9ef8bb5abf..043273a635c12 100644
--- a/pkgs/applications/networking/browsers/mozilla-plugins/flashplayer-10/default.nix
+++ b/pkgs/applications/networking/browsers/mozilla-plugins/flashplayer-10/default.nix
@@ -9,7 +9,7 @@ stdenv.mkDerivation {
   
   src = fetchurl {
     url = http://fpdownload.macromedia.com/get/flashplayer/current/install_flash_player_10_linux.tar.gz;
-    sha256 = "0bcn07a3684krqbh6cw08hb8lymm0wijnlcx5bvln44749kzg7wf";
+    sha256 = "cd3e8fbb05da4a5303f958cb627bc7f3845dd86576a96ab157effc4f0ae65e5d";
   };
 
   inherit zlib alsaLib;
diff --git a/pkgs/applications/networking/instant-messengers/mcabber/default.nix b/pkgs/applications/networking/instant-messengers/mcabber/default.nix
new file mode 100644
index 0000000000000..dd5a3dc8b9ee7
--- /dev/null
+++ b/pkgs/applications/networking/instant-messengers/mcabber/default.nix
@@ -0,0 +1,19 @@
+{stdenv, fetchurl, openssl, ncurses, pkgconfig, glib}:
+
+stdenv.mkDerivation {
+
+  name = "mcabber-0.9.9";
+
+  src = fetchurl {
+    url = http://mirror.mcabber.com/files/mcabber-0.9.9.tar.bz2;
+    sha256 = "2a231c9241211d33745f110f35cfa6bdb051b32791461b9579794b6623863bb1";
+  };
+
+  meta = { homepage = "http://mirror.mcabber.com/";
+           description = "Small Jabber console client";
+         };
+
+  buildInputs = [openssl ncurses pkgconfig glib];
+
+  configureFlags = "--with-openssl=${openssl}";
+}
diff --git a/pkgs/applications/networking/instant-messengers/psi/0.12.nix b/pkgs/applications/networking/instant-messengers/psi/0.12.nix
new file mode 100644
index 0000000000000..a9af276661fb6
--- /dev/null
+++ b/pkgs/applications/networking/instant-messengers/psi/0.12.nix
@@ -0,0 +1,20 @@
+args : with args;
+rec {
+  src = fetchurl {
+    url = mirror://sourceforge/psi/psi-0.12.tar.gz;
+    sha256 = "6afbb3b017009bf4d8d275ec1481e92831b0618ecb58f1372cd9189140a316af";
+  };
+
+  buildInputs = [aspell qt zlib sox openssl libX11 xproto
+    libSM libICE];
+  configureFlags = [" --with-zlib-inc=${zlib}/include "
+    " --with-openssl-inc=${openssl}/include "
+  ];
+
+  phaseNames = ["doConfigure" "doMakeInstall"];
+
+  name = "psi-" + version;
+  meta = {
+    description = "Psi, an XMPP (Jabber) client";
+  };
+}
diff --git a/pkgs/applications/networking/mailreaders/thunderbird-2.x/default.nix b/pkgs/applications/networking/mailreaders/thunderbird-2.x/default.nix
index 6f052936c13b8..db051fc026f9b 100644
--- a/pkgs/applications/networking/mailreaders/thunderbird-2.x/default.nix
+++ b/pkgs/applications/networking/mailreaders/thunderbird-2.x/default.nix
@@ -11,13 +11,13 @@
 }:
 
 stdenv.mkDerivation {
-  name = "thunderbird-2.0.0.18";
+  name = "thunderbird-2.0.0.19";
 
   builder = ./builder.sh;
   
   src = fetchurl {
-    url = ftp://ftp.mozilla.org/pub/mozilla.org/thunderbird/releases/2.0.0.18/source/thunderbird-2.0.0.18-source.tar.bz2;
-    sha1 = "4d05300280763e34c7a115835523ed2805f7733c";
+    url = ftp://ftp.mozilla.org/pub/mozilla.org/thunderbird/releases/2.0.0.19/source/thunderbird-2.0.0.19-source.tar.bz2;
+    sha1 = "4d2e0f8b405bb0ceab20a9f570ce91cf4640f456";
   };
 
   buildInputs = [
diff --git a/pkgs/applications/networking/p2p/mldonkey/default.nix b/pkgs/applications/networking/p2p/mldonkey/default.nix
new file mode 100644
index 0000000000000..4d284c5ebe787
--- /dev/null
+++ b/pkgs/applications/networking/p2p/mldonkey/default.nix
@@ -0,0 +1,18 @@
+{stdenv, fetchurl, ocaml, zlib, ncurses}:
+
+stdenv.mkDerivation {
+  name = "mldonkey-2.9.6";
+  
+  src = fetchurl {
+    url = mirror://sourceforge/mldonkey/mldonkey-2.9.6.tar.bz2;
+    sha256 = "27cc8ae95aa7a2934b6cc9b077d10ca6a776496c051d8f35d60f1e73d38fd505";
+  };
+  
+  meta = {
+    description = "Client for many p2p networks, with multiple frontends";
+    homepage = http://mldonkey.sourceforge.net/;
+  };
+
+  buildInputs = [ ocaml zlib ncurses ];
+  configureFlags = "--disable-gd --disable-gui";
+}
diff --git a/pkgs/applications/networking/skype/default.nix b/pkgs/applications/networking/skype/default.nix
index 25ab4f77d8499..f66579438c505 100644
--- a/pkgs/applications/networking/skype/default.nix
+++ b/pkgs/applications/networking/skype/default.nix
@@ -1,12 +1,12 @@
 args: with args;
 stdenv.mkDerivation ( rec {
   pname = "skype";
-  version = "1.4.0.118";
-  name = "skype-1.4";
+  version = "2.0.0.72";
+  name = "skype-2.0";
 
   src = fetchurl {
     url = http://www.skype.com/go/getskype-linux-static;
-    sha256 = "1293f54811a36b2a1b83c56a4ad2844e58c753fe39b61422fac66b001d0f9e0c";
+    sha256 = "2f37963e8f19c0ec5efd8631abe9633b6551f09dee024460c40fad10728bc580";
     name = "${pname}_static-${version}.tar.bz2";
   };
 
@@ -17,6 +17,8 @@ stdenv.mkDerivation ( rec {
     libSM 
     libICE 
     libXi 
+    libXv
+    libXScrnSaver
     libXrender 
     libXrandr 
     libXfixes 
diff --git a/pkgs/applications/science/math/maxima/default.nix b/pkgs/applications/science/math/maxima/default.nix
index 72770c9a918f7..73b10f5a21a0d 100644
--- a/pkgs/applications/science/math/maxima/default.nix
+++ b/pkgs/applications/science/math/maxima/default.nix
@@ -1,12 +1,11 @@
 args: with args;
 stdenv.mkDerivation {
-  name = "maxima-5.13.0";
+  name = "maxima-5.17.0";
 
-  src =	fetchurl {
-		name = "maxima-5.13.0.tar.gz";
-		url = mirror://sf/maxima/maxima-5.13.0.tar.gz;
-		sha256 = "11zidbbp4cbgsmdfyf9w0j7345ydka469ba0my7p73zqhnby09cn";
-	};
+  src = fetchurl {
+    url = "mirror://sourceforge/maxima/maxima-5.17.0.tar.gz";
+    sha256 = "1nzphlm4al0j8jcgalscdqfcgkbscl68qz2mkm8n8804mss32alj";
+  };
 
   buildInputs =[clisp];
 
diff --git a/pkgs/applications/version-management/bazaar/default.nix b/pkgs/applications/version-management/bazaar/default.nix
index c2b5306b2e2a6..22d972eac456c 100644
--- a/pkgs/applications/version-management/bazaar/default.nix
+++ b/pkgs/applications/version-management/bazaar/default.nix
@@ -1,11 +1,11 @@
 {stdenv, fetchurl, python, makeWrapper}:
 
 stdenv.mkDerivation {
-  name = "bazaar-1.5";
+  name = "bazaar-1.10rc1";
 
   src = fetchurl {
-    url = http://launchpad.net/bzr/1.5/1.5/+download/bzr-1.5.tar.gz;
-    sha256 = "0wacjmnil5pivkcqz3jcqfqh258yrwv33fg2p8vf45pbmr7yw0bv";
+    url = http://launchpad.net/bzr/1.10/1.10rc1/+download/bzr-1.10rc1.tar.gz;
+    sha256 = "dc3669e15ced93e0956c13b724f604075e0323ce07fb08f6463946c85e69bec0";
   };
 
   buildInputs = [python makeWrapper];
@@ -24,4 +24,5 @@ stdenv.mkDerivation {
     homepage = http://bazaar-vcs.org/;
     description = "A distributed version control system that Just Works";
   };
+
 }
diff --git a/pkgs/applications/version-management/git/default.nix b/pkgs/applications/version-management/git/default.nix
index 678f3c80613cf..7824eaf697354 100644
--- a/pkgs/applications/version-management/git/default.nix
+++ b/pkgs/applications/version-management/git/default.nix
@@ -75,7 +75,7 @@ stdenv.mkDerivation rec {
        for prog in bin/gitk libexec/git-core/git-gui
        do
          notSupported "$out/$prog" \
-                      "reinstall with config \`git = { guiSupport = true; }' set"
+                      "reinstall with config git = { guiSupport = true; } set"
        done
      '')
 
diff --git a/pkgs/applications/video/MPlayer/newconfig.nix b/pkgs/applications/video/MPlayer/newconfig.nix
deleted file mode 100644
index 323619e003295..0000000000000
--- a/pkgs/applications/video/MPlayer/newconfig.nix
+++ /dev/null
@@ -1,255 +0,0 @@
-# this nix expression is not well tested (experimental!)
-args: with args.lib; with args;
-let
-  win32codecs = (import ./win32codecs) {
-    inherit stdenv fetchurl;
-  };
-  co = chooseOptionsByFlags {
-    inherit args;
-    flagConfig = {
-      # FIXME: we only have to pass X11 if we want to use a X11 driver 
-      mandatory = { buildInputs = [ "x11" "libX11" "freetype" "zlib" ]; };
-
-      # FIXME this options are still a mess.. :) feel free to test and implement the missing ones
-
-      # Optional features
-      #--disable-mencoder     disable mencoder (a/v encoder) compilation [enable]
-      #--enable-gui           enable gmplayer compilation (GTK+ GUI) [disable]
-      #--enable-gtk1          force using GTK 1.2 for GUI  [disable]
-      #--enable-largefiles    enable support for files > 2 GBytes [disable]
-      #--enable-linux-devfs   set default devices to devfs ones [disable]
-      #--enable-termcap       use termcap database for key codes [autodetect]
-      #--enable-termios       use termios database for key codes [autodetect]
-      #--disable-iconv        do not use iconv(3) function [autodetect]
-      #--disable-langinfo     do not use langinfo [autodetect]
-      #--enable-lirc          enable LIRC (remote control) support [autodetect]
-      #--enable-lircc         enable LIRCCD (LIRC client daemon) input [autodetect]
-      #--enable-joystick      enable joystick support [disable]
-      #--disable-vm           disable support X video mode extensions [autodetect]
-      #--disable-xf86keysym   disable support for 'multimedia' keys [autodetect]
-      #--enable-radio         enable Radio Interface [disable]
-      #--enable-radio-capture enable Capture for Radio Interface (through pci/line-in) [disable]
-      #--disable-radio-v4l2   disable Video4Linux2 Radio Interface support [autodetect]
-      #--disable-tv           disable TV Interface (tv/dvb grabbers) [enable]
-      #--disable-tv-v4l1      disable Video4Linux TV Interface support [autodetect]
-      #--disable-tv-v4l2      disable Video4Linux2 TV Interface support [autodetect]
-      #--disable-tv-bsdbt848  disable BSD BT848 Interface support [autodetect]
-      #--disable-pvr          disable Video4Linux2 MPEG PVR support [autodetect]
-      #--disable-rtc          disable RTC (/dev/rtc) on Linux [autodetect]
-      #--disable-network      disable network support (for: http/mms/rtp) [enable]
-      #--enable-winsock2      enable winsock2 usage [autodetect]
-      #--enable-smb           enable Samba (SMB) input support [autodetect]
-      #--enable-live          enable LIVE555 Streaming Media support [autodetect]
-      #--disable-dvdnav       disable libdvdnav support [autodetect]
-      #--disable-dvdread      Disable libdvdread support [autodetect]
-      #--disable-mpdvdkit     Disable mpdvdkit2 support [autodetect]
-      #--disable-cdparanoia   Disable cdparanoia support [autodetect]
-      #--disable-bitmap-font  Disable bitmap font support [enable]
-      #--disable-freetype     Disable freetype2 font rendering support [autodetect]
-      #--disable-fontconfig   Disable fontconfig font lookup support [autodetect]
-      #--disable-unrarlib     Disable Unique RAR File Library [enabled]
-      #--enable-menu          Enable OSD menu support (NOT DVD MENU) [disabled]
-      #--disable-sortsub      Disable subtitles sorting [enabled]
-      #--enable-fribidi       Enable using the FriBiDi libs [autodetect]
-      #--disable-enca         Disable using ENCA charset oracle library [autodetect]
-      #--disable-macosx       Disable Mac OS X specific features [autodetect]
-      #--disable-maemo        Disable maemo specific features [autodetect]
-      #--enable-macosx-finder-support  Enable Mac OS X Finder invocation parameter parsing [disabled]
-      #--enable-macosx-bundle Enable Mac OS X bundle file locations [autodetect]
-      #--disable-inet6        Disable IPv6 support [autodetect]
-      #--disable-gethostbyname2  gethostbyname() function is not provided by the C
-                                #library [autodetect]
-      #--disable-ftp          Disable ftp support [enabled]
-      #--disable-vstream      Disable tivo vstream client support [autodetect]
-      #--disable-pthreads     Disable Posix threads support [autodetect]
-      #--disable-ass          Disable internal SSA/ASS subtitles support [autodetect]
-      #--enable-rpath         Enable runtime linker path for extra libs [disabled]
-
-      # Codecs
-      #--enable-png           enable png input/output support [autodetect]
-      #--enable-jpeg          enable jpeg input/output support [autodetect]
-      #--enable-libcdio       enable external libcdio support [autodetect]
-      #--enable-liblzo        enable external liblzo support [autodetect]
-      #--disable-win32        disable Win32 DLL support [autodetect]
-      #--disable-qtx          disable Quicktime codecs [autodetect]
-      #--disable-xanim        disable XAnim DLL support [autodetect]
-      #--disable-real         disable RealPlayer DLL support [autodetect]
-      #--disable-xvid         disable XviD codec [autodetect]
-      #--disable-x264         disable H.264 encoder [autodetect]
-      #--disable-nut          disable libnut demuxer [autodetect]
-      #--disable-libavutil    disable libavutil [autodetect]
-      #--disable-libavcodec   disable libavcodec [autodetect]
-      #--disable-libavformat  disable libavformat [autodetect]
-      #--disable-libpostproc  disable libpostproc [autodetect]
-      #--disable-libavutil_so   disable shared libavutil [autodetect]
-      #--disable-libavcodec_so  disable shared libavcodec [autodetect]
-      #--disable-libavformat_so disable shared libavformat [autodetect]
-      #--disable-libpostproc_so disable shared libpostproc [autodetect]
-      #--disable-libavcodec_mpegaudio_hp disable high precision audio decoding
-      #                                  in libavcodec [enabled]
-      #--enable-libfame       enable libfame realtime encoder [autodetect]
-      #--disable-tremor-internal do not build internal Tremor support [enabled]
-      #--enable-tremor-low    build with lower accuracy internal Tremor [disabled]
-      #--enable-tremor-external build with external Tremor [autodetect]
-      #--disable-libvorbis    disable libvorbis support [autodetect]
-      #--disable-speex        disable Speex support [autodetect]
-      theora = { cfgOption = "--enable-theora"; buildInputs = "libtheora"; };
-      #--enable-theora        build with OggTheora support [autodetect]
-      #--enable-faad-external build with external FAAD2 (AAC) support [autodetect]
-      #--disable-faad-internal disable internal FAAD2 (AAC) support [autodetect]
-      #--enable-faad-fixed    enable fixed-point mode in internal FAAD2 [disabled]
-      #--disable-faac         disable support for FAAC (AAC encoder) [autodetect]
-      #--disable-ladspa       disable LADSPA plugin support [autodetect]
-      #--disable-libdv        disable libdv 0.9.5 en/decoding support [autodetect]
-      #--disable-mad          disable libmad (MPEG audio) support [autodetect]
-      #--disable-toolame      disable Toolame (MPEG layer 2 audio) support in mencoder [autodetect]
-      #--disable-twolame      disable Twolame (MPEG layer 2 audio) support in mencoder [autodetect]
-      #--enable-xmms          build with XMMS inputplugin support [disabled]
-      #--disable-mp3lib       disable builtin mp3lib [enabled]
-      #--disable-liba52       disable builtin liba52 [enabled]
-      #--enable-libdts        enable libdts support [autodetect]
-      #--disable-libmpeg2     disable builtin libmpeg2 [enabled]
-      #--disable-musepack     disable musepack support [autodetect]
-      #--disable-amr_nb       disable amr narrowband, floating point [autodetect]
-      #--disable-amr_nb-fixed disable amr narrowband, fixed point [autodetect]
-      #--disable-amr_wb       disable amr wideband, floating point [autodetect]
-      #--disable-decoder=DECODER disable specified FFmpeg decoder
-      #--enable-decoder=DECODER  enable specified FFmpeg decoder
-      #--disable-encoder=ENCODER disable specified FFmpeg encoder
-      #--enable-encoder=ENCODER  enable specified FFmpeg encoder
-      #--disable-parser=PARSER   disable specified FFmpeg parser
-      #--enable-parser=PARSER    enable specified FFmpeg parser
-      #--disable-demuxer=DEMUXER disable specified FFmpeg demuxer
-      #--enable-demuxer=DEMUXER  enable specified FFmpeg demuxer
-      #--disable-muxer=MUXER     disable specified FFmpeg muxer
-      #--enable-muxer=MUXER      enable specified FFmpeg muxer--enable-muxer=MUXER      enable specified FFmpeg muxer
-
-     # Video output
-      #--disable-vidix-internal disable internal VIDIX [for x86 *nix]
-      #--disable-vidix-external disable external VIDIX [for x86 *nix]
-      #--enable-gl            build with OpenGL render support [autodetect]
-      #--enable-dga[=n]       build with DGA [n in {1, 2} ] support [autodetect]
-      #--enable-vesa          build with VESA support [autodetect]
-      #--enable-svga          build with SVGAlib support [autodetect]
-      #--enable-sdl           build with SDL render support [autodetect]
-      #--enable-aa            build with AAlib render support [autodetect]
-      caca =              { cfgOption = "--enable-caca"; buildInputs = "libcaca"; };    # CACA render support
-      #--enable-ggi           build with GGI render support [autodetect]
-      #--enable-ggiwmh        build with GGI libggiwmh extension [autodetect]
-      #--enable-directx       build with DirectX support [autodetect]
-      #--enable-dxr2          build with DXR2 render support [autodetect]
-      #--enable-dxr3          build with DXR3/H+ render support [autodetect]
-      #--enable-ivtv          build with IVTV TV-Out render support [autodetect]
-      #--enable-dvb           build with support for output via DVB-Card [autodetect]
-      #--enable-dvbhead       build with DVB support (HEAD version) [autodetect]
-      #--enable-mga           build with mga_vid (for Matrox G200/G4x0/G550) support
-      #                       (check for /dev/mga_vid) [autodetect]
-      #--enable-xmga          build with mga_vid X Window support
-      #                       (check for X & /dev/mga_vid) [autodetect]
-      xv       = { cfgOption = "--enable-xv"; buildInputs = "libXv"; }; # Xv render support for X 4.x
-      #--enable-xvmc          build with XvMC acceleration for X 4.x [disable]
-      #--enable-vm            build with XF86VidMode support for X11 [autodetect]
-      xinerama = { cfgOption = "--enable-xinerama"; buildInputs = "libXinerama"; }; # Xinerama support for X11
-      #--enable-x11           build with X11 render support [autodetect]
-      #--enable-xshape        build with XShape support [autodetect]
-      #--enable-fbdev         build with FBDev render support [autodetect]
-      #--enable-mlib          build with mediaLib support (Solaris only) [disable]
-      #--enable-3dfx          build with obsolete /dev/3dfx support [disable]
-      #--enable-tdfxfb        build with tdfxfb (Voodoo 3/banshee) support [disable]
-      #--enable-s3fb          build with s3fb (S3 ViRGE) support [disable]
-      #--enable-directfb      build with DirectFB support [autodetect]
-      #--enable-zr            build with ZR360[56]7/ZR36060 support [autodetect]
-      #--enable-bl            build with Blinkenlights support [disable]
-      #--enable-tdfxvid       build with tdfx_vid support [disable]
-      #--disable-tga          disable targa output support [enable]
-      #--disable-pnm          disable pnm output support [enable]
-      #--disable-md5sum       disable md5sum output support [enable]
-
-
-      # Audio Output (they are all autodetect but adding the enable flag will show \
-      #               wrong cofigured libraries I hope)
-        # the ones beeing commented out I don't know exactly which libraries they need?
-        alsa = { cfgOption = "--enable-alsa";  buildInputs = "alsaLib"; };
-        #oss = { cfgOption = "--enable-oss"; buildInputs = "oss"; };
-        #arts = { cfgOption = "--enable-arts"; buildInputs = "arts"; };
-        esd = { cfgOption = "--enable-esd"; buildInputs = "esound"; };
-        #polyp = { cfgOption = "--enable-polyp"; buildInputs = "polyp"; };
-        #jack = { cfgOption = "--enable-jack"; buildInputs = "jack"; };
-        #openal = { cfgOption = "--enable-openal"; buildInputs = "openal"; };
-        #nas = { cfgOption = "--enable-nas"; buildInputs = "nas"; };
-        #sgiaudio = { cfgOption = "--enable-sgiaudio"; buildInputs = "sgiaudio"; };
-        #sunaudio = { cfgOption = "--enable-sunaudio"; buildInputs = "sunaudio"; };
-        #win32waveout = { cfgOption = "--enable-win32waveout"; buildInputs = "win32waveout"; };
-
-        disableSelect = { cfgOption = "--disable-select"; }; # disable using select() on audio device [enable]
-
-      #Miscellaneous options:
-        #--enable-runtime-cpudetection    Enable runtime CPU detection [disable]
-        #--enable-cross-compile Enable cross-compilation [autodetect]
-        #--cc=COMPILER          use this C compiler to build MPlayer [gcc]
-        #--host-cc=COMPILER     use this C compiler to build apps needed for the build process [gcc]
-        #--as=ASSEMBLER         use this assembler to build MPlayer [as]
-        #--target=PLATFORM      target platform (i386-linux, arm-linux, etc)
-        #--enable-static        build a statically linked binary. Set further linking
-                               #options with --enable-static="-lslang -lncurses"
-        #--charset              convert the help messages to this charset
-        #--language=list        a white space or comma separated list of languages
-                               #for translated man pages, the first language is the
-                               #primary and therefore used for translated messages
-                               #and GUI (also the environment variable $LINGUAS is
-                               #honored) [en]
-                               #(Available: bg cs de dk el en es fr hu it ja ko mk nb nl pl ro ru sk sv tr uk pt_BR zh
-      #_CN zh_TW all)
-
-    };
-    optionals = [ "esound" "alsa" "xv" "theora" "caca" "xinerama" "libXrandr" "esd" ];
-  };
-
-in args.stdenv.mkDerivation {
-
-  inherit (co) buildInputs;
-
-  name = "MPlayer-1.0rc1try2NewConfig";
-  #name = "MPlayer-snapshot";
-
-  #src = fetchurl {
-  #  url = http://www7.mplayerhq.hu/MPlayer/releases/mplayer-checkout-snapshot.tar.bz2;
-  #  sha1 = "529682cdea4f412d35f2c456897ab8808810975c";
-  #};
-
-  src = fetchurl {
-    url = http://www1.mplayerhq.hu/MPlayer/releases/MPlayer-1.0rc1.tar.bz2;
-    sha1 = "a450c0b0749c343a8496ba7810363c9d46dfa73c";
-  };
-
-  configurePhase = "./configure --prefix=\$out " + co.configureFlags
-    # FIXME to which options do these settings belong?
-    + " --with-win32libdir=${win32codecs}"
-    + " --with-reallibdir=${win32codecs}"
-    + " --enable-runtime-cpudetection"
-    + " --enable-x11"
-    + " --with-x11libdir=/no-such-dir"
-    + " --with-extraincdir=${libX11}/include"
-    + " --disable-xanim";
-
-  # Provide a reasonable standard font.  Maybe we should symlink here.
-  postInstall = "cp ${freefont_ttf}/share/fonts/truetype/FreeSans.ttf $out/share/mplayer/subfont.ttf";
-
-  patches = [
-   # These fix MPlayer's aspect ratio when run in a screen rotated with
-   # Xrandr.
-   # See: http://itdp.de/~itdp/html/mplayer-dev-eng/2005-08/msg00427.html
-   ./mplayer-aspect.patch
-   ./mplayer-pivot.patch
-
-   # Security fix.
-   ./asmrules-fix.patch
-  ];
-
-  meta = {
-    homepage = http://www.mplayerhq.hu/;
-    description = "A movie player that supports many video formats";
-    license = "GPL-2";
-  };
-
-}
diff --git a/pkgs/applications/video/dvdauthor/default.nix b/pkgs/applications/video/dvdauthor/default.nix
new file mode 100644
index 0000000000000..45737effcce8e
--- /dev/null
+++ b/pkgs/applications/video/dvdauthor/default.nix
@@ -0,0 +1,17 @@
+args:
+args.stdenv.mkDerivation {
+  name = "dvdauthor-0.6.14";
+
+  src = args.fetchurl {
+    url = mirror://sourceforge/dvdauthor/dvdauthor-0.6.14.tar.gz;
+    sha256 = "1x4flj3ja7m8rbc956a6ha3qk0k6zxd1y6sl826r6r7dyc91a6yx";
+  };
+
+  buildInputs =(with args; [imagemagick libdvdread libxml2 freetype fribidi libpng]);
+
+  meta = { 
+      description = "Tools for generating DVD files to be played on standalone DVD players";
+      homepage = http://dvdauthor.sourceforge.net/;
+      license = ["GPLv2"];
+  };
+}
diff --git a/pkgs/applications/virtualization/qemu/linux-img/0.2.nix b/pkgs/applications/virtualization/qemu/linux-img/0.2.nix
index e8532caddd2eb..6c43a941b6686 100644
--- a/pkgs/applications/virtualization/qemu/linux-img/0.2.nix
+++ b/pkgs/applications/virtualization/qemu/linux-img/0.2.nix
@@ -21,9 +21,7 @@ stdenv.mkDerivation rec {
 	builder = writeScript (name + "-builder")
 		(textClosure localDefs [doCopy doForceShare doPropagate]);
 	meta = {
-		description = "
-		${abort "Write a description"}
-";
+		description = "Qemu sample image.";
 		inherit src;
 	};
 }
diff --git a/pkgs/applications/window-managers/compiz-fusion/compiz-manager/0.6.0.nix b/pkgs/applications/window-managers/compiz-fusion/compiz-manager/0.6.0.nix
index 689885d29b447..c53b8586f1cea 100644
--- a/pkgs/applications/window-managers/compiz-fusion/compiz-manager/0.6.0.nix
+++ b/pkgs/applications/window-managers/compiz-fusion/compiz-manager/0.6.0.nix
@@ -1,5 +1,5 @@
 args : with args;
-	let localDefs = builderDefs {
+	let localDefs = builderDefs.passthru.function {
 		src = /* put a fetchurl here */
 	fetchurl {
 		url = http://releases.compiz-fusion.org/0.6.0/compiz-manager-0.6.0.tar.bz2;
@@ -19,7 +19,7 @@ args : with args;
 			"INDIRECT" "yes"
 			"XORG_DRIVER_PATH" "/nix/store/.*"
 		]];
-	} null; /* null is a terminator for sumArgs */
+	};
 	in with localDefs;
 let
 	install = FullDepEntry ("
diff --git a/pkgs/applications/window-managers/compiz-fusion/default.nix b/pkgs/applications/window-managers/compiz-fusion/default.nix
index 334af5eb01221..bfd0810facf01 100644
--- a/pkgs/applications/window-managers/compiz-fusion/default.nix
+++ b/pkgs/applications/window-managers/compiz-fusion/default.nix
@@ -10,6 +10,6 @@ rec
 	ccsm = selectVersion ./ccsm (args // {inherit libcompizconfig bcop compizConfigPython configBackendGConf;});
 	pluginsMain = selectVersion ./main (args //{inherit bcop ;});
 	pluginsExtra = selectVersion ./extra (args //{inherit bcop pluginsMain;});
-	compizManager = selectVersion ./compiz-manager (args // {inherit bcop ccsm;});
+	compizManager = (import ./compiz-manager/0.6.0.nix) (args // {inherit bcop ccsm;});
 	ccsmSimple = selectVersion ./ccsm-simple (args // {inherit libcompizconfig bcop compizConfigPython configBackendGConf;});
 }
diff --git a/pkgs/applications/window-managers/compiz-fusion/general-dependencies.nix b/pkgs/applications/window-managers/compiz-fusion/general-dependencies.nix
index d8a0ffa3e7eb7..f83ae7d1c8bfd 100644
--- a/pkgs/applications/window-managers/compiz-fusion/general-dependencies.nix
+++ b/pkgs/applications/window-managers/compiz-fusion/general-dependencies.nix
@@ -6,4 +6,5 @@ args: with args;
 	libpng 
 	GConf mesa metacity librsvg dbus.libs dbus_glib gnomedesktop git autoconf automake
 	libtool libxslt libwnck intltool perl perlXMLParser compiz pkgconfig libxml2
+	gettext 
 ]
diff --git a/pkgs/applications/window-managers/dwm/default.nix b/pkgs/applications/window-managers/dwm/default.nix
index 125428c449cec..cb29a5b2a7c23 100644
--- a/pkgs/applications/window-managers/dwm/default.nix
+++ b/pkgs/applications/window-managers/dwm/default.nix
@@ -8,6 +8,7 @@ args: with args; stdenv.mkDerivation {
  
   buildInputs = [ libX11 libXinerama ];
  
+  patchPhase = ''sed -i "s@/usr/local@$out@" config.mk'';
   buildPhase = " make ";
  
   meta = { homepage = "www.suckless.org";
diff --git a/pkgs/build-support/release/debian-build.nix b/pkgs/build-support/release/debian-build.nix
index fad216fb1c24a..fad88a98f177e 100644
--- a/pkgs/build-support/release/debian-build.nix
+++ b/pkgs/build-support/release/debian-build.nix
@@ -34,13 +34,6 @@ vmTools.runInLinuxImage (stdenv.mkDerivation (
       fi
     ''; # */
 
-    extraDebs = [
-      (fetchurl {
-        url = http://checkinstall.izto.org/files/deb/checkinstall_1.6.1-1_i386.deb;
-        sha256 = "0c9wwk1m0w677gr37zd4lhvkskkcrwa0bk7csh7b3qy94pnab618";
-      })
-    ];
-
     installExtraDebsPhase = ''
       for i in $extraDebs; do
         dpkg --install $i    
@@ -56,7 +49,9 @@ vmTools.runInLinuxImage (stdenv.mkDerivation (
     '';
 
     installCommand = ''
-      /usr/local/sbin/checkinstall -y -D make install
+      export LOGNAME=root
+    
+      ${checkinstall}/sbin/checkinstall -y -D make install
 
       ensureDir $out/debs
       find . -name "*.deb" -exec cp {} $out/debs \;
diff --git a/pkgs/build-support/release/default.nix b/pkgs/build-support/release/default.nix
index 65813ef9cabb8..789def4ddffcc 100644
--- a/pkgs/build-support/release/default.nix
+++ b/pkgs/build-support/release/default.nix
@@ -20,7 +20,7 @@ rec {
   rpmBuild = args: import ./rpm-build.nix vmTools args;
 
   debBuild = args: import ./debian-build.nix {inherit vmTools fetchurl;} (
-    { inherit stdenv;
+    { inherit stdenv checkinstall;
     } // args);
 
 }
diff --git a/pkgs/data/documentation/man-pages/default.nix b/pkgs/data/documentation/man-pages/default.nix
index 7bab73543729c..c909cebb4b006 100644
--- a/pkgs/data/documentation/man-pages/default.nix
+++ b/pkgs/data/documentation/man-pages/default.nix
@@ -1,11 +1,11 @@
 {stdenv, fetchurl}:
 
 stdenv.mkDerivation rec {
-  name = "man-pages-3.11";
+  name = "man-pages-3.15";
   
   src = fetchurl {
     url = "mirror://kernel/linux/docs/man-pages/${name}.tar.bz2";
-    sha256 = "1pl3jdp7vh6vl2drqdal3ggdc22icdgfkfbswh21k8jlcxf00dn8";
+    sha256 = "0pr29ziz2d2zl2iii16372x2bqvx1a5g8xbb6wga4nxiz4w6ixhh";
   };
 
   preBuild = "
diff --git a/pkgs/data/fonts/freefont-ttf/default.nix b/pkgs/data/fonts/freefont-ttf/default.nix
index a8ddac8b9beb5..c3bd59f224b8c 100644
--- a/pkgs/data/fonts/freefont-ttf/default.nix
+++ b/pkgs/data/fonts/freefont-ttf/default.nix
@@ -1,10 +1,11 @@
 {stdenv, fetchurl}:
 
 stdenv.mkDerivation rec {
-  name = "freefont-ttf-20080912";
+  name = "freefont-ttf-20090104";
+
   src = fetchurl {
     url = "mirror://gnu/freefont/${name}.tar.gz";
-    sha256 = "1l6ip2xy4s4xacnz299y7afc4rhvnxb593nn8acxavmr623sh5ir";
+    sha256 = "13k3gm31wqa5ch14rmd3zpapckaif9bv4x82x72xaqn3n1j733ib";
   };
 
   installPhase = ''
@@ -22,6 +23,6 @@ stdenv.mkDerivation rec {
     '';
 
     homepage = http://www.gnu.org/software/freefont/;
-    license = "GPLv2+";
+    license = "GPLv3+";
   };
 }
diff --git a/pkgs/data/misc/themes/green.nix b/pkgs/data/misc/themes/green.nix
new file mode 100644
index 0000000000000..945bd3c9a3cf5
--- /dev/null
+++ b/pkgs/data/misc/themes/green.nix
@@ -0,0 +1,5 @@
+{fetchurl, ...} : 
+fetchurl {
+  url = http://www.kde-look.org/CONTENT/content-files/58501-green.tar.gz;
+  sha256 = "0sdykpziij1f3w4braq8r8nqg4lnsd7i7gi1k5d7c31m2q3b9a7r";
+}
diff --git a/pkgs/data/misc/themes/theme-gnu.nix b/pkgs/data/misc/themes/theme-gnu.nix
new file mode 100644
index 0000000000000..9b6cfd877e63d
--- /dev/null
+++ b/pkgs/data/misc/themes/theme-gnu.nix
@@ -0,0 +1,5 @@
+{fetchurl, ...}:
+fetchurl {
+  url = http://www.bootsplash.de/files/themes/Theme-GNU.tar.bz2;
+  md5 = "61969309d23c631e57b0a311102ef034";
+}
diff --git a/pkgs/data/misc/xkeyboard-config/eo.patch b/pkgs/data/misc/xkeyboard-config/eo.patch
new file mode 100644
index 0000000000000..3709d110917de
--- /dev/null
+++ b/pkgs/data/misc/xkeyboard-config/eo.patch
@@ -0,0 +1,83 @@
+diff --git a/rules/base.lst b/rules/base.lst
+index 7004bcd..804f9f0 100644
+--- a/rules/base.lst
++++ b/rules/base.lst
+@@ -168,6 +168,7 @@
+   nl              Netherlands
+   bt              Bhutan
+   ee              Estonia
++  eo              Esperanto
+   ir              Iran
+   iq              Iraq
+   fo              Faroe Islands
+diff --git a/rules/base.xml.in b/rules/base.xml.in
+index ec321f8..e9c3546 100644
+--- a/rules/base.xml.in
++++ b/rules/base.xml.in
+@@ -1786,6 +1786,13 @@
+     </layout>
+     <layout>
+       <configItem>
++        <name>eo</name>
++        <_shortDescription>Esp</_shortDescription>
++        <_description>Esperanto</_description>
++      </configItem>
++    </layout>
++    <layout>
++      <configItem>
+         <name>ir</name>
+         <_shortDescription>Irn</_shortDescription>
+         <_description>Iran</_description>
+diff --git a/symbols/Makefile.am b/symbols/Makefile.am
+index 97c816d..d7e3a4e 100644
+--- a/symbols/Makefile.am
++++ b/symbols/Makefile.am
+@@ -10,7 +10,7 @@ bt by braille \
+ ca cd \
+ ch cn cz \
+ de dk \
+-ee es et epo \
++ee eo es et epo \
+ fi fo fr \
+ gb ge gh gn \
+ gr hr hu \
+diff --git a/symbols/Makefile.in b/symbols/Makefile.in
+index b5be077..5cddcc7 100644
+--- a/symbols/Makefile.in
++++ b/symbols/Makefile.in
+@@ -222,7 +222,7 @@ bt by braille \
+ ca cd \
+ ch cn cz \
+ de dk \
+-ee es et epo \
++ee eo es et epo \
+ fi fo fr \
+ gb ge gh gn \
+ gr hr hu \
+diff --git a/symbols/eo b/symbols/eo
+new file mode 100644
+index 0000000..d6358c9
+--- /dev/null
++++ b/symbols/eo
+@@ -0,0 +1,21 @@
++// $XFree86$
++
++partial alphanumeric_keys
++xkb_symbols "basic" {
++
++     // Describes the differences between a very simple en_US
++     // keyboard and a simple Esperanto keyboard
++     // Press AltGr or Windows Menu key together with C, H, J, S, U
++     // to get accented letters.
++     // 2001 by Radovan Garabik <garabik@melkor.dnp.fmph.uniba.sk>
++
++    key.type = "FOUR_LEVEL";
++
++    key <AD02>  { [w,W, ubreve,Ubreve ] };
++    key <AD07>  { [u,U, ubreve, Ubreve ] };
++    key <AC02>  { [s,S, scircumflex,    Scircumflex ] };
++    key <AC05>  { [g,G, gcircumflex,Gcircumflex ] };
++    key <AC06>  { [h,H, hcircumflex,Hcircumflex ] };
++    key <AC07>  { [j,J, jcircumflex,Jcircumflex ] };
++    key <AB03>  { [c,C, ccircumflex,Ccircumflex ] };
++};
diff --git a/pkgs/development/compilers/bigloo/default.nix b/pkgs/development/compilers/bigloo/default.nix
index 53e1099a069e7..56145f1e77d3f 100644
--- a/pkgs/development/compilers/bigloo/default.nix
+++ b/pkgs/development/compilers/bigloo/default.nix
@@ -1,11 +1,11 @@
 { fetchurl, stdenv }:
 
 stdenv.mkDerivation rec {
-  name = "bigloo3.1b";
+  name = "bigloo3.2a";
 
   src = fetchurl {
     url = "ftp://ftp-sop.inria.fr/mimosa/fp/Bigloo/${name}.tar.gz";
-    sha256 = "1m7mrrrqm6668j6x834mclzc9am63wlf0knm4xiwrhv3zcky8vnv";
+    sha256 = "131jnn17rcccbijpji7v5xlx4z2jldhbn46gkysf6axdcwxwqgg4";
   };
 
   patchPhase = ''
diff --git a/pkgs/development/compilers/ghc/boot610.nix b/pkgs/development/compilers/ghc/boot610.nix
index 679f2c94dd8c7..7cfafaa13e8a5 100644
--- a/pkgs/development/compilers/ghc/boot610.nix
+++ b/pkgs/development/compilers/ghc/boot610.nix
@@ -27,34 +27,42 @@ stdenv.mkDerivation rec {
 
   buildInputs = [perl makeWrapper];
 
-  # On Linux, use patchelf to modify the executables so that they can
-  # find editline/gmp.
-  postUnpack = (if stdenv.isLinux then ''
-    find . -type f -perm +100 \
-        -exec patchelf --interpreter "$(cat $NIX_GCC/nix-support/dynamic-linker)" \
-        --set-rpath "${editline}/lib:${ncurses}/lib:${gmp}/lib" {} \;
-    for prog in strip ranlib; do
-      find . -name "setup-config" -exec sed -i "s@/usr/bin/$prog@$(type -p $prog)@g" {} \;
-    done
-  '' else "")
-  + ''
-    mkdir "$TMP/bin"
-    for i in strip; do
-      echo '#!/bin/sh' >> "$TMP/bin/$i"
-      chmod +x "$TMP/bin/$i"
-      PATH="$TMP/bin:$PATH"
-    done
-  ''
-  
-  ;
+  postUnpack =
+    # Strip is harmful, see also below. It's important that this happens
+    # first. The GHC Cabal build system makes use of strip by default and
+    # has hardcoded paths to /usr/bin/strip in many places. We replace
+    # those below, making them point to our dummy script.
+     ''
+      mkdir "$TMP/bin"
+      for i in strip; do
+        echo '#!/bin/sh' >> "$TMP/bin/$i"
+        chmod +x "$TMP/bin/$i"
+        PATH="$TMP/bin:$PATH"
+      done
+     '' +
+    # On Linux, use patchelf to modify the executables so that they can
+    # find editline/gmp.
+    (if stdenv.isLinux then ''
+      find . -type f -perm +100 \
+          -exec patchelf --interpreter "$(cat $NIX_GCC/nix-support/dynamic-linker)" \
+          --set-rpath "${editline}/lib:${ncurses}/lib:${gmp}/lib" {} \;
+      for prog in ld ar gcc strip ranlib; do
+        find . -name "setup-config" -exec sed -i "s@/usr/bin/$prog@$(type -p $prog)@g" {} \;
+      done
+     '' else "");
 
   configurePhase = ''
     ./configure --prefix=$out --with-gmp-libraries=${gmp}/lib --with-gmp-includes=${gmp}/include
   '';
+
   # Stripping combined with patchelf breaks the executables (they die
   # with a segfault or the kernel even refuses the execve). (NIXPKGS-85)
   dontStrip = true;
 
+  # No building is necessary, but calling make without flags ironically
+  # calls install-strip ...
+  buildPhase = ":";
+
   # The binaries for Darwin use frameworks, so fake those frameworks,
   # and create some wrapper scripts that set DYLD_FRAMEWORK_PATH so
   # that the executables work with no special setup.
@@ -78,9 +86,6 @@ stdenv.mkDerivation rec {
   " else "")
   +
   ''
-  # the installed ghc executable segfaults, maybe some stripping or such has been done somewhere?
-  # Just copy teh version from the $TMP dir over
-  cp ghc/dist-stage2/build/ghc/ghc $out/lib/ghc-${version}/ghc
   # bah, the passing gmp doesn't work, so let's add it to the final package.conf in a quick but dirty way
   sed -i "s@^\(.*pkgName = PackageName \"rts\".*\libraryDirs = \\[\)\(.*\)@\\1\"${gmp}/lib\",\2@" $out/lib/ghc-${version}/package.conf
 
diff --git a/pkgs/development/compilers/hugs/default.nix b/pkgs/development/compilers/hugs/default.nix
index 1918f8f372b2f..c910d88ccb19f 100644
--- a/pkgs/development/compilers/hugs/default.nix
+++ b/pkgs/development/compilers/hugs/default.nix
@@ -1,57 +1,56 @@
-args: with args.lib; with args;
-let
-  co = chooseOptionsByFlags {
-    inherit args;
-    flagDescr = {
-      # does without X make sense? We can try
-      mandatory ={ cfgOption = [ "--prefix=\$out" ]; implies = "pthreads"; };
-      pathcanonicalization = { cfgOption = "--enable-path-canonicalization"; }; # enable canonicalization of filenames
-      timer = { cfgOption = "--enable-timer"; };#          enable evaluation timing (for benchmarking Hugs)
-      profiling = { cfgOption = "--enable-profiling"; };#      enable heap profiler
-      stack = { cfgOption = "--enable-stack-dumps"; };#-dumps    enable stack dump on stack overflow
-      large = { cfgOption = "--disable-large-banner"; };#-banner  disable multiline startup banner
-      internal = { cfgOption = "--enable-internal-prims"; };#-prims experimental primitives to access Hugs's innards
-      debug = { cfgOption = "--enable-debug"; };#          include C debugging information (for debugging Hugs)
-      tag = { cfgOption = "--enable-tag-checks"; };#-checks     runtime tag checking (for debugging Hugs)
-      lint = { cfgOption = "--enable-lint"; };#           enable "lint" flags (for debugging Hugs)
-      only98 = { cfgOption = "--enable-only98"; };#         build Hugs to understand Haskell 98 only
-      ffi = { cfgOption = "--enable-ffi"; };#            include modules that use the FFI [default=autodetect]
-      char = { cfgOption = "--enable-char-encoding"; blocks = "utf8"; };
-                                                        #-encoding  encode all character I/O using the byte encoding
-                                                        #determined by the locale in effect at that time. To
-                                                        #require that the UTF-8 encoding is always used, give
-                                                        #the --enable-char-encoding=utf8 option.
-                                                        #[default=autodetect]
-      utf8 = { cfgOption = "--enable-char-encoding=utf8"; blocks="char"; };
-
-
-      #--with-nmake            produce a Makefile compatible with nmake
-      #--with-gui              build Hugs for Windows GUI (Borland C++ only)
-      pthreads = { cfgOption = "--with-pthreads"; }; #   build Hugs using POSIX threads C library
-                                                   # I think we need this as long as not using nptl ?
+args: with args;
+let edf = composableDerivation.edf;
+    wwf = composableDerivation.wwf; in
+composableDerivation.composableDerivation {
+  initial = {
 
-    };
-    optionals = [];
-    defaultFlags = ["ffi"];
-  };
-
-in args.stdenv.mkDerivation {
-
-  # passing the flags in case a library using this want's to check them (*) .. 
-  inherit (co) /* flags */ buildInputs;
+    name="hugs98";
 
-  configurePhase="./configure --prefix=\$out";
-
-  src = fetchurl {
-      url = http://cvs.haskell.org/Hugs/downloads/2006-09/hugs98-Sep2006.tar.gz;
-      sha256 = "3cf4d27673564cffe691bd14032369f646233f14daf2bc37c6c6df9f062b46b6";
+    src = fetchurl {
+        url = http://cvs.haskell.org/Hugs/downloads/2006-09/hugs98-Sep2006.tar.gz;
+        sha256 = "3cf4d27673564cffe691bd14032369f646233f14daf2bc37c6c6df9f062b46b6";
     };
 
-  name="hugs98";
-
-  meta = {
-    license = "as-is"; # gentoo is calling it this way..
-    description = "The HUGS98 Haskell <interpreter";
-    homepage = http://www.haskell.org/hugs;
+        #encode all character I/O using the byte encoding
+        #determined by the locale in effect at that time. To
+        #require that the UTF-8 encoding is always used, give
+        #the --enable-char-encoding=utf8 option.
+        #[default=autodetect]
+    postUnpack = ''
+      find -type f | xargs sed -i 's@/bin/cp@cp@';
+    '';
+    configurePhase="./configure --prefix=\$out --enable-char-encoding=utf8 $configureFlags";
+
+    flags =
+         edf { name = "pathCanonicalization"; feat="path-canonicalization"; }
+      // edf { name="timer"; }   # enable evaluation timing (for benchmarking Hugs)
+      // edf { name="profiling"; }# enable heap profiler
+      // edf { name="stackDumps"; feat="stack-dummps"; } # enable stack dump on stack overflow
+      // edf { name="largeBanner"; feat="large-banner"; } # disable multiline startup banner
+      // edf { name="internal-prims"; } # experimental primitives to access Hugs's innards
+      // edf { name="debug"; } # include C debugging information (for debugging Hugs)
+      // edf { name="tag"; } # runtime tag checking (for debugging Hugs)
+      // edf { name="lint"; } # enable "lint" flags (for debugging Hugs)
+      // edf { name="only98"; } # build Hugs to understand Haskell 98 only
+      // edf { name="ffi"; }
+        #--with-nmake            produce a Makefile compatible with nmake
+        #--with-gui              build Hugs for Windows GUI (Borland C++ only)
+      // wwf { name="pthreads"; } #   build Hugs using POSIX threads C library
+      ;
+
+    cfg = {
+      largeBannerSupport = true; # seems to be default
+
+
+        char = { cfgOption = "--enable-char-encoding"; blocks = "utf8"; };
+        utf8 = { cfgOption = "--enable-char-encoding=utf8"; blocks="char"; };
+
+      };
+
+    meta = {
+      license = "as-is"; # gentoo is calling it this way..
+      description = "The HUGS98 Haskell <interpreter";
+      homepage = http://www.haskell.org/hugs;
+    };
   };
 }
diff --git a/pkgs/development/compilers/roadsend/default.nix b/pkgs/development/compilers/roadsend/default.nix
index c7b04f8710908..c6d2249c8947d 100644
--- a/pkgs/development/compilers/roadsend/default.nix
+++ b/pkgs/development/compilers/roadsend/default.nix
@@ -1,31 +1,33 @@
-args:
-let edf = args.lib.enableDisableFeature; in
-( args.mkDerivationByConfiguration {
-    flagConfig = {
-      mandatory = { buildInputs = ["bigloo" "curl"]; };
-    } // edf "pcre" "pcre" { } #support pcre extension [default=check]
-      // edf "fcgi" "fcgi" { pass = "fcgi"; } #support FastCGI web backend [default=check]
-      // edf "xml" "xml" { pass ="libxml2"; } #support xml extension [default=check]
-      // edf "mysql" "mysql" { pass = "mysql"; } #support mysql extension [default=check]
-      #// edf "sqlite3=[ARG]" "sqlite3=[ARG]" { } [>use SQLite 3 library [default=yes], optionally
-                                #specify the prefix for sqlite3 library
-      // edf "odbc" "odbc" { } #support ODBC extension [default=check]
-      // edf "gtk" "gtk" { } #support PHP-GTK extension [default=no]
-      // edf "gtk2" "gtk2" { }; #support PHP-GTK 2 extension [default=no]
-
-    optionals = [ "libxml2" "gettext" "fcgi" ];
-    extraAttrs = co : {
-      name = "roadsend-2.9.3";
+args: with args;
+let edf = composableDerivation.edf; in
+composableDerivation.composableDerivation {
+  initial = {
+    name = "roadsend-2.9.3";
+    buildInputs = [bigloo curl];
+    flags = edf { name = "pcre"; }
+         // edf { name = "fcgi"; enable = { inherit fcgi; }; }
+         // edf { name = "xml"; enable = { buildInputs = [ libxml2 ]; }; }
+         // edf { name = "mysql"; enable = { buildInputs = [ mysql ]; }; }
+         // edf { name = "odbc"; };
+         # // edf { name = "gtk"} }
+         # // edf { name = "gtk2", enable = { buildInputs = [ mysql ]; } }
+    cfg = {
+      pcreSupport = true;
+      fcgiSupport = true;
+      xmlSupport = true;
+      mysqlSupport = true;
+    };
+    src = args.fetchurl {
+      url = "http://code.roadsend.com/snaps/roadsend-php-20081210.tar.bz2";
+      sha256 = "0yhpiik0dyayd964wvn2k0cq7b1gihx1k3qx343r2l7lla4mapsx";
+    };
 
-      src = args.fetchurl {
-        url = "http://code.roadsend.com/snaps/roadsend-php-2.9.4.tar.bz2";
-        sha256 = "0nw7rvrrwkss5cp6ws0m3q63q1mcyy27s8yjhy7kn508db1rgl9x";
-      };
+#    http://code.roadsend.com/snaps/roadsend-php-testsuite-2.9.7.tar.bz2";
+#   sha256 = "0rf0g9r0prla7daq3aif24d7dx0j01i35hcm8h5bbg3gvpfim463";
 
     # tell pcc where to find the fastcgi library 
-      postInstall = " sed -e \"s=(ldflags fastcgi.*=(ldflags -l fastcgi -L \$fcgi)=\" -i \$out/etc/pcc.conf ";
-
-    meta = { 
+    postInstall = " sed -e \"s=(ldflags fastcgi.*=(ldflags -l fastcgi -L \$fcgi)=\" -i \$out/etc/pcc.conf ";
+    meta = {
       description = "roadsend PHP -> C compiler";
       homepage = http://www.roadsend.com;
       # you can choose one of the following licenses: 
@@ -33,4 +35,4 @@ let edf = args.lib.enableDisableFeature; in
       license = ["GPL2"];
     };
   };
-} ) args
+}
diff --git a/pkgs/development/interpreters/php_configurable/default.nix b/pkgs/development/interpreters/php_configurable/default.nix
index d10efcec80211..025e48a0a7b98 100644
--- a/pkgs/development/interpreters/php_configurable/default.nix
+++ b/pkgs/development/interpreters/php_configurable/default.nix
@@ -1,122 +1,132 @@
 let version = "5.2.6"; in
 
-args:
+args: with args;
 
-(args.mkDerivationByConfiguration {
+let inherit (args.composableDerivation) composableDerivation edf wwf; in
 
-  flagConfig = {
+composableDerivation {
+  initial = fixed : {
 
-# much left to do here... 
+    name = "php_configurable-${version}";
 
-    mandatory = { buildInputs = ["flex" "bison" "pkgconfig"]; };
+    buildInputs = ["flex" "bison" "pkgconfig"];
 
-    # SAPI modules:
-    
-    apxs2 = {
-      cfgOption = "--with-apxs2=\$apacheHttpd/bin/apxs";
-      pass = "apacheHttpd";
-    };
+    flags = {
 
-    # Extensions 
+# much left to do here...
 
-    curl = {
-      cfgOption = "--with-curl=${args.curl} --with-curlwrappers";
-      pass = "curl";
-    };
+      # SAPI modules:
       
-    zlib = {
-      cfgOption = "--with-zlib=${args.zlib}";
-      pass = "zlib";
-    };
-
-    libxml2 = {
-      cfgOption = "--with-libxml-dir=\$libxml2";
-      pass = { inherit (args) libxml2; }; 
-    };
-    
-    no_libxml2 = {
-      cfgOption = "--disable-libxml";
-    };
+        apxs2 = {
+          configureFlags = ["--with-apxs2=${apacheHttpd}/bin/apxs"];
+          buildInputs = [apacheHttpd];
+        };
 
-    postgresql = {
-      cfgOption = "--with-pgsql=\$postgresql";
-      pass = { inherit (args) postgresql; };
-    };
-    
-    mysql = {
-      cfgOption = "--with-mysql=\$mysql";
-      pass = { inherit (args) mysql; };
-    };
+        # Extensions
 
-    mysqli = {
-      cfgOption = "--with-mysqli=\$mysql/bin/mysql_config";
-      pass = { inherit (args) mysql; }; 
-    };
-
-    mysqli_embedded = {
-      cfgOption = "--enable-embedded-mysqli";
-      depends = "mysqli";
-    };
+        curl = {
+          configureFlags = ["--with-curl=${args.curl}" "--with-curlwrappers"];
+          buildInputs = [curl];
+        };
+        
+        zlib = {
+          configureFlags = ["--with-zlib=${args.zlib}"];
+          buildInputs = [zlib];
+        };
 
-    pdo_mysql = {
-      cfgOption = "--with-pdo-mysql=\$mysql";
-      pass = { inherit (args) mysql; }; 
-    };
-    
-    no_pdo_mysql = { };
+        libxml2 = {
+          configureFlags = ["--with-libxml-dir=${libxml2}"];
+          buildInputs = [ libxml2 ];
+        };
+      
+        postgresql = {
+          configureFlags = ["--with-pgsql=${postgresql}"];
+          buildInputs = [ postgresql ];
+        };
+      
+        mysql = {
+          configureFlags = ["--with-mysql=${mysql}"];
+          buildInputs = [ mysql ];
+        };
 
-    bcmath = {
-      cfgOption = "--enable-bcmath";
-    };
+        mysqli = {
+          configureFlags = ["--with-mysqli=${mysql}/bin/mysql_config"];
+          buildInputs = [ mysql];
+        };
 
-    gd = {
-      cfgOption = "--with-gd=${args.gd}";
-      buildInputs = ["gd"]; # <-- urgh, these strings are ugly
-    };
+        mysqli_embedded = {
+          configureFlags = ["--enable-embedded-mysqli"];
+          depends = "mysqli";
+          assertion = fixed.mysqliSupport;
+        };
 
-    sockets = {
-      cfgOption = "--enable-sockets";
-    };
+        pdo_mysql = {
+          configureFlags = ["--with-pdo-mysql=${mysql}"];
+          buildInputs = [ mysql ];
+        };
+      
+        bcmath = {
+          configureFlags = ["--enable-bcmath"];
+        };
 
-    openssl = {
-      cfgOption = "--with-openssl=${args.openssl}";
-      buildInputs = ["openssl"];
-    };
+        gd = {
+          configureFlags = ["--with-gd=${args.gd}"];
+          buildInputs = [gd];
+        };
 
-    /*
-       Building xdebug withing php to be able to add the parameters to the ini file.. Ther should be a better way
-      meta = { 
-              description = "debugging support for PHP";
-              homepage = http://xdebug.org;
-              license = "based on the PHP license - as is";
-              };
-    */
-    xdebug = {
-      buildInputs = [ "automake" "autoconf" ];
-      pass = {
-        xdebug_src = args.fetchurl {
-          name = "xdebug-2.0.2.tar.gz";
-          url = "http://xdebug.org/link.php?url=xdebug202";
-          sha256 = "1h0bxvf8krr203fmk1k7izrrr81gz537xmd3pqh4vslwdlbhrvic";
+        sockets = {
+          configureFlags = ["--enable-sockets"];
         };
-      };
-    };
 
-  };
+        openssl = {
+          configureFlags = ["--with-openssl=${args.openssl}"];
+          buildInputs = ["openssl"];
+        };
 
-  defaults = [ "mysql" "mysqli" "pdo_mysql" "libxml2" "apxs2" "bcmath" ];
-  
-  optionals = [ "libxml2" "gettext" "postgresql" "zlib" "openssl" ];
+        mbstring = {
+          configureFlags = ["--enable-mbstring"];
+        };
 
-  extraAttrs = co: {
-    name = "php_configurable-${version}";
+        /*
+           Building xdebug withing php to be able to add the parameters to the ini file.. Ther should be a better way
+          meta = {
+                  description = "debugging support for PHP";
+                  homepage = http://xdebug.org;
+                  license = "based on the PHP license - as is";
+                  };
+        */
+        xdebug = {
+          buildInputs = [ automake autoconf ];
+          xdebug_src = args.fetchurl {
+            name = "xdebug-2.0.2.tar.gz";
+            url = "http://xdebug.org/link.php?url=xdebug202";
+            sha256 = "1h0bxvf8krr203fmk1k7izrrr81gz537xmd3pqh4vslwdlbhrvic";
+          };
+        };
+      };
 
-    buildInputs = args.lib.getAttr ["phpIncludes"] [] args ++ co.buildInputs;
+    cfg = {
+      mysqlSupport = true;
+      mysqliSupport = true;
+      pdo_mysqlSupport = true;
+      libxml2Support = true;
+      apxs2Support = true;
+      bcmathSupport = true;
+      socketsSupport = true;
+      curlSupport = true;
+      gettextSupport = true;
+      postgresqlSupport = true;
+      zlibSupport = true;
+      opnesslSupport = true;
+      xdebugSupport = true;
+      mbstringSupport = true;
+      gdSupport = true;
+    };
 
     configurePhase = ''
       iniFile=$out/etc/$name.ini
       [[ -z "$libxml2" ]] || export PATH=$PATH:$libxml2/bin
-      ./configure --with-config-file-scan-dir=/etc --with-config-file-path=$out/etc --prefix=$out ${co.configureFlags}
+      ./configure --with-config-file-scan-dir=/etc --with-config-file-path=$out/etc --prefix=$out  $configureFlags
       echo configurePhase end
     '';
 
@@ -124,11 +134,11 @@ args:
       unset installPhase; installPhase;
       cp php.ini-recommended $iniFile
 
-      # Now Let's build xdebug if flag has been given 
+      # Now Let's build xdebug if flag has been given
       # TODO I think there are better paths than the given below
       if [ -n $flag_set_xdebug ]; then
         PATH=$PATH:$out/bin
-        tar xfz $xdebug_src; 
+        tar xfz $xdebug_src;
         cd xdebug*
         phpize
         ./configure --prefix=$out
@@ -157,13 +167,14 @@ args:
       name = "php-${version}.tar.bz2";
     };
 
-    meta = { 
+    meta = {
       description = "The PHP language runtime engine";
       homepage = http://www.php.net/;
       license = "PHP-3";
     };
 
     patches = [./fix.patch];
+
   };
-  
-}) args
+
+}
diff --git a/pkgs/development/interpreters/python-new/2.5/default.nix b/pkgs/development/interpreters/python-new/2.5/default.nix
index 1bc7ca4b41941..dfe86683b5061 100644
--- a/pkgs/development/interpreters/python-new/2.5/default.nix
+++ b/pkgs/development/interpreters/python-new/2.5/default.nix
@@ -13,6 +13,7 @@
 p: # p = pkgs
 let 
   inherit (p) lib fetchurl stdenv getConfig;
+  inherit (p.composableDerivation) composableDerivation;
   # withName prevents  nix-env -qa \* from aborting (pythonLibStub is a derivation but hasn't a name)
   withName = lib.mapAttrs (n : v : if (__isAttrs v && (!__hasAttr "name" v)) then null else v);
 in
@@ -24,7 +25,8 @@ in
     # see pythonFull.
     pythonMinimal = ( (import ./python.nix) {
       name = "python-${t.version}";
-      inherit (p) fetchurl stdenv lib bzip2 ncurses composableDerivation;
+      inherit composableDerivation;
+      inherit (p) fetchurl stdenv lib bzip2 ncurses;
       inherit  (p) zlib sqlite db4 readline openssl gdbm;
     });
 
@@ -59,11 +61,16 @@ in
 
       buildPhase = ''
         ensureDir $out/bin
-        cat >> $out/bin/python << EOF
-        export NIX_PYTHON_SITES=\$NIX_PYTHON_SITES:$NIX_PYTHON_SITES
-        exec ${t.pythonFull}/bin/python "\$@"
+
+        for prog in python pydoc; do
+          echo ========= prog $prog
+          cat >> $out/bin/$prog << EOF
+          export NIX_PYTHON_SITES=\$NIX_PYTHON_SITES:$NIX_PYTHON_SITES
+          exec ${t.pythonFull}/bin/$prog "\$@"
         EOF
-        chmod +x $out/bin/python
+          echo chmod +x
+          chmod +x $out/bin/$prog
+        done
       '';
     };
 
@@ -72,7 +79,7 @@ in
     # lib to verify it works
     # You can define { python25 { debugCmd = "DISPLAY=:0.0 pathtoxterm"; }
     # in your config for easier debugging..
-    pythonLibStub = p.composableDerivation {
+    pythonLibStub = composableDerivation {
       initial = {
           propagatedBuildInputs = [ t.pythonFull ]; # see [1]
           postPhases = ["postAll"]; # using new name so that you dno't override this phase by accident
@@ -465,7 +472,7 @@ in
 
   ### python applications
 
-  pythonExStub = p.composableDerivation {
+  pythonExStub = composableDerivation {
     initial = {
       buildInputs = [p.makeWrapper];
       postPhases = ["wrapExecutables"];
diff --git a/pkgs/development/libraries/aterm/2.4.2-fixes.nix b/pkgs/development/libraries/aterm/2.4.2-fixes.nix
index 7c70afc621b7c..de1ea95a247f7 100644
--- a/pkgs/development/libraries/aterm/2.4.2-fixes.nix
+++ b/pkgs/development/libraries/aterm/2.4.2-fixes.nix
@@ -3,7 +3,7 @@
 stdenv.mkDerivation {
   name = "aterm-2.4.2-fixes-r2";
   src = fetchurl {
-    url = http://losser.st-lab.cs.uu.nl/~eelco/dist/aterm-2.4.2-fixes-r2.tar.bz2;
+    url = http://nixos.org/tarballs/aterm-2.4.2-fixes-r2.tar.bz2;
     sha256 = "1w3bxdpc2hz29li5ssmdcz3x0fn47r7g62ns0v8nazxwf40vff4j";
   };
   doCheck = true;
diff --git a/pkgs/development/libraries/avahi/0.6.21.nix b/pkgs/development/libraries/avahi/0.6.21.nix
deleted file mode 100644
index 26f03ca58bfe7..0000000000000
--- a/pkgs/development/libraries/avahi/0.6.21.nix
+++ /dev/null
@@ -1,2 +0,0 @@
-args:
-import ./common.nix "0q954lwhr6xnv7chhi4bqlmkn4nx9shyw0mbdr3n26018dgw65yq" args
diff --git a/pkgs/development/libraries/avahi/0.6.22.nix b/pkgs/development/libraries/avahi/0.6.22.nix
deleted file mode 100644
index 93b7184cdae20..0000000000000
--- a/pkgs/development/libraries/avahi/0.6.22.nix
+++ /dev/null
@@ -1,2 +0,0 @@
-args:
-import ./common.nix "0lnxzsdhihb3kjwd3vcrl9pq6ykfbp0vy9ja0mch01ffnrqgiilx" args
diff --git a/pkgs/development/libraries/avahi/common.nix b/pkgs/development/libraries/avahi/default.nix
index a44c2863cc9db..0db32ec685853 100644
--- a/pkgs/development/libraries/avahi/common.nix
+++ b/pkgs/development/libraries/avahi/default.nix
@@ -1,15 +1,20 @@
-sha256: args: with args;
+{ fetchurl, stdenv, pkgconfig, libdaemon, dbus, perl, perlXMLParser
+, expat, gettext, intltool, glib, gtk, qt4 ? null, lib
+, qt4Support ? false }:
 
 assert qt4Support -> qt4 != null;
 
 stdenv.mkDerivation rec {
-  name = "avahi-" + version;
+  name = "avahi-0.6.24";
   src = fetchurl {
     url = "${meta.homepage}/download/${name}.tar.gz";
-    inherit sha256;
+    sha256 = "0l5rsi4s7az7cs9p4aqs77v7jrh95iiwwx0ivksmivc8c7a70016";
   };
 
-  buildInputs = [pkgconfig libdaemon dbus perl perlXMLParser glib expat]
+  buildInputs = [
+      pkgconfig libdaemon dbus perl perlXMLParser glib expat
+      gettext intltool
+    ]
     ++ lib.optional qt4Support qt4;
 
   configureFlags = ''
diff --git a/pkgs/development/libraries/dbus/default.nix b/pkgs/development/libraries/dbus/default.nix
index 8d386be72de73..154958af6b9a6 100644
--- a/pkgs/development/libraries/dbus/default.nix
+++ b/pkgs/development/libraries/dbus/default.nix
@@ -1,16 +1,24 @@
-args: with args;
+{stdenv, fetchurl, pkgconfig, expat, libX11, libICE, libSM, useX11 ? true}:
+
 let
   version = "1.2.4";
+  
   src = fetchurl {
     url = "http://dbus.freedesktop.org/releases/dbus/dbus-${version}.tar.gz";
     sha256 = "1f7v79ws34mh6j75fk6w4w9v441vffll0fwf5vk94mwa0bc28g5b";
   };
+  
   configureFlags = "--disable-static --localstatedir=/var --with-session-socket-dir=/tmp";
+  
 in rec {
+
   libs = stdenv.mkDerivation {
     name = "dbus-library-" + version;
+    
     buildInputs = [pkgconfig expat];
+    
     inherit src configureFlags;
+    
     patchPhase = ''
       sed -i /mkinstalldirs.*localstatedir/d bus/Makefile.in
       sed -i '/SUBDIRS/s/ tools//' Makefile.in
@@ -19,21 +27,25 @@ in rec {
 
   tools = stdenv.mkDerivation {
     name = "dbus-tools-" + version;
+
     inherit src configureFlags;
+    
     buildInputs = [pkgconfig expat libs]
-      ++ (if useX11 then [libX11 libICE libSM] else []);
+      ++ stdenv.lib.optionals useX11 [libX11 libICE libSM];
+      
     postConfigure = "cd tools";
 
     NIX_LDFLAGS = "-ldbus-1";
+    
     makeFlags = "DBUS_DAEMONDIR=${daemon}/bin";
 
     patchPhase = ''
       sed -i 's@ $(top_builddir)/dbus/libdbus-1.la@@' tools/Makefile.in
-      sed -i '/mkdir.*localstate/d' tools/Makefile.in
+      substituteInPlace tools/Makefile.in --replace 'install-localstatelibDATA:' 'disabled:'
     '';
   };
 
-# I'm too lazy to separate daemon and libs now.
+  # I'm too lazy to separate daemon and libs now.
   daemon = libs;
   
   # FIXME TODO
diff --git a/pkgs/development/libraries/fltk/default.nix b/pkgs/development/libraries/fltk/default.nix
index 10034035ef1c6..6632088ade7a6 100644
--- a/pkgs/development/libraries/fltk/default.nix
+++ b/pkgs/development/libraries/fltk/default.nix
@@ -1,35 +1,47 @@
-args:
-( args.mkDerivationByConfiguration {
-    flagConfig = {
-      mandatory = { propagatedBuildInputs=["x11" "inputproto" "libXi"]; 
-                    blocks = ["cygwin" "quartz"]; }; # cgywin quartz and much more not yet tested
-      cygwin = { cfgOption = "--enable-cygwin"; }; #         use the CygWin libraries default=no
-      debug = { cfgOption = "--enable-debug"; }; #          turn on debugging default=no
-      gl = { cfgOption = "--enable-gl"; buildInputs = [ "mesa" ]; }; #             turn on OpenGL support default=yes
-      shared = { cfgOption = "--enable-shared"; }; #         turn on shared libraries default=no
-      threads = { cfgOption = "--enable-threads"; }; #        enable multi-threading support
-      quartz = { cfgOption = "--enable-quartz"; buildInputs = "quartz"; }; # don't konw yet what quartz is #         use Quartz instead of Quickdraw (default=no)
-      largefile = { cfgOption = "--disable-largefile"; }; #     omit support for large files
-      useNixLibs = { implies = [ "nixjpeg" "nixpng" "nixzlib" ]; }; # use nix libraries only
-      nixjpeg = { cfgOption = "--disable-localjpeg"; buildInputs = "libjpeg"; }; #      use local JPEG library, default=auto
-      nixzlib = { cfgOption = "--disable-localzlib"; buildInputs = "zlib"; }; #      use local ZLIB library, default=auto
-      nixpng = { cfgOption = "--disable-localpng"; buildInputs = "libpng"; }; #       use local PNG library, default=auto
-      xinerama = { cfgOption = "--enable-xinerama"; buildInputs = "xinerama"; }; #       turn on Xinerama support default=no
-      xft = { cfgOption = "--enable-xft"; buildInputs="xft"; }; #            turn on Xft support default=no
-      xdbe = { cfgOption = "--enable-xdbe"; }; #           turn on Xdbe support default=no
-    }; 
+args: with args;
+let inherit (args.composableDerivation) composableDerivation edf; in
+composableDerivation {
+  initial = {
 
-    extraAttrs = co : {
-      name = "fltk-2.0.x-r6483";
+    name = "fltk-2.0.x-r6483";
 
     src = args.fetchurl {
       url = ftp://ftp.easysw.com/pub/fltk/snapshots/fltk-2.0.x-r6483.tar.bz2;
       sha256 = "1n8b53r5p0zb4sbvr6pj8aasls4zjwksv1sdc3r3pzb20fikp5jb";
     };
 
-    meta = { 
+    propagatedBuildInputs=[x11 inputproto libXi freeglut];
+
+    buildInputs = [ args.pkgconfig ];
+
+    flags =
+      # this could be tidied up (?).. eg why does it require freeglut without glSupport?
+      edf { name = "cygwin"; }  #         use the CygWin libraries default=no
+      // edf { name = "debug"; }  #          turn on debugging default=no
+      // edf { name = "gl"; enable = { buildInputs = [ mesa ]; }; }  #             turn on OpenGL support default=yes
+      // edf { name = "shared"; }  #         turn on shared libraries default=no
+      // edf { name = "threads"; }  #        enable multi-threading support
+      // edf { name = "quartz"; enable = { buildInputs = "quartz"; }; }  # don't konw yet what quartz is #         use Quartz instead of Quickdraw (default=no)
+      // edf { name = "largefile"; } #     omit support for large files
+      // edf { name = "localjpeg"; disable = { buildInputs = [libjpeg]; }; } #       use local JPEG library, default=auto
+      // edf { name = "localzlib"; disable = { buildInputs = [zlib]; }; } #       use local ZLIB library, default=auto
+      // edf { name = "localpng"; disable = { buildInputs = [libpng]; }; } #       use local PNG library, default=auto
+      // edf { name = "xinerama"; enable = { buildInputs = [libXinerama]; }; } #       turn on Xinerama support default=no
+      // edf { name = "xft"; enable = { buildInputs=[libXft]; }; } #            turn on Xft support default=no
+      // edf { name = "xdbe"; };  #           turn on Xdbe support default=no
+    cfg = {
+        largefileSupport = true; # is default
+        glSupport = true; # doesn't build without it. Why?
+        localjpegSupport = false;
+        localzlibSupport = false;
+        localpngSupport = false;
+        sharedSupport = true;
+        threadsSupport = true;
+    };
+
+    meta = {
         description = "a C++ cross platform lightweight gui library binding";
         homepage = http://www.fltk.org;
     };
   };
-} ) args
+}
diff --git a/pkgs/development/libraries/freeimage/default.nix b/pkgs/development/libraries/freeimage/default.nix
new file mode 100644
index 0000000000000..7882b7fdfe53d
--- /dev/null
+++ b/pkgs/development/libraries/freeimage/default.nix
@@ -0,0 +1,22 @@
+{stdenv, fetchurl, unzip}:
+stdenv.mkDerivation {
+  name = "freeimage-3.11.0";
+  src = fetchurl {
+    url = mirror://sourceforge/freeimage/FreeImage3110.zip;
+    sha256 = "84021b8c0b86e5801479474ad9a99c18d121508ee16d363e02ddcbf24195340c";
+  };
+  buildInputs = [ unzip ];
+  patchPhase = ''
+      sed -e s@/usr/@$out/@ \
+        -e 's@-o root -g root@@' \
+        -e 's@ldconfig@echo not running ldconfig@' \
+        -i Makefile.gnu
+  '';
+  preInstall = "mkdir -p $out/include $out/lib";
+
+  meta = {
+    description = "Open Source library for accessing popular graphics image file formats";
+    homepage = http://freeimage.sourceforge.net/;
+    license = "GPL";
+  };
+}
diff --git a/pkgs/development/libraries/geos/default.nix b/pkgs/development/libraries/geos/default.nix
index bcfe8f757a24b..10cc4d94d4042 100644
--- a/pkgs/development/libraries/geos/default.nix
+++ b/pkgs/development/libraries/geos/default.nix
@@ -1,42 +1,38 @@
-args:
-( args.mkDerivationByConfiguration {
+args: with args;
+let inherit (args.composableDerivation) composableDerivation edf; in
+composableDerivation {
 
-    flagConfig = {
-      mandatory = { implies = "python"; 
-                    buildInputs = [ "which" ]; # which is needed for the autogen.sh
-                  };
+  initial = {
+
+    buildInputs = [ "which" ]; # which is needed for the autogen.sh
+
+    flags =
     # python and ruby untested 
-      python =            { cfgOption = "--enable-python"; #Enable build of python module
-                            buildInputs=["python"] ++ (if args.use_svn then ["libtool" "autoconf" "automake" "swig"] else []); 
-                          };
-      ruby =              { cfgOption = "--enable-ruby"; };  #Enable build of ruby module
-    }; 
+      edf { name = "python"; enable = { buildInputs = [ python ]; }; };
+      # (if args.use_svn then ["libtool" "autoconf" "automake" "swig"] else [])
+      # // edf { name = "ruby"; enable = { buildInputs = [ ruby ]; };}
 
-    extraAttrs = co : {
-      name = "geos-3.0.0rc4";
+    name = "geos-3.0.3";
 
-      src = if (args.use_svn) then
-        args.fetchsvn { 
-            url = http://svn.osgeo.org/geos/trunk; 
-            md5 = "b46f5ea517a337064006bab92f3090d4";
-        } else args.fetchurl {
-          url = http://geos.refractions.net/geos-3.0.0rc4.tar.bz2;
-          sha256 = "0pgwwv8q4p234r2jwdkaxcf68z2fwgmkc74c6dnmms2sdwkb5lbw";
-        };
+    src = fetchurl {
+        url = http://download.osgeo.org/geos/geos-3.0.3.tar.bz2;
+        sha256 = "1pxk20jcbyidp3bvip1vdf8wfw2wvh8pcn810qkf1y3zfnki0c7k";
+    };
 
-      configurePhase = "
-        [ -f configure ] || \\
-        LIBTOOLIZE=libtoolize ./autogen.sh
-        #{ automake --add-missing; autoconf; }
-        unset configurePhase; configurePhase
-        ";
+    # for development version. can be removed ?
+    #configurePhase = "
+    #  [ -f configure ] || \\
+    #  LIBTOOLIZE=libtoolize ./autogen.sh
+    #  [>{ automake --add-missing; autoconf; }
+    #  unset configurePhase; configurePhase
+    #";
 
-      meta = {
-          description = "C++ port of the Java Topology Suite (JTS)"
-            + "- all the OpenGIS \"Simple Features for SQL\" spatial predicate functions and spatial operators,"
-            + " as well as specific JTS topology functions such as IsValid";
-          homepage = http://geos.refractions.net/;
-          license = "GPL";
-      };
+    meta = {
+        description = "C++ port of the Java Topology Suite (JTS)"
+          + "- all the OpenGIS \"Simple Features for SQL\" spatial predicate functions and spatial operators,"
+          + " as well as specific JTS topology functions such as IsValid";
+        homepage = http://geos.refractions.net/;
+        license = "GPL";
+    };
   };
-} ) args
+}
diff --git a/pkgs/development/libraries/gnutls/default.nix b/pkgs/development/libraries/gnutls/default.nix
index 068d315e62a23..0506695a089bb 100644
--- a/pkgs/development/libraries/gnutls/default.nix
+++ b/pkgs/development/libraries/gnutls/default.nix
@@ -5,11 +5,11 @@ assert guileBindings -> guile != null;
 
 stdenv.mkDerivation rec {
 
-  name = "gnutls-2.6.2";
+  name = "gnutls-2.6.3";
 
   src = fetchurl {
     url = "mirror://gnu/gnutls/${name}.tar.bz2";
-    sha256 = "1jg7mcf8z9ghyzm8ca1b19pzwaaq3cvj5grsgi2hmlfms95zic80";
+    sha256 = "1rs0a9d5ag17ws7d442ywlsdm6nb8fdmxkpj5hv9byfwb7k7xpgd";
   };
 
   patches = [ ./tmpdir.patch ];
diff --git a/pkgs/development/libraries/gsl/default.nix b/pkgs/development/libraries/gsl/default.nix
index 6e76e3a938029..71c4ddcdad80a 100644
--- a/pkgs/development/libraries/gsl/default.nix
+++ b/pkgs/development/libraries/gsl/default.nix
@@ -1,15 +1,32 @@
-args: with args;
-stdenv.mkDerivation {
-  name = "gsl-1.11";
+{ fetchurl, stdenv }:
+
+stdenv.mkDerivation rec {
+  name = "gsl-1.12";
 
   src = fetchurl {
-    url = ftp://ftp.gnu.org/gnu/gsl/gsl-1.11.tar.gz;
-    sha256 = "1c8ijbykgm6w8q0a1j3bfjdd9764fcw9v709bv7pqrgimq3ya4bn";
+    url = "mirror://gnu/gsl/${name}.tar.gz";
+    sha256 = "1fdpqw981gcc0wkvcacm16mrrsq5f4jdq395zk59lxjcsa492092";
   };
 
+  doCheck = true;
+
+  configureFlags = "--disable-static";
+
   meta = { 
-      description = "numerical library (>1000 functions)";
-      homepage = http://www.gnu.org/software/gsl;
-      license = "GPL2";
+    description = "The GNU Scientific Library, a large numerical library";
+
+    longDescription = ''
+      The GNU Scientific Library (GSL) is a numerical library for C
+      and C++ programmers.  It is free software under the GNU General
+      Public License.
+
+      The library provides a wide range of mathematical routines such
+      as random number generators, special functions and least-squares
+      fitting.  There are over 1000 functions in total with an
+      extensive test suite.
+    '';
+
+    homepage = http://www.gnu.org/software/gsl/;
+    license = "GPLv3+";
   };
 }
diff --git a/pkgs/development/libraries/haskell/wxHaskell/default.nix b/pkgs/development/libraries/haskell/wxHaskell/default.nix
index b482d00fd469c..3a2099f54ce43 100644
--- a/pkgs/development/libraries/haskell/wxHaskell/default.nix
+++ b/pkgs/development/libraries/haskell/wxHaskell/default.nix
@@ -2,13 +2,21 @@
 
 stdenv.mkDerivation {
   name = "wxHaskell-0.10.1-pre20070124";
+  
   src = fetchurl {
-    url = http://losser.st-lab.cs.uu.nl/~eelco/dist/wxhaskell-src-0.10.1-pre20070124.tar.bz2;
+    url = http://nixos.org/tarballs/wxhaskell-src-0.10.1-pre20070124.tar.bz2;
     sha256 = "1cl0yd3blynjslzz05312bzg1dbymmj8pg88bhnr4p3rqxrlmhx9";
   };
+  
   buildInputs = [unzip ghc wxGTK];
-  postInstall = "
+  
+  postInstall = ''
     make wx
     make wx-install
-  ";
+  '';
+
+  meta = {
+    homepage = http://haskell.org/haskellwiki/WxHaskell;
+    description = "A portable and native GUI library for Haskell";
+  };
 }
diff --git a/pkgs/development/libraries/kerberos/heimdal.nix b/pkgs/development/libraries/kerberos/heimdal.nix
index c0133110d7927..e4800dfb94ba5 100644
--- a/pkgs/development/libraries/kerberos/heimdal.nix
+++ b/pkgs/development/libraries/kerberos/heimdal.nix
@@ -3,7 +3,8 @@ stdenv.mkDerivation rec {
 	name = "heimdal-1.0.2";
 
 	src = fetchurl {
-		url = "http://ftp.pdc.kth.se/pub/heimdal/src/${name}.tar.gz";
+		urls = [ "http://www.h5l.org/dist/src/${name}.tar.gz"
+                         "http://ftp.pdc.kth.se/pub/heimdal/src/${name}.tar.gz" ];
 		sha256 = "1h4x41lpv2abpv5l3yjd58pfzs0kkp5sbnih9iykhwd6sii1iig5";
 	};
 
diff --git a/pkgs/development/libraries/libassuan/default.nix b/pkgs/development/libraries/libassuan/default.nix
index ef0df51845233..9a161ec170f4b 100644
--- a/pkgs/development/libraries/libassuan/default.nix
+++ b/pkgs/development/libraries/libassuan/default.nix
@@ -1,16 +1,28 @@
-args: with args;
+{ fetchurl, stdenv, pth }:
+
 stdenv.mkDerivation rec {
-	name = "libassuan-1.0.4";
+  name = "libassuan-1.0.5";
+
+  src = fetchurl {
+    url = "mirror://gnupg/libassuan/${name}.tar.bz2";
+    sha256 = "1xar8i5jmah75wa9my4x7vkc5b6nmzd2p6k9kmpdg9hsv04292y5";
+  };
+
+  propagatedBuildInputs = [ pth ];
+
+  doCheck = true;
 
-	src = fetchurl {
-		url = "ftp://ftp.gnupg.org/gcrypt/libassuan/${name}.tar.bz2";
-		sha256 = "1milkb5128nkgvfvfc9yi3qq8d1bvci7b3qmzfibmyh7qga6pwpw";
-	};
+  meta = {
+    description = "Libassuan, the IPC library used by GnuPG and related software";
 
-	propagatedBuildInputs = [pth];
+    longDescription = ''
+      Libassuan is a small library implementing the so-called Assuan
+      protocol.  This protocol is used for IPC between most newer
+      GnuPG components.  Both, server and client side functions are
+      provided.
+    '';
 
-	meta = {
-		description = "Libassuan  is the IPC library used by some GnuPG related software";
-		homepage = http://www.gnupg.org;
-	};
+    homepage = http://gnupg.org;
+    license = "LGPLv2+";
+  };
 }
diff --git a/pkgs/development/libraries/libdv/default.nix b/pkgs/development/libraries/libdv/default.nix
index 4b0e05acf98d1..70211e928ee8a 100644
--- a/pkgs/development/libraries/libdv/default.nix
+++ b/pkgs/development/libraries/libdv/default.nix
@@ -1,30 +1,29 @@
-args:
-let edf = args.lib.enableDisableFeature; in
-( args.mkDerivationByConfiguration {
-    flagConfig = { }
+args: with args;
+let inherit (args.composableDerivation) composableDerivation edf; in
+composableDerivation {
+  initial = {
+    flags = { }
       # TODO! implement flags
       # I want to get kino and cinelerra working. That's why I don't spend more time on this now
-      // edf "libtool_lock" "libtool_lock" { } #avoid locking (might break parallel builds)
-      // edf "asm" "asm" { } #disable use of architecture specific assembly code
-      // edf "sdl" "sdl" { } #enable use of SDL for display
-      // edf "gtk" "gtk" { } #disable use of gtk for display
-      // edf "xv" "xv" { } #disable use of XVideo extension for display
-      // edf "gprof" "gprof" { } #enable compiler options for gprof profiling
-    ;
+      // edf { name = "libtool_lock"; } #avoid locking (might break parallel builds)
+      // edf { name ="asm"; } #disable use of architecture specific assembly code
+      // edf { name ="sdl"; } #enable use of SDL for display
+      // edf { name ="gtk"; } #disable use of gtk for display
+      // edf { name ="xv"; } #disable use of XVideo extension for display
+      // edf { name ="gprof"; }; #enable compiler options for gprof profiling
 
-    extraAttrs = co : {
-      name = "libdv-1.0.0";
+    name = "libdv-1.0.0";
 
-      src = args.fetchurl {
-        url = mirror://sourceforge/libdv/libdv-1.0.0.tar.gz;
-        sha256 = "1fl96f2xh2slkv1i1ix7kqk576a0ak1d33cylm0mbhm96d0761d3";
-      };
+    src = args.fetchurl {
+      url = mirror://sourceforge/libdv/libdv-1.0.0.tar.gz;
+      sha256 = "1fl96f2xh2slkv1i1ix7kqk576a0ak1d33cylm0mbhm96d0761d3";
+    };
 
-    meta = { 
+    meta = {
       description = "software decoder for DV format video, as defined by the IEC 61834 and SMPTE 314M standards";
       homepage = http://sourceforge.net/projects/libdv/;
       # you can choose one of the following licenses: 
       license = [];
     };
   };
-} ) args
+}
diff --git a/pkgs/development/libraries/libgpg-error/default.nix b/pkgs/development/libraries/libgpg-error/default.nix
index 05128094589b5..7554ec0e2f9a5 100644
--- a/pkgs/development/libraries/libgpg-error/default.nix
+++ b/pkgs/development/libraries/libgpg-error/default.nix
@@ -1,9 +1,27 @@
 {stdenv, fetchurl}:
 
 stdenv.mkDerivation rec {
-  name = "libgpg-error-1.4";
+  name = "libgpg-error-1.7";
+
   src = fetchurl {
-    url = "mirror://gnupg/libgpg-error/${name}.tar.gz";
-    sha256 = "06fn9rshrm7r49fkjc17xg39nz37kyda2l13qqgzjg69zz2pxxpz";
+    url = "mirror://gnupg/libgpg-error/${name}.tar.bz2";
+    sha256 = "14as9cpm4k9c6lxm517s9vzqrmjmdpf8i4s41k355xc27qdk6083";
   };
+
+  doCheck = true;
+
+  meta = {
+    description = "Libgpg-error, a small library that defines common error values for all GnuPG components";
+
+    longDescription = ''
+      Libgpg-error is a small library that defines common error values
+      for all GnuPG components.  Among these are GPG, GPGSM, GPGME,
+      GPG-Agent, libgcrypt, Libksba, DirMngr, Pinentry, SmartCard
+      Daemon and possibly more in the future.
+    '';
+
+    homepage = http://gnupg.org;
+
+    license = "LGPLv2+";
+  };    
 }
diff --git a/pkgs/development/libraries/libsamplerate/default.nix b/pkgs/development/libraries/libsamplerate/default.nix
index 2ea959528a873..aa218f102cdc7 100644
--- a/pkgs/development/libraries/libsamplerate/default.nix
+++ b/pkgs/development/libraries/libsamplerate/default.nix
@@ -1,35 +1,31 @@
-args:
-( args.mkDerivationByConfiguration {
-    flagConfig = {
-      mandatory = { buildInputs = ["pkgconfig"];};
-    # are these options of interest? We'll see
-    #--disable-fftw          disable usage of FFTW
-    #--enable-debug          enable debugging
-    #--disable-cpu-clip      disable tricky cpu specific clipper
+args: with args;
+stdenv.mkDerivation {
 
-    }; 
+  name = "libsamplerate-0.1.2";
+
+  src = args.fetchurl {
+    url = http://www.mega-nerd.com/SRC/libsamplerate-0.1.2.tar.gz;
+    sha256 = "1m1iwzpcny42kcqv5as2nyb0ggrb56wzckpximqpp2y74dipdf4q";
+  };
 
-    extraAttrs = co : {
-      name = "libsamplerate-0.1.2";
 
-      src = args.fetchurl {
-        url = http://www.mega-nerd.com/SRC/libsamplerate-0.1.2.tar.gz;
-        sha256 = "1m1iwzpcny42kcqv5as2nyb0ggrb56wzckpximqpp2y74dipdf4q";
-      };
+  buildInputs = ["pkgconfig"];
+  # maybe interesting configure flags:
+  #--disable-fftw          disable usage of FFTW
+  #--disable-cpu-clip      disable tricky cpu specific clipper
 
-    configurePhase = "
-     export LIBSAMPLERATE_CFLAGS=\"-I \$libsamplerate/include\"
-     export LIBSAMPLERATE_LIBS=\"-L \$libsamplerate/libs\"
-     ./configure --prefix=\$out"+co.configureFlags;
+  configurePhase = "
+   export LIBSAMPLERATE_CFLAGS=\"-I \$libsamplerate/include\"
+   export LIBSAMPLERATE_LIBS=\"-L \$libsamplerate/libs\"
+   ./configure --prefix=\$out";
 
-    meta = { 
-      description = "Sample Rate Converter for audio";
-      homepage = http://www.mega-nerd.com/SRC/index.html;
-      # you can choose one of the following licenses: 
-      license = [ "GPL" 
-                  { url=http://www.mega-nerd.com/SRC/libsamplerate-cul.pdf; 
-                    name="libsamplerate Commercial Use License";
-                  } ];
-    };
+  meta = {
+    description = "Sample Rate Converter for audio";
+    homepage = http://www.mega-nerd.com/SRC/index.html;
+    # you can choose one of the following licenses:
+    license = [ "GPL"
+                { url=http://www.mega-nerd.com/SRC/libsamplerate-cul.pdf;
+                  name="libsamplerate Commercial Use License";
+                } ];
   };
-} ) args
+}
diff --git a/pkgs/development/libraries/popt/popt-1.10.6.nix b/pkgs/development/libraries/popt/popt-1.10.6.nix
deleted file mode 100644
index f86a7824868a0..0000000000000
--- a/pkgs/development/libraries/popt/popt-1.10.6.nix
+++ /dev/null
@@ -1,13 +0,0 @@
-{stdenv, fetchurl, gettext, libtool, autoconf, automake}:
-
-assert gettext != null;
-
-stdenv.mkDerivation {
-  builder = ./builder-1.10.6.sh;
-  name = "popt-1.10.6";
-  src = fetchurl {
-    url = http://losser.st-lab.cs.uu.nl/~armijn/.nix/popt-1.10.6.tar.gz;
-    md5 = "130ee632bd4c677d898b0ef5efa67666";
-  };
-  buildInputs = [gettext libtool automake autoconf];
-}
diff --git a/pkgs/development/libraries/pthread-stubs/default.nix b/pkgs/development/libraries/pthread-stubs/default.nix
new file mode 100644
index 0000000000000..8a007b0f96872
--- /dev/null
+++ b/pkgs/development/libraries/pthread-stubs/default.nix
@@ -0,0 +1,8 @@
+{stdenv, fetchurl}:
+stdenv.mkDerivation {
+  name = "pthread-stubs-0.1";
+  src = fetchurl {
+    url = http://xcb.freedesktop.org/dist/libpthread-stubs-0.1.tar.bz2;
+    sha256 = "0raxl73kmviqinp00bfa025d0j4vmfjjcvfn754mi60mw48swk80";
+  };
+}
diff --git a/pkgs/development/libraries/vxl/default.nix b/pkgs/development/libraries/vxl/default.nix
new file mode 100644
index 0000000000000..7cdb6963cd251
--- /dev/null
+++ b/pkgs/development/libraries/vxl/default.nix
@@ -0,0 +1,17 @@
+{ stdenv, fetchurl, unzip, cmake, libtiff, expat, zlib, libpng, libjpeg }:
+stdenv.mkDerivation {
+  name = "vxl-1.11.0";
+
+  src = fetchurl {
+    url = mirror://sourceforge/vxl/vxl-1.11.0.zip;
+    sha256 = "84f38d0c3656b5e4470e16ddce715bafcaa478ff066e6cec6f54524b5d72fa68";
+  };
+
+  buildInputs = [ cmake unzip libtiff expat zlib libpng libjpeg ];
+
+  meta = {
+    description = "C++ Libraries for Computer Vision Research and Implementation";
+    homepage = http://vxl.sourceforge.net/;
+    license = "VXL License";
+  };
+}
diff --git a/pkgs/development/tools/analysis/valgrind/callgrind_annotate.patch b/pkgs/development/tools/analysis/valgrind/callgrind_annotate.patch
deleted file mode 100644
index 7b09ead451071..0000000000000
--- a/pkgs/development/tools/analysis/valgrind/callgrind_annotate.patch
+++ /dev/null
@@ -1,8 +0,0 @@
---- valgrind-3.3.0/callgrind/callgrind_annotate.in	2007-12-11 00:18:11.000000000 +0100
-+++ valgrind-3.3.0/callgrind/callgrind_annotate.in	2008-06-03 23:12:26.000000000 +0200
-@@ -1,4 +1,4 @@
--#! /usr/bin/perl -w
-+#! @PERL@ -w
- ##--------------------------------------------------------------------##
- ##--- The cache simulation framework: instrumentation, recording   ---##
- ##--- and results printing.                                        ---##
diff --git a/pkgs/development/tools/analysis/valgrind/default.nix b/pkgs/development/tools/analysis/valgrind/default.nix
index 23b6f5e08fab8..2ec5b2bd795c5 100644
--- a/pkgs/development/tools/analysis/valgrind/default.nix
+++ b/pkgs/development/tools/analysis/valgrind/default.nix
@@ -1,15 +1,13 @@
 { stdenv, fetchurl, perl, gdb }:
 
 stdenv.mkDerivation {
-  name = "valgrind-3.3.1";
+  name = "valgrind-3.4.0";
 
   src = fetchurl {
-    url = http://valgrind.org/downloads/valgrind-3.3.1.tar.bz2;
-    sha256 = "1ymai2xr3c7132vzkngrshlcsrs1qagfd4vwccr96ixx2pcb9dwm";
+    url = http://valgrind.org/downloads/valgrind-3.4.0.tar.bz2;
+    sha256 = "0x4zbwk9ml3kbjzwh887ahw0pdxcm5h9159qg9kwm7zgn7jlmsnm";
   };
 
-  patches = [ ./callgrind_annotate.patch ];
-
   # Perl is needed for `cg_annotate'.
   # GDB is needed to provide a sane default for `--db-command'.
   buildInputs = [ perl gdb ];
diff --git a/pkgs/development/tools/build-managers/cmake/default.nix b/pkgs/development/tools/build-managers/cmake/default.nix
index 9ce423bd934f8..171a44d373329 100644
--- a/pkgs/development/tools/build-managers/cmake/default.nix
+++ b/pkgs/development/tools/build-managers/cmake/default.nix
@@ -1,4 +1,4 @@
-{fetchurl, stdenv, replace}:
+{fetchurl, stdenv, replace, ncurses}:
 
 stdenv.mkDerivation rec {
   name = "cmake-2.6.2";
@@ -10,7 +10,12 @@ stdenv.mkDerivation rec {
     url = "http://www.cmake.org/files/v2.6/${name}.tar.gz";
     sha256 = "b3f5a9dfa97fb82cb1b7d78a62d949f93c8d4317af36674f337d27066fa6b7e9";
   };
+  inherit ncurses;
   propagatedBuildInputs = [replace];
-  postUnpack = "source \${setupHook}; fixCmakeFiles \${sourceRoot}";
+  postUnpack = "
+    source \${setupHook}; fixCmakeFiles \${sourceRoot};
+    echo 'SET (CMAKE_SYSTEM_PREFIX_PATH \"'\${ncurses}'\" CACHE FILEPATH \"Root for libs for cmake\" FORCE)' > \${sourceRoot}/cmakeInit.txt
+  ";
+  configureFlags= [ " --init=cmakeInit.txt " ];
   postInstall="fixCmakeFiles \$out/share";
 }
diff --git a/pkgs/development/tools/haskell/uuagc/default.nix b/pkgs/development/tools/haskell/uuagc/default.nix
index a5b276f9e1e3b..f9fe0d3a6870b 100644
--- a/pkgs/development/tools/haskell/uuagc/default.nix
+++ b/pkgs/development/tools/haskell/uuagc/default.nix
@@ -2,9 +2,9 @@
 
 cabal.mkDerivation (self : {
   pname = "uuagc";
-  version = "0.9.6";
+  version = "0.9.7";
   name = self.fname;
-  sha256 = "10e148bdf052e9a80e52c54a94314df9d1772e68416e5dfac289c47fd1ba8558";
+  sha256 = "7479ddbc8dc4b04cae278a942a50d7d76f06011aca06c56bcd26bdeba6eeb2d6";
   extraBuildInputs = [uulib];
   meta = {
     description = "Attribute Grammar System of Universiteit Utrecht";
diff --git a/pkgs/development/tools/misc/autoconf/2.13.nix b/pkgs/development/tools/misc/autoconf/2.13.nix
new file mode 100644
index 0000000000000..6bca865d8ed43
--- /dev/null
+++ b/pkgs/development/tools/misc/autoconf/2.13.nix
@@ -0,0 +1,37 @@
+{stdenv, fetchurl, m4, perl, lzma}:
+
+stdenv.mkDerivation rec {
+  name = "autoconf-2.13";
+  
+  src = fetchurl {
+    url = "mirror://gnu/autoconf/${name}.tar.gz";
+    sha256 = "07krzl4czczdsgzrrw9fiqx35xcf32naf751khg821g5pqv12qgh";
+  };
+
+  buildInputs = [m4 perl lzma];
+  
+  unpackCmd = "lzma -d < $src | tar -x ";
+
+  doCheck = true;
+
+  # Don't fixup "#! /bin/sh" in Autoconf, otherwise it will use the
+  # "fixed" path in generated files!
+  dontPatchShebangs = true;
+
+  meta = {
+    homepage = http://www.gnu.org/software/autoconf/;
+    description = "GNU Autoconf, a part of the GNU Build System";
+
+    longDescription = ''
+      GNU Autoconf is an extensible package of M4 macros that produce
+      shell scripts to automatically configure software source code
+      packages.  These scripts can adapt the packages to many kinds of
+      UNIX-like systems without manual user intervention.  Autoconf
+      creates a configuration script for a package from a template
+      file that lists the operating system features that the package
+      can use, in the form of M4 macro calls.
+    '';
+
+    license = "GPLv2+";
+  };
+}
diff --git a/pkgs/development/tools/misc/avrdude/default.nix b/pkgs/development/tools/misc/avrdude/default.nix
index f87d305dfb2cf..38871c8fd4c56 100644
--- a/pkgs/development/tools/misc/avrdude/default.nix
+++ b/pkgs/development/tools/misc/avrdude/default.nix
@@ -1,32 +1,32 @@
-args:
-with args.lib; with args;
-let
-  co = chooseOptionsByFlags {
-    inherit args;
-    flagDescr = {
-      mandatory ={ cfgOption = [ "--disable-dependency-tracking" ]; 
-                   buildInputs=["yacc" "flex"]; };
-      doc = { cfgOption = "--enable-doc"; buildInputs=["tetex"]; blocks=["doc" "because untested"]; }; #Enable building documents
-      no_parport = { cfgOption = "--disable-parport"; }; #Enable accessing parallel ports(default)
+args: with args;
+let edf = composableDerivation.edf; in
+composableDerivation.composableDerivation {
+  initial = {
+    name="avrdude-5.4";
+
+    src = fetchurl {
+        url = http://mirror.switch.ch/mirror/gentoo/distfiles/avrdude-5.4.tar.gz;
+        sha256 = "bee4148c51ec95999d803cb9f68f12ac2e9128b06f07afe307d38966c0833b30";
     };
-    #defaultFlags = ["doc"];
-  };
 
-in stdenv.mkDerivation {
+    configureFlags = [ "--disable-dependency-tracking" ];
 
-  # passing the flags in case a library using this want's to check them (*) .. 
-  inherit (co) /* flags */ buildInputs configureFlags;
+    buildInputs = [yacc flex];
 
-  src = fetchurl {
-      url = http://mirror.switch.ch/mirror/gentoo/distfiles/avrdude-5.4.tar.gz;
-      sha256 = "bee4148c51ec95999d803cb9f68f12ac2e9128b06f07afe307d38966c0833b30";
-    };
+    flags =
+           edf { name = "doc"; enable = { buildInputs = texLive;  configureFlags = ["--enable-doc"]; }; }
+        // edf { name = "parport"; }
+        ;
 
-  name="avrdude-5.4";
+    cfg = {
+      docSupport = false; # untested
+      parportSupport = true;
+    };
 
-  meta = {
-    license = "GPL-2";
-    description = "AVR Downloader/UploaDEr";
-    homepage = http://savannah.nongnu.org/projects/avrdude;
+    meta = {
+      license = "GPL-2";
+      description = "AVR Downloader/UploaDEr";
+      homepage = http://savannah.nongnu.org/projects/avrdude;
+    };
   };
 }
diff --git a/pkgs/development/tools/misc/gdb/default.nix b/pkgs/development/tools/misc/gdb/default.nix
index 0853b9d221b79..fd8f7c4be9611 100644
--- a/pkgs/development/tools/misc/gdb/default.nix
+++ b/pkgs/development/tools/misc/gdb/default.nix
@@ -1,4 +1,4 @@
-{ fetchurl, stdenv, ncurses, gmp, mpfr, texinfo }:
+{ fetchurl, stdenv, ncurses, readline, gmp, mpfr, texinfo }:
 
 stdenv.mkDerivation rec {
   name = "gdb-6.8";
@@ -8,9 +8,9 @@ stdenv.mkDerivation rec {
     sha256 = "067qpnpgmz9jffi208q5c981xsyn8naq3rkp5ypg477lddcgvpzf";
   };
 
-  buildInputs = [ ncurses gmp mpfr texinfo ];
+  buildInputs = [ ncurses readline gmp mpfr texinfo ];
 
-  configureFlags = "--with-gmp=${gmp} --with-mpfr=${mpfr}";
+  configureFlags = "--with-gmp=${gmp} --with-mpfr=${mpfr} --with-system-readline";
 
   postInstall = ''
     # Remove Info files already provided by Binutils and other packages.
diff --git a/pkgs/development/tools/misc/gnum4/default.nix b/pkgs/development/tools/misc/gnum4/default.nix
index 0158f6b5e2a5c..43cb96d8987c6 100644
--- a/pkgs/development/tools/misc/gnum4/default.nix
+++ b/pkgs/development/tools/misc/gnum4/default.nix
@@ -1,9 +1,10 @@
 {stdenv, fetchurl}:
 
 stdenv.mkDerivation rec {
-  name = "m4-1.4.12";
+  name = "gnum4-1.4.12";
+
   src = fetchurl {
-    url = "mirror://gnu/m4/${name}.tar.bz2";
+    url = mirror://gnu/m4/m4-1.4.12.tar.bz2;
     sha256 = "18qvi12843kvqkpcmrjxz1929s833q5d0jzm8hc965j663g1fll5";
   };
 
diff --git a/pkgs/development/tools/misc/strace/default.nix b/pkgs/development/tools/misc/strace/default.nix
index 5091a715167d9..38c4445d2200b 100644
--- a/pkgs/development/tools/misc/strace/default.nix
+++ b/pkgs/development/tools/misc/strace/default.nix
@@ -1,10 +1,10 @@
 {stdenv, fetchurl}:
 
 stdenv.mkDerivation {
-  name = "strace-4.5.16";
+  name = "strace-4.5.18";
 
   src = fetchurl {
-    url = mirror://sourceforge/strace/strace-4.5.16.tar.bz2;
-    sha256 = "15ks9i1gv7mbyiwnzbjls2xy0pyv5x4j9a5ca2x0258fq8lxwdhp";
+    url = mirror://sourceforge/strace/strace-4.5.18.tar.bz2;
+    sha256 = "1l16vax3mn2wak288g1inmn30i49vlghnvfwr0z2rwh41r3vgrwm";
   };
 }
diff --git a/pkgs/development/tools/misc/yodl/default.nix b/pkgs/development/tools/misc/yodl/default.nix
new file mode 100644
index 0000000000000..f25d8e7512cef
--- /dev/null
+++ b/pkgs/development/tools/misc/yodl/default.nix
@@ -0,0 +1,23 @@
+# This package is only used to create the documentation of zsh-cvs
+# eg have a look at http://www.zsh.org/mla/users/2008/msg00715.html
+# latest release is newer though
+args: with args;
+stdenv.mkDerivation {
+  name = "yodl-2.13.2";
+
+  buildInputs = [perl];
+
+  src = fetchurl {
+    url = "mirror://sourceforge/sourceforge/yodl/yodl_2.13.2.orig.tar.gz";
+    sha256 = "07zzyx8vf27y3p549qza0pqrb61hfh0gynxqb8i1cghjmxhrlxj3";
+  };
+  # maybe apply diff?
+
+  # This doesn't isntall docs yet, do you need them?
+  installPhase = ''
+    # -> $out
+    sed -i "s@'/usr/@'$out/@" contrib/build.pl
+    perl contrib/build.pl make-software
+    perl contrib/build.pl install-software
+  '';
+}
diff --git a/pkgs/development/tools/parsing/bison/bison-2.4.nix b/pkgs/development/tools/parsing/bison/bison-2.4.nix
index 09596f173d01c..5d65eacecd9d2 100644
--- a/pkgs/development/tools/parsing/bison/bison-2.4.nix
+++ b/pkgs/development/tools/parsing/bison/bison-2.4.nix
@@ -1,11 +1,11 @@
 {stdenv, fetchurl, m4}:
 
 stdenv.mkDerivation rec {
-  name = "bison-2.4";
+  name = "bison-2.4.1";
 
   src = fetchurl {
     url = "mirror://gnu/bison/${name}.tar.bz2";
-    sha256 = "0c9sv03wsqnqc7wfpa51yc9yy1i3kdgsrjg7qchx0sk8zr11cvqf";
+    sha256 = "0swf0qbxrcqwb5dw19fd47nj8m490m8kwz5f8k33d7hlhablcm13";
   };
 
   buildInputs = [m4];
diff --git a/pkgs/games/keen4/default.nix b/pkgs/games/keen4/default.nix
index 603714be3d1c0..745d9f6b38ca9 100644
--- a/pkgs/games/keen4/default.nix
+++ b/pkgs/games/keen4/default.nix
@@ -5,7 +5,7 @@ stdenv.mkDerivation {
   builder = ./builder.sh;
 
   dist = fetchurl {
-    url = http://losser.st-lab.cs.uu.nl/~eelco/dist/keen4.zip;
+    url = http://nixos.org/tarballs/keen4.zip;
     md5 = "ffcdd9e3bce224d92797166bc3f56f1c";
   };
 
diff --git a/pkgs/games/quake3/demo/default.nix b/pkgs/games/quake3/demo/default.nix
index f3c417aed2968..fb6d1f0b232b5 100644
--- a/pkgs/games/quake3/demo/default.nix
+++ b/pkgs/games/quake3/demo/default.nix
@@ -6,13 +6,13 @@ stdenv.mkDerivation {
 
   # This is needed for pak0.pk3.
   demo = fetchurl {
-    url = http://losser.st-lab.cs.uu.nl/~eelco/dist/linuxq3ademo-1.11-6.x86.gz.sh;
+    url = http://nixos.org/tarballs/linuxq3ademo-1.11-6.x86.gz.sh;
     md5 = "484610c1ce34272223a52ec331c99d5d";
   };
 
   # This is needed for the additional pak?.pk3 files.
   update = fetchurl {
-    url = http://losser.st-lab.cs.uu.nl/~eelco/dist/linuxq3apoint-1.31.x86.run;
+    url = http://nixos.org/tarballs/linuxq3apoint-1.31.x86.run;
     md5 = "2620b9eefb6d0775f766b6570870157a";
   };
 
diff --git a/pkgs/games/sgt-puzzles/default.nix b/pkgs/games/sgt-puzzles/default.nix
new file mode 100644
index 0000000000000..9eaa17e15b37b
--- /dev/null
+++ b/pkgs/games/sgt-puzzles/default.nix
@@ -0,0 +1,34 @@
+a :  
+let 
+  fetchurl = a.fetchurl;
+
+  version = a.lib.getAttr ["version"] "r8373" a; 
+  buildInputs = with a; [
+    gtk glib pkgconfig libX11 
+  ];
+in
+rec {
+  src = fetchurl {
+    url = "http://www.chiark.greenend.org.uk/~sgtatham/puzzles/puzzles-${version}.tar.gz";
+    sha256 = "1mkf36rah61x0pxpmjbpgy8ccv8m38hf088mf2i5cx9paya830dc";
+  };
+
+  inherit buildInputs;
+  configureFlags = [];
+  makeFlags = ["prefix=$out" "gamesdir=$out/bin"];
+
+  neededDirs = ["$out/bin" "$out/share" ""];
+  extraDoc = ["puzzles.txt"];
+
+  /* doConfigure should be removed if not needed */
+  phaseNames = ["addInputs" "doExport" "doMakeInstall"];
+
+  doExport = a.noDepEntry ''
+    export NIX_LDFLAGS="$NIX_LDFLAGS -L${a.libX11}/lib -lX11"
+  '';
+
+  name = "sgt-puzzles-" + version;
+  meta = {
+    description = "Simon Tatham's portable puzzle collection";
+  };
+}
diff --git a/pkgs/games/teeworlds/default.nix b/pkgs/games/teeworlds/default.nix
new file mode 100644
index 0000000000000..9e0bd2794d089
--- /dev/null
+++ b/pkgs/games/teeworlds/default.nix
@@ -0,0 +1,81 @@
+{ fetchurl, stdenv, python, alsaLib, libX11, mesa, SDL }:
+
+stdenv.mkDerivation rec {
+  name = "teeworlds-0.5.0";
+
+  src = fetchurl {
+    url = "http://www.teeworlds.com/files/${name}-src.tar.gz";
+    sha256 = "1akns8852j208cy3q4ki0fgbbpp0wyjm5fhnma7qs5k60321305x";
+  };
+
+  # Note: Teeworlds requires Python 2.x to compile.  Python 3.0 will
+  # not work.
+  buildInputs = [ python alsaLib libX11 mesa SDL ];
+
+  patchPhase = ''
+    substituteInPlace "default.bam"                             \
+      --replace 'settings.linker.flags = ""'                    \
+                'settings.linker.flags = "-fstack-protector-all"'
+  '';
+  configurePhase = ''
+    # Fetch and build BAM, the home-made build system.
+    # FIXME: Move BAM outside of here.  See http://www.teeworlds.com/trac/bam .
+    tar xzvf ${fetchurl {
+        url = "http://teeworlds.com/trac/bam/browser/releases/bam-0.2.0.tar.gz?format=raw";
+        sha256 = "0n077iiidw7xsyna4y92pz5dwqaywps3w0v5c88dic27vz0xsv7g";
+      }
+    }
+    ( cd bam-* && ./make_unix.sh )
+
+    # Build Teeworlds.
+    ./bam-*/src/bam release
+  '';
+
+  installPhase = ''
+    # Copy the graphics, sounds, etc.
+    ensureDir "$out/share/${name}"
+    cp -rv data other/icons "$out/share/${name}"
+
+    # Copy the executables (client, server, etc.).
+    ensureDir "$out/bin"
+    executables=""
+    for file in *
+    do
+      if [ -f "$file" ] && [ -x "$file" ]
+      then
+          executables="$file $executables"
+      fi
+    done
+    cp -v $executables "$out/bin"
+
+    # Make sure the programs are executed from the right directory so
+    # that they can access the graphics and sounds.
+    for program in $executables
+    do
+      mv -v "$out/bin/$program" "$out/bin/.wrapped-$program"
+      cat > "$out/bin/$program" <<EOF
+#!/bin/sh
+cd "$out/share/${name}" && exec "$out/bin/.wrapped-$program"
+EOF
+      chmod -v +x "$out/bin/$program"
+    done
+
+    # Copy the documentation.
+    ensureDir "$out/doc/${name}"
+    cp -v *.txt "$out/doc/${name}"
+  '';
+
+  meta = {
+    description = "Teeworlds, a retro multiplayer shooter game";
+
+    longDescription = ''
+      Teeworlds is a free online multiplayer game, available for all
+      major operating systems.  Battle with up to 12 players in a
+      variety of game modes, including Team Deathmatch and Capture The
+      Flag.  You can even design your own maps!
+    '';
+
+    homepage = http://teeworlds.com/;
+    license = "BSD-style, see `license.txt'";
+  };
+}
diff --git a/pkgs/games/xsokoban/default.nix b/pkgs/games/xsokoban/default.nix
new file mode 100644
index 0000000000000..733c7646a6ee8
--- /dev/null
+++ b/pkgs/games/xsokoban/default.nix
@@ -0,0 +1,48 @@
+a :  
+let 
+  fetchurl = a.fetchurl;
+
+  version = a.lib.getAttr ["version"] "3.3c" a; 
+  buildInputs = with a; [
+    a.libX11 a.xproto a.libXpm a.libXt
+  ];
+in
+rec {
+  src = fetchurl {
+    url = "http://www.cs.cornell.edu/andru/release/xsokoban-${version}.tar.gz";
+    sha256 = "006lp8y22b9pi81x1a9ldfgkl1fbmkdzfw0lqw5y9svmisbafbr9";
+  };
+
+  inherit buildInputs;
+  configureFlags = [];
+
+  /* doConfigure should be removed if not needed */
+  phaseNames = ["preConfigure" "doConfigure" "preBuild" "doMakeInstall"];
+
+  preConfigure = a.FullDepEntry (''
+    export NIX_CFLAGS_COMPILE="$NIX_CFLAGS_COMPILE -I${a.libXpm}/include/X11"
+    for i in  $NIX_CFLAGS_COMPILE; do echo $i; ls ''${i#-I}; done
+    chmod a+rw config.h
+    echo '#define HERE "@nixos-packaged"' >> config.h
+    echo '#define WWW 0' >> config.h
+    echo '#define OWNER "'$(whoami)'"' >> config.h
+    echo '#define ROOTDIR "'$out/lib/xsokoban'"' >> config.h
+    echo '#define ANYLEVEL 1' >> config.h
+    echo '#define SCOREFILE "/tmp/.xsokoban-score"' >> config.h
+    echo '#define LOCKFILE "/tmp/.xsokoban-score-lock"' >> config.h
+
+    sed -e 's/getpass[(][^)]*[)]/PASSWORD/' -i main.c
+    sed -e '/if [(]owner[)]/iowner=1;' -i main.c
+  '') ["minInit" "doUnpack"];
+      
+  preBuild = a.FullDepEntry (''
+    sed -e "s@/usr/local/@$out/@" -i Makefile
+    sed -e "s@ /bin/@ @" -i Makefile 
+    ensureDir $out/bin $out/share $out/man/man1 $out/lib
+  '') ["minInit" "doConfigure" "defEnsureDir"];
+
+  name = "xsokoban-" + version;
+  meta = {
+    description = "X sokoban";
+  };
+}
diff --git a/pkgs/lib/composable-derivation.nix b/pkgs/lib/composable-derivation.nix
new file mode 100644
index 0000000000000..790a0bcc9dbcb
--- /dev/null
+++ b/pkgs/lib/composable-derivation.nix
@@ -0,0 +1,46 @@
+{lib, pkgs} :
+let inherit (lib) nv nvs; in
+{
+  # see new python derivations for example..
+  # You should be able to override anything you like easily
+  # grep the mailinglist by title "python proposal" (dec 08)
+  # -> http://mail.cs.uu.nl/pipermail/nix-dev/2008-December/001571.html
+  # to see why this got complicated when using all its features
+  composableDerivation = {
+          # modify args before applying stdenv.mkDerivation, this should remove at least attrs removeAttrsBy
+        f ? lib.prepareDerivationArgs,
+        stdenv ? pkgs.stdenv,
+          # initial set of arguments to be passed to stdenv.mkDerivation passing prepareDerivationArgs by default
+        initial ? {},
+          # example func :  (x: x // { x.buildInputs ++ ["foo"] }), but see mergeAttrByFunc which does this for you
+        merge ? (lib.mergeOrApply lib.mergeAttrByFunc)
+      }: lib.applyAndFun
+            (args: stdenv.mkDerivation (f args))
+            merge
+            (merge { inherit (lib) mergeAttrBy; } initial);
+
+  # some utility functions
+  # use this function to generate flag attrs for prepareDerivationArgs
+  # E nable  D isable F eature
+  edf = {name, feat ? name, enable ? {}, disable ? {} , value ? ""}:
+    nvs name {
+    set = {
+      configureFlags = ["--enable-${feat}${if value == "" then "" else "="}${value}"];
+    } // enable;
+    unset = {
+      configureFlags = ["--disable-${feat}"];
+    } // disable;
+  };
+
+  # same for --with and --without-
+  # W ith or W ithout F eature
+  wwf = {name, feat ? name, enable ? {}, disable ? {}, value ? ""}:
+    nvs name {
+    set = {
+      configureFlags = ["--with-${feat}${if value == "" then "" else "="}${value}"];
+    } // enable;
+    unset = {
+      configureFlags = ["--without-${feat}"];
+    } // disable;
+  };
+}
diff --git a/pkgs/lib/default.nix b/pkgs/lib/default.nix
index 66b67baafef76..73cb9d383c44e 100644
--- a/pkgs/lib/default.nix
+++ b/pkgs/lib/default.nix
@@ -484,6 +484,7 @@ rec {
     else if all __isList list then concatLists list
     else if all __isAttrs list then mergeAttrs list
     else if all (x: true == x || false == x) list then fold logicalOR false list
+    else if all (x: x == toString x) list then concatStrings list
     else abort "${name}: Cannot merge values.";
 
   mergeTypedOption = typeName: predicate: merge: name: list:
@@ -803,253 +804,7 @@ rec {
                   else throw "assertion of flag ${a} of derivation ${args.name} failed"
                ) args2.flags );
     in removeAttrs
-      (mergeAttrsByFuncDefaults ([args] ++ opts))
+      (mergeAttrsByFuncDefaults ([args] ++ opts ++ [{ passthru = cfgWithDefaults; }]))
       ["flags" "cfg" "mergeAttrBy" "fixed" ]; # fixed may be passed as fix argument or such
-  # supportFlag functions for convinience
-  sFlagEnable = { name, buildInputs ? [], propagatedBuildInputs ? [] } : {
-      set = { configureFlags = "--enable-${name}"; inherit buildInputs; inherit propagatedBuildInputs; };
-      unset = { configureFlags = "--disable-${name}"; };
-    };
-
-
-
-# Marc 2nd proposal: (not everything has been tested in detail yet..)
-# depreceated because it's too complicated. use prepareDerivationArgs instead
-
-  # usage / example
-  # flagConfig = {
-  # } // (enableDisableFeature "flagName" "configure_feature" extraAttrs;)
-  #
-  # is equal to
-  # flagConfig = {
-  #   flagName = { cfgOption = "--enable-configure_feature"; } // extraAttrs;
-  #   no_flagName = { cfgOption = "--disable-configure_feature"; };
-  enableDisableFeature = flagName : configure_feature : extraAttrs :
-    listToAttrs [ ( nv flagName ({ cfgOption = "--enable-${configure_feature}"; } // extraAttrs ) )
-                  ( nv "no_${flagName}" ({ cfgOption = "--disable-${configure_feature}"; } ) )];
-
-  # calls chooseOptionsByFlags2 with some preprocessing
-  # chooseOptionsByFlags2 returns an attribute set meant to be used to create new derivaitons.
-  # see mkDerivationByConfiguration in all-packages.nix and the examples given below.
-  # You can just copy paste them into all-packages.nix to test them..
-
-  chooseOptionsByFlags = { flagConfig, args, optionals ? [], defaults ? [],
-                           collectExtraPhaseActions ? [] } :
-    let passedOptionals = filter ( x : hasAttr x args ) optionals; # these are in optionals and in args
-        # we simply merge in <optional_name> = { buildInputs = <arg.<optional_name>; pass = <arg.optional_name>; }
-        flagConfigWithOptionals = flagConfig // ( listToAttrs
-          (map ( o : nv o ( { buildInputs = o; pass = nvs o (builtins.getAttr o args); }
-                            // getAttr [o] {} flagConfig )
-               )
-               passedOptionals ) );
-
-    in chooseOptionsByFlags2 flagConfigWithOptionals collectExtraPhaseActions args 
-       ( (getAttr ["flags"] defaults args) ++ passedOptionals);
-
-  chooseOptionsByFlags2 = flagConfig : collectExtraPhaseActions : args : flags :
-    let   
-        # helper function
-        collectFlags = # state : flags :
-              fold ( flag : s : (
-                     if (hasAttr flag s.result) then s # this state has already been visited
-                     else if (! hasAttr flag flagConfig) then throw "unkown flag `${flag}' specified"
-                           else let fDesc = (builtins.getAttr flag flagConfig);
-                                    implied = flatten ( getAttr ["implies"] [] fDesc );
-                                    blocked = flatten ( getAttr ["blocks"] [] fDesc ); 
-                                    # add this flag
-                                    s2 =  s // { result = ( setAttr s.result flag (builtins.getAttr flag flagConfig) );
-                                                 blockedFlagsBy = s.blockedFlagsBy 
-                                                   // listToAttrs (map (b: nv b flag ) blocked); };
-                                    # add implied flags
-                                in collectFlags s2 implied
-                   ));
-
-        # chosen contains flagConfig but only having those attributes elected by flags 
-        # (or by implies attributes of elected attributes)
-        options = let stateOpts = collectFlags { blockedFlagsBy = {}; result = {}; } 
-                                               (flags ++ ( if (hasAttr "mandatory" flagConfig) then ["mandatory"] else [] ));
-                      # these options have not been chosen (neither by flags nor by implies)
-                      unsetOptions = filter ( x : (! hasAttr x stateOpts.result) && (hasAttr ("no_"+x) flagConfig)) 
-                                            ( attrNames flagConfig );
-                      # no add the corresponding no_ attributes as well ..
-                      state = collectFlags stateOpts (map ( x : "no_" + x ) unsetOptions);
-                  in # check for blockings:
-                     assert ( all id ( map ( b: if (hasAttr b state.result) 
-                                             then throw "flag ${b} is blocked by flag ${__getAttr b state.blockedFlagsBy}"
-                                             else true ) 
-                                           (attrNames state.blockedFlagsBy) ) ); 
-                    state.result;
-        flatOptions = flattenAttrs options;
-
-        # helper functions :
-        collectAttrs = attr : catAttrs attr flatOptions;
-        optsConcatStrs = delimiter : attrs : concatStrings 
-                ( intersperse delimiter (flatten ( collectAttrs attrs ) ) );
-
-        ifStringGetArg = x : if (__isAttrs x) then x # ( TODO implement __isString ?)
-                             else nvs x (__getAttr x args);
-          
-    in assert ( all id ( mapRecordFlatten ( attr : r : if ( all id ( flatten (getAttr ["assertion"] [] r ) ) ) 
-                                              then true else throw "assertion failed flag ${attr}" )
-                                         options) );
-      ( rec {
-
-          #foldOptions = attr: f : start: fold f start (catAttrs attr flatOptions);
-
-          # compared to flags flagsSet does also contain the implied flags.. This makes it easy to write assertions. ( assert args.
-          inherit options flatOptions collectAttrs optsConcatStrs;
 
-          buildInputs = map ( attr: if (! hasAttr attr args) then throw "argument ${attr} is missing!" else (builtins.getAttr attr args) )
-                        (flatten  (catAttrs "buildInputs" flatOptions));
-          propagatedBuildInputs = map ( attr: if (! hasAttr attr args) then throw "argument ${attr} is missing!" else (builtins.getAttr attr args) )
-                        (flatten  (catAttrs "propagatedBuildInputs" flatOptions));
-
-          configureFlags = optsConcatStrs " " "cfgOption";
-
-          #flags = listToAttrs (map ( flag: nv flag (hasAttr flag options) ) (attrNames flagConfig) );
-          flags_prefixed = listToAttrs (map ( flag: nv ("flag_set_"+flag) (hasAttr flag options) ) (attrNames flagConfig) );
-
-          pass = mergeAttrs ( map ifStringGetArg ( flatten (collectAttrs "pass") ) );
-      } #  now add additional phase actions (see examples)
-      // listToAttrs ( map ( x : nv x (optsConcatStrs "\n" x) ) collectExtraPhaseActions ) );
 }
-
-/* 
-  TODO: Perhaps it's better to move this documentation / these tests into some extra packages ..
-
-  # ###########################################################################
-  #  configuration tutorial .. examples and tests.. 
-  #  Copy this into all-packages.nix and  try
-
-  # The following derviations will all fail.. 
-  # But they will print the passed options so that you can get to know
-  # how these configurations ought to work.
-  # TODO: There is no nice way to pass an otpion yet.
-  #       I could imagine something like
-  #       flags = [ "flagA" "flagB" { flagC = 4; } ];
-
-  # They are named:
-  # simpleYes, simpleNo, 
-  # defaultsimpleYes, defaultsimpleNo
-  # optionalssimpleYes, optionalssimpleNo
-  # bitingsimpleYes can only be ran with -iA  blockingBiteMonster
-  # assertionsimpleNo
-  # of course you can use -iA and the attribute name as well to select these examples
-
-  # dummy build input
-  whoGetsTheFlagFirst = gnused;
-  whoGetsTheFlagLast = gnumake;
-
-  # simple example demonstrating containing one flag.
-  # features:
-  # * configure options are passed automatically
-  # * buildInputs are collected (they are special, see the setup script)
-  # * they can be passed by additional name as well using pass = { inherit (args) python } 
-  #                                       ( or short (value not attrs) : pass = "python" )
-  # * an attribute named the same way as the flag is added indicating 
-  #   true/ false (flag has been set/ not set)
-  # * extra phase dependend commands can be added
-  #   Its easy to add your own stuff using co.collectAttrs or co.optsConcatStrs 
-  #   ( perhaps this name will change?)
-  simpleFlagYesNoF = namePrefix : extraFlagAttrs : mkDerivationByConfiguration ( {
-    flagConfig = {
-      flag    = { name = namePrefix + "simpleYes"; 
-                  cfgOption = [ "--Yes" "--you-dont-need-a-list" ]; 
-                  buildInputs = [ "whoGetsTheFlagFirst" ]; 
-                  pass = { inherit gnumake; };
-                  extraConfigureCmd = "echo Hello, it worked! ";
-                  blocks = "bitingMonster";
-                };
-      no_flag = { name = namePrefix + "simpleNo"; 
-                  cfgOption = "--no"; 
-                  implies = ["bitingMonster"];
-                };
-      bitingMonster = {
-                  extraConfigureCmd = "echo Ill bite you";
-                };
-      gnutar = { cfgOption="--with-gnutar";
-                  # buildInputs and pass will be added automatically if gnutar is added to optionals
-               };
-      # can be used to check configure options of dependencies
-      # eg testFlag = { assertion = [ arg.desktop.flag_set_wmii (! arg.desktop.flag_set_gnome) (! arg.desktops.flag_set_kde ]; }
-      assertionFlag = { assertion = false; }; # assert is nix language keyword
-                                        
-    }; 
-
-    collectExtraPhaseActions = [ "extraConfigureCmd" ];
-
-    extraAttrs = co : {
-      name = ( __head (co.collectAttrs "name") );
-
-      unpackPhase = "
-       echo my name is 
-       echo \$name
-       echo
-       echo flag given \\(should be 1 or empty string\\) ? 
-       echo \$flag_set_flag
-       echo
-       echo my build inputs are 
-       echo \$buildInputs
-       echo
-       echo my configuration flags are 
-       echo \$configureFlags
-       echo
-       echo what about gnumake? Did it pass?
-       echo \$gnumake
-       echo 
-       echo configurePhase command is
-       echo $\configurePhase
-       echo 
-       echo gnutar passed? \\(optional test\\)
-       echo \$gnutar
-       echo
-       echo dying now
-       echo die_Hopefully_Soon
-      ";
-    configurePhase = co.extraConfigureCmd;
-    };
-  } // extraFlagAttrs ); 
-
-
-  simpleYes = simpleFlagYesNoF "" {} {
-    inherit whoGetsTheFlagFirst lib stdenv;
-    flags = ["flag"];
-  };
-  # note the "I'll bite you" because of the implies attribute
-  simpleNo = simpleFlagYesNoF "" {} {
-    inherit whoGetsTheFlagFirst lib stdenv;
-    flags = [];
-  };
-
-  # specifying defaults by adding a default attribute
-  
-  yesAgainDefault = simpleFlagYesNoF "default" { defaults = [ "flag" ];} {
-    inherit whoGetsTheFlagFirst lib stdenv;
-  };
-  noAgainOverridingDefault = simpleFlagYesNoF "default" { defaults = [ "flag" ];} {
-    inherit whoGetsTheFlagFirst lib stdenv;
-    flags = [];
-  };
-
-  # requested by Michael Raskin: activate flag automatically if dependency is passed:
-  withGnutarOptional = simpleFlagYesNoF "optionals" { optionals = [ "gnutar" ];} {
-    flags = [ "flag" ]; # I only need to pass this to trigger name optionalssimpleYes
-    inherit whoGetsTheFlagFirst lib stdenv;
-    inherit gnutar;
-  };
-  withoutGnutarOptional = simpleFlagYesNoF "optionals" { optionals = [ "gnutar" ];} {
-    inherit whoGetsTheFlagFirst lib stdenv;
-  };
-
-  # blocking example, this shouldn't even start building:
-  blockingBiteMonster = simpleFlagYesNoF "biting" {} {
-    inherit whoGetsTheFlagFirst lib stdenv;
-    flags = [ "flag" "bitingMonster" ];
-  };
-
-  # assertion example this shouldn't even start building:
-  assertion = simpleFlagYesNoF "assertion" {} {
-    inherit whoGetsTheFlagFirst lib stdenv;
-    flags = [ "assertionFlag" ];
-  };
-*/
diff --git a/pkgs/misc/bleeding-edge-fetch-infos.nix b/pkgs/misc/bleeding-edge-fetch-infos.nix
index 86a75eac5bb16..3ab6bcd44f56f 100644
--- a/pkgs/misc/bleeding-edge-fetch-infos.nix
+++ b/pkgs/misc/bleeding-edge-fetch-infos.nix
@@ -227,4 +227,8 @@
    url = "http://mawercer.de/~nix/repos/octave-03b414516dd8.tar.gz";
    sha256 = "28ca0be1407954e746909241bda95c5bf0a04f611e73100c1e3967ddc249c519";
  };
+  zsh = args: with args; fetchurl { # Sun Dec 21 12:50:24 UTC 2008
+    url = "http://mawercer.de/~nix/repos/zsh-2008-12-21_12-50-23.tar.gz";
+    sha256 = "9af16f89205759d7ade51268dbdfa02cec3db10b35dc7a56ffe8e1fde2074ae7";
+  };
 }
diff --git a/pkgs/misc/emulators/wine/default.nix b/pkgs/misc/emulators/wine/default.nix
index 95505071a385d..0c6b48c929abc 100644
--- a/pkgs/misc/emulators/wine/default.nix
+++ b/pkgs/misc/emulators/wine/default.nix
@@ -8,11 +8,11 @@ assert stdenv.isLinux;
 let lib = import ../../../lib/default.nix; in
 
 stdenv.mkDerivation {
-  name = "wine-1.1.9";
+  name = "wine-1.1.10";
 
   src = fetchurl {
-    url = mirror://sourceforge/wine/wine-1.1.9.tar.bz2;
-    sha256 = "1jhy7l5q1jri529n5070f4wjigbw4dr7d4jgdc10v6hxfmlp1mzy";
+    url = mirror://sourceforge/wine/wine-1.1.10.tar.bz2;
+    sha256 = "0saj7c2cmx720pdha04niz5c1jkym8zf5snjvdgxmwlizfjy2qr2";
   };
 
   buildInputs = [
diff --git a/pkgs/misc/gxemul/default.nix b/pkgs/misc/gxemul/default.nix
index e7d0c92a1c561..548aad3bc27ae 100644
--- a/pkgs/misc/gxemul/default.nix
+++ b/pkgs/misc/gxemul/default.nix
@@ -1,34 +1,37 @@
-args: with args.lib; with args;
-let
-  name="gxemul-0.4.6";
-  co = chooseOptionsByFlags {
-    inherit args;
-    flagDescr = {
-      mandatory = { install = "ensureDir \$out/bin; cp gxemul \$out/bin;"; };
-      doc   = { install = "ensureDir \$out/share/${name}; cp -r doc \$out/share/${name};"; implies = "man"; };
-      demos = { install = "ensureDir \$out/share/${name}; cp -r demos \$out/share/${name};"; };
-      man   = { install = "cp -r ./man \$out/;";};
+args: with args;
+let edf = composableDerivation.edf;
+    name = "gxemul-0.4.6"; in
+composableDerivation.composableDerivation {
+
+  initial = {
+    inherit name;
+    flags = {
+        doc   = { installPhase = "ensureDir \$out/share/${name}; cp -r doc \$out/share/${name};"; implies = "man"; };
+        demos = { installPhase = "ensureDir \$out/share/${name}; cp -r demos \$out/share/${name};"; };
+        man   = { installPhase = "cp -r ./man \$out/;";};
     };
-    optionals = ["libX11"];
-    defaultFlags = [ "demos" "doc" ];
-  };
-in stdenv.mkDerivation {
 
-  inherit name;
-  inherit (co) /* flags */ buildInputs configureFlags;
+    cfg = {
+      docSupport = true;
+      demosSupport = true;
+      manSupport = true;
+    };
 
-  src = fetchurl {
-    url = http://gavare.se/gxemul/src/gxemul-0.4.6.tar.gz;
-    sha256 = "0hf3gi6hfd2qr5090zimfiddcjgank2q6m7dfsr81wwpxfbhb2z3";
-  };
+    installPhase = "ensureDir \$out/bin; cp gxemul \$out/bin;";
 
-  configurePhase="./configure";
+    src = fetchurl {
+      url = http://gavare.se/gxemul/src/gxemul-0.4.6.tar.gz;
+      sha256 = "0hf3gi6hfd2qr5090zimfiddcjgank2q6m7dfsr81wwpxfbhb2z3";
+    };
+
+    configurePhase="./configure";
 
-  installPhase = concatStrings ( catAttrs "install" co.flatOptions );
+    meta = {
+      license = "BSD";
+      description = "A Machine Emulator, Mainly emulates MIPS, but supports other CPU type";
+      homepage = http://gavare.se/gxemul/;
+    };
 
-  meta = {
-    license = "BSD";
-    description = "A Machine Emulator, Mainly emulates MIPS, but supports other CPU type";
-    homepage = http://gavare.se/gxemul/;
+    mergeAttrBy = { installPhase = a : b : "${a}\n${b}"; };
   };
 }
diff --git a/pkgs/misc/jackaudio/default.nix b/pkgs/misc/jackaudio/default.nix
index 7c4450a8a2bdd..c7c010963c54c 100644
--- a/pkgs/misc/jackaudio/default.nix
+++ b/pkgs/misc/jackaudio/default.nix
@@ -1,57 +1,53 @@
-# Perhaps we can get some ideas from here ? http://gentoo-wiki.com/HOWTO_Jack 
+# Perhaps we can get some ideas from here ? http://gentoo-wiki.com/HOWTO_Jack
 # still much to test but it compiles now
 args:
-args.mkDerivationByConfiguration {
-    flagConfig = {
-    mandatory = { buildInputs = [ "pkgconfig" ];};
-
-    # FIXME: tidy up
-
-    # static[=PKGS] =     { cfgOption = "--enable-static[=PKGS]"; };                  #build static libraries [default=no]
-    # shared[=PKGS] =     { cfgOption = "--enable-shared[=PKGS]"; };                  #build shared libraries [default=yes]
-    posix_shm =         { cfgOption = "--enable-posix-shm"; };                        #use POSIX shm API
-    # altivec seems to be for mac only ?
-    #  altivec =           { cfgOption = "--enable-altivec"; };                        #enable Altivec support (default=auto)
-
-    # keeping default values by now:
-    # optimization_by_compiler = { cfgOption = "--enable-optimization-by-compiler"; }; [>use compiler (NOT processor) capabilities to determine optimization flags
-    # optimization_by_cpu = { cfgOption = "--enable-optimization-by-cpu"; };          [>use processor capabilities to determine optimization flags
-
-    # I think the default is ok
-    # mmx =               { cfgOption = "--enable-mmx"; };                           #enable MMX support (default=auto)
-    #sse =               { cfgOption = "--enable-sse"; };                            #enable SSE support (default=auto)
-    #dynsimd =           { cfgOption = "--enable-dynsimd"; };                        #enable dynamic SIMD selection (default=no)
-    #optimize =          { cfgOption = "--enable-optimize"; };                       #ask the compiler for its best optimizations
-    #resize =            { cfgOption = "--enable-resize"; };                         #enable buffer resizing feature
-    #ensure_mlock =      { cfgOption = "--enable-ensure-mlock"; };                   #fail if unable to lock memory
-    #debug =             { cfgOption = "--enable-debug"; };                          #enable debugging messages in jackd and libjack
-    timestamps =        { cfgOption = "--enable-timestamps"; };                      # allow clients to use the JACK timestamp API
-    #preemption_check =  { cfgOption = "--enable-preemption-check"; };               #
-
-    capabilities =      { cfgOption = "--enable-capabilities"; };                   #use libcap to gain realtime scheduling priviledges
-    no_oldtrans =       { cfgOption = "--disable-oldtrans"; };                      #remove old transport interfaces
-    stripped_jackd =    { cfgOption = "--enable-stripped-jackd"; };                 #strip jack before computing its md5 sum
-    no_portaudio =      { cfgOption = "--disable-portaudio"; };                     #ignore PortAudio driver
-    no_coreaudio =      { cfgOption = "--disable-coreaudio"; };                     #ignore CoreAudio driver
-    no_oss =            { cfgOption = "--disable-oss"; };                           #ignore OSS driver
-    no_freebob =        { cfgOption = "--disable-freebob"; };                       #ignore FreeBob driver
-    alsa =              { cfgOption = "--enable-alsa"; buildInputs="alsaLib"; };        #enable ALSA driver
-    no_alsa =           { cfgOption = "--disable-alsa"; };                          #ignore ALSA driver
-
-    }; 
-
-    extraAttrs = co : {
-      name = "jack-0.103.0";
-
-      src = args.fetchurl {
-        url = "mirror://sourceforge/jackit/jack-audio-connection-kit-0.109.2.tar.gz";
-        sha256 = "1m5z8dzalqspsa63pkcgyns0cvh0kqwhb9g1ivcwvnz0bc7ag9r7";
-      };
-
-      meta = { 
-        description = "jack audio connection kit";
-        homepage = "http://jackaudio.org";
-        license = "GPL";
-      };
+let inherit (args.composableDerivation) composableDerivation edf; in
+composableDerivation {
+  initial = {
+    buildInputs = [ args.pkgconfig ];
+    flags =
+        # FIXME: tidy up
+         edf { name = "posix-shm"; } #use POSIX shm API
+      // edf { name = "timestamps"; }                      # allow clients to use the JACK timestamp API
+      // edf { name = "capabilities"; }                   #use libcap to gain realtime scheduling priviledges
+      // edf { name = "oldtrans"; }                      #remove old transport interfaces
+      // edf { name = "stripped-jackd"; }                 #strip jack before computing its md5 sum
+      // edf { name = "portaudio"; }                     #ignore PortAudio driver
+      // edf { name = "coreaudio"; }                     #ignore CoreAudio driver
+      // edf { name = "oss"; }                           #ignore OSS driver
+      // edf { name = "freebob"; }                       #ignore FreeBob driver
+      // edf { name = "alsa"; enable = { buildInputs=[args.alsaLib]; }; };
+
+      # altivec seems to be for mac only ?
+      #  altivec =           { configureFlags = ["--enable-altivec"]; };                        #enable Altivec support (default=auto)
+
+      # keeping default values by now:
+      # optimization_by_compiler = { configureFlags = ["--enable-optimization-by-compiler"]; }; [>use compiler (NOT processor) capabilities to determine optimization flags
+      # optimization_by_cpu = { configureFlags = ["--enable-optimization-by-cpu"]; };          [>use processor capabilities to determine optimization flags
+
+      # I think the default is ok
+      # mmx =              edf { name = "mmx"; };                           #enable MMX support (default=auto)
+      #sse =               edf { name = "sse"; };                            #enable SSE support (default=auto)
+      #dynsimd =           edf { name = "dynsimd"; };                        #enable dynamic SIMD selection (default=no)
+      #optimize =          edf { name = "optimize"; };                       #ask the compiler for its best optimizations
+      #resize =            edf { name = "resize"; };                         #enable buffer resizing feature
+      #ensure_mlock =      edf { name = "ensure-mlock"; };                   #fail if unable to lock memory
+      #debug =             edf { name = "debug"; };                          #enable debugging messages in jackd and libjack
+      #preemption_check =  edf { name = "preemption-check"; };               #
+    cfg = {
+      posix_shmSupport = true;
+      timestampsSupport = true;
+      alsaSupport = true;
+    };
+    name = "jack-0.103.0";
+    src = args.fetchurl {
+      url = "mirror://sourceforge/jackit/jack-audio-connection-kit-0.109.2.tar.gz";
+      sha256 = "1m5z8dzalqspsa63pkcgyns0cvh0kqwhb9g1ivcwvnz0bc7ag9r7";
+    };
+    meta = {
+      description = "jack audio connection kit";
+      homepage = "http://jackaudio.org";
+      license = "GPL";
+    };
     };
-} args
+}
diff --git a/pkgs/misc/tex/nix/run-latex.sh b/pkgs/misc/tex/nix/run-latex.sh
index 0b6e29988fe44..ecce893950ba1 100644
--- a/pkgs/misc/tex/nix/run-latex.sh
+++ b/pkgs/misc/tex/nix/run-latex.sh
@@ -61,13 +61,18 @@ runLaTeX
 echo
 
 
-if grep -q '\\citation' $rootNameBase.aux; then
-    echo "RUNNING BIBTEX..."
-    bibtex --terse $rootNameBase
-    cp $rootNameBase.bbl $out
-    runNeeded=1
-    echo
-fi
+# Run bibtex to process all bibliographies.  There may be several when
+# we're using the multibib package.
+for auxFile in $(find . -name "*.aux"); do
+    if grep -q '\\citation' $auxFile; then
+        echo "RUNNING BIBTEX ON $auxFile..."
+        auxBase=$(basename $auxFile .aux)
+        bibtex --terse $auxBase
+        cp $auxBase.bbl $out
+        runNeeded=1
+        echo
+    fi
+done
 
 
 if test "$runNeeded"; then
diff --git a/pkgs/os-specific/linux/cpufrequtils/default.nix b/pkgs/os-specific/linux/cpufrequtils/default.nix
new file mode 100644
index 0000000000000..f2ee49ef75b20
--- /dev/null
+++ b/pkgs/os-specific/linux/cpufrequtils/default.nix
@@ -0,0 +1,19 @@
+{stdenv, fetchurl, kernelHeaders, glibc, libtool, gettext}:
+
+assert stdenv.isLinux;
+
+stdenv.mkDerivation {
+  name = "cpufrequtils-005";
+  src = fetchurl {
+    url = http://www.kernel.org/pub/linux/utils/kernel/cpufreq/cpufrequtils-005.tar.gz;
+    md5 = "100a8220a546ce61ce943d4107e67db9";
+  };
+
+  patchPhase = ''
+      sed -e "s@= /usr/bin/@= @g" \
+      -e "s@/usr/@$out/@" \
+      -i Makefile
+  '';
+
+  buildInputs = [ kernelHeaders glibc libtool gettext ];
+}
diff --git a/pkgs/os-specific/linux/e2fsprogs/default.nix b/pkgs/os-specific/linux/e2fsprogs/default.nix
index a56149d007a44..c116b74a8103f 100644
--- a/pkgs/os-specific/linux/e2fsprogs/default.nix
+++ b/pkgs/os-specific/linux/e2fsprogs/default.nix
@@ -1,20 +1,35 @@
 {stdenv, fetchurl}:
 
 stdenv.mkDerivation {
-  name = "e2fsprogs-1.40.11";
+  name = "e2fsprogs-1.41.3";
+  
   src = fetchurl {
-    url = mirror://sourceforge/e2fsprogs/e2fsprogs-1.40.11.tar.gz;
-    sha256 = "0yw97irzwrra09wijjn8ig5j2fkyqwxl3hqyspsm3cmk2cshrsry";
+    url = mirror://sourceforge/e2fsprogs/e2fsprogs-1.41.3.tar.gz;
+    sha256 = "0yldax5z1d1gfxpvzmr8y2z5zg5xhbi9pjjy4yw0q28dd2pfsxyf";
   };
+  
   configureFlags =
     if stdenv ? isDietLibC
-    then ""
+    then "--with-diet-libc"
     else "--enable-elf-shlibs";
+
+  preBuild = if stdenv ? isDietLibC then ''
+    sed -e 's/-lpthread//' -i Makefile */Makefile */*/Makefile
+  '' else "";
+    
   preInstall = "installFlagsArray=('LN=ln -s')";
+  
   postInstall = "make install-libs";
+  
   NIX_CFLAGS_COMPILE =
     if stdenv ? isDietLibC then
       "-UHAVE_SYS_PRCTL_H " +
       (if stdenv.system == "x86_64-linux" then "-DHAVE_LSEEK64_PROTOTYPE=1 -Dstat64=stat" else "")
+      + " -lcompat -lpthread "
     else "";
+
+  meta = {
+    homepage = http://e2fsprogs.sourceforge.net/;
+    description = "Tools for creating and checking ext2/ext3/ext4 filesystems";
+  };
 }
diff --git a/pkgs/os-specific/linux/firmware/iwlwifi-3945-ucode/default.nix b/pkgs/os-specific/linux/firmware/iwlwifi-3945-ucode/default.nix
index c17d29cafa40e..f3cff66ea5cfb 100644
--- a/pkgs/os-specific/linux/firmware/iwlwifi-3945-ucode/default.nix
+++ b/pkgs/os-specific/linux/firmware/iwlwifi-3945-ucode/default.nix
@@ -1,11 +1,11 @@
 {stdenv, fetchurl}:
 
 stdenv.mkDerivation {
-  name = "iwlwifi-3945-ucode-2.14.1.5";
+  name = "iwlwifi-3945-ucode-15.28.1.8";
   
   src = fetchurl {
-    url = http://intellinuxwireless.org/iwlwifi/downloads/iwlwifi-3945-ucode-2.14.1.5.tgz;
-    sha256 = "06gy21qkd4kj6pf3nsz5z3xkgmcafzrm1krywd8lbb8i56i3jkra";
+    url = http://www.intellinuxwireless.org/iwlwifi/downloads/iwlwifi-3945-ucode-15.28.1.8.tgz;
+    sha256 = "0pwilsk8m9f5ihlp3wlam485a52lkbj2di5990bnz2m6ina9j8v2";
   };
   
   buildPhase = "true";
diff --git a/pkgs/os-specific/linux/firmware/iwlwifi-4965-ucode/default.nix b/pkgs/os-specific/linux/firmware/iwlwifi-4965-ucode/default.nix
index 3b50d8688a4d6..b75eae6acf217 100644
--- a/pkgs/os-specific/linux/firmware/iwlwifi-4965-ucode/default.nix
+++ b/pkgs/os-specific/linux/firmware/iwlwifi-4965-ucode/default.nix
@@ -1,11 +1,11 @@
 {stdenv, fetchurl}:
 
 stdenv.mkDerivation rec {
-  name = "iwlwifi-4965-ucode-4.44.17";
+  name = "iwlwifi-4965-ucode-228.57.1.21";
   
   src = fetchurl {
     url = "http://intellinuxwireless.org/iwlwifi/downloads/" + name + ".tgz";
-    sha256 = "1mfnxsp58jvh0njvwaxrkbiggbzr4jd0hk314hxfwyjpjdd2hj6w";
+    sha256 = "1rry0kpzszxk60h5gb94advzi009010xb332iyvfpaiwbj6aiyas";
   };
   
   buildPhase = "true";
diff --git a/pkgs/os-specific/linux/htop/default.nix b/pkgs/os-specific/linux/htop/default.nix
index 721068a5c7289..5424fa56d62e7 100644
--- a/pkgs/os-specific/linux/htop/default.nix
+++ b/pkgs/os-specific/linux/htop/default.nix
@@ -1,14 +1,14 @@
-args: with args;
-stdenv.mkDerivation {
-	name = "htop-0.6.6";
-	src = fetchurl {
-		url = mirror://sourceforge/htop/htop-0.6.6.tar.gz;
-		sha256 = "1q2jlyxgvx7bj4z0vfvlpq1ap3ykzd9rp598fbpwjw68mwwyzqmj";
-	};
-	buildInputs = [ncurses];
+{fetchurl, stdenv, ncurses}:
 
-	meta = {
-		description = "An interactive process viewer for Linux";
-		homepage = http://htop.sourceforge.net;
-	};
+stdenv.mkDerivation rec {
+  name = "htop-0.8.1";
+  src = fetchurl {
+    url = "mirror://sourceforge/htop/${name}.tar.gz";
+    sha256 = "0a2x28ibz7bg18nnb75gdssxwys0xvzd760j1vnq5dx45wh2ibi5";
+  };
+  buildInputs = [ncurses];
+  meta = {
+    description = "An interactive process viewer for Linux";
+    homepage = "http://htop.sourceforge.net";
+  };
 }
diff --git a/pkgs/os-specific/linux/iproute/default.nix b/pkgs/os-specific/linux/iproute/default.nix
index ef277b5e06ece..cf0b735c75290 100644
--- a/pkgs/os-specific/linux/iproute/default.nix
+++ b/pkgs/os-specific/linux/iproute/default.nix
@@ -1,16 +1,25 @@
+{fetchurl, stdenv, flex, bison, db4}:
 
-pkgs:
-pkgs.stdenv.mkDerivation {
-  name = "iproute-20070313";
+stdenv.mkDerivation {
+  name = "iproute-2.6.22-070710";
 
-  src = pkgs.fetchurl {
-    url = http://ftp.debian.org/debian/pool/main/i/iproute/iproute_20070313.orig.tar.gz;
-    sha256 = "1j7cmlr7p9xcg9ys8fhjnynwrp475rbkr2j2c5jqm1xzczw60f9v";
+  src = fetchurl {
+    url = http://developer.osdl.org/dev/iproute2/download/iproute2-2.6.22-070710.tar.gz;
+    sha256 = "3c6b48af9e655e4f0a34c7718e288960a1dc84a3ac7eb726e855adb45fbd953a";
   };
+ 
+  unpackPhase = ''
+      mkdir tmp; cd tmp
+      unpackFile "$src"
+  '';
 
-  preConfigure = "for script in $(find . -type f); do sed -e 's@#! /bin/bash@#! /bin/sh@' -i $script; done;";
+  patchPhase = ''
+    for script in $(find . -type f); do sed -e 's@#! /bin/bash@#! /bin/sh@' -i $script;
+    done;
+    sed -e s@/usr/lib@$out/lib@ -i tc/Makefile
+  '';
 
   makeFlags = " SBINDIR=\\$(out)/sbin CONFDIR=\\$(out)/etc DOCDIR=\\$(out)/doc MANDIR=\\$(out)/man ";
- 
-  buildInputs = [pkgs.bison pkgs.flex pkgs.db4];
+
+  buildInputs = [bison flex db4];
 }
diff --git a/pkgs/os-specific/linux/kernel-headers/2.6.26.2.nix b/pkgs/os-specific/linux/kernel-headers/2.6.26.2.nix
index 1226754e1fbe1..6f0c01e6ee513 100644
--- a/pkgs/os-specific/linux/kernel-headers/2.6.26.2.nix
+++ b/pkgs/os-specific/linux/kernel-headers/2.6.26.2.nix
@@ -2,13 +2,13 @@
 
 assert stdenv.isLinux;
 
+let version = "2.6.26.2"; in 
+
 stdenv.mkDerivation {
-  name = "linux-headers-2.6.26.2";
-  
-  builder = ./builder.sh;
+  name = "linux-headers-${version}";
   
   src = fetchurl {
-    url = "mirror://kernel/linux/kernel/v2.6/linux-2.6.26.2.tar.bz2";
+    url = "mirror://kernel/linux/kernel/v2.6/linux-${version}.tar.bz2";
     sha256 = "0xrkv6wk5l4qhza35a76cd00a7g9xv3ymw7znwskig2kmqswnp1m";
   };
 
@@ -23,4 +23,20 @@ stdenv.mkDerivation {
 
   extraIncludeDirs =
     if stdenv.system == "powerpc-linux" then ["ppc"] else [];
+
+  patchPhase = ''
+    sed -i '/scsi/d' include/Kbuild
+  '';
+
+  buildPhase = ''
+    make mrproper headers_check
+  '';
+
+  installPhase = ''
+    make INSTALL_HDR_PATH=$out headers_install
+
+    # Some builds (e.g. KVM) want a kernel.release.
+    ensureDir $out/include/config
+    echo "${version}-default" > $out/include/config/kernel.release
+  '';
 }
diff --git a/pkgs/os-specific/linux/kernel-headers/2.6.28.nix b/pkgs/os-specific/linux/kernel-headers/2.6.28.nix
new file mode 100644
index 0000000000000..46f662e46b1b7
--- /dev/null
+++ b/pkgs/os-specific/linux/kernel-headers/2.6.28.nix
@@ -0,0 +1,44 @@
+{stdenv, fetchurl, perl}:
+
+assert stdenv.isLinux;
+
+let version = "2.6.28"; in 
+
+stdenv.mkDerivation {
+  name = "linux-headers-${version}";
+  
+  src = fetchurl {
+    url = "mirror://kernel/linux/kernel/v2.6/linux-${version}.tar.bz2";
+    sha256 = "1023nl992s4qmnwzbfz385azzpph58azi5rw4w0wwzzybv2rf3df";
+  };
+
+  platform = 
+    if stdenv.system == "i686-linux" then "i386" else
+    if stdenv.system == "x86_64-linux" then "x86_64" else
+    if stdenv.system == "powerpc-linux" then "powerpc" else
+    abort "don't know what the kernel include directory is called for this platform";
+
+  buildInputs = [perl];
+
+  # !!! hacky
+  fixupPhase = "ln -s $out/include/asm $out/include/asm-$platform";
+
+  extraIncludeDirs =
+    if stdenv.system == "powerpc-linux" then ["ppc"] else [];
+
+  patchPhase = ''
+    sed -i '/scsi/d' include/Kbuild
+  '';
+
+  buildPhase = ''
+    make mrproper headers_check
+  '';
+
+  installPhase = ''
+    make INSTALL_HDR_PATH=$out headers_install
+
+    # Some builds (e.g. KVM) want a kernel.release.
+    ensureDir $out/include/config
+    echo "${version}-default" > $out/include/config/kernel.release
+  '';
+}
diff --git a/pkgs/os-specific/linux/kernel/builder-custom.sh b/pkgs/os-specific/linux/kernel/builder-custom.sh
deleted file mode 100644
index b4592e74c48ea..0000000000000
--- a/pkgs/os-specific/linux/kernel/builder-custom.sh
+++ /dev/null
@@ -1,127 +0,0 @@
-source $stdenv/setup
-
-configurePhase=configurePhase
-configurePhase() {
-    export INSTALL_PATH=$out
-    export INSTALL_MOD_PATH=$out
-	
-    eval "$preConfigure"
-
-    # Get rid of any "localversion" files installed by patches.
-    if test -z "$allowLocalVersion"; then
-        rm -f localversion*
-    fi
-
-    # Set our own localversion, if specified.
-    if test -n "$localVersion"; then
-        echo "$localVersion" > localversion-nix
-    fi
-
-
-    # Create the config file.
-    cp $config .config
-    chmod u+w .config
-
-    echo --extraConfig--;
-    echo "${extraConfig}";
-
-    echo "$extraConfig" | while read; do
-	optionName=$( echo "$REPLY" | sed -e 's/[^A-Z_]//g' );
-	echo --optionName--;
-	echo "$REPLY";
-	echo ${optionName};
-	if [ -n "${optionName}" ]; then 
-	    sed -e s/.'*'${optionName}.'*'/"$REPLY/" -i .config
-	fi;
-    done;
-
-    echo "$extraConfig" >> .config
-
-    #substituteInPlace scripts/kconfig/lxdialog/check-lxdialog.sh \
-    #    --replace /usr /no-such-path
-
-    # Necessary until NIXPKGS-38 is fixed:
-    echo "#! $SHELL" > scripts/kconfig/lxdialog/check-lxdialog.sh
-    chmod +x scripts/kconfig/lxdialog/check-lxdialog.sh
-    
-    make oldconfig \
-        $makeFlags "${makeFlagsArray[@]}"
-
-    echo --finalConfig--
-    cat .config
-}
-
-
-installPhase=installPhase
-installPhase() {
-
-    ensureDir $out
-
-    # Copy the bzImage and System.map.
-    cp System.map $out
-    if test "$arch" = um; then
-        ensureDir $out/bin
-        cp linux $out/bin
-    else
-        cp arch/$arch/boot/bzImage $out/vmlinuz
-    fi
-
-    # Install the modules in $out/lib/modules with matching paths
-    # in modules.dep (i.e., refererring to $out/lib/modules, not
-    # /lib/modules).  The depmod_opts= is to prevent the kernel
-    # from passing `-b PATH' to depmod.
-    export MODULE_DIR=$out/lib/modules/
-    make modules_install \
-        DEPMOD=$module_init_tools/sbin/depmod depmod_opts= \
-        $makeFlags "${makeFlagsArray[@]}" \
-        $installFlags "${installFlagsArray[@]}"
-
-    # Strip the kernel modules.
-    echo "Stripping kernel modules..."
-    find $out -name "*.ko" -print0 | xargs -0 strip -S
-
-    # move this to install later on
-    # largely copied from early FC3 kernel spec files
-    version=$(cd $out/lib/modules && ls -d *)
-
-    # remove symlinks and create directories
-    rm -f $out/lib/modules/$version/build
-    rm -f $out/lib/modules/$version/source
-    mkdir $out/lib/modules/$version/build
-
-    # copy config
-    cp .config $out/lib/modules/$version/build/.config
-
-    if test "$arch" != um; then
-        # copy all Makefiles and Kconfig files
-        ln -s $out/lib/modules/$version/build $out/lib/modules/$version/source
-        cp --parents `find  -type f -name "Makefile*" -o -name "Kconfig*"` $out/lib/modules/$version/build
-        cp Module.symvers $out/lib/modules/$version/build
-
-        # weed out unneeded stuff
-        rm -rf $out/lib/modules/$version/build/Documentation
-        rm -rf $out/lib/modules/$version/build/scripts
-        rm -rf $out/lib/modules/$version/build/include
-
-        # copy architecture dependent files
-        cp -a arch/$arch/scripts $out/lib/modules/$version/build || true
-        cp -a arch/$arch/*lds $out/lib/modules/$version/build || true
-        cp -a "arch/$arch/Makefile*.cpu" $out/lib/modules/$version/build/arch/$arch || true
-        cp -a --parents arch/$arch/kernel/asm-offsets.s $out/lib/modules/$version/build/arch/$arch/kernel || true
-
-        # copy scripts
-        rm -f scripts/*.o
-        rm -f scripts/*/*.o
-        cp -a scripts $out/lib/modules/$version/build
-
-        # copy include files
-        mkdir -p $out/lib/modules/$version/build/include
-        cd include
-        cp -a acpi config linux math-emu media net pcmcia rxrpc scsi sound video asm asm-generic $out/lib/modules/$version/build/include
-        cp -a `readlink asm` $out/lib/modules/$version/build/include
-        cd ..
-    fi
-}
-
-
-genericBuild
diff --git a/pkgs/os-specific/linux/kernel/builder.sh b/pkgs/os-specific/linux/kernel/builder.sh
index c5805d3242e41..4e3461cc25ac9 100644
--- a/pkgs/os-specific/linux/kernel/builder.sh
+++ b/pkgs/os-specific/linux/kernel/builder.sh
@@ -122,11 +122,14 @@ installPhase() {
         cp -a scripts $out/lib/modules/$version/build
 
         # copy include files
-        mkdir -p $out/lib/modules/$version/build/include
-        cd include
-        cp -a acpi config linux math-emu media net pcmcia rxrpc scsi sound video asm asm-generic $out/lib/modules/$version/build/include
-        cp -a `readlink asm` $out/lib/modules/$version/build/include
-        cd ..
+        includeDir=$out/lib/modules/$version/build/include
+        mkdir -p $includeDir
+        (cd include && cp -a acpi config linux math-emu media net pcmcia rxrpc scsi sound video asm-generic $includeDir)
+        if test -e arch/$archDir/include/asm; then
+            cp -a arch/$archDir/include/asm $includeDir
+        else
+            cp -a include/asm-$archDir $includeDir/asm
+        fi
     fi
 }
 
diff --git a/pkgs/os-specific/linux/kernel/config-2.6.28-i686-smp b/pkgs/os-specific/linux/kernel/config-2.6.28-i686-smp
new file mode 100644
index 0000000000000..0e2cfc2fe0668
--- /dev/null
+++ b/pkgs/os-specific/linux/kernel/config-2.6.28-i686-smp
@@ -0,0 +1,4227 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.28
+# Mon Jan 12 11:46:54 2009
+#
+# CONFIG_64BIT is not set
+CONFIG_X86_32=y
+# CONFIG_X86_64 is not set
+CONFIG_X86=y
+CONFIG_ARCH_DEFCONFIG="arch/x86/configs/i386_defconfig"
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CMOS_UPDATE=y
+CONFIG_CLOCKSOURCE_WATCHDOG=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_FAST_CMPXCHG_LOCAL=y
+CONFIG_MMU=y
+CONFIG_ZONE_DMA=y
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_GENERIC_IOMAP=y
+CONFIG_GENERIC_BUG=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+# CONFIG_RWSEM_GENERIC_SPINLOCK is not set
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+# CONFIG_GENERIC_TIME_VSYSCALL is not set
+CONFIG_ARCH_HAS_CPU_RELAX=y
+CONFIG_ARCH_HAS_DEFAULT_IDLE=y
+CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y
+CONFIG_HAVE_SETUP_PER_CPU_AREA=y
+# CONFIG_HAVE_CPUMASK_OF_CPU_MAP is not set
+CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+# CONFIG_ZONE_DMA32 is not set
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+# CONFIG_AUDIT_ARCH is not set
+CONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_PENDING_IRQ=y
+CONFIG_X86_SMP=y
+CONFIG_USE_GENERIC_SMP_HELPERS=y
+CONFIG_X86_32_SMP=y
+CONFIG_X86_HT=y
+CONFIG_X86_BIOS_REBOOT=y
+CONFIG_X86_TRAMPOLINE=y
+CONFIG_KTIME_SCALAR=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION="-default"
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_BSD_PROCESS_ACCT_V3=y
+CONFIG_TASKSTATS=y
+CONFIG_TASK_DELAY_ACCT=y
+CONFIG_TASK_XACCT=y
+CONFIG_TASK_IO_ACCOUNTING=y
+CONFIG_AUDIT=y
+CONFIG_AUDITSYSCALL=y
+CONFIG_AUDIT_TREE=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=17
+# CONFIG_CGROUPS is not set
+CONFIG_HAVE_UNSTABLE_SCHED_CLOCK=y
+CONFIG_GROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+# CONFIG_RT_GROUP_SCHED is not set
+CONFIG_USER_SCHED=y
+# CONFIG_CGROUP_SCHED is not set
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
+CONFIG_RELAY=y
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_IPC_NS is not set
+# CONFIG_USER_NS is not set
+# CONFIG_PID_NS is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+# CONFIG_EMBEDDED is not set
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_PCSPKR_PLATFORM=y
+CONFIG_COMPAT_BRK=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_PCI_QUIRKS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+CONFIG_PROFILING=y
+# CONFIG_MARKERS is not set
+CONFIG_OPROFILE=m
+CONFIG_OPROFILE_IBS=y
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
+CONFIG_HAVE_IOREMAP_PROT=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_KMOD=y
+CONFIG_STOP_MACHINE=y
+CONFIG_BLOCK=y
+CONFIG_LBD=y
+# CONFIG_BLK_DEV_IO_TRACE is not set
+CONFIG_LSF=y
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_BLK_DEV_INTEGRITY=y
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+CONFIG_PREEMPT_NOTIFIERS=y
+CONFIG_CLASSIC_RCU=y
+CONFIG_FREEZER=y
+
+#
+# Processor type and features
+#
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_SMP=y
+CONFIG_X86_FIND_SMP_CONFIG=y
+CONFIG_X86_MPPARSE=y
+CONFIG_X86_PC=y
+# CONFIG_X86_ELAN is not set
+# CONFIG_X86_VOYAGER is not set
+# CONFIG_X86_GENERICARCH is not set
+# CONFIG_X86_VSMP is not set
+# CONFIG_X86_RDC321X is not set
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_PARAVIRT_GUEST=y
+CONFIG_XEN=y
+CONFIG_XEN_MAX_DOMAIN_MEMORY=8
+CONFIG_XEN_SAVE_RESTORE=y
+# CONFIG_XEN_DEBUG_FS is not set
+CONFIG_VMI=y
+CONFIG_KVM_CLOCK=y
+CONFIG_KVM_GUEST=y
+CONFIG_PARAVIRT=y
+CONFIG_PARAVIRT_CLOCK=y
+# CONFIG_PARAVIRT_DEBUG is not set
+CONFIG_MEMTEST=y
+# CONFIG_M386 is not set
+# CONFIG_M486 is not set
+# CONFIG_M586 is not set
+# CONFIG_M586TSC is not set
+# CONFIG_M586MMX is not set
+CONFIG_M686=y
+# CONFIG_MPENTIUMII is not set
+# CONFIG_MPENTIUMIII is not set
+# CONFIG_MPENTIUMM is not set
+# CONFIG_MPENTIUM4 is not set
+# CONFIG_MK6 is not set
+# CONFIG_MK7 is not set
+# CONFIG_MK8 is not set
+# CONFIG_MCRUSOE is not set
+# CONFIG_MEFFICEON is not set
+# CONFIG_MWINCHIPC6 is not set
+# CONFIG_MWINCHIP3D is not set
+# CONFIG_MGEODEGX1 is not set
+# CONFIG_MGEODE_LX is not set
+# CONFIG_MCYRIXIII is not set
+# CONFIG_MVIAC3_2 is not set
+# CONFIG_MVIAC7 is not set
+# CONFIG_MPSC is not set
+# CONFIG_MCORE2 is not set
+# CONFIG_GENERIC_CPU is not set
+CONFIG_X86_GENERIC=y
+CONFIG_X86_CPU=y
+CONFIG_X86_CMPXCHG=y
+CONFIG_X86_L1_CACHE_SHIFT=7
+CONFIG_X86_XADD=y
+CONFIG_X86_PPRO_FENCE=y
+CONFIG_X86_WP_WORKS_OK=y
+CONFIG_X86_INVLPG=y
+CONFIG_X86_BSWAP=y
+CONFIG_X86_POPAD_OK=y
+CONFIG_X86_INTEL_USERCOPY=y
+CONFIG_X86_USE_PPRO_CHECKSUM=y
+CONFIG_X86_TSC=y
+CONFIG_X86_CMPXCHG64=y
+CONFIG_X86_CMOV=y
+CONFIG_X86_MINIMUM_CPU_FAMILY=4
+CONFIG_X86_DEBUGCTLMSR=y
+CONFIG_CPU_SUP_INTEL=y
+CONFIG_CPU_SUP_CYRIX_32=y
+CONFIG_CPU_SUP_AMD=y
+CONFIG_CPU_SUP_CENTAUR_32=y
+CONFIG_CPU_SUP_TRANSMETA_32=y
+CONFIG_CPU_SUP_UMC_32=y
+# CONFIG_X86_DS is not set
+CONFIG_HPET_TIMER=y
+CONFIG_HPET_EMULATE_RTC=y
+CONFIG_DMI=y
+# CONFIG_IOMMU_HELPER is not set
+CONFIG_NR_CPUS=8
+CONFIG_SCHED_SMT=y
+CONFIG_SCHED_MC=y
+# CONFIG_PREEMPT_NONE is not set
+CONFIG_PREEMPT_VOLUNTARY=y
+# CONFIG_PREEMPT is not set
+CONFIG_X86_LOCAL_APIC=y
+CONFIG_X86_IO_APIC=y
+CONFIG_X86_MCE=y
+CONFIG_X86_MCE_NONFATAL=y
+CONFIG_X86_MCE_P4THERMAL=y
+CONFIG_VM86=y
+CONFIG_TOSHIBA=m
+CONFIG_I8K=m
+CONFIG_X86_REBOOTFIXUPS=y
+CONFIG_MICROCODE=m
+CONFIG_MICROCODE_INTEL=y
+CONFIG_MICROCODE_AMD=y
+CONFIG_MICROCODE_OLD_INTERFACE=y
+CONFIG_X86_MSR=m
+CONFIG_X86_CPUID=m
+# CONFIG_NOHIGHMEM is not set
+# CONFIG_HIGHMEM4G is not set
+CONFIG_HIGHMEM64G=y
+CONFIG_PAGE_OFFSET=0xC0000000
+CONFIG_HIGHMEM=y
+CONFIG_X86_PAE=y
+CONFIG_ARCH_PHYS_ADDR_T_64BIT=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_SPARSEMEM_STATIC=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_RESOURCES_64BIT=y
+CONFIG_PHYS_ADDR_T_64BIT=y
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
+CONFIG_MMU_NOTIFIER=y
+CONFIG_HIGHPTE=y
+CONFIG_X86_CHECK_BIOS_CORRUPTION=y
+# CONFIG_X86_BOOTPARAM_MEMORY_CORRUPTION_CHECK is not set
+CONFIG_X86_RESERVE_LOW_64K=y
+# CONFIG_MATH_EMULATION is not set
+CONFIG_MTRR=y
+CONFIG_MTRR_SANITIZER=y
+CONFIG_MTRR_SANITIZER_ENABLE_DEFAULT=0
+CONFIG_MTRR_SANITIZER_SPARE_REG_NR_DEFAULT=1
+CONFIG_X86_PAT=y
+CONFIG_EFI=y
+CONFIG_SECCOMP=y
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+CONFIG_SCHED_HRTICK=y
+CONFIG_KEXEC=y
+# CONFIG_CRASH_DUMP is not set
+# CONFIG_KEXEC_JUMP is not set
+CONFIG_PHYSICAL_START=0x100000
+# CONFIG_RELOCATABLE is not set
+CONFIG_PHYSICAL_ALIGN=0x100000
+CONFIG_HOTPLUG_CPU=y
+CONFIG_COMPAT_VDSO=y
+# CONFIG_CMDLINE_BOOL is not set
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+
+#
+# Power management and ACPI options
+#
+CONFIG_PM=y
+# CONFIG_PM_DEBUG is not set
+CONFIG_PM_SLEEP_SMP=y
+CONFIG_PM_SLEEP=y
+CONFIG_SUSPEND=y
+CONFIG_SUSPEND_FREEZER=y
+CONFIG_HIBERNATION=y
+CONFIG_PM_STD_PARTITION=""
+CONFIG_ACPI=y
+CONFIG_ACPI_SLEEP=y
+CONFIG_ACPI_PROCFS=y
+CONFIG_ACPI_PROCFS_POWER=y
+CONFIG_ACPI_SYSFS_POWER=y
+CONFIG_ACPI_PROC_EVENT=y
+CONFIG_ACPI_AC=m
+CONFIG_ACPI_BATTERY=m
+CONFIG_ACPI_BUTTON=m
+CONFIG_ACPI_VIDEO=m
+CONFIG_ACPI_FAN=m
+CONFIG_ACPI_DOCK=y
+CONFIG_ACPI_PROCESSOR=m
+CONFIG_ACPI_HOTPLUG_CPU=y
+CONFIG_ACPI_THERMAL=m
+CONFIG_ACPI_WMI=m
+CONFIG_ACPI_ASUS=m
+CONFIG_ACPI_TOSHIBA=m
+CONFIG_ACPI_CUSTOM_DSDT_FILE=""
+# CONFIG_ACPI_CUSTOM_DSDT is not set
+CONFIG_ACPI_BLACKLIST_YEAR=2001
+# CONFIG_ACPI_DEBUG is not set
+CONFIG_ACPI_PCI_SLOT=m
+CONFIG_ACPI_SYSTEM=y
+CONFIG_X86_PM_TIMER=y
+CONFIG_ACPI_CONTAINER=m
+# CONFIG_ACPI_SBS is not set
+CONFIG_X86_APM_BOOT=y
+CONFIG_APM=y
+# CONFIG_APM_IGNORE_USER_SUSPEND is not set
+CONFIG_APM_DO_ENABLE=y
+# CONFIG_APM_CPU_IDLE is not set
+CONFIG_APM_DISPLAY_BLANK=y
+CONFIG_APM_ALLOW_INTS=y
+# CONFIG_APM_REAL_MODE_POWER_OFF is not set
+
+#
+# CPU Frequency scaling
+#
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_TABLE=m
+# CONFIG_CPU_FREQ_DEBUG is not set
+CONFIG_CPU_FREQ_STAT=m
+CONFIG_CPU_FREQ_STAT_DETAILS=y
+CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=m
+CONFIG_CPU_FREQ_GOV_USERSPACE=m
+CONFIG_CPU_FREQ_GOV_ONDEMAND=m
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m
+
+#
+# CPUFreq processor drivers
+#
+CONFIG_X86_ACPI_CPUFREQ=m
+CONFIG_X86_POWERNOW_K6=m
+CONFIG_X86_POWERNOW_K7=m
+CONFIG_X86_POWERNOW_K7_ACPI=y
+CONFIG_X86_POWERNOW_K8=m
+CONFIG_X86_POWERNOW_K8_ACPI=y
+CONFIG_X86_GX_SUSPMOD=m
+CONFIG_X86_SPEEDSTEP_CENTRINO=m
+CONFIG_X86_SPEEDSTEP_CENTRINO_TABLE=y
+CONFIG_X86_SPEEDSTEP_ICH=m
+CONFIG_X86_SPEEDSTEP_SMI=m
+CONFIG_X86_P4_CLOCKMOD=m
+CONFIG_X86_CPUFREQ_NFORCE2=m
+CONFIG_X86_LONGRUN=m
+CONFIG_X86_LONGHAUL=m
+CONFIG_X86_E_POWERSAVER=m
+
+#
+# shared options
+#
+# CONFIG_X86_ACPI_CPUFREQ_PROC_INTF is not set
+CONFIG_X86_SPEEDSTEP_LIB=m
+CONFIG_X86_SPEEDSTEP_RELAXED_CAP_CHECK=y
+CONFIG_CPU_IDLE=y
+CONFIG_CPU_IDLE_GOV_LADDER=y
+CONFIG_CPU_IDLE_GOV_MENU=y
+
+#
+# Bus options (PCI etc.)
+#
+CONFIG_PCI=y
+# CONFIG_PCI_GOBIOS is not set
+# CONFIG_PCI_GOMMCONFIG is not set
+# CONFIG_PCI_GODIRECT is not set
+# CONFIG_PCI_GOOLPC is not set
+CONFIG_PCI_GOANY=y
+CONFIG_PCI_BIOS=y
+CONFIG_PCI_DIRECT=y
+CONFIG_PCI_MMCONFIG=y
+CONFIG_PCI_DOMAINS=y
+CONFIG_PCIEPORTBUS=y
+CONFIG_HOTPLUG_PCI_PCIE=m
+CONFIG_PCIEAER=y
+# CONFIG_PCIEASPM is not set
+CONFIG_ARCH_SUPPORTS_MSI=y
+CONFIG_PCI_MSI=y
+CONFIG_PCI_LEGACY=y
+# CONFIG_PCI_DEBUG is not set
+CONFIG_HT_IRQ=y
+CONFIG_ISA_DMA_API=y
+CONFIG_ISA=y
+# CONFIG_EISA is not set
+# CONFIG_MCA is not set
+CONFIG_SCx200=m
+CONFIG_SCx200HR_TIMER=m
+# CONFIG_OLPC is not set
+CONFIG_K8_NB=y
+CONFIG_PCCARD=m
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_PCMCIA=m
+CONFIG_PCMCIA_LOAD_CIS=y
+CONFIG_PCMCIA_IOCTL=y
+CONFIG_CARDBUS=y
+
+#
+# PC-card bridges
+#
+CONFIG_YENTA=m
+CONFIG_YENTA_O2=y
+CONFIG_YENTA_RICOH=y
+CONFIG_YENTA_TI=y
+CONFIG_YENTA_ENE_TUNE=y
+CONFIG_YENTA_TOSHIBA=y
+CONFIG_PD6729=m
+CONFIG_I82092=m
+CONFIG_I82365=m
+CONFIG_TCIC=m
+CONFIG_PCMCIA_PROBE=y
+CONFIG_PCCARD_NONSTATIC=m
+CONFIG_HOTPLUG_PCI=m
+CONFIG_HOTPLUG_PCI_FAKE=m
+CONFIG_HOTPLUG_PCI_COMPAQ=m
+CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM=y
+CONFIG_HOTPLUG_PCI_IBM=m
+CONFIG_HOTPLUG_PCI_ACPI=m
+CONFIG_HOTPLUG_PCI_ACPI_IBM=m
+CONFIG_HOTPLUG_PCI_CPCI=y
+CONFIG_HOTPLUG_PCI_CPCI_ZT5550=m
+CONFIG_HOTPLUG_PCI_CPCI_GENERIC=m
+CONFIG_HOTPLUG_PCI_SHPC=m
+
+#
+# Executable file formats / Emulations
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_HAVE_AOUT=y
+CONFIG_BINFMT_AOUT=m
+CONFIG_BINFMT_MISC=m
+CONFIG_HAVE_ATOMIC_IOMAP=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=m
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+CONFIG_XFRM_IPCOMP=m
+CONFIG_NET_KEY=m
+# CONFIG_NET_KEY_MIGRATE is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_ASK_IP_FIB_HASH=y
+# CONFIG_IP_FIB_TRIE is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=y
+# CONFIG_IP_PNP is not set
+CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE=m
+CONFIG_NET_IPGRE_BROADCAST=y
+CONFIG_IP_MROUTE=y
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+CONFIG_INET_AH=m
+CONFIG_INET_ESP=m
+CONFIG_INET_IPCOMP=m
+CONFIG_INET_XFRM_TUNNEL=m
+CONFIG_INET_TUNNEL=m
+CONFIG_INET_XFRM_MODE_TRANSPORT=m
+CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_XFRM_MODE_BEET=m
+CONFIG_INET_LRO=m
+CONFIG_INET_DIAG=m
+CONFIG_INET_TCP_DIAG=m
+CONFIG_TCP_CONG_ADVANCED=y
+CONFIG_TCP_CONG_BIC=m
+CONFIG_TCP_CONG_CUBIC=m
+CONFIG_TCP_CONG_WESTWOOD=m
+CONFIG_TCP_CONG_HTCP=m
+CONFIG_TCP_CONG_HSTCP=m
+CONFIG_TCP_CONG_HYBLA=m
+CONFIG_TCP_CONG_VEGAS=m
+CONFIG_TCP_CONG_SCALABLE=m
+# CONFIG_TCP_CONG_LP is not set
+# CONFIG_TCP_CONG_VENO is not set
+CONFIG_TCP_CONG_YEAH=m
+CONFIG_TCP_CONG_ILLINOIS=m
+# CONFIG_DEFAULT_BIC is not set
+# CONFIG_DEFAULT_CUBIC is not set
+# CONFIG_DEFAULT_HTCP is not set
+# CONFIG_DEFAULT_VEGAS is not set
+# CONFIG_DEFAULT_WESTWOOD is not set
+CONFIG_DEFAULT_RENO=y
+CONFIG_DEFAULT_TCP_CONG="reno"
+# CONFIG_TCP_MD5SIG is not set
+CONFIG_IPV6=m
+CONFIG_IPV6_PRIVACY=y
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+# CONFIG_IPV6_MIP6 is not set
+CONFIG_INET6_XFRM_TUNNEL=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_BEET=m
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+CONFIG_IPV6_SIT=m
+CONFIG_IPV6_NDISC_NODETYPE=y
+CONFIG_IPV6_TUNNEL=m
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
+# CONFIG_IPV6_MROUTE is not set
+# CONFIG_NETLABEL is not set
+CONFIG_NETWORK_SECMARK=y
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_NETFILTER_ADVANCED=y
+CONFIG_BRIDGE_NETFILTER=y
+
+#
+# Core Netfilter Configuration
+#
+CONFIG_NETFILTER_NETLINK=m
+CONFIG_NETFILTER_NETLINK_QUEUE=m
+CONFIG_NETFILTER_NETLINK_LOG=m
+CONFIG_NF_CONNTRACK=m
+CONFIG_NF_CT_ACCT=y
+CONFIG_NF_CONNTRACK_MARK=y
+# CONFIG_NF_CONNTRACK_SECMARK is not set
+# CONFIG_NF_CONNTRACK_EVENTS is not set
+CONFIG_NF_CT_PROTO_DCCP=m
+CONFIG_NF_CT_PROTO_GRE=m
+CONFIG_NF_CT_PROTO_SCTP=m
+CONFIG_NF_CT_PROTO_UDPLITE=m
+CONFIG_NF_CONNTRACK_AMANDA=m
+CONFIG_NF_CONNTRACK_FTP=m
+CONFIG_NF_CONNTRACK_H323=m
+CONFIG_NF_CONNTRACK_IRC=m
+CONFIG_NF_CONNTRACK_NETBIOS_NS=m
+CONFIG_NF_CONNTRACK_PPTP=m
+CONFIG_NF_CONNTRACK_SANE=m
+CONFIG_NF_CONNTRACK_SIP=m
+CONFIG_NF_CONNTRACK_TFTP=m
+CONFIG_NF_CT_NETLINK=m
+CONFIG_NETFILTER_TPROXY=m
+CONFIG_NETFILTER_XTABLES=m
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
+CONFIG_NETFILTER_XT_TARGET_DSCP=m
+CONFIG_NETFILTER_XT_TARGET_MARK=m
+CONFIG_NETFILTER_XT_TARGET_NFLOG=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
+CONFIG_NETFILTER_XT_TARGET_RATEEST=m
+CONFIG_NETFILTER_XT_TARGET_TPROXY=m
+CONFIG_NETFILTER_XT_TARGET_TRACE=m
+CONFIG_NETFILTER_XT_TARGET_SECMARK=m
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
+# CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set
+CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_DSCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
+CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
+CONFIG_NETFILTER_XT_MATCH_LENGTH=m
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+CONFIG_NETFILTER_XT_MATCH_OWNER=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
+CONFIG_NETFILTER_XT_MATCH_QUOTA=m
+CONFIG_NETFILTER_XT_MATCH_RATEEST=m
+CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_RECENT=m
+# CONFIG_NETFILTER_XT_MATCH_RECENT_PROC_COMPAT is not set
+CONFIG_NETFILTER_XT_MATCH_SCTP=m
+CONFIG_NETFILTER_XT_MATCH_SOCKET=m
+CONFIG_NETFILTER_XT_MATCH_STATE=m
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
+CONFIG_NETFILTER_XT_MATCH_STRING=m
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+CONFIG_NETFILTER_XT_MATCH_TIME=m
+CONFIG_NETFILTER_XT_MATCH_U32=m
+CONFIG_IP_VS=m
+# CONFIG_IP_VS_IPV6 is not set
+# CONFIG_IP_VS_DEBUG is not set
+CONFIG_IP_VS_TAB_BITS=12
+
+#
+# IPVS transport protocol load balancing support
+#
+CONFIG_IP_VS_PROTO_TCP=y
+CONFIG_IP_VS_PROTO_UDP=y
+CONFIG_IP_VS_PROTO_AH_ESP=y
+CONFIG_IP_VS_PROTO_ESP=y
+CONFIG_IP_VS_PROTO_AH=y
+
+#
+# IPVS scheduler
+#
+CONFIG_IP_VS_RR=m
+CONFIG_IP_VS_WRR=m
+CONFIG_IP_VS_LC=m
+CONFIG_IP_VS_WLC=m
+CONFIG_IP_VS_LBLC=m
+CONFIG_IP_VS_LBLCR=m
+CONFIG_IP_VS_DH=m
+CONFIG_IP_VS_SH=m
+CONFIG_IP_VS_SED=m
+CONFIG_IP_VS_NQ=m
+
+#
+# IPVS application helper
+#
+CONFIG_IP_VS_FTP=m
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_NF_DEFRAG_IPV4=m
+CONFIG_NF_CONNTRACK_IPV4=m
+CONFIG_NF_CONNTRACK_PROC_COMPAT=y
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_NF_NAT=m
+CONFIG_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_NF_NAT_SNMP_BASIC=m
+CONFIG_NF_NAT_PROTO_DCCP=m
+CONFIG_NF_NAT_PROTO_GRE=m
+CONFIG_NF_NAT_PROTO_UDPLITE=m
+CONFIG_NF_NAT_PROTO_SCTP=m
+CONFIG_NF_NAT_FTP=m
+CONFIG_NF_NAT_IRC=m
+CONFIG_NF_NAT_TFTP=m
+CONFIG_NF_NAT_AMANDA=m
+CONFIG_NF_NAT_PPTP=m
+CONFIG_NF_NAT_H323=m
+CONFIG_NF_NAT_SIP=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_SECURITY=m
+# CONFIG_IP_NF_ARPTABLES is not set
+
+#
+# IPv6: Netfilter Configuration
+#
+CONFIG_NF_CONNTRACK_IPV6=m
+CONFIG_IP6_NF_QUEUE=m
+CONFIG_IP6_NF_IPTABLES=m
+CONFIG_IP6_NF_MATCH_AH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
+CONFIG_IP6_NF_MATCH_FRAG=m
+CONFIG_IP6_NF_MATCH_OPTS=m
+CONFIG_IP6_NF_MATCH_HL=m
+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
+CONFIG_IP6_NF_MATCH_MH=m
+CONFIG_IP6_NF_MATCH_RT=m
+CONFIG_IP6_NF_TARGET_LOG=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_IP6_NF_TARGET_HL=m
+CONFIG_IP6_NF_RAW=m
+CONFIG_IP6_NF_SECURITY=m
+
+#
+# DECnet: Netfilter Configuration
+#
+CONFIG_DECNET_NF_GRABULATOR=m
+CONFIG_BRIDGE_NF_EBTABLES=m
+CONFIG_BRIDGE_EBT_BROUTE=m
+CONFIG_BRIDGE_EBT_T_FILTER=m
+CONFIG_BRIDGE_EBT_T_NAT=m
+CONFIG_BRIDGE_EBT_802_3=m
+CONFIG_BRIDGE_EBT_AMONG=m
+CONFIG_BRIDGE_EBT_ARP=m
+CONFIG_BRIDGE_EBT_IP=m
+CONFIG_BRIDGE_EBT_IP6=m
+CONFIG_BRIDGE_EBT_LIMIT=m
+CONFIG_BRIDGE_EBT_MARK=m
+CONFIG_BRIDGE_EBT_PKTTYPE=m
+CONFIG_BRIDGE_EBT_STP=m
+CONFIG_BRIDGE_EBT_VLAN=m
+CONFIG_BRIDGE_EBT_ARPREPLY=m
+CONFIG_BRIDGE_EBT_DNAT=m
+CONFIG_BRIDGE_EBT_MARK_T=m
+CONFIG_BRIDGE_EBT_REDIRECT=m
+CONFIG_BRIDGE_EBT_SNAT=m
+CONFIG_BRIDGE_EBT_LOG=m
+CONFIG_BRIDGE_EBT_ULOG=m
+CONFIG_BRIDGE_EBT_NFLOG=m
+# CONFIG_IP_DCCP is not set
+CONFIG_IP_SCTP=m
+# CONFIG_SCTP_DBG_MSG is not set
+# CONFIG_SCTP_DBG_OBJCNT is not set
+# CONFIG_SCTP_HMAC_NONE is not set
+# CONFIG_SCTP_HMAC_SHA1 is not set
+CONFIG_SCTP_HMAC_MD5=y
+# CONFIG_TIPC is not set
+CONFIG_ATM=m
+CONFIG_ATM_CLIP=m
+CONFIG_ATM_CLIP_NO_ICMP=y
+CONFIG_ATM_LANE=m
+CONFIG_ATM_MPOA=m
+CONFIG_ATM_BR2684=m
+# CONFIG_ATM_BR2684_IPFILTER is not set
+CONFIG_STP=m
+CONFIG_BRIDGE=m
+# CONFIG_NET_DSA is not set
+CONFIG_VLAN_8021Q=m
+# CONFIG_VLAN_8021Q_GVRP is not set
+CONFIG_DECNET=m
+CONFIG_DECNET_ROUTER=y
+CONFIG_LLC=y
+CONFIG_LLC2=m
+CONFIG_IPX=m
+# CONFIG_IPX_INTERN is not set
+CONFIG_ATALK=m
+CONFIG_DEV_APPLETALK=m
+CONFIG_LTPC=m
+CONFIG_COPS=m
+CONFIG_COPS_DAYNA=y
+CONFIG_COPS_TANGENT=y
+CONFIG_IPDDP=m
+CONFIG_IPDDP_ENCAP=y
+CONFIG_IPDDP_DECAP=y
+CONFIG_X25=m
+CONFIG_LAPB=m
+CONFIG_ECONET=m
+# CONFIG_ECONET_AUNUDP is not set
+# CONFIG_ECONET_NATIVE is not set
+CONFIG_WAN_ROUTER=m
+CONFIG_NET_SCHED=y
+
+#
+# Queueing/Scheduling
+#
+CONFIG_NET_SCH_CBQ=m
+CONFIG_NET_SCH_HTB=m
+CONFIG_NET_SCH_HFSC=m
+CONFIG_NET_SCH_ATM=m
+CONFIG_NET_SCH_PRIO=m
+CONFIG_NET_SCH_MULTIQ=m
+CONFIG_NET_SCH_RED=m
+CONFIG_NET_SCH_SFQ=m
+CONFIG_NET_SCH_TEQL=m
+CONFIG_NET_SCH_TBF=m
+CONFIG_NET_SCH_GRED=m
+CONFIG_NET_SCH_DSMARK=m
+CONFIG_NET_SCH_NETEM=m
+CONFIG_NET_SCH_INGRESS=m
+
+#
+# Classification
+#
+CONFIG_NET_CLS=y
+CONFIG_NET_CLS_BASIC=m
+CONFIG_NET_CLS_TCINDEX=m
+CONFIG_NET_CLS_ROUTE4=m
+CONFIG_NET_CLS_ROUTE=y
+CONFIG_NET_CLS_FW=m
+CONFIG_NET_CLS_U32=m
+CONFIG_CLS_U32_PERF=y
+CONFIG_CLS_U32_MARK=y
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+CONFIG_NET_CLS_FLOW=m
+# CONFIG_NET_EMATCH is not set
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_ACT_POLICE=m
+CONFIG_NET_ACT_GACT=m
+CONFIG_GACT_PROB=y
+CONFIG_NET_ACT_MIRRED=m
+CONFIG_NET_ACT_IPT=m
+CONFIG_NET_ACT_NAT=m
+CONFIG_NET_ACT_PEDIT=m
+CONFIG_NET_ACT_SIMP=m
+CONFIG_NET_ACT_SKBEDIT=m
+# CONFIG_NET_CLS_IND is not set
+CONFIG_NET_SCH_FIFO=y
+
+#
+# Network testing
+#
+CONFIG_NET_PKTGEN=m
+CONFIG_HAMRADIO=y
+
+#
+# Packet Radio protocols
+#
+CONFIG_AX25=m
+CONFIG_AX25_DAMA_SLAVE=y
+CONFIG_NETROM=m
+CONFIG_ROSE=m
+
+#
+# AX.25 network device drivers
+#
+CONFIG_MKISS=m
+CONFIG_6PACK=m
+CONFIG_BPQETHER=m
+CONFIG_SCC=m
+CONFIG_SCC_DELAY=y
+CONFIG_SCC_TRXECHO=y
+CONFIG_BAYCOM_SER_FDX=m
+CONFIG_BAYCOM_SER_HDX=m
+CONFIG_BAYCOM_PAR=m
+CONFIG_BAYCOM_EPP=m
+CONFIG_YAM=m
+# CONFIG_CAN is not set
+CONFIG_IRDA=m
+
+#
+# IrDA protocols
+#
+CONFIG_IRLAN=m
+CONFIG_IRNET=m
+CONFIG_IRCOMM=m
+CONFIG_IRDA_ULTRA=y
+
+#
+# IrDA options
+#
+CONFIG_IRDA_CACHE_LAST_LSAP=y
+# CONFIG_IRDA_FAST_RR is not set
+# CONFIG_IRDA_DEBUG is not set
+
+#
+# Infrared-port device drivers
+#
+
+#
+# SIR device drivers
+#
+CONFIG_IRTTY_SIR=m
+
+#
+# Dongle support
+#
+CONFIG_DONGLE=y
+CONFIG_ESI_DONGLE=m
+CONFIG_ACTISYS_DONGLE=m
+CONFIG_TEKRAM_DONGLE=m
+# CONFIG_TOIM3232_DONGLE is not set
+CONFIG_LITELINK_DONGLE=m
+CONFIG_MA600_DONGLE=m
+CONFIG_GIRBIL_DONGLE=m
+CONFIG_MCP2120_DONGLE=m
+CONFIG_OLD_BELKIN_DONGLE=m
+CONFIG_ACT200L_DONGLE=m
+CONFIG_KINGSUN_DONGLE=m
+# CONFIG_KSDAZZLE_DONGLE is not set
+# CONFIG_KS959_DONGLE is not set
+
+#
+# FIR device drivers
+#
+CONFIG_USB_IRDA=m
+CONFIG_SIGMATEL_FIR=m
+CONFIG_NSC_FIR=m
+CONFIG_WINBOND_FIR=m
+CONFIG_TOSHIBA_FIR=m
+CONFIG_SMC_IRCC_FIR=m
+CONFIG_ALI_FIR=m
+CONFIG_VLSI_FIR=m
+CONFIG_VIA_FIR=m
+CONFIG_MCS_FIR=m
+CONFIG_BT=m
+CONFIG_BT_L2CAP=m
+CONFIG_BT_SCO=m
+CONFIG_BT_RFCOMM=m
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=m
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=m
+
+#
+# Bluetooth device drivers
+#
+CONFIG_BT_HCIBTUSB=m
+CONFIG_BT_HCIBTSDIO=m
+CONFIG_BT_HCIUART=m
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_BCSP=y
+CONFIG_BT_HCIUART_LL=y
+CONFIG_BT_HCIBCM203X=m
+CONFIG_BT_HCIBPA10X=m
+CONFIG_BT_HCIBFUSB=m
+CONFIG_BT_HCIDTL1=m
+CONFIG_BT_HCIBT3C=m
+CONFIG_BT_HCIBLUECARD=m
+CONFIG_BT_HCIBTUART=m
+CONFIG_BT_HCIVHCI=m
+CONFIG_AF_RXRPC=m
+# CONFIG_AF_RXRPC_DEBUG is not set
+CONFIG_RXKAD=m
+CONFIG_PHONET=m
+CONFIG_FIB_RULES=y
+CONFIG_WIRELESS=y
+CONFIG_CFG80211=m
+CONFIG_NL80211=y
+CONFIG_WIRELESS_OLD_REGULATORY=y
+CONFIG_WIRELESS_EXT=y
+CONFIG_WIRELESS_EXT_SYSFS=y
+CONFIG_MAC80211=m
+
+#
+# Rate control algorithm selection
+#
+CONFIG_MAC80211_RC_PID=y
+# CONFIG_MAC80211_RC_MINSTREL is not set
+CONFIG_MAC80211_RC_DEFAULT_PID=y
+# CONFIG_MAC80211_RC_DEFAULT_MINSTREL is not set
+CONFIG_MAC80211_RC_DEFAULT="pid"
+# CONFIG_MAC80211_MESH is not set
+CONFIG_MAC80211_LEDS=y
+# CONFIG_MAC80211_DEBUGFS is not set
+# CONFIG_MAC80211_DEBUG_MENU is not set
+CONFIG_IEEE80211=m
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT_WEP=m
+CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_CRYPT_TKIP=m
+CONFIG_RFKILL=m
+CONFIG_RFKILL_INPUT=m
+CONFIG_RFKILL_LEDS=y
+CONFIG_NET_9P=m
+# CONFIG_NET_9P_VIRTIO is not set
+CONFIG_NET_9P_RDMA=m
+# CONFIG_NET_9P_DEBUG is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_STANDALONE is not set
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+CONFIG_CONNECTOR=m
+CONFIG_MTD=m
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_CONCAT=m
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_REDBOOT_PARTS=m
+CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
+# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
+# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
+CONFIG_MTD_AR7_PARTS=m
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=m
+CONFIG_HAVE_MTD_OTP=y
+CONFIG_MTD_BLKDEVS=m
+CONFIG_MTD_BLOCK=m
+# CONFIG_MTD_BLOCK_RO is not set
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+CONFIG_MTD_OOPS=m
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=m
+CONFIG_MTD_JEDECPROBE=m
+CONFIG_MTD_GEN_PROBE=m
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_NOSWAP=y
+# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
+# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
+# CONFIG_MTD_CFI_GEOMETRY is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_OTP is not set
+CONFIG_MTD_CFI_INTELEXT=m
+CONFIG_MTD_CFI_AMDSTD=m
+CONFIG_MTD_CFI_STAA=m
+CONFIG_MTD_CFI_UTIL=m
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+CONFIG_MTD_ABSENT=m
+
+#
+# Mapping drivers for chip access
+#
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+CONFIG_MTD_PHYSMAP=m
+CONFIG_MTD_PHYSMAP_START=0x8000000
+CONFIG_MTD_PHYSMAP_LEN=0x4000000
+CONFIG_MTD_PHYSMAP_BANKWIDTH=2
+CONFIG_MTD_SC520CDP=m
+CONFIG_MTD_NETSC520=m
+CONFIG_MTD_TS5500=m
+CONFIG_MTD_SBC_GXX=m
+CONFIG_MTD_SCx200_DOCFLASH=m
+CONFIG_MTD_AMD76XROM=m
+CONFIG_MTD_ICHXROM=m
+CONFIG_MTD_ESB2ROM=m
+CONFIG_MTD_CK804XROM=m
+CONFIG_MTD_SCB2_FLASH=m
+CONFIG_MTD_NETtel=m
+CONFIG_MTD_DILNETPC=m
+CONFIG_MTD_DILNETPC_BOOTSIZE=0x80000
+CONFIG_MTD_L440GX=m
+CONFIG_MTD_PCI=m
+CONFIG_MTD_INTEL_VR_NOR=m
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+CONFIG_MTD_PMC551=m
+CONFIG_MTD_PMC551_BUGFIX=y
+# CONFIG_MTD_PMC551_DEBUG is not set
+CONFIG_MTD_DATAFLASH=m
+# CONFIG_MTD_DATAFLASH_WRITE_VERIFY is not set
+CONFIG_MTD_DATAFLASH_OTP=y
+CONFIG_MTD_M25P80=m
+CONFIG_M25PXX_USE_FAST_READ=y
+CONFIG_MTD_SLRAM=m
+CONFIG_MTD_PHRAM=m
+CONFIG_MTD_MTDRAM=m
+CONFIG_MTDRAM_TOTAL_SIZE=4096
+CONFIG_MTDRAM_ERASE_SIZE=128
+CONFIG_MTD_BLOCK2MTD=m
+
+#
+# Disk-On-Chip Device Drivers
+#
+CONFIG_MTD_DOC2000=m
+CONFIG_MTD_DOC2001=m
+CONFIG_MTD_DOC2001PLUS=m
+CONFIG_MTD_DOCPROBE=m
+CONFIG_MTD_DOCECC=m
+CONFIG_MTD_DOCPROBE_ADVANCED=y
+CONFIG_MTD_DOCPROBE_ADDRESS=0x0000
+CONFIG_MTD_DOCPROBE_HIGH=y
+CONFIG_MTD_DOCPROBE_55AA=y
+CONFIG_MTD_NAND=m
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+# CONFIG_MTD_NAND_ECC_SMC is not set
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+CONFIG_MTD_NAND_IDS=m
+CONFIG_MTD_NAND_DISKONCHIP=m
+# CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADVANCED is not set
+CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS=0
+CONFIG_MTD_NAND_DISKONCHIP_BBTWRITE=y
+CONFIG_MTD_NAND_CAFE=m
+# CONFIG_MTD_NAND_CS553X is not set
+CONFIG_MTD_NAND_NANDSIM=m
+CONFIG_MTD_NAND_PLATFORM=m
+CONFIG_MTD_ALAUDA=m
+# CONFIG_MTD_ONENAND is not set
+
+#
+# UBI - Unsorted block images
+#
+CONFIG_MTD_UBI=m
+CONFIG_MTD_UBI_WL_THRESHOLD=4096
+CONFIG_MTD_UBI_BEB_RESERVE=1
+# CONFIG_MTD_UBI_GLUEBI is not set
+
+#
+# UBI debugging options
+#
+# CONFIG_MTD_UBI_DEBUG is not set
+CONFIG_PARPORT=m
+CONFIG_PARPORT_PC=m
+CONFIG_PARPORT_SERIAL=m
+CONFIG_PARPORT_PC_FIFO=y
+CONFIG_PARPORT_PC_SUPERIO=y
+CONFIG_PARPORT_PC_PCMCIA=m
+# CONFIG_PARPORT_GSC is not set
+# CONFIG_PARPORT_AX88796 is not set
+CONFIG_PARPORT_1284=y
+CONFIG_PARPORT_NOT_PC=y
+CONFIG_PNP=y
+CONFIG_PNP_DEBUG_MESSAGES=y
+
+#
+# Protocols
+#
+CONFIG_ISAPNP=y
+# CONFIG_PNPBIOS is not set
+CONFIG_PNPACPI=y
+CONFIG_BLK_DEV=y
+CONFIG_BLK_DEV_FD=y
+CONFIG_BLK_DEV_XD=m
+CONFIG_PARIDE=m
+
+#
+# Parallel IDE high-level drivers
+#
+CONFIG_PARIDE_PD=m
+CONFIG_PARIDE_PCD=m
+CONFIG_PARIDE_PF=m
+CONFIG_PARIDE_PT=m
+CONFIG_PARIDE_PG=m
+
+#
+# Parallel IDE protocol modules
+#
+CONFIG_PARIDE_ATEN=m
+CONFIG_PARIDE_BPCK=m
+CONFIG_PARIDE_BPCK6=m
+CONFIG_PARIDE_COMM=m
+CONFIG_PARIDE_DSTR=m
+CONFIG_PARIDE_FIT2=m
+CONFIG_PARIDE_FIT3=m
+CONFIG_PARIDE_EPAT=m
+CONFIG_PARIDE_EPATC8=y
+CONFIG_PARIDE_EPIA=m
+CONFIG_PARIDE_FRIQ=m
+CONFIG_PARIDE_FRPW=m
+CONFIG_PARIDE_KBIC=m
+CONFIG_PARIDE_KTTI=m
+CONFIG_PARIDE_ON20=m
+CONFIG_PARIDE_ON26=m
+CONFIG_BLK_CPQ_DA=m
+CONFIG_BLK_CPQ_CISS_DA=m
+CONFIG_CISS_SCSI_TAPE=y
+CONFIG_BLK_DEV_DAC960=m
+CONFIG_BLK_DEV_UMEM=m
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+CONFIG_BLK_DEV_NBD=m
+CONFIG_BLK_DEV_SX8=m
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=64000
+# CONFIG_BLK_DEV_XIP is not set
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+CONFIG_CDROM_PKTCDVD_WCACHE=y
+CONFIG_ATA_OVER_ETH=m
+CONFIG_XEN_BLKDEV_FRONTEND=m
+CONFIG_VIRTIO_BLK=m
+# CONFIG_BLK_DEV_HD is not set
+CONFIG_MISC_DEVICES=y
+CONFIG_IBM_ASM=m
+CONFIG_PHANTOM=m
+CONFIG_EEPROM_93CX6=m
+# CONFIG_SGI_IOC4 is not set
+CONFIG_TIFM_CORE=m
+CONFIG_TIFM_7XX1=m
+CONFIG_ACER_WMI=m
+CONFIG_ASUS_LAPTOP=m
+CONFIG_FUJITSU_LAPTOP=m
+# CONFIG_FUJITSU_LAPTOP_DEBUG is not set
+CONFIG_TC1100_WMI=m
+CONFIG_HP_WMI=m
+CONFIG_ICS932S401=m
+CONFIG_MSI_LAPTOP=m
+CONFIG_PANASONIC_LAPTOP=m
+CONFIG_COMPAL_LAPTOP=m
+CONFIG_SONY_LAPTOP=m
+CONFIG_SONYPI_COMPAT=y
+CONFIG_THINKPAD_ACPI=m
+# CONFIG_THINKPAD_ACPI_DEBUG is not set
+CONFIG_THINKPAD_ACPI_BAY=y
+CONFIG_THINKPAD_ACPI_VIDEO=y
+CONFIG_THINKPAD_ACPI_HOTKEY_POLL=y
+CONFIG_INTEL_MENLOW=m
+CONFIG_EEEPC_LAPTOP=m
+CONFIG_ENCLOSURE_SERVICES=m
+CONFIG_HP_ILO=m
+# CONFIG_C2PORT is not set
+CONFIG_HAVE_IDE=y
+CONFIG_IDE=m
+
+#
+# Please see Documentation/ide/ide.txt for help/info on IDE drives
+#
+CONFIG_IDE_TIMINGS=y
+CONFIG_IDE_ATAPI=y
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_IDE_GD=m
+CONFIG_IDE_GD_ATA=y
+CONFIG_IDE_GD_ATAPI=y
+CONFIG_BLK_DEV_IDECS=m
+CONFIG_BLK_DEV_DELKIN=m
+CONFIG_BLK_DEV_IDECD=m
+CONFIG_BLK_DEV_IDECD_VERBOSE_ERRORS=y
+CONFIG_BLK_DEV_IDETAPE=m
+CONFIG_BLK_DEV_IDESCSI=m
+CONFIG_BLK_DEV_IDEACPI=y
+# CONFIG_IDE_TASK_IOCTL is not set
+CONFIG_IDE_PROC_FS=y
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=m
+CONFIG_BLK_DEV_PLATFORM=m
+CONFIG_BLK_DEV_CMD640=m
+CONFIG_BLK_DEV_CMD640_ENHANCED=y
+CONFIG_BLK_DEV_IDEPNP=m
+CONFIG_BLK_DEV_IDEDMA_SFF=y
+
+#
+# PCI IDE chipsets support
+#
+CONFIG_BLK_DEV_IDEPCI=y
+CONFIG_BLK_DEV_OFFBOARD=y
+CONFIG_BLK_DEV_GENERIC=m
+CONFIG_BLK_DEV_OPTI621=m
+CONFIG_BLK_DEV_RZ1000=m
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+CONFIG_BLK_DEV_AEC62XX=m
+CONFIG_BLK_DEV_ALI15X3=m
+CONFIG_BLK_DEV_AMD74XX=m
+CONFIG_BLK_DEV_ATIIXP=m
+CONFIG_BLK_DEV_CMD64X=m
+CONFIG_BLK_DEV_TRIFLEX=m
+CONFIG_BLK_DEV_CS5520=m
+CONFIG_BLK_DEV_CS5530=m
+CONFIG_BLK_DEV_CS5535=m
+CONFIG_BLK_DEV_HPT366=m
+CONFIG_BLK_DEV_JMICRON=m
+CONFIG_BLK_DEV_SC1200=m
+CONFIG_BLK_DEV_PIIX=m
+CONFIG_BLK_DEV_IT8213=m
+CONFIG_BLK_DEV_IT821X=m
+CONFIG_BLK_DEV_NS87415=m
+CONFIG_BLK_DEV_PDC202XX_OLD=m
+CONFIG_BLK_DEV_PDC202XX_NEW=m
+CONFIG_BLK_DEV_SVWKS=m
+CONFIG_BLK_DEV_SIIMAGE=m
+CONFIG_BLK_DEV_SIS5513=m
+CONFIG_BLK_DEV_SLC90E66=m
+CONFIG_BLK_DEV_TRM290=m
+CONFIG_BLK_DEV_VIA82CXXX=m
+CONFIG_BLK_DEV_TC86C001=m
+
+#
+# Other IDE chipsets support
+#
+
+#
+# Note: most of these also require special kernel boot parameters
+#
+CONFIG_BLK_DEV_4DRIVES=m
+CONFIG_BLK_DEV_ALI14XX=m
+CONFIG_BLK_DEV_DTC2278=m
+CONFIG_BLK_DEV_HT6560B=m
+CONFIG_BLK_DEV_QD65XX=m
+CONFIG_BLK_DEV_UMC8672=m
+CONFIG_BLK_DEV_IDEDMA=y
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=m
+CONFIG_SCSI_DMA=y
+CONFIG_SCSI_TGT=m
+CONFIG_SCSI_NETLINK=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+CONFIG_CHR_DEV_ST=m
+CONFIG_CHR_DEV_OSST=m
+CONFIG_BLK_DEV_SR=m
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+CONFIG_CHR_DEV_SG=m
+CONFIG_CHR_DEV_SCH=m
+CONFIG_SCSI_ENCLOSURE=m
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+CONFIG_SCSI_SPI_ATTRS=m
+CONFIG_SCSI_FC_ATTRS=m
+# CONFIG_SCSI_FC_TGT_ATTRS is not set
+CONFIG_SCSI_ISCSI_ATTRS=m
+CONFIG_SCSI_SAS_ATTRS=m
+CONFIG_SCSI_SAS_LIBSAS=m
+# CONFIG_SCSI_SAS_ATA is not set
+CONFIG_SCSI_SAS_HOST_SMP=y
+# CONFIG_SCSI_SAS_LIBSAS_DEBUG is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
+CONFIG_ISCSI_TCP=m
+CONFIG_BLK_DEV_3W_XXXX_RAID=m
+CONFIG_SCSI_3W_9XXX=m
+CONFIG_SCSI_7000FASST=m
+CONFIG_SCSI_ACARD=m
+CONFIG_SCSI_AHA152X=m
+CONFIG_SCSI_AHA1542=m
+CONFIG_SCSI_AACRAID=m
+CONFIG_SCSI_AIC7XXX=m
+CONFIG_AIC7XXX_CMDS_PER_DEVICE=32
+CONFIG_AIC7XXX_RESET_DELAY_MS=5000
+# CONFIG_AIC7XXX_DEBUG_ENABLE is not set
+CONFIG_AIC7XXX_DEBUG_MASK=0
+CONFIG_AIC7XXX_REG_PRETTY_PRINT=y
+CONFIG_SCSI_AIC7XXX_OLD=m
+CONFIG_SCSI_AIC79XX=m
+CONFIG_AIC79XX_CMDS_PER_DEVICE=32
+CONFIG_AIC79XX_RESET_DELAY_MS=15000
+# CONFIG_AIC79XX_DEBUG_ENABLE is not set
+CONFIG_AIC79XX_DEBUG_MASK=0
+CONFIG_AIC79XX_REG_PRETTY_PRINT=y
+CONFIG_SCSI_AIC94XX=m
+# CONFIG_AIC94XX_DEBUG is not set
+CONFIG_SCSI_DPT_I2O=m
+CONFIG_SCSI_ADVANSYS=m
+CONFIG_SCSI_IN2000=m
+CONFIG_SCSI_ARCMSR=m
+# CONFIG_SCSI_ARCMSR_AER is not set
+CONFIG_MEGARAID_NEWGEN=y
+CONFIG_MEGARAID_MM=m
+CONFIG_MEGARAID_MAILBOX=m
+CONFIG_MEGARAID_LEGACY=m
+CONFIG_MEGARAID_SAS=m
+CONFIG_SCSI_HPTIOP=m
+CONFIG_SCSI_BUSLOGIC=m
+# CONFIG_SCSI_FLASHPOINT is not set
+CONFIG_SCSI_DMX3191D=m
+CONFIG_SCSI_DTC3280=m
+CONFIG_SCSI_EATA=m
+CONFIG_SCSI_EATA_TAGGED_QUEUE=y
+CONFIG_SCSI_EATA_LINKED_COMMANDS=y
+CONFIG_SCSI_EATA_MAX_TAGS=16
+CONFIG_SCSI_FUTURE_DOMAIN=m
+CONFIG_SCSI_GDTH=m
+CONFIG_SCSI_GENERIC_NCR5380=m
+CONFIG_SCSI_GENERIC_NCR5380_MMIO=m
+CONFIG_SCSI_GENERIC_NCR53C400=y
+CONFIG_SCSI_IPS=m
+CONFIG_SCSI_INITIO=m
+CONFIG_SCSI_INIA100=m
+CONFIG_SCSI_PPA=m
+CONFIG_SCSI_IMM=m
+# CONFIG_SCSI_IZIP_EPP16 is not set
+# CONFIG_SCSI_IZIP_SLOW_CTR is not set
+CONFIG_SCSI_MVSAS=m
+CONFIG_SCSI_NCR53C406A=m
+CONFIG_SCSI_STEX=m
+CONFIG_SCSI_SYM53C8XX_2=m
+CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1
+CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
+CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
+CONFIG_SCSI_SYM53C8XX_MMIO=y
+CONFIG_SCSI_IPR=m
+# CONFIG_SCSI_IPR_TRACE is not set
+# CONFIG_SCSI_IPR_DUMP is not set
+CONFIG_SCSI_PAS16=m
+CONFIG_SCSI_QLOGIC_FAS=m
+CONFIG_SCSI_QLOGIC_1280=m
+CONFIG_SCSI_QLA_FC=m
+CONFIG_SCSI_QLA_ISCSI=m
+CONFIG_SCSI_LPFC=m
+CONFIG_SCSI_SYM53C416=m
+CONFIG_SCSI_DC395x=m
+CONFIG_SCSI_DC390T=m
+CONFIG_SCSI_T128=m
+CONFIG_SCSI_U14_34F=m
+CONFIG_SCSI_U14_34F_TAGGED_QUEUE=y
+CONFIG_SCSI_U14_34F_LINKED_COMMANDS=y
+CONFIG_SCSI_U14_34F_MAX_TAGS=8
+CONFIG_SCSI_ULTRASTOR=m
+CONFIG_SCSI_NSP32=m
+CONFIG_SCSI_DEBUG=m
+CONFIG_SCSI_SRP=m
+CONFIG_SCSI_LOWLEVEL_PCMCIA=y
+CONFIG_PCMCIA_AHA152X=m
+CONFIG_PCMCIA_FDOMAIN=m
+CONFIG_PCMCIA_NINJA_SCSI=m
+CONFIG_PCMCIA_QLOGIC=m
+CONFIG_PCMCIA_SYM53C500=m
+CONFIG_SCSI_DH=m
+CONFIG_SCSI_DH_RDAC=m
+CONFIG_SCSI_DH_HP_SW=m
+CONFIG_SCSI_DH_EMC=m
+CONFIG_SCSI_DH_ALUA=m
+CONFIG_ATA=m
+# CONFIG_ATA_NONSTANDARD is not set
+CONFIG_ATA_ACPI=y
+CONFIG_SATA_PMP=y
+CONFIG_SATA_AHCI=m
+CONFIG_SATA_SIL24=m
+CONFIG_ATA_SFF=y
+CONFIG_SATA_SVW=m
+CONFIG_ATA_PIIX=m
+# CONFIG_SATA_MV is not set
+CONFIG_SATA_NV=m
+CONFIG_PDC_ADMA=m
+CONFIG_SATA_QSTOR=m
+CONFIG_SATA_PROMISE=m
+CONFIG_SATA_SX4=m
+CONFIG_SATA_SIL=m
+CONFIG_SATA_SIS=m
+CONFIG_SATA_ULI=m
+CONFIG_SATA_VIA=m
+CONFIG_SATA_VITESSE=m
+CONFIG_SATA_INIC162X=m
+CONFIG_PATA_ACPI=m
+CONFIG_PATA_ALI=m
+CONFIG_PATA_AMD=m
+CONFIG_PATA_ARTOP=m
+CONFIG_PATA_ATIIXP=m
+# CONFIG_PATA_CMD640_PCI is not set
+# CONFIG_PATA_CMD64X is not set
+CONFIG_PATA_CS5520=m
+CONFIG_PATA_CS5530=m
+CONFIG_PATA_CS5535=m
+CONFIG_PATA_CS5536=m
+# CONFIG_PATA_CYPRESS is not set
+CONFIG_PATA_EFAR=m
+CONFIG_ATA_GENERIC=m
+CONFIG_PATA_HPT366=m
+CONFIG_PATA_HPT37X=m
+CONFIG_PATA_HPT3X2N=m
+CONFIG_PATA_HPT3X3=m
+# CONFIG_PATA_HPT3X3_DMA is not set
+# CONFIG_PATA_ISAPNP is not set
+CONFIG_PATA_IT821X=m
+CONFIG_PATA_IT8213=m
+CONFIG_PATA_JMICRON=m
+# CONFIG_PATA_LEGACY is not set
+CONFIG_PATA_TRIFLEX=m
+CONFIG_PATA_MARVELL=m
+CONFIG_PATA_MPIIX=m
+CONFIG_PATA_OLDPIIX=m
+CONFIG_PATA_NETCELL=m
+CONFIG_PATA_NINJA32=m
+CONFIG_PATA_NS87410=m
+CONFIG_PATA_NS87415=m
+# CONFIG_PATA_OPTI is not set
+# CONFIG_PATA_OPTIDMA is not set
+CONFIG_PATA_PCMCIA=m
+# CONFIG_PATA_PDC_OLD is not set
+CONFIG_PATA_QDI=m
+# CONFIG_PATA_RADISYS is not set
+CONFIG_PATA_RZ1000=m
+CONFIG_PATA_SC1200=m
+CONFIG_PATA_SERVERWORKS=m
+CONFIG_PATA_PDC2027X=m
+CONFIG_PATA_SIL680=m
+CONFIG_PATA_SIS=m
+CONFIG_PATA_VIA=m
+CONFIG_PATA_WINBOND=m
+CONFIG_PATA_WINBOND_VLB=m
+CONFIG_PATA_SCH=m
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=y
+CONFIG_MD_AUTODETECT=y
+CONFIG_MD_LINEAR=m
+CONFIG_MD_RAID0=m
+CONFIG_MD_RAID1=m
+CONFIG_MD_RAID10=m
+CONFIG_MD_RAID456=m
+# CONFIG_MD_RAID5_RESHAPE is not set
+CONFIG_MD_MULTIPATH=m
+CONFIG_MD_FAULTY=m
+CONFIG_BLK_DEV_DM=m
+# CONFIG_DM_DEBUG is not set
+CONFIG_DM_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
+CONFIG_DM_MULTIPATH=m
+# CONFIG_DM_DELAY is not set
+CONFIG_DM_UEVENT=y
+CONFIG_FUSION=y
+CONFIG_FUSION_SPI=m
+CONFIG_FUSION_FC=m
+CONFIG_FUSION_SAS=m
+CONFIG_FUSION_MAX_SGE=128
+CONFIG_FUSION_CTL=m
+CONFIG_FUSION_LAN=m
+# CONFIG_FUSION_LOGGING is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# Enable only one of the two stacks, unless you know what you are doing
+#
+# CONFIG_FIREWIRE is not set
+CONFIG_IEEE1394=m
+CONFIG_IEEE1394_OHCI1394=m
+CONFIG_IEEE1394_PCILYNX=m
+CONFIG_IEEE1394_SBP2=m
+# CONFIG_IEEE1394_SBP2_PHYS_DMA is not set
+CONFIG_IEEE1394_ETH1394_ROM_ENTRY=y
+CONFIG_IEEE1394_ETH1394=m
+CONFIG_IEEE1394_RAWIO=m
+CONFIG_IEEE1394_VIDEO1394=m
+CONFIG_IEEE1394_DV1394=m
+# CONFIG_IEEE1394_VERBOSEDEBUG is not set
+CONFIG_I2O=m
+CONFIG_I2O_LCT_NOTIFY_ON_CHANGES=y
+CONFIG_I2O_EXT_ADAPTEC=y
+CONFIG_I2O_EXT_ADAPTEC_DMA64=y
+CONFIG_I2O_CONFIG=m
+CONFIG_I2O_CONFIG_OLD_IOCTL=y
+CONFIG_I2O_BUS=m
+CONFIG_I2O_BLOCK=m
+CONFIG_I2O_SCSI=m
+CONFIG_I2O_PROC=m
+CONFIG_MACINTOSH_DRIVERS=y
+CONFIG_MAC_EMUMOUSEBTN=y
+CONFIG_NETDEVICES=y
+# CONFIG_IFB is not set
+CONFIG_DUMMY=m
+CONFIG_BONDING=m
+# CONFIG_MACVLAN is not set
+CONFIG_EQUALIZER=m
+CONFIG_TUN=m
+CONFIG_VETH=m
+CONFIG_NET_SB1000=m
+CONFIG_ARCNET=m
+CONFIG_ARCNET_1201=m
+CONFIG_ARCNET_1051=m
+CONFIG_ARCNET_RAW=m
+CONFIG_ARCNET_CAP=m
+CONFIG_ARCNET_COM90xx=m
+CONFIG_ARCNET_COM90xxIO=m
+CONFIG_ARCNET_RIM_I=m
+# CONFIG_ARCNET_COM20020 is not set
+CONFIG_PHYLIB=m
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=m
+CONFIG_DAVICOM_PHY=m
+CONFIG_QSEMI_PHY=m
+CONFIG_LXT_PHY=m
+CONFIG_CICADA_PHY=m
+CONFIG_VITESSE_PHY=m
+CONFIG_SMSC_PHY=m
+CONFIG_BROADCOM_PHY=m
+CONFIG_ICPLUS_PHY=m
+CONFIG_REALTEK_PHY=m
+# CONFIG_MDIO_BITBANG is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=m
+CONFIG_HAPPYMEAL=m
+CONFIG_SUNGEM=m
+CONFIG_CASSINI=m
+CONFIG_NET_VENDOR_3COM=y
+CONFIG_EL1=m
+CONFIG_EL2=m
+CONFIG_ELPLUS=m
+CONFIG_EL16=m
+CONFIG_EL3=m
+CONFIG_3C515=m
+CONFIG_VORTEX=m
+CONFIG_TYPHOON=m
+CONFIG_LANCE=m
+CONFIG_NET_VENDOR_SMC=y
+CONFIG_WD80x3=m
+CONFIG_ULTRA=m
+CONFIG_SMC9194=m
+CONFIG_ENC28J60=m
+# CONFIG_ENC28J60_WRITEVERIFY is not set
+CONFIG_NET_VENDOR_RACAL=y
+CONFIG_NI52=m
+CONFIG_NI65=m
+CONFIG_NET_TULIP=y
+CONFIG_DE2104X=m
+CONFIG_TULIP=m
+# CONFIG_TULIP_MWI is not set
+# CONFIG_TULIP_MMIO is not set
+CONFIG_TULIP_NAPI=y
+CONFIG_TULIP_NAPI_HW_MITIGATION=y
+CONFIG_DE4X5=m
+CONFIG_WINBOND_840=m
+CONFIG_DM9102=m
+CONFIG_ULI526X=m
+CONFIG_PCMCIA_XIRCOM=m
+CONFIG_AT1700=m
+CONFIG_DEPCA=m
+CONFIG_HP100=m
+CONFIG_NET_ISA=y
+CONFIG_E2100=m
+CONFIG_EWRK3=m
+CONFIG_EEXPRESS=m
+CONFIG_EEXPRESS_PRO=m
+CONFIG_HPLAN_PLUS=m
+CONFIG_HPLAN=m
+CONFIG_LP486E=m
+CONFIG_ETH16I=m
+CONFIG_NE2000=m
+CONFIG_ZNET=m
+CONFIG_SEEQ8005=m
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+CONFIG_NET_PCI=y
+CONFIG_PCNET32=m
+CONFIG_AMD8111_ETH=m
+CONFIG_ADAPTEC_STARFIRE=m
+CONFIG_AC3200=m
+CONFIG_APRICOT=m
+CONFIG_B44=m
+CONFIG_B44_PCI_AUTOSELECT=y
+CONFIG_B44_PCICORE_AUTOSELECT=y
+CONFIG_B44_PCI=y
+CONFIG_FORCEDETH=m
+# CONFIG_FORCEDETH_NAPI is not set
+CONFIG_CS89x0=m
+CONFIG_EEPRO100=m
+CONFIG_E100=m
+CONFIG_FEALNX=m
+CONFIG_NATSEMI=m
+CONFIG_NE2K_PCI=m
+CONFIG_8139CP=m
+CONFIG_8139TOO=m
+# CONFIG_8139TOO_PIO is not set
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+CONFIG_8139TOO_8129=y
+# CONFIG_8139_OLD_RX_RESET is not set
+CONFIG_R6040=m
+CONFIG_SIS900=m
+CONFIG_EPIC100=m
+CONFIG_SUNDANCE=m
+# CONFIG_SUNDANCE_MMIO is not set
+CONFIG_TLAN=m
+CONFIG_VIA_RHINE=m
+# CONFIG_VIA_RHINE_MMIO is not set
+CONFIG_SC92031=m
+CONFIG_NET_POCKET=y
+CONFIG_ATP=m
+CONFIG_DE600=m
+CONFIG_DE620=m
+CONFIG_ATL2=m
+CONFIG_NETDEV_1000=y
+CONFIG_ACENIC=m
+# CONFIG_ACENIC_OMIT_TIGON_I is not set
+CONFIG_DL2K=m
+CONFIG_E1000=m
+CONFIG_E1000E=m
+CONFIG_IP1000=m
+CONFIG_IGB=m
+# CONFIG_IGB_LRO is not set
+CONFIG_NS83820=m
+CONFIG_HAMACHI=m
+CONFIG_YELLOWFIN=m
+CONFIG_R8169=m
+CONFIG_R8169_VLAN=y
+CONFIG_SIS190=m
+CONFIG_SKGE=m
+# CONFIG_SKGE_DEBUG is not set
+# CONFIG_SKY2 is not set
+CONFIG_VIA_VELOCITY=m
+CONFIG_TIGON3=m
+CONFIG_BNX2=m
+CONFIG_QLA3XXX=m
+CONFIG_ATL1=m
+CONFIG_ATL1E=m
+CONFIG_JME=m
+CONFIG_NETDEV_10000=y
+CONFIG_CHELSIO_T1=m
+CONFIG_CHELSIO_T1_1G=y
+CONFIG_CHELSIO_T3=m
+CONFIG_ENIC=m
+CONFIG_IXGBE=m
+CONFIG_IXGB=m
+CONFIG_S2IO=m
+CONFIG_MYRI10GE=m
+CONFIG_NETXEN_NIC=m
+CONFIG_NIU=m
+CONFIG_MLX4_EN=m
+CONFIG_MLX4_CORE=m
+CONFIG_MLX4_DEBUG=y
+CONFIG_TEHUTI=m
+CONFIG_BNX2X=m
+CONFIG_QLGE=m
+CONFIG_SFC=m
+CONFIG_TR=y
+CONFIG_IBMTR=m
+CONFIG_IBMOL=m
+CONFIG_IBMLS=m
+CONFIG_3C359=m
+CONFIG_TMS380TR=m
+CONFIG_TMSPCI=m
+CONFIG_SKISA=m
+CONFIG_PROTEON=m
+CONFIG_ABYSS=m
+CONFIG_SMCTR=m
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+CONFIG_WLAN_80211=y
+CONFIG_PCMCIA_RAYCS=m
+CONFIG_IPW2100=m
+CONFIG_IPW2100_MONITOR=y
+# CONFIG_IPW2100_DEBUG is not set
+CONFIG_IPW2200=m
+CONFIG_IPW2200_MONITOR=y
+CONFIG_IPW2200_RADIOTAP=y
+CONFIG_IPW2200_PROMISCUOUS=y
+CONFIG_IPW2200_QOS=y
+# CONFIG_IPW2200_DEBUG is not set
+CONFIG_LIBERTAS=m
+CONFIG_LIBERTAS_USB=m
+CONFIG_LIBERTAS_CS=m
+CONFIG_LIBERTAS_SDIO=m
+# CONFIG_LIBERTAS_DEBUG is not set
+CONFIG_LIBERTAS_THINFIRM=m
+CONFIG_LIBERTAS_THINFIRM_USB=m
+CONFIG_AIRO=m
+CONFIG_HERMES=m
+CONFIG_PLX_HERMES=m
+CONFIG_TMD_HERMES=m
+CONFIG_NORTEL_HERMES=m
+CONFIG_PCI_HERMES=m
+CONFIG_PCMCIA_HERMES=m
+CONFIG_PCMCIA_SPECTRUM=m
+CONFIG_ATMEL=m
+CONFIG_PCI_ATMEL=m
+CONFIG_PCMCIA_ATMEL=m
+CONFIG_AIRO_CS=m
+CONFIG_PCMCIA_WL3501=m
+CONFIG_PRISM54=m
+CONFIG_USB_ZD1201=m
+CONFIG_USB_NET_RNDIS_WLAN=m
+CONFIG_RTL8180=m
+CONFIG_RTL8187=m
+CONFIG_ADM8211=m
+# CONFIG_MAC80211_HWSIM is not set
+CONFIG_P54_COMMON=m
+CONFIG_P54_USB=m
+CONFIG_P54_PCI=m
+CONFIG_ATH5K=m
+# CONFIG_ATH5K_DEBUG is not set
+CONFIG_ATH9K=m
+CONFIG_IWLWIFI=m
+CONFIG_IWLCORE=m
+CONFIG_IWLWIFI_LEDS=y
+CONFIG_IWLWIFI_RFKILL=y
+# CONFIG_IWLWIFI_DEBUG is not set
+CONFIG_IWLAGN=m
+# CONFIG_IWLAGN_SPECTRUM_MEASUREMENT is not set
+CONFIG_IWLAGN_LEDS=y
+CONFIG_IWL4965=y
+CONFIG_IWL5000=y
+CONFIG_IWL3945=m
+CONFIG_IWL3945_RFKILL=y
+# CONFIG_IWL3945_SPECTRUM_MEASUREMENT is not set
+CONFIG_IWL3945_LEDS=y
+# CONFIG_IWL3945_DEBUG is not set
+CONFIG_HOSTAP=m
+CONFIG_HOSTAP_FIRMWARE=y
+CONFIG_HOSTAP_FIRMWARE_NVRAM=y
+CONFIG_HOSTAP_PLX=m
+CONFIG_HOSTAP_PCI=m
+CONFIG_HOSTAP_CS=m
+CONFIG_B43=m
+CONFIG_B43_PCI_AUTOSELECT=y
+CONFIG_B43_PCICORE_AUTOSELECT=y
+CONFIG_B43_PCMCIA=y
+CONFIG_B43_PIO=y
+CONFIG_B43_LEDS=y
+CONFIG_B43_RFKILL=y
+# CONFIG_B43_DEBUG is not set
+CONFIG_B43LEGACY=m
+CONFIG_B43LEGACY_PCI_AUTOSELECT=y
+CONFIG_B43LEGACY_PCICORE_AUTOSELECT=y
+CONFIG_B43LEGACY_LEDS=y
+CONFIG_B43LEGACY_RFKILL=y
+CONFIG_B43LEGACY_DEBUG=y
+CONFIG_B43LEGACY_DMA=y
+CONFIG_B43LEGACY_PIO=y
+CONFIG_B43LEGACY_DMA_AND_PIO_MODE=y
+# CONFIG_B43LEGACY_DMA_MODE is not set
+# CONFIG_B43LEGACY_PIO_MODE is not set
+CONFIG_ZD1211RW=m
+# CONFIG_ZD1211RW_DEBUG is not set
+CONFIG_RT2X00=m
+CONFIG_RT2400PCI=m
+CONFIG_RT2500PCI=m
+CONFIG_RT61PCI=m
+CONFIG_RT2500USB=m
+CONFIG_RT73USB=m
+CONFIG_RT2X00_LIB_PCI=m
+CONFIG_RT2X00_LIB_USB=m
+CONFIG_RT2X00_LIB=m
+CONFIG_RT2X00_LIB_FIRMWARE=y
+CONFIG_RT2X00_LIB_CRYPTO=y
+CONFIG_RT2X00_LIB_RFKILL=y
+CONFIG_RT2X00_LIB_LEDS=y
+# CONFIG_RT2X00_DEBUG is not set
+
+#
+# USB Network Adapters
+#
+CONFIG_USB_CATC=m
+CONFIG_USB_KAWETH=m
+CONFIG_USB_PEGASUS=m
+CONFIG_USB_RTL8150=m
+CONFIG_USB_USBNET=m
+CONFIG_USB_NET_AX8817X=m
+CONFIG_USB_NET_CDCETHER=m
+CONFIG_USB_NET_DM9601=m
+CONFIG_USB_NET_SMSC95XX=m
+CONFIG_USB_NET_GL620A=m
+CONFIG_USB_NET_NET1080=m
+CONFIG_USB_NET_PLUSB=m
+CONFIG_USB_NET_MCS7830=m
+CONFIG_USB_NET_RNDIS_HOST=m
+CONFIG_USB_NET_CDC_SUBSET=m
+CONFIG_USB_ALI_M5632=y
+CONFIG_USB_AN2720=y
+CONFIG_USB_BELKIN=y
+CONFIG_USB_ARMLINUX=y
+# CONFIG_USB_EPSON2888 is not set
+# CONFIG_USB_KC2190 is not set
+CONFIG_USB_NET_ZAURUS=m
+CONFIG_USB_HSO=m
+CONFIG_NET_PCMCIA=y
+CONFIG_PCMCIA_3C589=m
+CONFIG_PCMCIA_3C574=m
+CONFIG_PCMCIA_FMVJ18X=m
+CONFIG_PCMCIA_PCNET=m
+CONFIG_PCMCIA_NMCLAN=m
+CONFIG_PCMCIA_SMC91C92=m
+CONFIG_PCMCIA_XIRC2PS=m
+CONFIG_PCMCIA_AXNET=m
+CONFIG_PCMCIA_IBMTR=m
+CONFIG_WAN=y
+CONFIG_HOSTESS_SV11=m
+# CONFIG_COSA is not set
+CONFIG_LANMEDIA=m
+CONFIG_SEALEVEL_4021=m
+CONFIG_HDLC=m
+CONFIG_HDLC_RAW=m
+CONFIG_HDLC_RAW_ETH=m
+CONFIG_HDLC_CISCO=m
+CONFIG_HDLC_FR=m
+CONFIG_HDLC_PPP=m
+CONFIG_HDLC_X25=m
+CONFIG_PCI200SYN=m
+CONFIG_WANXL=m
+# CONFIG_PC300TOO is not set
+CONFIG_N2=m
+CONFIG_C101=m
+CONFIG_FARSYNC=m
+# CONFIG_DSCC4 is not set
+CONFIG_DLCI=m
+CONFIG_DLCI_MAX=8
+CONFIG_SDLA=m
+# CONFIG_WAN_ROUTER_DRIVERS is not set
+CONFIG_LAPBETHER=m
+CONFIG_X25_ASY=m
+# CONFIG_SBNI is not set
+CONFIG_ATM_DRIVERS=y
+# CONFIG_ATM_DUMMY is not set
+CONFIG_ATM_TCP=m
+CONFIG_ATM_LANAI=m
+CONFIG_ATM_ENI=m
+# CONFIG_ATM_ENI_DEBUG is not set
+# CONFIG_ATM_ENI_TUNE_BURST is not set
+CONFIG_ATM_FIRESTREAM=m
+CONFIG_ATM_ZATM=m
+# CONFIG_ATM_ZATM_DEBUG is not set
+CONFIG_ATM_NICSTAR=m
+CONFIG_ATM_NICSTAR_USE_SUNI=y
+CONFIG_ATM_NICSTAR_USE_IDT77105=y
+CONFIG_ATM_IDT77252=m
+# CONFIG_ATM_IDT77252_DEBUG is not set
+CONFIG_ATM_IDT77252_RCV_ALL=y
+CONFIG_ATM_IDT77252_USE_SUNI=y
+# CONFIG_ATM_AMBASSADOR is not set
+CONFIG_ATM_HORIZON=m
+# CONFIG_ATM_HORIZON_DEBUG is not set
+CONFIG_ATM_IA=m
+# CONFIG_ATM_IA_DEBUG is not set
+CONFIG_ATM_FORE200E=m
+CONFIG_ATM_FORE200E_USE_TASKLET=y
+CONFIG_ATM_FORE200E_TX_RETRY=16
+CONFIG_ATM_FORE200E_DEBUG=0
+CONFIG_ATM_HE=m
+CONFIG_ATM_HE_USE_SUNI=y
+CONFIG_XEN_NETDEV_FRONTEND=m
+CONFIG_FDDI=y
+CONFIG_DEFXX=m
+# CONFIG_DEFXX_MMIO is not set
+CONFIG_SKFP=m
+CONFIG_HIPPI=y
+CONFIG_ROADRUNNER=m
+CONFIG_ROADRUNNER_LARGE_RINGS=y
+CONFIG_PLIP=m
+CONFIG_PPP=m
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_MPPE=m
+CONFIG_PPPOE=m
+CONFIG_PPPOATM=m
+# CONFIG_PPPOL2TP is not set
+CONFIG_SLIP=m
+CONFIG_SLIP_COMPRESSED=y
+CONFIG_SLHC=m
+CONFIG_SLIP_SMART=y
+CONFIG_SLIP_MODE_SLIP6=y
+CONFIG_NET_FC=y
+CONFIG_NETCONSOLE=m
+# CONFIG_NETCONSOLE_DYNAMIC is not set
+CONFIG_NETPOLL=y
+CONFIG_NETPOLL_TRAP=y
+CONFIG_NET_POLL_CONTROLLER=y
+CONFIG_VIRTIO_NET=m
+# CONFIG_ISDN is not set
+CONFIG_PHONE=m
+CONFIG_PHONE_IXJ=m
+CONFIG_PHONE_IXJ_PCMCIA=m
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+CONFIG_INPUT_FF_MEMLESS=m
+CONFIG_INPUT_POLLDEV=m
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+CONFIG_INPUT_JOYDEV=m
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+CONFIG_XEN_KBDDEV_FRONTEND=m
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+CONFIG_KEYBOARD_SUNKBD=m
+# CONFIG_KEYBOARD_LKKBD is not set
+CONFIG_KEYBOARD_XTKBD=m
+CONFIG_KEYBOARD_NEWTON=m
+CONFIG_KEYBOARD_STOWAWAY=m
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_PS2_ALPS=y
+CONFIG_MOUSE_PS2_LOGIPS2PP=y
+CONFIG_MOUSE_PS2_SYNAPTICS=y
+CONFIG_MOUSE_PS2_LIFEBOOK=y
+CONFIG_MOUSE_PS2_TRACKPOINT=y
+CONFIG_MOUSE_PS2_ELANTECH=y
+# CONFIG_MOUSE_PS2_TOUCHKIT is not set
+CONFIG_MOUSE_SERIAL=m
+CONFIG_MOUSE_APPLETOUCH=m
+CONFIG_MOUSE_BCM5974=m
+CONFIG_MOUSE_INPORT=m
+CONFIG_MOUSE_ATIXL=y
+CONFIG_MOUSE_LOGIBM=m
+CONFIG_MOUSE_PC110PAD=m
+# CONFIG_MOUSE_VSXXXAA is not set
+CONFIG_INPUT_JOYSTICK=y
+CONFIG_JOYSTICK_ANALOG=m
+CONFIG_JOYSTICK_A3D=m
+CONFIG_JOYSTICK_ADI=m
+CONFIG_JOYSTICK_COBRA=m
+CONFIG_JOYSTICK_GF2K=m
+CONFIG_JOYSTICK_GRIP=m
+CONFIG_JOYSTICK_GRIP_MP=m
+CONFIG_JOYSTICK_GUILLEMOT=m
+CONFIG_JOYSTICK_INTERACT=m
+CONFIG_JOYSTICK_SIDEWINDER=m
+CONFIG_JOYSTICK_TMDC=m
+CONFIG_JOYSTICK_IFORCE=m
+CONFIG_JOYSTICK_IFORCE_USB=y
+CONFIG_JOYSTICK_IFORCE_232=y
+CONFIG_JOYSTICK_WARRIOR=m
+CONFIG_JOYSTICK_MAGELLAN=m
+CONFIG_JOYSTICK_SPACEORB=m
+CONFIG_JOYSTICK_SPACEBALL=m
+CONFIG_JOYSTICK_STINGER=m
+CONFIG_JOYSTICK_TWIDJOY=m
+# CONFIG_JOYSTICK_ZHENHUA is not set
+CONFIG_JOYSTICK_DB9=m
+CONFIG_JOYSTICK_GAMECON=m
+CONFIG_JOYSTICK_TURBOGRAFX=m
+CONFIG_JOYSTICK_JOYDUMP=m
+CONFIG_JOYSTICK_XPAD=m
+CONFIG_JOYSTICK_XPAD_FF=y
+CONFIG_JOYSTICK_XPAD_LEDS=y
+CONFIG_INPUT_TABLET=y
+CONFIG_TABLET_USB_ACECAD=m
+CONFIG_TABLET_USB_AIPTEK=m
+CONFIG_TABLET_USB_GTCO=m
+CONFIG_TABLET_USB_KBTAB=m
+CONFIG_TABLET_USB_WACOM=m
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_ADS7846=m
+CONFIG_TOUCHSCREEN_FUJITSU=m
+CONFIG_TOUCHSCREEN_GUNZE=m
+CONFIG_TOUCHSCREEN_ELO=m
+CONFIG_TOUCHSCREEN_MTOUCH=m
+CONFIG_TOUCHSCREEN_INEXIO=m
+CONFIG_TOUCHSCREEN_MK712=m
+CONFIG_TOUCHSCREEN_HTCPEN=m
+CONFIG_TOUCHSCREEN_PENMOUNT=m
+CONFIG_TOUCHSCREEN_TOUCHRIGHT=m
+CONFIG_TOUCHSCREEN_TOUCHWIN=m
+CONFIG_TOUCHSCREEN_WM97XX=m
+CONFIG_TOUCHSCREEN_WM9705=y
+CONFIG_TOUCHSCREEN_WM9712=y
+CONFIG_TOUCHSCREEN_WM9713=y
+CONFIG_TOUCHSCREEN_USB_COMPOSITE=m
+CONFIG_TOUCHSCREEN_USB_EGALAX=y
+CONFIG_TOUCHSCREEN_USB_PANJIT=y
+CONFIG_TOUCHSCREEN_USB_3M=y
+CONFIG_TOUCHSCREEN_USB_ITM=y
+CONFIG_TOUCHSCREEN_USB_ETURBO=y
+CONFIG_TOUCHSCREEN_USB_GUNZE=y
+CONFIG_TOUCHSCREEN_USB_DMC_TSC10=y
+CONFIG_TOUCHSCREEN_USB_IRTOUCH=y
+CONFIG_TOUCHSCREEN_USB_IDEALTEK=y
+CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH=y
+CONFIG_TOUCHSCREEN_USB_GOTOP=y
+CONFIG_TOUCHSCREEN_TOUCHIT213=m
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_PCSPKR=y
+CONFIG_INPUT_APANEL=m
+CONFIG_INPUT_WISTRON_BTNS=m
+CONFIG_INPUT_ATLAS_BTNS=m
+CONFIG_INPUT_ATI_REMOTE=m
+CONFIG_INPUT_ATI_REMOTE2=m
+CONFIG_INPUT_KEYSPAN_REMOTE=m
+CONFIG_INPUT_POWERMATE=m
+CONFIG_INPUT_YEALINK=m
+CONFIG_INPUT_CM109=m
+CONFIG_INPUT_UINPUT=m
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=m
+CONFIG_SERIO_CT82C710=m
+CONFIG_SERIO_PARKBD=m
+CONFIG_SERIO_PCIPS2=m
+CONFIG_SERIO_LIBPS2=y
+CONFIG_SERIO_RAW=m
+CONFIG_GAMEPORT=m
+CONFIG_GAMEPORT_NS558=m
+CONFIG_GAMEPORT_L4=m
+CONFIG_GAMEPORT_EMU10K1=m
+CONFIG_GAMEPORT_FM801=m
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_DEVKMEM=y
+CONFIG_SERIAL_NONSTANDARD=y
+# CONFIG_COMPUTONE is not set
+CONFIG_ROCKETPORT=m
+CONFIG_CYCLADES=m
+# CONFIG_CYZ_INTR is not set
+CONFIG_DIGIEPCA=m
+# CONFIG_ESPSERIAL is not set
+# CONFIG_MOXA_INTELLIO is not set
+CONFIG_MOXA_SMARTIO=m
+# CONFIG_ISI is not set
+CONFIG_SYNCLINK=m
+CONFIG_SYNCLINKMP=m
+CONFIG_SYNCLINK_GT=m
+CONFIG_N_HDLC=m
+CONFIG_RISCOM8=m
+# CONFIG_SPECIALIX is not set
+CONFIG_SX=m
+CONFIG_RIO=m
+CONFIG_RIO_OLDPCI=y
+CONFIG_STALDRV=y
+CONFIG_STALLION=m
+CONFIG_ISTALLION=m
+CONFIG_NOZOMI=m
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_FIX_EARLYCON_MEM=y
+CONFIG_SERIAL_8250_PCI=y
+CONFIG_SERIAL_8250_PNP=y
+CONFIG_SERIAL_8250_CS=m
+CONFIG_SERIAL_8250_NR_UARTS=8
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_FOURPORT=m
+CONFIG_SERIAL_8250_ACCENT=m
+CONFIG_SERIAL_8250_BOCA=m
+CONFIG_SERIAL_8250_EXAR_ST16C554=m
+CONFIG_SERIAL_8250_HUB6=m
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+CONFIG_SERIAL_8250_RSA=y
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_JSM=m
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+CONFIG_PRINTER=m
+# CONFIG_LP_CONSOLE is not set
+CONFIG_PPDEV=m
+CONFIG_HVC_DRIVER=y
+CONFIG_HVC_IRQ=y
+CONFIG_HVC_XEN=y
+CONFIG_VIRTIO_CONSOLE=m
+CONFIG_IPMI_HANDLER=m
+CONFIG_IPMI_PANIC_EVENT=y
+CONFIG_IPMI_PANIC_STRING=y
+CONFIG_IPMI_DEVICE_INTERFACE=m
+CONFIG_IPMI_SI=m
+CONFIG_IPMI_WATCHDOG=m
+CONFIG_IPMI_POWEROFF=m
+CONFIG_HW_RANDOM=y
+CONFIG_HW_RANDOM_INTEL=m
+CONFIG_HW_RANDOM_AMD=m
+CONFIG_HW_RANDOM_GEODE=m
+CONFIG_HW_RANDOM_VIA=m
+CONFIG_HW_RANDOM_VIRTIO=m
+CONFIG_NVRAM=m
+CONFIG_DTLK=m
+CONFIG_R3964=m
+CONFIG_APPLICOM=m
+CONFIG_SONYPI=m
+
+#
+# PCMCIA character devices
+#
+CONFIG_SYNCLINK_CS=m
+CONFIG_CARDMAN_4000=m
+CONFIG_CARDMAN_4040=m
+CONFIG_IPWIRELESS=m
+CONFIG_MWAVE=m
+CONFIG_SCx200_GPIO=m
+CONFIG_PC8736x_GPIO=m
+CONFIG_NSC_GPIO=m
+CONFIG_CS5535_GPIO=m
+CONFIG_RAW_DRIVER=m
+CONFIG_MAX_RAW_DEVS=4096
+CONFIG_HPET=y
+CONFIG_HPET_MMAP=y
+CONFIG_HANGCHECK_TIMER=m
+CONFIG_TCG_TPM=m
+CONFIG_TCG_TIS=m
+CONFIG_TCG_NSC=m
+CONFIG_TCG_ATMEL=m
+CONFIG_TCG_INFINEON=m
+CONFIG_TELCLOCK=m
+CONFIG_DEVPORT=y
+CONFIG_I2C=m
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=m
+CONFIG_I2C_HELPER_AUTO=y
+CONFIG_I2C_ALGOBIT=m
+CONFIG_I2C_ALGOPCA=m
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# PC SMBus host controller drivers
+#
+CONFIG_I2C_ALI1535=m
+CONFIG_I2C_ALI1563=m
+CONFIG_I2C_ALI15X3=m
+CONFIG_I2C_AMD756=m
+CONFIG_I2C_AMD756_S4882=m
+CONFIG_I2C_AMD8111=m
+CONFIG_I2C_I801=m
+CONFIG_I2C_ISCH=m
+CONFIG_I2C_PIIX4=m
+CONFIG_I2C_NFORCE2=m
+CONFIG_I2C_NFORCE2_S4985=m
+CONFIG_I2C_SIS5595=m
+CONFIG_I2C_SIS630=m
+CONFIG_I2C_SIS96X=m
+CONFIG_I2C_VIA=m
+CONFIG_I2C_VIAPRO=m
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+CONFIG_I2C_OCORES=m
+CONFIG_I2C_SIMTEC=m
+
+#
+# External I2C/SMBus adapter drivers
+#
+CONFIG_I2C_PARPORT=m
+CONFIG_I2C_PARPORT_LIGHT=m
+CONFIG_I2C_TAOS_EVM=m
+CONFIG_I2C_TINY_USB=m
+
+#
+# Graphics adapter I2C/DDC channel drivers
+#
+CONFIG_I2C_VOODOO3=m
+
+#
+# Other I2C/SMBus bus drivers
+#
+CONFIG_I2C_PCA_ISA=m
+CONFIG_I2C_PCA_PLATFORM=m
+CONFIG_I2C_STUB=m
+CONFIG_SCx200_I2C=m
+CONFIG_SCx200_I2C_SCL=12
+CONFIG_SCx200_I2C_SDA=13
+CONFIG_SCx200_ACB=m
+
+#
+# Miscellaneous I2C Chip support
+#
+CONFIG_DS1682=m
+CONFIG_AT24=m
+CONFIG_SENSORS_EEPROM=m
+CONFIG_SENSORS_PCF8574=m
+CONFIG_PCF8575=m
+# CONFIG_SENSORS_PCA9539 is not set
+CONFIG_SENSORS_PCF8591=m
+CONFIG_SENSORS_MAX6875=m
+CONFIG_SENSORS_TSL2550=m
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+CONFIG_SPI=y
+# CONFIG_SPI_DEBUG is not set
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+CONFIG_SPI_BITBANG=m
+# CONFIG_SPI_BUTTERFLY is not set
+CONFIG_SPI_LM70_LLP=m
+
+#
+# SPI Protocol Masters
+#
+CONFIG_SPI_AT25=m
+CONFIG_SPI_SPIDEV=m
+CONFIG_SPI_TLE62X0=m
+CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
+# CONFIG_GPIOLIB is not set
+CONFIG_W1=m
+CONFIG_W1_CON=y
+
+#
+# 1-wire Bus Masters
+#
+CONFIG_W1_MASTER_MATROX=m
+CONFIG_W1_MASTER_DS2490=m
+CONFIG_W1_MASTER_DS2482=m
+
+#
+# 1-wire Slaves
+#
+CONFIG_W1_SLAVE_THERM=m
+CONFIG_W1_SLAVE_SMEM=m
+CONFIG_W1_SLAVE_DS2433=m
+# CONFIG_W1_SLAVE_DS2433_CRC is not set
+CONFIG_W1_SLAVE_DS2760=m
+CONFIG_W1_SLAVE_BQ27000=m
+CONFIG_POWER_SUPPLY=y
+# CONFIG_POWER_SUPPLY_DEBUG is not set
+# CONFIG_PDA_POWER is not set
+# CONFIG_BATTERY_DS2760 is not set
+CONFIG_BATTERY_BQ27x00=m
+CONFIG_HWMON=m
+CONFIG_HWMON_VID=m
+CONFIG_SENSORS_ABITUGURU=m
+CONFIG_SENSORS_ABITUGURU3=m
+CONFIG_SENSORS_AD7414=m
+CONFIG_SENSORS_AD7418=m
+CONFIG_SENSORS_ADCXX=m
+CONFIG_SENSORS_ADM1021=m
+CONFIG_SENSORS_ADM1025=m
+CONFIG_SENSORS_ADM1026=m
+CONFIG_SENSORS_ADM1029=m
+CONFIG_SENSORS_ADM1031=m
+CONFIG_SENSORS_ADM9240=m
+CONFIG_SENSORS_ADT7462=m
+CONFIG_SENSORS_ADT7470=m
+CONFIG_SENSORS_ADT7473=m
+CONFIG_SENSORS_K8TEMP=m
+CONFIG_SENSORS_ASB100=m
+CONFIG_SENSORS_ATXP1=m
+CONFIG_SENSORS_DS1621=m
+CONFIG_SENSORS_I5K_AMB=m
+CONFIG_SENSORS_F71805F=m
+CONFIG_SENSORS_F71882FG=m
+CONFIG_SENSORS_F75375S=m
+CONFIG_SENSORS_FSCHER=m
+CONFIG_SENSORS_FSCPOS=m
+CONFIG_SENSORS_FSCHMD=m
+CONFIG_SENSORS_GL518SM=m
+CONFIG_SENSORS_GL520SM=m
+CONFIG_SENSORS_CORETEMP=m
+CONFIG_SENSORS_IBMAEM=m
+CONFIG_SENSORS_IBMPEX=m
+CONFIG_SENSORS_IT87=m
+CONFIG_SENSORS_LM63=m
+CONFIG_SENSORS_LM70=m
+CONFIG_SENSORS_LM75=m
+CONFIG_SENSORS_LM77=m
+CONFIG_SENSORS_LM78=m
+CONFIG_SENSORS_LM80=m
+CONFIG_SENSORS_LM83=m
+CONFIG_SENSORS_LM85=m
+CONFIG_SENSORS_LM87=m
+CONFIG_SENSORS_LM90=m
+CONFIG_SENSORS_LM92=m
+CONFIG_SENSORS_LM93=m
+CONFIG_SENSORS_MAX1111=m
+CONFIG_SENSORS_MAX1619=m
+CONFIG_SENSORS_MAX6650=m
+CONFIG_SENSORS_PC87360=m
+CONFIG_SENSORS_PC87427=m
+CONFIG_SENSORS_SIS5595=m
+CONFIG_SENSORS_DME1737=m
+CONFIG_SENSORS_SMSC47M1=m
+CONFIG_SENSORS_SMSC47M192=m
+CONFIG_SENSORS_SMSC47B397=m
+CONFIG_SENSORS_ADS7828=m
+CONFIG_SENSORS_THMC50=m
+CONFIG_SENSORS_VIA686A=m
+CONFIG_SENSORS_VT1211=m
+CONFIG_SENSORS_VT8231=m
+CONFIG_SENSORS_W83781D=m
+CONFIG_SENSORS_W83791D=m
+CONFIG_SENSORS_W83792D=m
+CONFIG_SENSORS_W83793=m
+CONFIG_SENSORS_W83L785TS=m
+CONFIG_SENSORS_W83L786NG=m
+CONFIG_SENSORS_W83627HF=m
+CONFIG_SENSORS_W83627EHF=m
+CONFIG_SENSORS_HDAPS=m
+CONFIG_SENSORS_LIS3LV02D=m
+CONFIG_SENSORS_APPLESMC=m
+# CONFIG_HWMON_DEBUG_CHIP is not set
+CONFIG_THERMAL=y
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+CONFIG_SOFT_WATCHDOG=m
+CONFIG_ACQUIRE_WDT=m
+CONFIG_ADVANTECH_WDT=m
+CONFIG_ALIM1535_WDT=m
+CONFIG_ALIM7101_WDT=m
+CONFIG_SC520_WDT=m
+CONFIG_EUROTECH_WDT=m
+CONFIG_IB700_WDT=m
+CONFIG_IBMASR=m
+CONFIG_WAFER_WDT=m
+CONFIG_I6300ESB_WDT=m
+CONFIG_ITCO_WDT=m
+CONFIG_ITCO_VENDOR_SUPPORT=y
+CONFIG_IT8712F_WDT=m
+CONFIG_IT87_WDT=m
+CONFIG_HP_WATCHDOG=m
+CONFIG_SC1200_WDT=m
+CONFIG_SCx200_WDT=m
+CONFIG_PC87413_WDT=m
+CONFIG_60XX_WDT=m
+CONFIG_SBC8360_WDT=m
+CONFIG_SBC7240_WDT=m
+CONFIG_CPU5_WDT=m
+CONFIG_SMSC37B787_WDT=m
+CONFIG_W83627HF_WDT=m
+CONFIG_W83697HF_WDT=m
+CONFIG_W83697UG_WDT=m
+CONFIG_W83877F_WDT=m
+CONFIG_W83977F_WDT=m
+CONFIG_MACHZ_WDT=m
+CONFIG_SBC_EPX_C3_WATCHDOG=m
+
+#
+# ISA-based Watchdog Cards
+#
+CONFIG_PCWATCHDOG=m
+CONFIG_MIXCOMWD=m
+CONFIG_WDT=m
+CONFIG_WDT_501=y
+
+#
+# PCI-based Watchdog Cards
+#
+CONFIG_PCIPCWATCHDOG=m
+CONFIG_WDTPCI=m
+CONFIG_WDT_501_PCI=y
+
+#
+# USB-based Watchdog Cards
+#
+CONFIG_USBPCWATCHDOG=m
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+CONFIG_SSB=m
+CONFIG_SSB_SPROM=y
+CONFIG_SSB_BLOCKIO=y
+CONFIG_SSB_PCIHOST_POSSIBLE=y
+CONFIG_SSB_PCIHOST=y
+CONFIG_SSB_B43_PCI_BRIDGE=y
+CONFIG_SSB_PCMCIAHOST_POSSIBLE=y
+CONFIG_SSB_PCMCIAHOST=y
+# CONFIG_SSB_DEBUG is not set
+CONFIG_SSB_DRIVER_PCICORE_POSSIBLE=y
+CONFIG_SSB_DRIVER_PCICORE=y
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+CONFIG_MFD_SM501=m
+CONFIG_HTC_PASIC3=m
+# CONFIG_MFD_TMIO is not set
+CONFIG_MFD_WM8400=m
+CONFIG_MFD_WM8350=m
+CONFIG_MFD_WM8350_I2C=m
+CONFIG_REGULATOR=y
+# CONFIG_REGULATOR_DEBUG is not set
+# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
+# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
+CONFIG_REGULATOR_BQ24022=m
+CONFIG_REGULATOR_WM8350=m
+CONFIG_REGULATOR_WM8400=m
+
+#
+# Multimedia devices
+#
+
+#
+# Multimedia core support
+#
+CONFIG_VIDEO_DEV=m
+CONFIG_VIDEO_V4L2_COMMON=m
+CONFIG_VIDEO_ALLOW_V4L1=y
+CONFIG_VIDEO_V4L1_COMPAT=y
+CONFIG_DVB_CORE=m
+CONFIG_VIDEO_MEDIA=m
+
+#
+# Multimedia drivers
+#
+CONFIG_VIDEO_SAA7146=m
+CONFIG_VIDEO_SAA7146_VV=m
+CONFIG_MEDIA_ATTACH=y
+CONFIG_MEDIA_TUNER=m
+# CONFIG_MEDIA_TUNER_CUSTOMIZE is not set
+CONFIG_MEDIA_TUNER_SIMPLE=m
+CONFIG_MEDIA_TUNER_TDA8290=m
+CONFIG_MEDIA_TUNER_TDA827X=m
+CONFIG_MEDIA_TUNER_TDA18271=m
+CONFIG_MEDIA_TUNER_TDA9887=m
+CONFIG_MEDIA_TUNER_TEA5761=m
+CONFIG_MEDIA_TUNER_TEA5767=m
+CONFIG_MEDIA_TUNER_MT20XX=m
+CONFIG_MEDIA_TUNER_MT2060=m
+CONFIG_MEDIA_TUNER_MT2266=m
+CONFIG_MEDIA_TUNER_MT2131=m
+CONFIG_MEDIA_TUNER_QT1010=m
+CONFIG_MEDIA_TUNER_XC2028=m
+CONFIG_MEDIA_TUNER_XC5000=m
+CONFIG_MEDIA_TUNER_MXL5005S=m
+CONFIG_MEDIA_TUNER_MXL5007T=m
+CONFIG_VIDEO_V4L2=m
+CONFIG_VIDEO_V4L1=m
+CONFIG_VIDEOBUF_GEN=m
+CONFIG_VIDEOBUF_DMA_SG=m
+CONFIG_VIDEOBUF_VMALLOC=m
+CONFIG_VIDEOBUF_DMA_CONTIG=m
+CONFIG_VIDEOBUF_DVB=m
+CONFIG_VIDEO_BTCX=m
+CONFIG_VIDEO_IR=m
+CONFIG_VIDEO_TVEEPROM=m
+CONFIG_VIDEO_TUNER=m
+CONFIG_VIDEO_CAPTURE_DRIVERS=y
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set
+CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
+CONFIG_VIDEO_IR_I2C=m
+CONFIG_VIDEO_TVAUDIO=m
+CONFIG_VIDEO_TDA7432=m
+CONFIG_VIDEO_TDA9840=m
+CONFIG_VIDEO_TDA9875=m
+CONFIG_VIDEO_TEA6415C=m
+CONFIG_VIDEO_TEA6420=m
+CONFIG_VIDEO_MSP3400=m
+CONFIG_VIDEO_CS5345=m
+CONFIG_VIDEO_CS53L32A=m
+CONFIG_VIDEO_M52790=m
+CONFIG_VIDEO_WM8775=m
+CONFIG_VIDEO_WM8739=m
+CONFIG_VIDEO_VP27SMPX=m
+CONFIG_VIDEO_BT819=m
+CONFIG_VIDEO_BT856=m
+CONFIG_VIDEO_OV7670=m
+CONFIG_VIDEO_SAA7110=m
+CONFIG_VIDEO_SAA7111=m
+CONFIG_VIDEO_SAA7114=m
+CONFIG_VIDEO_SAA711X=m
+CONFIG_VIDEO_SAA717X=m
+CONFIG_VIDEO_TVP5150=m
+CONFIG_VIDEO_VPX3220=m
+CONFIG_VIDEO_CX25840=m
+CONFIG_VIDEO_CX2341X=m
+CONFIG_VIDEO_SAA7127=m
+CONFIG_VIDEO_SAA7185=m
+CONFIG_VIDEO_ADV7170=m
+CONFIG_VIDEO_ADV7175=m
+CONFIG_VIDEO_UPD64031A=m
+CONFIG_VIDEO_UPD64083=m
+CONFIG_VIDEO_VIVI=m
+CONFIG_VIDEO_BT848=m
+CONFIG_VIDEO_BT848_DVB=y
+CONFIG_VIDEO_SAA6588=m
+CONFIG_VIDEO_PMS=m
+CONFIG_VIDEO_BWQCAM=m
+CONFIG_VIDEO_CQCAM=m
+CONFIG_VIDEO_W9966=m
+CONFIG_VIDEO_CPIA=m
+CONFIG_VIDEO_CPIA_PP=m
+CONFIG_VIDEO_CPIA_USB=m
+# CONFIG_VIDEO_CPIA2 is not set
+CONFIG_VIDEO_SAA5246A=m
+CONFIG_VIDEO_SAA5249=m
+CONFIG_VIDEO_STRADIS=m
+CONFIG_VIDEO_ZORAN=m
+CONFIG_VIDEO_ZORAN_DC30=m
+CONFIG_VIDEO_ZORAN_ZR36060=m
+CONFIG_VIDEO_ZORAN_BUZ=m
+CONFIG_VIDEO_ZORAN_DC10=m
+CONFIG_VIDEO_ZORAN_LML33=m
+CONFIG_VIDEO_ZORAN_LML33R10=m
+# CONFIG_VIDEO_ZORAN_AVS6EYES is not set
+CONFIG_VIDEO_MEYE=m
+CONFIG_VIDEO_SAA7134=m
+CONFIG_VIDEO_SAA7134_ALSA=m
+CONFIG_VIDEO_SAA7134_DVB=m
+CONFIG_VIDEO_MXB=m
+CONFIG_VIDEO_HEXIUM_ORION=m
+CONFIG_VIDEO_HEXIUM_GEMINI=m
+CONFIG_VIDEO_CX88=m
+CONFIG_VIDEO_CX88_ALSA=m
+CONFIG_VIDEO_CX88_BLACKBIRD=m
+CONFIG_VIDEO_CX88_DVB=m
+CONFIG_VIDEO_CX88_VP3054=m
+CONFIG_VIDEO_CX23885=m
+CONFIG_VIDEO_AU0828=m
+CONFIG_VIDEO_IVTV=m
+CONFIG_VIDEO_FB_IVTV=m
+CONFIG_VIDEO_CX18=m
+CONFIG_VIDEO_CAFE_CCIC=m
+CONFIG_SOC_CAMERA=m
+CONFIG_SOC_CAMERA_MT9M001=m
+CONFIG_SOC_CAMERA_MT9M111=m
+CONFIG_SOC_CAMERA_MT9V022=m
+CONFIG_SOC_CAMERA_PLATFORM=m
+CONFIG_VIDEO_SH_MOBILE_CEU=m
+CONFIG_V4L_USB_DRIVERS=y
+CONFIG_USB_VIDEO_CLASS=m
+CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y
+CONFIG_USB_GSPCA=m
+CONFIG_USB_M5602=m
+CONFIG_USB_GSPCA_CONEX=m
+CONFIG_USB_GSPCA_ETOMS=m
+CONFIG_USB_GSPCA_FINEPIX=m
+CONFIG_USB_GSPCA_MARS=m
+CONFIG_USB_GSPCA_OV519=m
+CONFIG_USB_GSPCA_PAC207=m
+CONFIG_USB_GSPCA_PAC7311=m
+CONFIG_USB_GSPCA_SONIXB=m
+CONFIG_USB_GSPCA_SONIXJ=m
+CONFIG_USB_GSPCA_SPCA500=m
+CONFIG_USB_GSPCA_SPCA501=m
+CONFIG_USB_GSPCA_SPCA505=m
+CONFIG_USB_GSPCA_SPCA506=m
+CONFIG_USB_GSPCA_SPCA508=m
+CONFIG_USB_GSPCA_SPCA561=m
+CONFIG_USB_GSPCA_STK014=m
+CONFIG_USB_GSPCA_SUNPLUS=m
+CONFIG_USB_GSPCA_T613=m
+CONFIG_USB_GSPCA_TV8532=m
+CONFIG_USB_GSPCA_VC032X=m
+CONFIG_USB_GSPCA_ZC3XX=m
+CONFIG_VIDEO_PVRUSB2=m
+CONFIG_VIDEO_PVRUSB2_SYSFS=y
+CONFIG_VIDEO_PVRUSB2_DVB=y
+# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set
+CONFIG_VIDEO_EM28XX=m
+CONFIG_VIDEO_EM28XX_ALSA=m
+CONFIG_VIDEO_EM28XX_DVB=m
+CONFIG_VIDEO_USBVISION=m
+CONFIG_VIDEO_USBVIDEO=m
+CONFIG_USB_VICAM=m
+CONFIG_USB_IBMCAM=m
+CONFIG_USB_KONICAWC=m
+CONFIG_USB_QUICKCAM_MESSENGER=m
+CONFIG_USB_ET61X251=m
+CONFIG_VIDEO_OVCAMCHIP=m
+CONFIG_USB_W9968CF=m
+CONFIG_USB_OV511=m
+CONFIG_USB_SE401=m
+CONFIG_USB_SN9C102=m
+CONFIG_USB_STV680=m
+CONFIG_USB_ZC0301=m
+CONFIG_USB_PWC=m
+# CONFIG_USB_PWC_DEBUG is not set
+CONFIG_USB_ZR364XX=m
+CONFIG_USB_STKWEBCAM=m
+CONFIG_USB_S2255=m
+CONFIG_RADIO_ADAPTERS=y
+CONFIG_RADIO_CADET=m
+CONFIG_RADIO_RTRACK=m
+CONFIG_RADIO_RTRACK2=m
+CONFIG_RADIO_AZTECH=m
+CONFIG_RADIO_GEMTEK=m
+CONFIG_RADIO_GEMTEK_PCI=m
+CONFIG_RADIO_MAXIRADIO=m
+CONFIG_RADIO_MAESTRO=m
+CONFIG_RADIO_SF16FMI=m
+CONFIG_RADIO_SF16FMR2=m
+CONFIG_RADIO_TERRATEC=m
+CONFIG_RADIO_TRUST=m
+CONFIG_RADIO_TYPHOON=m
+CONFIG_RADIO_TYPHOON_PROC_FS=y
+CONFIG_RADIO_ZOLTRIX=m
+CONFIG_USB_DSBR=m
+CONFIG_USB_SI470X=m
+CONFIG_USB_MR800=m
+CONFIG_DVB_CAPTURE_DRIVERS=y
+
+#
+# Supported SAA7146 based PCI Adapters
+#
+CONFIG_TTPCI_EEPROM=m
+CONFIG_DVB_AV7110=m
+# CONFIG_DVB_AV7110_FIRMWARE is not set
+CONFIG_DVB_AV7110_OSD=y
+CONFIG_DVB_BUDGET_CORE=m
+CONFIG_DVB_BUDGET=m
+CONFIG_DVB_BUDGET_CI=m
+CONFIG_DVB_BUDGET_AV=m
+CONFIG_DVB_BUDGET_PATCH=m
+
+#
+# Supported USB Adapters
+#
+CONFIG_DVB_USB=m
+# CONFIG_DVB_USB_DEBUG is not set
+CONFIG_DVB_USB_A800=m
+CONFIG_DVB_USB_DIBUSB_MB=m
+# CONFIG_DVB_USB_DIBUSB_MB_FAULTY is not set
+CONFIG_DVB_USB_DIBUSB_MC=m
+CONFIG_DVB_USB_DIB0700=m
+CONFIG_DVB_USB_UMT_010=m
+CONFIG_DVB_USB_CXUSB=m
+CONFIG_DVB_USB_M920X=m
+CONFIG_DVB_USB_GL861=m
+CONFIG_DVB_USB_AU6610=m
+CONFIG_DVB_USB_DIGITV=m
+CONFIG_DVB_USB_VP7045=m
+CONFIG_DVB_USB_VP702X=m
+CONFIG_DVB_USB_GP8PSK=m
+CONFIG_DVB_USB_NOVA_T_USB2=m
+CONFIG_DVB_USB_TTUSB2=m
+CONFIG_DVB_USB_DTT200U=m
+CONFIG_DVB_USB_OPERA1=m
+CONFIG_DVB_USB_AF9005=m
+CONFIG_DVB_USB_AF9005_REMOTE=m
+CONFIG_DVB_USB_DW2102=m
+CONFIG_DVB_USB_CINERGY_T2=m
+CONFIG_DVB_USB_ANYSEE=m
+CONFIG_DVB_USB_DTV5100=m
+CONFIG_DVB_USB_AF9015=m
+CONFIG_DVB_TTUSB_BUDGET=m
+CONFIG_DVB_TTUSB_DEC=m
+CONFIG_DVB_SIANO_SMS1XXX=m
+CONFIG_DVB_SIANO_SMS1XXX_SMS_IDS=y
+
+#
+# Supported FlexCopII (B2C2) Adapters
+#
+CONFIG_DVB_B2C2_FLEXCOP=m
+CONFIG_DVB_B2C2_FLEXCOP_PCI=m
+CONFIG_DVB_B2C2_FLEXCOP_USB=m
+# CONFIG_DVB_B2C2_FLEXCOP_DEBUG is not set
+
+#
+# Supported BT878 Adapters
+#
+CONFIG_DVB_BT8XX=m
+
+#
+# Supported Pluto2 Adapters
+#
+# CONFIG_DVB_PLUTO2 is not set
+
+#
+# Supported SDMC DM1105 Adapters
+#
+CONFIG_DVB_DM1105=m
+
+#
+# Supported DVB Frontends
+#
+
+#
+# Customise DVB Frontends
+#
+# CONFIG_DVB_FE_CUSTOMISE is not set
+
+#
+# DVB-S (satellite) frontends
+#
+CONFIG_DVB_CX24110=m
+CONFIG_DVB_CX24123=m
+CONFIG_DVB_MT312=m
+CONFIG_DVB_S5H1420=m
+CONFIG_DVB_STV0288=m
+CONFIG_DVB_STB6000=m
+CONFIG_DVB_STV0299=m
+CONFIG_DVB_TDA8083=m
+CONFIG_DVB_TDA10086=m
+CONFIG_DVB_VES1X93=m
+CONFIG_DVB_TUNER_ITD1000=m
+CONFIG_DVB_TDA826X=m
+CONFIG_DVB_TUA6100=m
+CONFIG_DVB_CX24116=m
+CONFIG_DVB_SI21XX=m
+
+#
+# DVB-T (terrestrial) frontends
+#
+CONFIG_DVB_SP8870=m
+CONFIG_DVB_SP887X=m
+CONFIG_DVB_CX22700=m
+CONFIG_DVB_CX22702=m
+CONFIG_DVB_DRX397XD=m
+CONFIG_DVB_L64781=m
+CONFIG_DVB_TDA1004X=m
+CONFIG_DVB_NXT6000=m
+CONFIG_DVB_MT352=m
+CONFIG_DVB_ZL10353=m
+CONFIG_DVB_DIB3000MB=m
+CONFIG_DVB_DIB3000MC=m
+CONFIG_DVB_DIB7000M=m
+CONFIG_DVB_DIB7000P=m
+CONFIG_DVB_TDA10048=m
+
+#
+# DVB-C (cable) frontends
+#
+CONFIG_DVB_VES1820=m
+CONFIG_DVB_TDA10021=m
+CONFIG_DVB_TDA10023=m
+CONFIG_DVB_STV0297=m
+
+#
+# ATSC (North American/Korean Terrestrial/Cable DTV) frontends
+#
+CONFIG_DVB_NXT200X=m
+CONFIG_DVB_OR51211=m
+CONFIG_DVB_OR51132=m
+CONFIG_DVB_BCM3510=m
+CONFIG_DVB_LGDT330X=m
+CONFIG_DVB_S5H1409=m
+CONFIG_DVB_AU8522=m
+CONFIG_DVB_S5H1411=m
+
+#
+# Digital terrestrial only tuners/PLL
+#
+CONFIG_DVB_PLL=m
+CONFIG_DVB_TUNER_DIB0070=m
+
+#
+# SEC control devices for DVB-S
+#
+CONFIG_DVB_LNBP21=m
+CONFIG_DVB_ISL6405=m
+CONFIG_DVB_ISL6421=m
+CONFIG_DVB_LGS8GL5=m
+
+#
+# Tools to develop new frontends
+#
+# CONFIG_DVB_DUMMY_FE is not set
+CONFIG_DVB_AF9013=m
+CONFIG_DAB=y
+CONFIG_USB_DABUSB=m
+
+#
+# Graphics support
+#
+CONFIG_AGP=m
+CONFIG_AGP_ALI=m
+CONFIG_AGP_ATI=m
+CONFIG_AGP_AMD=m
+CONFIG_AGP_AMD64=m
+CONFIG_AGP_INTEL=m
+CONFIG_AGP_NVIDIA=m
+CONFIG_AGP_SIS=m
+CONFIG_AGP_SWORKS=m
+CONFIG_AGP_VIA=m
+CONFIG_AGP_EFFICEON=m
+CONFIG_DRM=m
+CONFIG_DRM_TDFX=m
+CONFIG_DRM_R128=m
+CONFIG_DRM_RADEON=m
+CONFIG_DRM_I810=m
+CONFIG_DRM_I830=m
+CONFIG_DRM_I915=m
+CONFIG_DRM_MGA=m
+CONFIG_DRM_SIS=m
+CONFIG_DRM_VIA=m
+CONFIG_DRM_SAVAGE=m
+CONFIG_VGASTATE=m
+CONFIG_VIDEO_OUTPUT_CONTROL=m
+CONFIG_FB=y
+CONFIG_FIRMWARE_EDID=y
+CONFIG_FB_DDC=m
+CONFIG_FB_BOOT_VESA_SUPPORT=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+CONFIG_FB_SYS_FILLRECT=m
+CONFIG_FB_SYS_COPYAREA=m
+CONFIG_FB_SYS_IMAGEBLIT=m
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+CONFIG_FB_SYS_FOPS=m
+CONFIG_FB_DEFERRED_IO=y
+CONFIG_FB_HECUBA=m
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+CONFIG_FB_BACKLIGHT=y
+CONFIG_FB_MODE_HELPERS=y
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+CONFIG_FB_CIRRUS=m
+CONFIG_FB_PM2=m
+CONFIG_FB_PM2_FIFO_DISCONNECT=y
+CONFIG_FB_CYBER2000=m
+CONFIG_FB_ARC=m
+# CONFIG_FB_ASILIANT is not set
+CONFIG_FB_IMSTT=y
+CONFIG_FB_VGA16=m
+CONFIG_FB_UVESA=m
+CONFIG_FB_VESA=y
+# CONFIG_FB_EFI is not set
+CONFIG_FB_N411=m
+CONFIG_FB_HGA=m
+CONFIG_FB_HGA_ACCEL=y
+CONFIG_FB_S1D13XXX=m
+CONFIG_FB_NVIDIA=m
+CONFIG_FB_NVIDIA_I2C=y
+# CONFIG_FB_NVIDIA_DEBUG is not set
+CONFIG_FB_NVIDIA_BACKLIGHT=y
+CONFIG_FB_RIVA=m
+CONFIG_FB_RIVA_I2C=y
+# CONFIG_FB_RIVA_DEBUG is not set
+CONFIG_FB_RIVA_BACKLIGHT=y
+CONFIG_FB_I810=m
+CONFIG_FB_I810_GTF=y
+CONFIG_FB_I810_I2C=y
+CONFIG_FB_LE80578=m
+CONFIG_FB_CARILLO_RANCH=m
+CONFIG_FB_INTEL=m
+# CONFIG_FB_INTEL_DEBUG is not set
+CONFIG_FB_INTEL_I2C=y
+# CONFIG_FB_MATROX is not set
+CONFIG_FB_RADEON=m
+CONFIG_FB_RADEON_I2C=y
+CONFIG_FB_RADEON_BACKLIGHT=y
+# CONFIG_FB_RADEON_DEBUG is not set
+# CONFIG_FB_ATY128 is not set
+CONFIG_FB_ATY=m
+CONFIG_FB_ATY_CT=y
+CONFIG_FB_ATY_GENERIC_LCD=y
+CONFIG_FB_ATY_GX=y
+CONFIG_FB_ATY_BACKLIGHT=y
+# CONFIG_FB_S3 is not set
+CONFIG_FB_SAVAGE=m
+CONFIG_FB_SAVAGE_I2C=y
+CONFIG_FB_SAVAGE_ACCEL=y
+CONFIG_FB_SIS=m
+CONFIG_FB_SIS_300=y
+CONFIG_FB_SIS_315=y
+CONFIG_FB_VIA=m
+CONFIG_FB_NEOMAGIC=m
+CONFIG_FB_KYRO=m
+CONFIG_FB_3DFX=m
+CONFIG_FB_3DFX_ACCEL=y
+CONFIG_FB_VOODOO1=m
+# CONFIG_FB_VT8623 is not set
+CONFIG_FB_CYBLA=m
+CONFIG_FB_TRIDENT=m
+CONFIG_FB_TRIDENT_ACCEL=y
+# CONFIG_FB_ARK is not set
+CONFIG_FB_PM3=m
+CONFIG_FB_CARMINE=m
+CONFIG_FB_CARMINE_DRAM_EVAL=y
+# CONFIG_CARMINE_DRAM_CUSTOM is not set
+CONFIG_FB_GEODE=y
+CONFIG_FB_GEODE_LX=m
+CONFIG_FB_GEODE_GX=m
+CONFIG_FB_GEODE_GX1=m
+CONFIG_FB_SM501=m
+# CONFIG_FB_VIRTUAL is not set
+CONFIG_XEN_FBDEV_FRONTEND=m
+CONFIG_FB_METRONOME=m
+CONFIG_FB_MB862XX=m
+CONFIG_FB_MB862XX_PCI_GDC=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_LCD_CLASS_DEVICE=m
+CONFIG_LCD_LTV350QV=m
+CONFIG_LCD_ILI9320=m
+CONFIG_LCD_TDO24M=m
+CONFIG_LCD_VGG2432A4=m
+CONFIG_LCD_PLATFORM=m
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_CORGI=m
+CONFIG_BACKLIGHT_PROGEAR=m
+CONFIG_BACKLIGHT_CARILLO_RANCH=m
+CONFIG_BACKLIGHT_MBP_NVIDIA=m
+CONFIG_BACKLIGHT_SAHARA=m
+
+#
+# Display device support
+#
+CONFIG_DISPLAY_SUPPORT=m
+
+#
+# Display hardware drivers
+#
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+# CONFIG_VGACON_SOFT_SCROLLBACK is not set
+CONFIG_MDA_CONSOLE=m
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+# CONFIG_LOGO is not set
+CONFIG_SOUND=m
+CONFIG_SOUND_OSS_CORE=y
+CONFIG_SND=m
+CONFIG_SND_TIMER=m
+CONFIG_SND_PCM=m
+CONFIG_SND_HWDEP=m
+CONFIG_SND_RAWMIDI=m
+CONFIG_SND_SEQUENCER=m
+CONFIG_SND_SEQ_DUMMY=m
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+CONFIG_SND_PCM_OSS_PLUGINS=y
+CONFIG_SND_SEQUENCER_OSS=y
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
+CONFIG_SND_VERBOSE_PRINTK=y
+CONFIG_SND_DEBUG=y
+# CONFIG_SND_DEBUG_VERBOSE is not set
+# CONFIG_SND_PCM_XRUN_DEBUG is not set
+CONFIG_SND_VMASTER=y
+CONFIG_SND_MPU401_UART=m
+CONFIG_SND_OPL3_LIB=m
+CONFIG_SND_OPL4_LIB=m
+CONFIG_SND_VX_LIB=m
+CONFIG_SND_AC97_CODEC=m
+CONFIG_SND_DRIVERS=y
+CONFIG_SND_PCSP=m
+CONFIG_SND_DUMMY=m
+CONFIG_SND_VIRMIDI=m
+CONFIG_SND_MTPAV=m
+CONFIG_SND_MTS64=m
+CONFIG_SND_SERIAL_U16550=m
+CONFIG_SND_MPU401=m
+CONFIG_SND_PORTMAN2X4=m
+CONFIG_SND_AC97_POWER_SAVE=y
+CONFIG_SND_AC97_POWER_SAVE_DEFAULT=0
+CONFIG_SND_WSS_LIB=m
+CONFIG_SND_SB_COMMON=m
+CONFIG_SND_SB8_DSP=m
+CONFIG_SND_SB16_DSP=m
+CONFIG_SND_ISA=y
+# CONFIG_SND_ADLIB is not set
+CONFIG_SND_AD1816A=m
+CONFIG_SND_AD1848=m
+CONFIG_SND_ALS100=m
+CONFIG_SND_AZT2320=m
+CONFIG_SND_CMI8330=m
+CONFIG_SND_CS4231=m
+CONFIG_SND_CS4232=m
+CONFIG_SND_CS4236=m
+CONFIG_SND_DT019X=m
+CONFIG_SND_ES968=m
+CONFIG_SND_ES1688=m
+CONFIG_SND_ES18XX=m
+CONFIG_SND_SC6000=m
+CONFIG_SND_GUSCLASSIC=m
+CONFIG_SND_GUSEXTREME=m
+CONFIG_SND_GUSMAX=m
+CONFIG_SND_INTERWAVE=m
+CONFIG_SND_INTERWAVE_STB=m
+CONFIG_SND_OPL3SA2=m
+CONFIG_SND_OPTI92X_AD1848=m
+CONFIG_SND_OPTI92X_CS4231=m
+CONFIG_SND_OPTI93X=m
+CONFIG_SND_MIRO=m
+CONFIG_SND_SB8=m
+CONFIG_SND_SB16=m
+CONFIG_SND_SBAWE=m
+CONFIG_SND_SB16_CSP=y
+CONFIG_SND_SGALAXY=m
+CONFIG_SND_SSCAPE=m
+CONFIG_SND_WAVEFRONT=m
+CONFIG_SND_WAVEFRONT_FIRMWARE_IN_KERNEL=y
+CONFIG_SND_PCI=y
+CONFIG_SND_AD1889=m
+CONFIG_SND_ALS300=m
+CONFIG_SND_ALS4000=m
+CONFIG_SND_ALI5451=m
+CONFIG_SND_ATIIXP=m
+CONFIG_SND_ATIIXP_MODEM=m
+CONFIG_SND_AU8810=m
+CONFIG_SND_AU8820=m
+CONFIG_SND_AU8830=m
+CONFIG_SND_AW2=m
+CONFIG_SND_AZT3328=m
+CONFIG_SND_BT87X=m
+# CONFIG_SND_BT87X_OVERCLOCK is not set
+CONFIG_SND_CA0106=m
+CONFIG_SND_CMIPCI=m
+CONFIG_SND_OXYGEN_LIB=m
+CONFIG_SND_OXYGEN=m
+CONFIG_SND_CS4281=m
+CONFIG_SND_CS46XX=m
+CONFIG_SND_CS46XX_NEW_DSP=y
+CONFIG_SND_CS5530=m
+CONFIG_SND_CS5535AUDIO=m
+CONFIG_SND_DARLA20=m
+CONFIG_SND_GINA20=m
+CONFIG_SND_LAYLA20=m
+CONFIG_SND_DARLA24=m
+CONFIG_SND_GINA24=m
+CONFIG_SND_LAYLA24=m
+CONFIG_SND_MONA=m
+CONFIG_SND_MIA=m
+CONFIG_SND_ECHO3G=m
+CONFIG_SND_INDIGO=m
+CONFIG_SND_INDIGOIO=m
+CONFIG_SND_INDIGODJ=m
+CONFIG_SND_EMU10K1=m
+CONFIG_SND_EMU10K1X=m
+CONFIG_SND_ENS1370=m
+CONFIG_SND_ENS1371=m
+CONFIG_SND_ES1938=m
+CONFIG_SND_ES1968=m
+CONFIG_SND_FM801=m
+CONFIG_SND_FM801_TEA575X_BOOL=y
+CONFIG_SND_FM801_TEA575X=m
+CONFIG_SND_HDA_INTEL=m
+# CONFIG_SND_HDA_HWDEP is not set
+CONFIG_SND_HDA_INPUT_BEEP=y
+CONFIG_SND_HDA_CODEC_REALTEK=y
+CONFIG_SND_HDA_CODEC_ANALOG=y
+CONFIG_SND_HDA_CODEC_SIGMATEL=y
+CONFIG_SND_HDA_CODEC_VIA=y
+CONFIG_SND_HDA_CODEC_ATIHDMI=y
+CONFIG_SND_HDA_CODEC_NVHDMI=y
+CONFIG_SND_HDA_CODEC_CONEXANT=y
+CONFIG_SND_HDA_CODEC_CMEDIA=y
+CONFIG_SND_HDA_CODEC_SI3054=y
+CONFIG_SND_HDA_GENERIC=y
+# CONFIG_SND_HDA_POWER_SAVE is not set
+CONFIG_SND_HDSP=m
+CONFIG_SND_HDSPM=m
+CONFIG_SND_HIFIER=m
+CONFIG_SND_ICE1712=m
+CONFIG_SND_ICE1724=m
+CONFIG_SND_INTEL8X0=m
+CONFIG_SND_INTEL8X0M=m
+CONFIG_SND_KORG1212=m
+CONFIG_SND_MAESTRO3=m
+CONFIG_SND_MIXART=m
+CONFIG_SND_NM256=m
+CONFIG_SND_PCXHR=m
+CONFIG_SND_RIPTIDE=m
+CONFIG_SND_RME32=m
+CONFIG_SND_RME96=m
+CONFIG_SND_RME9652=m
+CONFIG_SND_SIS7019=m
+CONFIG_SND_SONICVIBES=m
+CONFIG_SND_TRIDENT=m
+CONFIG_SND_VIA82XX=m
+CONFIG_SND_VIA82XX_MODEM=m
+CONFIG_SND_VIRTUOSO=m
+CONFIG_SND_VX222=m
+CONFIG_SND_YMFPCI=m
+CONFIG_SND_SPI=y
+CONFIG_SND_USB=y
+CONFIG_SND_USB_AUDIO=m
+CONFIG_SND_USB_USX2Y=m
+CONFIG_SND_USB_CAIAQ=m
+CONFIG_SND_USB_CAIAQ_INPUT=y
+CONFIG_SND_USB_US122L=m
+CONFIG_SND_PCMCIA=y
+CONFIG_SND_VXPOCKET=m
+CONFIG_SND_PDAUDIOCF=m
+# CONFIG_SND_SOC is not set
+CONFIG_SOUND_PRIME=m
+# CONFIG_SOUND_MSNDCLAS is not set
+# CONFIG_SOUND_MSNDPIN is not set
+CONFIG_SOUND_OSS=m
+CONFIG_SOUND_TRACEINIT=y
+CONFIG_SOUND_DMAP=y
+CONFIG_SOUND_SSCAPE=m
+CONFIG_SOUND_VMIDI=m
+CONFIG_SOUND_TRIX=m
+CONFIG_SOUND_MSS=m
+CONFIG_SOUND_MPU401=m
+CONFIG_SOUND_PAS=m
+CONFIG_SOUND_PSS=m
+CONFIG_PSS_MIXER=y
+# CONFIG_PSS_HAVE_BOOT is not set
+CONFIG_SOUND_SB=m
+CONFIG_SOUND_YM3812=m
+CONFIG_SOUND_UART6850=m
+CONFIG_SOUND_AEDSP16=m
+CONFIG_SC6600=y
+CONFIG_SC6600_JOY=y
+CONFIG_SC6600_CDROM=4
+CONFIG_SC6600_CDROMBASE=0x0
+CONFIG_SOUND_KAHLUA=m
+CONFIG_AC97_BUS=m
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+CONFIG_HIDRAW=y
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=m
+CONFIG_HID_PID=y
+CONFIG_USB_HIDDEV=y
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+
+#
+# Special HID drivers
+#
+# CONFIG_HID_COMPAT is not set
+CONFIG_HID_A4TECH=m
+CONFIG_HID_APPLE=m
+CONFIG_HID_BELKIN=m
+CONFIG_HID_BRIGHT=m
+CONFIG_HID_CHERRY=m
+CONFIG_HID_CHICONY=m
+CONFIG_HID_CYPRESS=m
+CONFIG_HID_DELL=m
+CONFIG_HID_EZKEY=m
+CONFIG_HID_GYRATION=m
+CONFIG_HID_LOGITECH=m
+CONFIG_LOGITECH_FF=y
+CONFIG_LOGIRUMBLEPAD2_FF=y
+CONFIG_HID_MICROSOFT=m
+CONFIG_HID_MONTEREY=m
+CONFIG_HID_PANTHERLORD=m
+CONFIG_PANTHERLORD_FF=y
+CONFIG_HID_PETALYNX=m
+CONFIG_HID_SAMSUNG=m
+CONFIG_HID_SONY=m
+CONFIG_HID_SUNPLUS=m
+CONFIG_THRUSTMASTER_FF=m
+CONFIG_ZEROPLUS_FF=m
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=m
+# CONFIG_USB_DEBUG is not set
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+CONFIG_USB_DEVICE_CLASS=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+CONFIG_USB_SUSPEND=y
+# CONFIG_USB_OTG is not set
+CONFIG_USB_MON=y
+CONFIG_USB_WUSB=m
+CONFIG_USB_WUSB_CBAF=m
+# CONFIG_USB_WUSB_CBAF_DEBUG is not set
+
+#
+# USB Host Controller Drivers
+#
+CONFIG_USB_C67X00_HCD=m
+CONFIG_USB_EHCI_HCD=m
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+CONFIG_USB_ISP116X_HCD=m
+CONFIG_USB_ISP1760_HCD=m
+CONFIG_USB_OHCI_HCD=m
+CONFIG_USB_OHCI_HCD_SSB=y
+# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_UHCI_HCD=m
+CONFIG_USB_U132_HCD=m
+CONFIG_USB_SL811_HCD=m
+CONFIG_USB_SL811_CS=m
+CONFIG_USB_R8A66597_HCD=m
+CONFIG_USB_WHCI_HCD=m
+CONFIG_USB_HWA_HCD=m
+
+#
+# Enable Host or Gadget support to see Inventra options
+#
+
+#
+# USB Device Class drivers
+#
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+CONFIG_USB_WDM=m
+CONFIG_USB_TMC=m
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
+#
+
+#
+# see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+CONFIG_USB_STORAGE_ISD200=y
+CONFIG_USB_STORAGE_DPCM=y
+CONFIG_USB_STORAGE_USBAT=y
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+# CONFIG_USB_STORAGE_ALAUDA is not set
+CONFIG_USB_STORAGE_ONETOUCH=y
+CONFIG_USB_STORAGE_KARMA=y
+CONFIG_USB_STORAGE_CYPRESS_ATACB=y
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Imaging devices
+#
+CONFIG_USB_MDC800=m
+CONFIG_USB_MICROTEK=m
+
+#
+# USB port drivers
+#
+CONFIG_USB_USS720=m
+CONFIG_USB_SERIAL=m
+CONFIG_USB_EZUSB=y
+CONFIG_USB_SERIAL_GENERIC=y
+# CONFIG_USB_SERIAL_AIRCABLE is not set
+CONFIG_USB_SERIAL_ARK3116=m
+CONFIG_USB_SERIAL_BELKIN=m
+CONFIG_USB_SERIAL_CH341=m
+CONFIG_USB_SERIAL_WHITEHEAT=m
+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
+CONFIG_USB_SERIAL_CP2101=m
+CONFIG_USB_SERIAL_CYPRESS_M8=m
+CONFIG_USB_SERIAL_EMPEG=m
+CONFIG_USB_SERIAL_FTDI_SIO=m
+# CONFIG_USB_SERIAL_FUNSOFT is not set
+CONFIG_USB_SERIAL_VISOR=m
+CONFIG_USB_SERIAL_IPAQ=m
+CONFIG_USB_SERIAL_IR=m
+CONFIG_USB_SERIAL_EDGEPORT=m
+CONFIG_USB_SERIAL_EDGEPORT_TI=m
+CONFIG_USB_SERIAL_GARMIN=m
+CONFIG_USB_SERIAL_IPW=m
+CONFIG_USB_SERIAL_IUU=m
+CONFIG_USB_SERIAL_KEYSPAN_PDA=m
+CONFIG_USB_SERIAL_KEYSPAN=m
+CONFIG_USB_SERIAL_KEYSPAN_MPR=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19=y
+CONFIG_USB_SERIAL_KEYSPAN_USA18X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y
+CONFIG_USB_SERIAL_KLSI=m
+CONFIG_USB_SERIAL_KOBIL_SCT=m
+CONFIG_USB_SERIAL_MCT_U232=m
+CONFIG_USB_SERIAL_MOS7720=m
+CONFIG_USB_SERIAL_MOS7840=m
+CONFIG_USB_SERIAL_MOTOROLA=m
+CONFIG_USB_SERIAL_NAVMAN=m
+CONFIG_USB_SERIAL_PL2303=m
+CONFIG_USB_SERIAL_OTI6858=m
+CONFIG_USB_SERIAL_SPCP8X5=m
+CONFIG_USB_SERIAL_HP4X=m
+CONFIG_USB_SERIAL_SAFE=m
+CONFIG_USB_SERIAL_SAFE_PADDED=y
+CONFIG_USB_SERIAL_SIERRAWIRELESS=m
+CONFIG_USB_SERIAL_TI=m
+CONFIG_USB_SERIAL_CYBERJACK=m
+CONFIG_USB_SERIAL_XIRCOM=m
+CONFIG_USB_SERIAL_OPTION=m
+CONFIG_USB_SERIAL_OMNINET=m
+# CONFIG_USB_SERIAL_DEBUG is not set
+
+#
+# USB Miscellaneous drivers
+#
+CONFIG_USB_EMI62=m
+CONFIG_USB_EMI26=m
+CONFIG_USB_ADUTUX=m
+CONFIG_USB_SEVSEG=m
+CONFIG_USB_RIO500=m
+CONFIG_USB_LEGOTOWER=m
+CONFIG_USB_LCD=m
+CONFIG_USB_BERRY_CHARGE=m
+CONFIG_USB_LED=m
+CONFIG_USB_CYPRESS_CY7C63=m
+CONFIG_USB_CYTHERM=m
+CONFIG_USB_PHIDGET=m
+CONFIG_USB_PHIDGETKIT=m
+CONFIG_USB_PHIDGETMOTORCONTROL=m
+CONFIG_USB_PHIDGETSERVO=m
+CONFIG_USB_IDMOUSE=m
+CONFIG_USB_FTDI_ELAN=m
+CONFIG_USB_APPLEDISPLAY=m
+CONFIG_USB_SISUSBVGA=m
+# CONFIG_USB_SISUSBVGA_CON is not set
+CONFIG_USB_LD=m
+CONFIG_USB_TRANCEVIBRATOR=m
+CONFIG_USB_IOWARRIOR=m
+# CONFIG_USB_TEST is not set
+CONFIG_USB_ISIGHTFW=m
+CONFIG_USB_VST=m
+CONFIG_USB_ATM=m
+CONFIG_USB_SPEEDTOUCH=m
+CONFIG_USB_CXACRU=m
+CONFIG_USB_UEAGLEATM=m
+CONFIG_USB_XUSBATM=m
+# CONFIG_USB_GADGET is not set
+CONFIG_UWB=m
+CONFIG_UWB_HWA=m
+CONFIG_UWB_WHCI=m
+CONFIG_UWB_WLP=m
+CONFIG_UWB_I1480U=m
+CONFIG_UWB_I1480U_WLP=m
+CONFIG_MMC=m
+# CONFIG_MMC_DEBUG is not set
+# CONFIG_MMC_UNSAFE_RESUME is not set
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=m
+CONFIG_MMC_BLOCK_BOUNCE=y
+CONFIG_SDIO_UART=m
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+# CONFIG_MMC_SDHCI is not set
+CONFIG_MMC_WBSD=m
+CONFIG_MMC_TIFM_SD=m
+CONFIG_MMC_SDRICOH_CS=m
+CONFIG_MEMSTICK=m
+# CONFIG_MEMSTICK_DEBUG is not set
+
+#
+# MemoryStick drivers
+#
+# CONFIG_MEMSTICK_UNSAFE_RESUME is not set
+CONFIG_MSPRO_BLOCK=m
+
+#
+# MemoryStick Host Controller Drivers
+#
+CONFIG_MEMSTICK_TIFM_MS=m
+CONFIG_MEMSTICK_JMICRON_38X=m
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=m
+
+#
+# LED drivers
+#
+CONFIG_LEDS_NET48XX=m
+CONFIG_LEDS_WRAP=m
+CONFIG_LEDS_PCA9532=m
+CONFIG_LEDS_HP_DISK=m
+CONFIG_LEDS_CLEVO_MAIL=m
+CONFIG_LEDS_PCA955X=m
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=m
+CONFIG_LEDS_TRIGGER_IDE_DISK=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=m
+CONFIG_LEDS_TRIGGER_BACKLIGHT=m
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=m
+CONFIG_ACCESSIBILITY=y
+# CONFIG_A11Y_BRAILLE_CONSOLE is not set
+CONFIG_INFINIBAND=m
+CONFIG_INFINIBAND_USER_MAD=m
+CONFIG_INFINIBAND_USER_ACCESS=m
+CONFIG_INFINIBAND_USER_MEM=y
+CONFIG_INFINIBAND_ADDR_TRANS=y
+CONFIG_INFINIBAND_MTHCA=m
+CONFIG_INFINIBAND_MTHCA_DEBUG=y
+CONFIG_INFINIBAND_AMSO1100=m
+# CONFIG_INFINIBAND_AMSO1100_DEBUG is not set
+CONFIG_INFINIBAND_CXGB3=m
+# CONFIG_INFINIBAND_CXGB3_DEBUG is not set
+CONFIG_MLX4_INFINIBAND=m
+CONFIG_INFINIBAND_NES=m
+# CONFIG_INFINIBAND_NES_DEBUG is not set
+CONFIG_INFINIBAND_IPOIB=m
+# CONFIG_INFINIBAND_IPOIB_CM is not set
+CONFIG_INFINIBAND_IPOIB_DEBUG=y
+# CONFIG_INFINIBAND_IPOIB_DEBUG_DATA is not set
+# CONFIG_INFINIBAND_SRP is not set
+# CONFIG_INFINIBAND_ISER is not set
+# CONFIG_EDAC is not set
+CONFIG_RTC_LIB=m
+CONFIG_RTC_CLASS=m
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+CONFIG_RTC_INTF_DEV_UIE_EMUL=y
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+CONFIG_RTC_DRV_DS1307=m
+CONFIG_RTC_DRV_DS1374=m
+CONFIG_RTC_DRV_DS1672=m
+CONFIG_RTC_DRV_MAX6900=m
+CONFIG_RTC_DRV_RS5C372=m
+CONFIG_RTC_DRV_ISL1208=m
+CONFIG_RTC_DRV_X1205=m
+CONFIG_RTC_DRV_PCF8563=m
+CONFIG_RTC_DRV_PCF8583=m
+CONFIG_RTC_DRV_M41T80=m
+CONFIG_RTC_DRV_M41T80_WDT=y
+CONFIG_RTC_DRV_S35390A=m
+CONFIG_RTC_DRV_FM3130=m
+CONFIG_RTC_DRV_RX8581=m
+
+#
+# SPI RTC drivers
+#
+CONFIG_RTC_DRV_M41T94=m
+CONFIG_RTC_DRV_DS1305=m
+CONFIG_RTC_DRV_DS1390=m
+CONFIG_RTC_DRV_MAX6902=m
+CONFIG_RTC_DRV_R9701=m
+CONFIG_RTC_DRV_RS5C348=m
+CONFIG_RTC_DRV_DS3234=m
+
+#
+# Platform RTC drivers
+#
+CONFIG_RTC_DRV_CMOS=m
+CONFIG_RTC_DRV_DS1286=m
+CONFIG_RTC_DRV_DS1511=m
+CONFIG_RTC_DRV_DS1553=m
+CONFIG_RTC_DRV_DS1742=m
+CONFIG_RTC_DRV_STK17TA8=m
+CONFIG_RTC_DRV_M48T86=m
+CONFIG_RTC_DRV_M48T35=m
+CONFIG_RTC_DRV_M48T59=m
+CONFIG_RTC_DRV_BQ4802=m
+CONFIG_RTC_DRV_V3020=m
+CONFIG_RTC_DRV_WM8350=m
+
+#
+# on-CPU RTC drivers
+#
+CONFIG_AUXDISPLAY=y
+CONFIG_KS0108=m
+CONFIG_KS0108_PORT=0x378
+CONFIG_KS0108_DELAY=2
+CONFIG_CFAG12864B=m
+CONFIG_CFAG12864B_RATE=20
+CONFIG_UIO=m
+CONFIG_UIO_CIF=m
+CONFIG_UIO_PDRV=m
+CONFIG_UIO_PDRV_GENIRQ=m
+# CONFIG_UIO_SMX is not set
+CONFIG_UIO_SERCOS3=m
+CONFIG_XEN_BALLOON=y
+CONFIG_XEN_SCRUB_PAGES=y
+# CONFIG_STAGING is not set
+
+#
+# Firmware Drivers
+#
+CONFIG_EDD=m
+# CONFIG_EDD_OFF is not set
+CONFIG_FIRMWARE_MEMMAP=y
+CONFIG_EFI_VARS=m
+CONFIG_DELL_RBU=m
+CONFIG_DCDBAS=m
+CONFIG_DMIID=y
+CONFIG_ISCSI_IBFT_FIND=y
+CONFIG_ISCSI_IBFT=m
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+CONFIG_EXT2_FS_XIP=y
+CONFIG_EXT3_FS=m
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_EXT4_FS=m
+# CONFIG_EXT4DEV_COMPAT is not set
+CONFIG_EXT4_FS_XATTR=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
+CONFIG_FS_XIP=y
+CONFIG_JBD=m
+CONFIG_JBD_DEBUG=y
+CONFIG_JBD2=m
+# CONFIG_JBD2_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+CONFIG_REISERFS_FS_XATTR=y
+CONFIG_REISERFS_FS_POSIX_ACL=y
+CONFIG_REISERFS_FS_SECURITY=y
+CONFIG_JFS_FS=m
+CONFIG_JFS_POSIX_ACL=y
+CONFIG_JFS_SECURITY=y
+# CONFIG_JFS_DEBUG is not set
+CONFIG_JFS_STATISTICS=y
+CONFIG_FS_POSIX_ACL=y
+CONFIG_FILE_LOCKING=y
+CONFIG_XFS_FS=m
+CONFIG_XFS_QUOTA=y
+CONFIG_XFS_POSIX_ACL=y
+CONFIG_XFS_RT=y
+# CONFIG_XFS_DEBUG is not set
+CONFIG_OCFS2_FS=m
+CONFIG_OCFS2_FS_O2CB=m
+CONFIG_OCFS2_FS_USERSPACE_CLUSTER=m
+CONFIG_OCFS2_FS_STATS=y
+# CONFIG_OCFS2_DEBUG_MASKLOG is not set
+# CONFIG_OCFS2_DEBUG_FS is not set
+# CONFIG_OCFS2_COMPAT_JBD is not set
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+CONFIG_QUOTA=y
+CONFIG_QUOTA_NETLINK_INTERFACE=y
+CONFIG_PRINT_QUOTA_WARNING=y
+CONFIG_QFMT_V1=m
+CONFIG_QFMT_V2=m
+CONFIG_QUOTACTL=y
+CONFIG_AUTOFS_FS=m
+CONFIG_AUTOFS4_FS=m
+CONFIG_FUSE_FS=m
+CONFIG_GENERIC_ACL=y
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+CONFIG_NTFS_FS=m
+# CONFIG_NTFS_DEBUG is not set
+CONFIG_NTFS_RW=y
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_HUGETLBFS=y
+CONFIG_HUGETLB_PAGE=y
+CONFIG_CONFIGFS_FS=m
+
+#
+# Miscellaneous filesystems
+#
+CONFIG_ADFS_FS=m
+# CONFIG_ADFS_FS_RW is not set
+CONFIG_AFFS_FS=m
+CONFIG_ECRYPT_FS=m
+CONFIG_HFS_FS=m
+CONFIG_HFSPLUS_FS=m
+CONFIG_BEFS_FS=m
+# CONFIG_BEFS_DEBUG is not set
+CONFIG_BFS_FS=m
+CONFIG_EFS_FS=m
+CONFIG_JFFS2_FS=m
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_LZO=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_JFFS2_CMODE_NONE is not set
+CONFIG_JFFS2_CMODE_PRIORITY=y
+# CONFIG_JFFS2_CMODE_SIZE is not set
+# CONFIG_JFFS2_CMODE_FAVOURLZO is not set
+CONFIG_UBIFS_FS=m
+CONFIG_UBIFS_FS_XATTR=y
+CONFIG_UBIFS_FS_ADVANCED_COMPR=y
+CONFIG_UBIFS_FS_LZO=y
+CONFIG_UBIFS_FS_ZLIB=y
+# CONFIG_UBIFS_FS_DEBUG is not set
+CONFIG_CRAMFS=m
+CONFIG_VXFS_FS=m
+CONFIG_MINIX_FS=y
+CONFIG_OMFS_FS=m
+CONFIG_HPFS_FS=m
+CONFIG_QNX4FS_FS=m
+CONFIG_ROMFS_FS=m
+CONFIG_SYSV_FS=m
+CONFIG_UFS_FS=m
+# CONFIG_UFS_FS_WRITE is not set
+# CONFIG_UFS_DEBUG is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_NFSD=m
+CONFIG_NFSD_V2_ACL=y
+CONFIG_NFSD_V3=y
+CONFIG_NFSD_V3_ACL=y
+CONFIG_NFSD_V4=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_NFS_ACL_SUPPORT=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+CONFIG_SUNRPC_XPRT_RDMA=m
+# CONFIG_SUNRPC_REGISTER_V4 is not set
+CONFIG_RPCSEC_GSS_KRB5=y
+CONFIG_RPCSEC_GSS_SPKM3=m
+CONFIG_SMB_FS=m
+CONFIG_SMB_NLS_DEFAULT=y
+CONFIG_SMB_NLS_REMOTE="cp850"
+CONFIG_CIFS=m
+CONFIG_CIFS_STATS=y
+# CONFIG_CIFS_STATS2 is not set
+CONFIG_CIFS_WEAK_PW_HASH=y
+CONFIG_CIFS_UPCALL=y
+CONFIG_CIFS_XATTR=y
+CONFIG_CIFS_POSIX=y
+# CONFIG_CIFS_DEBUG2 is not set
+# CONFIG_CIFS_EXPERIMENTAL is not set
+CONFIG_NCP_FS=m
+CONFIG_NCPFS_PACKET_SIGNING=y
+CONFIG_NCPFS_IOCTL_LOCKING=y
+CONFIG_NCPFS_STRONG=y
+CONFIG_NCPFS_NFS_NS=y
+CONFIG_NCPFS_OS2_NS=y
+CONFIG_NCPFS_SMALLDOS=y
+CONFIG_NCPFS_NLS=y
+CONFIG_NCPFS_EXTRAS=y
+CONFIG_CODA_FS=m
+CONFIG_AFS_FS=m
+# CONFIG_AFS_DEBUG is not set
+CONFIG_9P_FS=m
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+CONFIG_OSF_PARTITION=y
+# CONFIG_AMIGA_PARTITION is not set
+CONFIG_ATARI_PARTITION=y
+CONFIG_MAC_PARTITION=y
+CONFIG_MSDOS_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+# CONFIG_MINIX_SUBPARTITION is not set
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+CONFIG_LDM_PARTITION=y
+# CONFIG_LDM_DEBUG is not set
+CONFIG_SGI_PARTITION=y
+CONFIG_ULTRIX_PARTITION=y
+CONFIG_SUN_PARTITION=y
+CONFIG_KARMA_PARTITION=y
+CONFIG_EFI_PARTITION=y
+CONFIG_SYSV68_PARTITION=y
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="utf8"
+CONFIG_NLS_CODEPAGE_437=m
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=m
+CONFIG_NLS_ISO8859_1=m
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_UTF8=m
+CONFIG_DLM=m
+CONFIG_DLM_DEBUG=y
+
+#
+# Kernel hacking
+#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_UNUSED_SYMBOLS=y
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC=y
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=1
+CONFIG_SCHED_DEBUG=y
+# CONFIG_SCHEDSTATS is not set
+CONFIG_TIMER_STATS=y
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_HIGHMEM is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_VIRTUAL is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+CONFIG_DEBUG_MEMORY_INIT=y
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_FRAME_POINTER is not set
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_SYSPROF_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_PROVIDE_OHCI1394_DMA_INIT is not set
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+CONFIG_STRICT_DEVMEM=y
+CONFIG_X86_VERBOSE_BOOTUP=y
+CONFIG_EARLY_PRINTK=y
+# CONFIG_EARLY_PRINTK_DBGP is not set
+CONFIG_DEBUG_STACKOVERFLOW=y
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
+# CONFIG_DEBUG_PER_CPU_MAPS is not set
+# CONFIG_X86_PTDUMP is not set
+# CONFIG_DEBUG_RODATA is not set
+# CONFIG_DEBUG_NX_TEST is not set
+# CONFIG_4KSTACKS is not set
+CONFIG_DOUBLEFAULT=y
+# CONFIG_MMIOTRACE is not set
+CONFIG_IO_DELAY_TYPE_0X80=0
+CONFIG_IO_DELAY_TYPE_0XED=1
+CONFIG_IO_DELAY_TYPE_UDELAY=2
+CONFIG_IO_DELAY_TYPE_NONE=3
+CONFIG_IO_DELAY_0X80=y
+# CONFIG_IO_DELAY_0XED is not set
+# CONFIG_IO_DELAY_UDELAY is not set
+# CONFIG_IO_DELAY_NONE is not set
+CONFIG_DEFAULT_IO_DELAY_TYPE=0
+# CONFIG_DEBUG_BOOT_PARAMS is not set
+# CONFIG_CPA_DEBUG is not set
+# CONFIG_OPTIMIZE_INLINING is not set
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+# CONFIG_KEYS_DEBUG_PROC_KEYS is not set
+CONFIG_SECURITY=y
+CONFIG_SECURITYFS=y
+CONFIG_SECURITY_NETWORK=y
+# CONFIG_SECURITY_NETWORK_XFRM is not set
+CONFIG_SECURITY_FILE_CAPABILITIES=y
+CONFIG_SECURITY_DEFAULT_MMAP_MIN_ADDR=0
+CONFIG_SECURITY_SELINUX=y
+CONFIG_SECURITY_SELINUX_BOOTPARAM=y
+CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=0
+CONFIG_SECURITY_SELINUX_DISABLE=y
+CONFIG_SECURITY_SELINUX_DEVELOP=y
+CONFIG_SECURITY_SELINUX_AVC_STATS=y
+CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1
+# CONFIG_SECURITY_SELINUX_ENABLE_SECMARK_DEFAULT is not set
+# CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX is not set
+CONFIG_XOR_BLOCKS=m
+CONFIG_ASYNC_CORE=m
+CONFIG_ASYNC_MEMCPY=m
+CONFIG_ASYNC_XOR=m
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_FIPS=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD=m
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG=m
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+CONFIG_CRYPTO_GF128MUL=m
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_CRYPTD=m
+CONFIG_CRYPTO_AUTHENC=m
+CONFIG_CRYPTO_TEST=m
+
+#
+# Authenticated Encryption with Associated Data
+#
+CONFIG_CRYPTO_CCM=m
+CONFIG_CRYPTO_GCM=m
+CONFIG_CRYPTO_SEQIV=m
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_CTR=m
+CONFIG_CRYPTO_CTS=m
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_LRW=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_XTS=m
+
+#
+# Hash modes
+#
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_XCBC=m
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=m
+CONFIG_CRYPTO_CRC32C_INTEL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_RMD128=m
+CONFIG_CRYPTO_RMD160=m
+CONFIG_CRYPTO_RMD256=m
+CONFIG_CRYPTO_RMD320=m
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_WP512=m
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_AES_586=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_CAMELLIA=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_DES=y
+CONFIG_CRYPTO_FCRYPT=m
+CONFIG_CRYPTO_KHAZAD=m
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SALSA20_586 is not set
+CONFIG_CRYPTO_SEED=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_TWOFISH_COMMON=m
+CONFIG_CRYPTO_TWOFISH_586=m
+
+#
+# Compression
+#
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_LZO=m
+
+#
+# Random Number Generation
+#
+CONFIG_CRYPTO_ANSI_CPRNG=m
+CONFIG_CRYPTO_HW=y
+CONFIG_CRYPTO_DEV_PADLOCK=m
+CONFIG_CRYPTO_DEV_PADLOCK_AES=m
+CONFIG_CRYPTO_DEV_PADLOCK_SHA=m
+CONFIG_CRYPTO_DEV_GEODE=m
+CONFIG_CRYPTO_DEV_HIFN_795X=m
+# CONFIG_CRYPTO_DEV_HIFN_795X_RNG is not set
+CONFIG_HAVE_KVM=y
+CONFIG_VIRTUALIZATION=y
+CONFIG_KVM=m
+CONFIG_KVM_INTEL=m
+CONFIG_KVM_AMD=m
+CONFIG_VIRTIO=m
+CONFIG_VIRTIO_RING=m
+CONFIG_VIRTIO_PCI=m
+CONFIG_VIRTIO_BALLOON=m
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_FIRST_BIT=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_CRC_CCITT=m
+CONFIG_CRC16=m
+CONFIG_CRC_T10DIF=m
+CONFIG_CRC_ITU_T=m
+CONFIG_CRC32=y
+CONFIG_CRC7=m
+CONFIG_LIBCRC32C=m
+CONFIG_AUDIT_GENERIC=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=m
+CONFIG_LZO_COMPRESS=m
+CONFIG_LZO_DECOMPRESS=m
+CONFIG_GENERIC_ALLOCATOR=y
+CONFIG_REED_SOLOMON=m
+CONFIG_REED_SOLOMON_DEC16=y
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=m
+CONFIG_TEXTSEARCH_BM=m
+CONFIG_TEXTSEARCH_FSM=m
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_CHECK_SIGNATURE=y
diff --git a/pkgs/os-specific/linux/kernel/config-2.6.28-x86_64-smp b/pkgs/os-specific/linux/kernel/config-2.6.28-x86_64-smp
new file mode 100644
index 0000000000000..cb79ec2cc43fa
--- /dev/null
+++ b/pkgs/os-specific/linux/kernel/config-2.6.28-x86_64-smp
@@ -0,0 +1,4002 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.28
+# Mon Jan 12 13:28:01 2009
+#
+CONFIG_64BIT=y
+# CONFIG_X86_32 is not set
+CONFIG_X86_64=y
+CONFIG_X86=y
+CONFIG_ARCH_DEFCONFIG="arch/x86/configs/x86_64_defconfig"
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CMOS_UPDATE=y
+CONFIG_CLOCKSOURCE_WATCHDOG=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_FAST_CMPXCHG_LOCAL=y
+CONFIG_MMU=y
+CONFIG_ZONE_DMA=y
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_GENERIC_IOMAP=y
+CONFIG_GENERIC_BUG=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_TIME_VSYSCALL=y
+CONFIG_ARCH_HAS_CPU_RELAX=y
+CONFIG_ARCH_HAS_DEFAULT_IDLE=y
+CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y
+CONFIG_HAVE_SETUP_PER_CPU_AREA=y
+CONFIG_HAVE_CPUMASK_OF_CPU_MAP=y
+CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_ZONE_DMA32=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_AUDIT_ARCH=y
+CONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_PENDING_IRQ=y
+CONFIG_X86_SMP=y
+CONFIG_USE_GENERIC_SMP_HELPERS=y
+CONFIG_X86_64_SMP=y
+CONFIG_X86_HT=y
+CONFIG_X86_BIOS_REBOOT=y
+CONFIG_X86_TRAMPOLINE=y
+# CONFIG_KTIME_SCALAR is not set
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION="-default"
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_BSD_PROCESS_ACCT_V3=y
+CONFIG_TASKSTATS=y
+CONFIG_TASK_DELAY_ACCT=y
+CONFIG_TASK_XACCT=y
+CONFIG_TASK_IO_ACCOUNTING=y
+CONFIG_AUDIT=y
+CONFIG_AUDITSYSCALL=y
+CONFIG_AUDIT_TREE=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=17
+# CONFIG_CGROUPS is not set
+CONFIG_HAVE_UNSTABLE_SCHED_CLOCK=y
+CONFIG_GROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+# CONFIG_RT_GROUP_SCHED is not set
+CONFIG_USER_SCHED=y
+# CONFIG_CGROUP_SCHED is not set
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
+CONFIG_RELAY=y
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_IPC_NS is not set
+# CONFIG_USER_NS is not set
+# CONFIG_PID_NS is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+# CONFIG_EMBEDDED is not set
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_PCSPKR_PLATFORM=y
+CONFIG_COMPAT_BRK=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_PCI_QUIRKS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+CONFIG_PROFILING=y
+# CONFIG_MARKERS is not set
+CONFIG_OPROFILE=m
+CONFIG_OPROFILE_IBS=y
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
+CONFIG_HAVE_IOREMAP_PROT=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_KMOD=y
+CONFIG_STOP_MACHINE=y
+CONFIG_BLOCK=y
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_BLK_DEV_INTEGRITY=y
+CONFIG_BLOCK_COMPAT=y
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+CONFIG_PREEMPT_NOTIFIERS=y
+CONFIG_CLASSIC_RCU=y
+CONFIG_FREEZER=y
+
+#
+# Processor type and features
+#
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_SMP=y
+CONFIG_X86_FIND_SMP_CONFIG=y
+CONFIG_X86_MPPARSE=y
+CONFIG_X86_PC=y
+# CONFIG_X86_ELAN is not set
+# CONFIG_X86_VOYAGER is not set
+# CONFIG_X86_GENERICARCH is not set
+# CONFIG_X86_VSMP is not set
+CONFIG_PARAVIRT_GUEST=y
+CONFIG_XEN=y
+CONFIG_XEN_MAX_DOMAIN_MEMORY=32
+CONFIG_XEN_SAVE_RESTORE=y
+# CONFIG_XEN_DEBUG_FS is not set
+CONFIG_KVM_CLOCK=y
+CONFIG_KVM_GUEST=y
+CONFIG_PARAVIRT=y
+CONFIG_PARAVIRT_CLOCK=y
+# CONFIG_PARAVIRT_DEBUG is not set
+CONFIG_MEMTEST=y
+# CONFIG_M386 is not set
+# CONFIG_M486 is not set
+# CONFIG_M586 is not set
+# CONFIG_M586TSC is not set
+# CONFIG_M586MMX is not set
+# CONFIG_M686 is not set
+# CONFIG_MPENTIUMII is not set
+# CONFIG_MPENTIUMIII is not set
+# CONFIG_MPENTIUMM is not set
+# CONFIG_MPENTIUM4 is not set
+# CONFIG_MK6 is not set
+# CONFIG_MK7 is not set
+# CONFIG_MK8 is not set
+# CONFIG_MCRUSOE is not set
+# CONFIG_MEFFICEON is not set
+# CONFIG_MWINCHIPC6 is not set
+# CONFIG_MWINCHIP3D is not set
+# CONFIG_MGEODEGX1 is not set
+# CONFIG_MGEODE_LX is not set
+# CONFIG_MCYRIXIII is not set
+# CONFIG_MVIAC3_2 is not set
+# CONFIG_MVIAC7 is not set
+# CONFIG_MPSC is not set
+# CONFIG_MCORE2 is not set
+CONFIG_GENERIC_CPU=y
+CONFIG_X86_CPU=y
+CONFIG_X86_L1_CACHE_BYTES=128
+CONFIG_X86_INTERNODE_CACHE_BYTES=128
+CONFIG_X86_CMPXCHG=y
+CONFIG_X86_L1_CACHE_SHIFT=7
+CONFIG_X86_WP_WORKS_OK=y
+CONFIG_X86_TSC=y
+CONFIG_X86_CMPXCHG64=y
+CONFIG_X86_CMOV=y
+CONFIG_X86_MINIMUM_CPU_FAMILY=64
+CONFIG_X86_DEBUGCTLMSR=y
+CONFIG_CPU_SUP_INTEL=y
+CONFIG_CPU_SUP_AMD=y
+CONFIG_CPU_SUP_CENTAUR_64=y
+# CONFIG_X86_DS is not set
+CONFIG_HPET_TIMER=y
+CONFIG_HPET_EMULATE_RTC=y
+CONFIG_DMI=y
+CONFIG_GART_IOMMU=y
+CONFIG_CALGARY_IOMMU=y
+CONFIG_CALGARY_IOMMU_ENABLED_BY_DEFAULT=y
+CONFIG_AMD_IOMMU=y
+CONFIG_SWIOTLB=y
+CONFIG_IOMMU_HELPER=y
+CONFIG_NR_CPUS=8
+CONFIG_SCHED_SMT=y
+CONFIG_SCHED_MC=y
+# CONFIG_PREEMPT_NONE is not set
+CONFIG_PREEMPT_VOLUNTARY=y
+# CONFIG_PREEMPT is not set
+CONFIG_X86_LOCAL_APIC=y
+CONFIG_X86_IO_APIC=y
+CONFIG_X86_MCE=y
+CONFIG_X86_MCE_INTEL=y
+CONFIG_X86_MCE_AMD=y
+CONFIG_I8K=m
+CONFIG_MICROCODE=m
+CONFIG_MICROCODE_INTEL=y
+CONFIG_MICROCODE_AMD=y
+CONFIG_MICROCODE_OLD_INTERFACE=y
+CONFIG_X86_MSR=m
+CONFIG_X86_CPUID=m
+CONFIG_ARCH_PHYS_ADDR_T_64BIT=y
+# CONFIG_NUMA is not set
+CONFIG_ARCH_SPARSEMEM_DEFAULT=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
+CONFIG_SELECT_MEMORY_MODEL=y
+# CONFIG_FLATMEM_MANUAL is not set
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+CONFIG_SPARSEMEM_MANUAL=y
+CONFIG_SPARSEMEM=y
+CONFIG_HAVE_MEMORY_PRESENT=y
+CONFIG_SPARSEMEM_EXTREME=y
+CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y
+CONFIG_SPARSEMEM_VMEMMAP=y
+
+#
+# Memory hotplug is currently incompatible with Software Suspend
+#
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_RESOURCES_64BIT=y
+CONFIG_PHYS_ADDR_T_64BIT=y
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
+CONFIG_MMU_NOTIFIER=y
+CONFIG_X86_CHECK_BIOS_CORRUPTION=y
+# CONFIG_X86_BOOTPARAM_MEMORY_CORRUPTION_CHECK is not set
+CONFIG_X86_RESERVE_LOW_64K=y
+CONFIG_MTRR=y
+CONFIG_MTRR_SANITIZER=y
+CONFIG_MTRR_SANITIZER_ENABLE_DEFAULT=0
+CONFIG_MTRR_SANITIZER_SPARE_REG_NR_DEFAULT=1
+CONFIG_X86_PAT=y
+CONFIG_EFI=y
+CONFIG_SECCOMP=y
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+CONFIG_SCHED_HRTICK=y
+CONFIG_KEXEC=y
+# CONFIG_CRASH_DUMP is not set
+CONFIG_PHYSICAL_START=0x200000
+# CONFIG_RELOCATABLE is not set
+CONFIG_PHYSICAL_ALIGN=0x200000
+CONFIG_HOTPLUG_CPU=y
+CONFIG_COMPAT_VDSO=y
+# CONFIG_CMDLINE_BOOL is not set
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+
+#
+# Power management and ACPI options
+#
+CONFIG_ARCH_HIBERNATION_HEADER=y
+CONFIG_PM=y
+# CONFIG_PM_DEBUG is not set
+CONFIG_PM_SLEEP_SMP=y
+CONFIG_PM_SLEEP=y
+CONFIG_SUSPEND=y
+CONFIG_SUSPEND_FREEZER=y
+CONFIG_HIBERNATION=y
+CONFIG_PM_STD_PARTITION=""
+CONFIG_ACPI=y
+CONFIG_ACPI_SLEEP=y
+CONFIG_ACPI_PROCFS=y
+CONFIG_ACPI_PROCFS_POWER=y
+CONFIG_ACPI_SYSFS_POWER=y
+CONFIG_ACPI_PROC_EVENT=y
+CONFIG_ACPI_AC=m
+CONFIG_ACPI_BATTERY=m
+CONFIG_ACPI_BUTTON=m
+CONFIG_ACPI_VIDEO=m
+CONFIG_ACPI_FAN=m
+CONFIG_ACPI_DOCK=y
+CONFIG_ACPI_PROCESSOR=m
+CONFIG_ACPI_HOTPLUG_CPU=y
+CONFIG_ACPI_THERMAL=m
+CONFIG_ACPI_WMI=m
+CONFIG_ACPI_ASUS=m
+CONFIG_ACPI_TOSHIBA=m
+CONFIG_ACPI_CUSTOM_DSDT_FILE=""
+# CONFIG_ACPI_CUSTOM_DSDT is not set
+CONFIG_ACPI_BLACKLIST_YEAR=0
+# CONFIG_ACPI_DEBUG is not set
+CONFIG_ACPI_PCI_SLOT=m
+CONFIG_ACPI_SYSTEM=y
+CONFIG_X86_PM_TIMER=y
+CONFIG_ACPI_CONTAINER=m
+# CONFIG_ACPI_SBS is not set
+
+#
+# CPU Frequency scaling
+#
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_TABLE=m
+# CONFIG_CPU_FREQ_DEBUG is not set
+CONFIG_CPU_FREQ_STAT=m
+CONFIG_CPU_FREQ_STAT_DETAILS=y
+CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=m
+CONFIG_CPU_FREQ_GOV_USERSPACE=m
+CONFIG_CPU_FREQ_GOV_ONDEMAND=m
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m
+
+#
+# CPUFreq processor drivers
+#
+CONFIG_X86_ACPI_CPUFREQ=m
+CONFIG_X86_POWERNOW_K8=m
+CONFIG_X86_POWERNOW_K8_ACPI=y
+CONFIG_X86_SPEEDSTEP_CENTRINO=m
+CONFIG_X86_P4_CLOCKMOD=m
+
+#
+# shared options
+#
+# CONFIG_X86_ACPI_CPUFREQ_PROC_INTF is not set
+CONFIG_X86_SPEEDSTEP_LIB=m
+CONFIG_CPU_IDLE=y
+CONFIG_CPU_IDLE_GOV_LADDER=y
+CONFIG_CPU_IDLE_GOV_MENU=y
+
+#
+# Memory power savings
+#
+CONFIG_I7300_IDLE_IOAT_CHANNEL=y
+CONFIG_I7300_IDLE=m
+
+#
+# Bus options (PCI etc.)
+#
+CONFIG_PCI=y
+CONFIG_PCI_DIRECT=y
+CONFIG_PCI_MMCONFIG=y
+CONFIG_PCI_DOMAINS=y
+# CONFIG_DMAR is not set
+# CONFIG_INTR_REMAP is not set
+CONFIG_PCIEPORTBUS=y
+CONFIG_HOTPLUG_PCI_PCIE=m
+CONFIG_PCIEAER=y
+# CONFIG_PCIEASPM is not set
+CONFIG_ARCH_SUPPORTS_MSI=y
+CONFIG_PCI_MSI=y
+CONFIG_PCI_LEGACY=y
+# CONFIG_PCI_DEBUG is not set
+CONFIG_HT_IRQ=y
+CONFIG_ISA_DMA_API=y
+CONFIG_K8_NB=y
+CONFIG_PCCARD=m
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_PCMCIA=m
+CONFIG_PCMCIA_LOAD_CIS=y
+CONFIG_PCMCIA_IOCTL=y
+CONFIG_CARDBUS=y
+
+#
+# PC-card bridges
+#
+CONFIG_YENTA=m
+CONFIG_YENTA_O2=y
+CONFIG_YENTA_RICOH=y
+CONFIG_YENTA_TI=y
+CONFIG_YENTA_ENE_TUNE=y
+CONFIG_YENTA_TOSHIBA=y
+CONFIG_PD6729=m
+CONFIG_I82092=m
+CONFIG_PCCARD_NONSTATIC=m
+CONFIG_HOTPLUG_PCI=m
+CONFIG_HOTPLUG_PCI_FAKE=m
+CONFIG_HOTPLUG_PCI_ACPI=m
+CONFIG_HOTPLUG_PCI_ACPI_IBM=m
+CONFIG_HOTPLUG_PCI_CPCI=y
+CONFIG_HOTPLUG_PCI_CPCI_ZT5550=m
+CONFIG_HOTPLUG_PCI_CPCI_GENERIC=m
+CONFIG_HOTPLUG_PCI_SHPC=m
+
+#
+# Executable file formats / Emulations
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_COMPAT_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_HAVE_AOUT is not set
+CONFIG_BINFMT_MISC=m
+CONFIG_IA32_EMULATION=y
+CONFIG_IA32_AOUT=y
+CONFIG_COMPAT=y
+CONFIG_COMPAT_FOR_U64_ALIGNMENT=y
+CONFIG_SYSVIPC_COMPAT=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=m
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+CONFIG_XFRM_IPCOMP=m
+CONFIG_NET_KEY=m
+# CONFIG_NET_KEY_MIGRATE is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_ASK_IP_FIB_HASH=y
+# CONFIG_IP_FIB_TRIE is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=y
+# CONFIG_IP_PNP is not set
+CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE=m
+CONFIG_NET_IPGRE_BROADCAST=y
+CONFIG_IP_MROUTE=y
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+CONFIG_INET_AH=m
+CONFIG_INET_ESP=m
+CONFIG_INET_IPCOMP=m
+CONFIG_INET_XFRM_TUNNEL=m
+CONFIG_INET_TUNNEL=m
+CONFIG_INET_XFRM_MODE_TRANSPORT=m
+CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_XFRM_MODE_BEET=m
+CONFIG_INET_LRO=m
+CONFIG_INET_DIAG=m
+CONFIG_INET_TCP_DIAG=m
+CONFIG_TCP_CONG_ADVANCED=y
+CONFIG_TCP_CONG_BIC=m
+CONFIG_TCP_CONG_CUBIC=m
+CONFIG_TCP_CONG_WESTWOOD=m
+CONFIG_TCP_CONG_HTCP=m
+CONFIG_TCP_CONG_HSTCP=m
+CONFIG_TCP_CONG_HYBLA=m
+CONFIG_TCP_CONG_VEGAS=m
+CONFIG_TCP_CONG_SCALABLE=m
+# CONFIG_TCP_CONG_LP is not set
+# CONFIG_TCP_CONG_VENO is not set
+CONFIG_TCP_CONG_YEAH=m
+CONFIG_TCP_CONG_ILLINOIS=m
+# CONFIG_DEFAULT_BIC is not set
+# CONFIG_DEFAULT_CUBIC is not set
+# CONFIG_DEFAULT_HTCP is not set
+# CONFIG_DEFAULT_VEGAS is not set
+# CONFIG_DEFAULT_WESTWOOD is not set
+CONFIG_DEFAULT_RENO=y
+CONFIG_DEFAULT_TCP_CONG="reno"
+# CONFIG_TCP_MD5SIG is not set
+CONFIG_IPV6=m
+CONFIG_IPV6_PRIVACY=y
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+# CONFIG_IPV6_MIP6 is not set
+CONFIG_INET6_XFRM_TUNNEL=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_BEET=m
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+CONFIG_IPV6_SIT=m
+CONFIG_IPV6_NDISC_NODETYPE=y
+CONFIG_IPV6_TUNNEL=m
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
+# CONFIG_IPV6_MROUTE is not set
+# CONFIG_NETLABEL is not set
+CONFIG_NETWORK_SECMARK=y
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_NETFILTER_ADVANCED=y
+CONFIG_BRIDGE_NETFILTER=y
+
+#
+# Core Netfilter Configuration
+#
+CONFIG_NETFILTER_NETLINK=m
+CONFIG_NETFILTER_NETLINK_QUEUE=m
+CONFIG_NETFILTER_NETLINK_LOG=m
+CONFIG_NF_CONNTRACK=m
+CONFIG_NF_CT_ACCT=y
+CONFIG_NF_CONNTRACK_MARK=y
+# CONFIG_NF_CONNTRACK_SECMARK is not set
+# CONFIG_NF_CONNTRACK_EVENTS is not set
+# CONFIG_NF_CT_PROTO_DCCP is not set
+CONFIG_NF_CT_PROTO_GRE=m
+CONFIG_NF_CT_PROTO_SCTP=m
+CONFIG_NF_CT_PROTO_UDPLITE=m
+CONFIG_NF_CONNTRACK_AMANDA=m
+CONFIG_NF_CONNTRACK_FTP=m
+CONFIG_NF_CONNTRACK_H323=m
+CONFIG_NF_CONNTRACK_IRC=m
+CONFIG_NF_CONNTRACK_NETBIOS_NS=m
+CONFIG_NF_CONNTRACK_PPTP=m
+CONFIG_NF_CONNTRACK_SANE=m
+CONFIG_NF_CONNTRACK_SIP=m
+CONFIG_NF_CONNTRACK_TFTP=m
+CONFIG_NF_CT_NETLINK=m
+CONFIG_NETFILTER_TPROXY=m
+CONFIG_NETFILTER_XTABLES=m
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
+CONFIG_NETFILTER_XT_TARGET_DSCP=m
+CONFIG_NETFILTER_XT_TARGET_MARK=m
+CONFIG_NETFILTER_XT_TARGET_NFLOG=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
+CONFIG_NETFILTER_XT_TARGET_RATEEST=m
+CONFIG_NETFILTER_XT_TARGET_TPROXY=m
+CONFIG_NETFILTER_XT_TARGET_TRACE=m
+CONFIG_NETFILTER_XT_TARGET_SECMARK=m
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
+# CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set
+CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_DSCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
+CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
+CONFIG_NETFILTER_XT_MATCH_LENGTH=m
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+CONFIG_NETFILTER_XT_MATCH_OWNER=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
+CONFIG_NETFILTER_XT_MATCH_QUOTA=m
+CONFIG_NETFILTER_XT_MATCH_RATEEST=m
+CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_RECENT=m
+# CONFIG_NETFILTER_XT_MATCH_RECENT_PROC_COMPAT is not set
+CONFIG_NETFILTER_XT_MATCH_SCTP=m
+CONFIG_NETFILTER_XT_MATCH_SOCKET=m
+CONFIG_NETFILTER_XT_MATCH_STATE=m
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
+CONFIG_NETFILTER_XT_MATCH_STRING=m
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+CONFIG_NETFILTER_XT_MATCH_TIME=m
+CONFIG_NETFILTER_XT_MATCH_U32=m
+CONFIG_IP_VS=m
+# CONFIG_IP_VS_IPV6 is not set
+# CONFIG_IP_VS_DEBUG is not set
+CONFIG_IP_VS_TAB_BITS=12
+
+#
+# IPVS transport protocol load balancing support
+#
+CONFIG_IP_VS_PROTO_TCP=y
+CONFIG_IP_VS_PROTO_UDP=y
+CONFIG_IP_VS_PROTO_AH_ESP=y
+CONFIG_IP_VS_PROTO_ESP=y
+CONFIG_IP_VS_PROTO_AH=y
+
+#
+# IPVS scheduler
+#
+CONFIG_IP_VS_RR=m
+CONFIG_IP_VS_WRR=m
+CONFIG_IP_VS_LC=m
+CONFIG_IP_VS_WLC=m
+CONFIG_IP_VS_LBLC=m
+CONFIG_IP_VS_LBLCR=m
+CONFIG_IP_VS_DH=m
+CONFIG_IP_VS_SH=m
+CONFIG_IP_VS_SED=m
+CONFIG_IP_VS_NQ=m
+
+#
+# IPVS application helper
+#
+CONFIG_IP_VS_FTP=m
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_NF_DEFRAG_IPV4=m
+CONFIG_NF_CONNTRACK_IPV4=m
+CONFIG_NF_CONNTRACK_PROC_COMPAT=y
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_NF_NAT=m
+CONFIG_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_NF_NAT_SNMP_BASIC=m
+CONFIG_NF_NAT_PROTO_GRE=m
+CONFIG_NF_NAT_PROTO_UDPLITE=m
+CONFIG_NF_NAT_PROTO_SCTP=m
+CONFIG_NF_NAT_FTP=m
+CONFIG_NF_NAT_IRC=m
+CONFIG_NF_NAT_TFTP=m
+CONFIG_NF_NAT_AMANDA=m
+CONFIG_NF_NAT_PPTP=m
+CONFIG_NF_NAT_H323=m
+CONFIG_NF_NAT_SIP=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_SECURITY=m
+# CONFIG_IP_NF_ARPTABLES is not set
+
+#
+# IPv6: Netfilter Configuration
+#
+CONFIG_NF_CONNTRACK_IPV6=m
+CONFIG_IP6_NF_QUEUE=m
+CONFIG_IP6_NF_IPTABLES=m
+CONFIG_IP6_NF_MATCH_AH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
+CONFIG_IP6_NF_MATCH_FRAG=m
+CONFIG_IP6_NF_MATCH_OPTS=m
+CONFIG_IP6_NF_MATCH_HL=m
+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
+CONFIG_IP6_NF_MATCH_MH=m
+CONFIG_IP6_NF_MATCH_RT=m
+CONFIG_IP6_NF_TARGET_LOG=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_IP6_NF_TARGET_HL=m
+CONFIG_IP6_NF_RAW=m
+CONFIG_IP6_NF_SECURITY=m
+
+#
+# DECnet: Netfilter Configuration
+#
+CONFIG_DECNET_NF_GRABULATOR=m
+CONFIG_BRIDGE_NF_EBTABLES=m
+CONFIG_BRIDGE_EBT_BROUTE=m
+CONFIG_BRIDGE_EBT_T_FILTER=m
+CONFIG_BRIDGE_EBT_T_NAT=m
+CONFIG_BRIDGE_EBT_802_3=m
+CONFIG_BRIDGE_EBT_AMONG=m
+CONFIG_BRIDGE_EBT_ARP=m
+CONFIG_BRIDGE_EBT_IP=m
+CONFIG_BRIDGE_EBT_IP6=m
+CONFIG_BRIDGE_EBT_LIMIT=m
+CONFIG_BRIDGE_EBT_MARK=m
+CONFIG_BRIDGE_EBT_PKTTYPE=m
+CONFIG_BRIDGE_EBT_STP=m
+CONFIG_BRIDGE_EBT_VLAN=m
+CONFIG_BRIDGE_EBT_ARPREPLY=m
+CONFIG_BRIDGE_EBT_DNAT=m
+CONFIG_BRIDGE_EBT_MARK_T=m
+CONFIG_BRIDGE_EBT_REDIRECT=m
+CONFIG_BRIDGE_EBT_SNAT=m
+CONFIG_BRIDGE_EBT_LOG=m
+CONFIG_BRIDGE_EBT_ULOG=m
+CONFIG_BRIDGE_EBT_NFLOG=m
+# CONFIG_IP_DCCP is not set
+CONFIG_IP_SCTP=m
+# CONFIG_SCTP_DBG_MSG is not set
+# CONFIG_SCTP_DBG_OBJCNT is not set
+# CONFIG_SCTP_HMAC_NONE is not set
+# CONFIG_SCTP_HMAC_SHA1 is not set
+CONFIG_SCTP_HMAC_MD5=y
+# CONFIG_TIPC is not set
+CONFIG_ATM=m
+CONFIG_ATM_CLIP=m
+CONFIG_ATM_CLIP_NO_ICMP=y
+CONFIG_ATM_LANE=m
+CONFIG_ATM_MPOA=m
+CONFIG_ATM_BR2684=m
+# CONFIG_ATM_BR2684_IPFILTER is not set
+CONFIG_STP=m
+CONFIG_BRIDGE=m
+# CONFIG_NET_DSA is not set
+CONFIG_VLAN_8021Q=m
+# CONFIG_VLAN_8021Q_GVRP is not set
+CONFIG_DECNET=m
+CONFIG_DECNET_ROUTER=y
+CONFIG_LLC=y
+CONFIG_LLC2=m
+CONFIG_IPX=m
+# CONFIG_IPX_INTERN is not set
+CONFIG_ATALK=m
+CONFIG_DEV_APPLETALK=m
+CONFIG_IPDDP=m
+CONFIG_IPDDP_ENCAP=y
+CONFIG_IPDDP_DECAP=y
+CONFIG_X25=m
+CONFIG_LAPB=m
+CONFIG_ECONET=m
+# CONFIG_ECONET_AUNUDP is not set
+# CONFIG_ECONET_NATIVE is not set
+CONFIG_WAN_ROUTER=m
+CONFIG_NET_SCHED=y
+
+#
+# Queueing/Scheduling
+#
+CONFIG_NET_SCH_CBQ=m
+CONFIG_NET_SCH_HTB=m
+CONFIG_NET_SCH_HFSC=m
+CONFIG_NET_SCH_ATM=m
+CONFIG_NET_SCH_PRIO=m
+CONFIG_NET_SCH_MULTIQ=m
+CONFIG_NET_SCH_RED=m
+CONFIG_NET_SCH_SFQ=m
+CONFIG_NET_SCH_TEQL=m
+CONFIG_NET_SCH_TBF=m
+CONFIG_NET_SCH_GRED=m
+CONFIG_NET_SCH_DSMARK=m
+CONFIG_NET_SCH_NETEM=m
+CONFIG_NET_SCH_INGRESS=m
+
+#
+# Classification
+#
+CONFIG_NET_CLS=y
+CONFIG_NET_CLS_BASIC=m
+CONFIG_NET_CLS_TCINDEX=m
+CONFIG_NET_CLS_ROUTE4=m
+CONFIG_NET_CLS_ROUTE=y
+CONFIG_NET_CLS_FW=m
+CONFIG_NET_CLS_U32=m
+CONFIG_CLS_U32_PERF=y
+CONFIG_CLS_U32_MARK=y
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+CONFIG_NET_CLS_FLOW=m
+# CONFIG_NET_EMATCH is not set
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_ACT_POLICE=m
+CONFIG_NET_ACT_GACT=m
+CONFIG_GACT_PROB=y
+CONFIG_NET_ACT_MIRRED=m
+CONFIG_NET_ACT_IPT=m
+CONFIG_NET_ACT_NAT=m
+CONFIG_NET_ACT_PEDIT=m
+CONFIG_NET_ACT_SIMP=m
+CONFIG_NET_ACT_SKBEDIT=m
+# CONFIG_NET_CLS_IND is not set
+CONFIG_NET_SCH_FIFO=y
+
+#
+# Network testing
+#
+CONFIG_NET_PKTGEN=m
+CONFIG_HAMRADIO=y
+
+#
+# Packet Radio protocols
+#
+CONFIG_AX25=m
+CONFIG_AX25_DAMA_SLAVE=y
+CONFIG_NETROM=m
+CONFIG_ROSE=m
+
+#
+# AX.25 network device drivers
+#
+CONFIG_MKISS=m
+CONFIG_6PACK=m
+CONFIG_BPQETHER=m
+CONFIG_BAYCOM_SER_FDX=m
+CONFIG_BAYCOM_SER_HDX=m
+CONFIG_BAYCOM_PAR=m
+CONFIG_YAM=m
+# CONFIG_CAN is not set
+CONFIG_IRDA=m
+
+#
+# IrDA protocols
+#
+CONFIG_IRLAN=m
+CONFIG_IRNET=m
+CONFIG_IRCOMM=m
+CONFIG_IRDA_ULTRA=y
+
+#
+# IrDA options
+#
+CONFIG_IRDA_CACHE_LAST_LSAP=y
+# CONFIG_IRDA_FAST_RR is not set
+# CONFIG_IRDA_DEBUG is not set
+
+#
+# Infrared-port device drivers
+#
+
+#
+# SIR device drivers
+#
+CONFIG_IRTTY_SIR=m
+
+#
+# Dongle support
+#
+CONFIG_DONGLE=y
+CONFIG_ESI_DONGLE=m
+CONFIG_ACTISYS_DONGLE=m
+CONFIG_TEKRAM_DONGLE=m
+# CONFIG_TOIM3232_DONGLE is not set
+CONFIG_LITELINK_DONGLE=m
+CONFIG_MA600_DONGLE=m
+CONFIG_GIRBIL_DONGLE=m
+CONFIG_MCP2120_DONGLE=m
+CONFIG_OLD_BELKIN_DONGLE=m
+CONFIG_ACT200L_DONGLE=m
+CONFIG_KINGSUN_DONGLE=m
+# CONFIG_KSDAZZLE_DONGLE is not set
+# CONFIG_KS959_DONGLE is not set
+
+#
+# FIR device drivers
+#
+CONFIG_USB_IRDA=m
+CONFIG_SIGMATEL_FIR=m
+CONFIG_NSC_FIR=m
+CONFIG_WINBOND_FIR=m
+CONFIG_SMC_IRCC_FIR=m
+CONFIG_ALI_FIR=m
+CONFIG_VLSI_FIR=m
+CONFIG_VIA_FIR=m
+CONFIG_MCS_FIR=m
+CONFIG_BT=m
+CONFIG_BT_L2CAP=m
+CONFIG_BT_SCO=m
+CONFIG_BT_RFCOMM=m
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=m
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=m
+
+#
+# Bluetooth device drivers
+#
+CONFIG_BT_HCIBTUSB=m
+CONFIG_BT_HCIBTSDIO=m
+CONFIG_BT_HCIUART=m
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_BCSP=y
+CONFIG_BT_HCIUART_LL=y
+CONFIG_BT_HCIBCM203X=m
+CONFIG_BT_HCIBPA10X=m
+CONFIG_BT_HCIBFUSB=m
+CONFIG_BT_HCIDTL1=m
+CONFIG_BT_HCIBT3C=m
+CONFIG_BT_HCIBLUECARD=m
+CONFIG_BT_HCIBTUART=m
+CONFIG_BT_HCIVHCI=m
+CONFIG_AF_RXRPC=m
+# CONFIG_AF_RXRPC_DEBUG is not set
+CONFIG_RXKAD=m
+CONFIG_PHONET=m
+CONFIG_FIB_RULES=y
+CONFIG_WIRELESS=y
+CONFIG_CFG80211=m
+CONFIG_NL80211=y
+CONFIG_WIRELESS_OLD_REGULATORY=y
+CONFIG_WIRELESS_EXT=y
+CONFIG_WIRELESS_EXT_SYSFS=y
+CONFIG_MAC80211=m
+
+#
+# Rate control algorithm selection
+#
+CONFIG_MAC80211_RC_PID=y
+# CONFIG_MAC80211_RC_MINSTREL is not set
+CONFIG_MAC80211_RC_DEFAULT_PID=y
+# CONFIG_MAC80211_RC_DEFAULT_MINSTREL is not set
+CONFIG_MAC80211_RC_DEFAULT="pid"
+# CONFIG_MAC80211_MESH is not set
+CONFIG_MAC80211_LEDS=y
+# CONFIG_MAC80211_DEBUGFS is not set
+# CONFIG_MAC80211_DEBUG_MENU is not set
+CONFIG_IEEE80211=m
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT_WEP=m
+CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_CRYPT_TKIP=m
+CONFIG_RFKILL=m
+CONFIG_RFKILL_INPUT=m
+CONFIG_RFKILL_LEDS=y
+CONFIG_NET_9P=m
+# CONFIG_NET_9P_VIRTIO is not set
+CONFIG_NET_9P_RDMA=m
+# CONFIG_NET_9P_DEBUG is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_STANDALONE is not set
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+CONFIG_CONNECTOR=m
+CONFIG_MTD=m
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_CONCAT=m
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_REDBOOT_PARTS=m
+CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
+# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
+# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
+CONFIG_MTD_AR7_PARTS=m
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=m
+CONFIG_HAVE_MTD_OTP=y
+CONFIG_MTD_BLKDEVS=m
+CONFIG_MTD_BLOCK=m
+# CONFIG_MTD_BLOCK_RO is not set
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+CONFIG_MTD_OOPS=m
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=m
+CONFIG_MTD_JEDECPROBE=m
+CONFIG_MTD_GEN_PROBE=m
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_NOSWAP=y
+# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
+# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
+# CONFIG_MTD_CFI_GEOMETRY is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_OTP is not set
+CONFIG_MTD_CFI_INTELEXT=m
+CONFIG_MTD_CFI_AMDSTD=m
+CONFIG_MTD_CFI_STAA=m
+CONFIG_MTD_CFI_UTIL=m
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+CONFIG_MTD_ABSENT=m
+
+#
+# Mapping drivers for chip access
+#
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+CONFIG_MTD_PHYSMAP=m
+CONFIG_MTD_PHYSMAP_START=0x8000000
+CONFIG_MTD_PHYSMAP_LEN=0x4000000
+CONFIG_MTD_PHYSMAP_BANKWIDTH=2
+CONFIG_MTD_SC520CDP=m
+CONFIG_MTD_NETSC520=m
+CONFIG_MTD_TS5500=m
+CONFIG_MTD_SBC_GXX=m
+CONFIG_MTD_AMD76XROM=m
+CONFIG_MTD_ICHXROM=m
+CONFIG_MTD_ESB2ROM=m
+CONFIG_MTD_CK804XROM=m
+CONFIG_MTD_SCB2_FLASH=m
+CONFIG_MTD_NETtel=m
+CONFIG_MTD_DILNETPC=m
+CONFIG_MTD_DILNETPC_BOOTSIZE=0x80000
+CONFIG_MTD_L440GX=m
+CONFIG_MTD_PCI=m
+CONFIG_MTD_INTEL_VR_NOR=m
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+CONFIG_MTD_PMC551=m
+CONFIG_MTD_PMC551_BUGFIX=y
+# CONFIG_MTD_PMC551_DEBUG is not set
+CONFIG_MTD_DATAFLASH=m
+# CONFIG_MTD_DATAFLASH_WRITE_VERIFY is not set
+CONFIG_MTD_DATAFLASH_OTP=y
+CONFIG_MTD_M25P80=m
+CONFIG_M25PXX_USE_FAST_READ=y
+CONFIG_MTD_SLRAM=m
+CONFIG_MTD_PHRAM=m
+CONFIG_MTD_MTDRAM=m
+CONFIG_MTDRAM_TOTAL_SIZE=4096
+CONFIG_MTDRAM_ERASE_SIZE=128
+CONFIG_MTD_BLOCK2MTD=m
+
+#
+# Disk-On-Chip Device Drivers
+#
+CONFIG_MTD_DOC2000=m
+CONFIG_MTD_DOC2001=m
+CONFIG_MTD_DOC2001PLUS=m
+CONFIG_MTD_DOCPROBE=m
+CONFIG_MTD_DOCECC=m
+CONFIG_MTD_DOCPROBE_ADVANCED=y
+CONFIG_MTD_DOCPROBE_ADDRESS=0x0000
+CONFIG_MTD_DOCPROBE_HIGH=y
+CONFIG_MTD_DOCPROBE_55AA=y
+CONFIG_MTD_NAND=m
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+# CONFIG_MTD_NAND_ECC_SMC is not set
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+CONFIG_MTD_NAND_IDS=m
+CONFIG_MTD_NAND_DISKONCHIP=m
+# CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADVANCED is not set
+CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS=0
+CONFIG_MTD_NAND_DISKONCHIP_BBTWRITE=y
+CONFIG_MTD_NAND_CAFE=m
+CONFIG_MTD_NAND_NANDSIM=m
+CONFIG_MTD_NAND_PLATFORM=m
+CONFIG_MTD_ALAUDA=m
+# CONFIG_MTD_ONENAND is not set
+
+#
+# UBI - Unsorted block images
+#
+CONFIG_MTD_UBI=m
+CONFIG_MTD_UBI_WL_THRESHOLD=4096
+CONFIG_MTD_UBI_BEB_RESERVE=1
+# CONFIG_MTD_UBI_GLUEBI is not set
+
+#
+# UBI debugging options
+#
+# CONFIG_MTD_UBI_DEBUG is not set
+CONFIG_PARPORT=m
+CONFIG_PARPORT_PC=m
+CONFIG_PARPORT_SERIAL=m
+CONFIG_PARPORT_PC_FIFO=y
+CONFIG_PARPORT_PC_SUPERIO=y
+CONFIG_PARPORT_PC_PCMCIA=m
+# CONFIG_PARPORT_GSC is not set
+# CONFIG_PARPORT_AX88796 is not set
+CONFIG_PARPORT_1284=y
+CONFIG_PARPORT_NOT_PC=y
+CONFIG_PNP=y
+CONFIG_PNP_DEBUG_MESSAGES=y
+
+#
+# Protocols
+#
+CONFIG_PNPACPI=y
+CONFIG_BLK_DEV=y
+CONFIG_BLK_DEV_FD=y
+CONFIG_PARIDE=m
+
+#
+# Parallel IDE high-level drivers
+#
+CONFIG_PARIDE_PD=m
+CONFIG_PARIDE_PCD=m
+CONFIG_PARIDE_PF=m
+CONFIG_PARIDE_PT=m
+CONFIG_PARIDE_PG=m
+
+#
+# Parallel IDE protocol modules
+#
+CONFIG_PARIDE_ATEN=m
+CONFIG_PARIDE_BPCK=m
+CONFIG_PARIDE_COMM=m
+CONFIG_PARIDE_DSTR=m
+CONFIG_PARIDE_FIT2=m
+CONFIG_PARIDE_FIT3=m
+CONFIG_PARIDE_EPAT=m
+CONFIG_PARIDE_EPATC8=y
+CONFIG_PARIDE_EPIA=m
+CONFIG_PARIDE_FRIQ=m
+CONFIG_PARIDE_FRPW=m
+CONFIG_PARIDE_KBIC=m
+CONFIG_PARIDE_KTTI=m
+CONFIG_PARIDE_ON20=m
+CONFIG_PARIDE_ON26=m
+CONFIG_BLK_CPQ_DA=m
+CONFIG_BLK_CPQ_CISS_DA=m
+CONFIG_CISS_SCSI_TAPE=y
+CONFIG_BLK_DEV_DAC960=m
+CONFIG_BLK_DEV_UMEM=m
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+CONFIG_BLK_DEV_NBD=m
+CONFIG_BLK_DEV_SX8=m
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=64000
+# CONFIG_BLK_DEV_XIP is not set
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+CONFIG_CDROM_PKTCDVD_WCACHE=y
+CONFIG_ATA_OVER_ETH=m
+CONFIG_XEN_BLKDEV_FRONTEND=m
+CONFIG_VIRTIO_BLK=m
+# CONFIG_BLK_DEV_HD is not set
+CONFIG_MISC_DEVICES=y
+CONFIG_IBM_ASM=m
+CONFIG_PHANTOM=m
+CONFIG_EEPROM_93CX6=m
+# CONFIG_SGI_IOC4 is not set
+CONFIG_TIFM_CORE=m
+CONFIG_TIFM_7XX1=m
+CONFIG_ACER_WMI=m
+CONFIG_ASUS_LAPTOP=m
+CONFIG_FUJITSU_LAPTOP=m
+# CONFIG_FUJITSU_LAPTOP_DEBUG is not set
+CONFIG_HP_WMI=m
+CONFIG_ICS932S401=m
+CONFIG_MSI_LAPTOP=m
+CONFIG_PANASONIC_LAPTOP=m
+CONFIG_COMPAL_LAPTOP=m
+CONFIG_SONY_LAPTOP=m
+CONFIG_SONYPI_COMPAT=y
+CONFIG_THINKPAD_ACPI=m
+# CONFIG_THINKPAD_ACPI_DEBUG is not set
+CONFIG_THINKPAD_ACPI_BAY=y
+CONFIG_THINKPAD_ACPI_VIDEO=y
+CONFIG_THINKPAD_ACPI_HOTKEY_POLL=y
+CONFIG_INTEL_MENLOW=m
+CONFIG_EEEPC_LAPTOP=m
+CONFIG_ENCLOSURE_SERVICES=m
+CONFIG_SGI_XP=m
+CONFIG_HP_ILO=m
+CONFIG_SGI_GRU=m
+# CONFIG_SGI_GRU_DEBUG is not set
+# CONFIG_C2PORT is not set
+CONFIG_HAVE_IDE=y
+CONFIG_IDE=m
+
+#
+# Please see Documentation/ide/ide.txt for help/info on IDE drives
+#
+CONFIG_IDE_TIMINGS=y
+CONFIG_IDE_ATAPI=y
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_IDE_GD=m
+CONFIG_IDE_GD_ATA=y
+CONFIG_IDE_GD_ATAPI=y
+CONFIG_BLK_DEV_IDECS=m
+CONFIG_BLK_DEV_DELKIN=m
+CONFIG_BLK_DEV_IDECD=m
+CONFIG_BLK_DEV_IDECD_VERBOSE_ERRORS=y
+CONFIG_BLK_DEV_IDETAPE=m
+CONFIG_BLK_DEV_IDESCSI=m
+CONFIG_BLK_DEV_IDEACPI=y
+# CONFIG_IDE_TASK_IOCTL is not set
+CONFIG_IDE_PROC_FS=y
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=m
+CONFIG_BLK_DEV_PLATFORM=m
+CONFIG_BLK_DEV_CMD640=m
+CONFIG_BLK_DEV_CMD640_ENHANCED=y
+CONFIG_BLK_DEV_IDEPNP=m
+CONFIG_BLK_DEV_IDEDMA_SFF=y
+
+#
+# PCI IDE chipsets support
+#
+CONFIG_BLK_DEV_IDEPCI=y
+CONFIG_BLK_DEV_OFFBOARD=y
+CONFIG_BLK_DEV_GENERIC=m
+CONFIG_BLK_DEV_OPTI621=m
+CONFIG_BLK_DEV_RZ1000=m
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+CONFIG_BLK_DEV_AEC62XX=m
+CONFIG_BLK_DEV_ALI15X3=m
+CONFIG_BLK_DEV_AMD74XX=m
+CONFIG_BLK_DEV_ATIIXP=m
+CONFIG_BLK_DEV_CMD64X=m
+CONFIG_BLK_DEV_TRIFLEX=m
+CONFIG_BLK_DEV_CS5520=m
+CONFIG_BLK_DEV_CS5530=m
+CONFIG_BLK_DEV_HPT366=m
+CONFIG_BLK_DEV_JMICRON=m
+CONFIG_BLK_DEV_SC1200=m
+CONFIG_BLK_DEV_PIIX=m
+CONFIG_BLK_DEV_IT8213=m
+CONFIG_BLK_DEV_IT821X=m
+CONFIG_BLK_DEV_NS87415=m
+CONFIG_BLK_DEV_PDC202XX_OLD=m
+CONFIG_BLK_DEV_PDC202XX_NEW=m
+CONFIG_BLK_DEV_SVWKS=m
+CONFIG_BLK_DEV_SIIMAGE=m
+CONFIG_BLK_DEV_SIS5513=m
+CONFIG_BLK_DEV_SLC90E66=m
+CONFIG_BLK_DEV_TRM290=m
+CONFIG_BLK_DEV_VIA82CXXX=m
+CONFIG_BLK_DEV_TC86C001=m
+CONFIG_BLK_DEV_IDEDMA=y
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=m
+CONFIG_SCSI_DMA=y
+CONFIG_SCSI_TGT=m
+CONFIG_SCSI_NETLINK=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+CONFIG_CHR_DEV_ST=m
+CONFIG_CHR_DEV_OSST=m
+CONFIG_BLK_DEV_SR=m
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+CONFIG_CHR_DEV_SG=m
+CONFIG_CHR_DEV_SCH=m
+CONFIG_SCSI_ENCLOSURE=m
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+CONFIG_SCSI_SPI_ATTRS=m
+CONFIG_SCSI_FC_ATTRS=m
+# CONFIG_SCSI_FC_TGT_ATTRS is not set
+CONFIG_SCSI_ISCSI_ATTRS=m
+CONFIG_SCSI_SAS_ATTRS=m
+CONFIG_SCSI_SAS_LIBSAS=m
+# CONFIG_SCSI_SAS_ATA is not set
+CONFIG_SCSI_SAS_HOST_SMP=y
+# CONFIG_SCSI_SAS_LIBSAS_DEBUG is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
+CONFIG_ISCSI_TCP=m
+CONFIG_BLK_DEV_3W_XXXX_RAID=m
+CONFIG_SCSI_3W_9XXX=m
+CONFIG_SCSI_ACARD=m
+CONFIG_SCSI_AACRAID=m
+CONFIG_SCSI_AIC7XXX=m
+CONFIG_AIC7XXX_CMDS_PER_DEVICE=32
+CONFIG_AIC7XXX_RESET_DELAY_MS=5000
+# CONFIG_AIC7XXX_DEBUG_ENABLE is not set
+CONFIG_AIC7XXX_DEBUG_MASK=0
+CONFIG_AIC7XXX_REG_PRETTY_PRINT=y
+CONFIG_SCSI_AIC7XXX_OLD=m
+CONFIG_SCSI_AIC79XX=m
+CONFIG_AIC79XX_CMDS_PER_DEVICE=32
+CONFIG_AIC79XX_RESET_DELAY_MS=15000
+# CONFIG_AIC79XX_DEBUG_ENABLE is not set
+CONFIG_AIC79XX_DEBUG_MASK=0
+CONFIG_AIC79XX_REG_PRETTY_PRINT=y
+CONFIG_SCSI_AIC94XX=m
+# CONFIG_AIC94XX_DEBUG is not set
+CONFIG_SCSI_DPT_I2O=m
+CONFIG_SCSI_ADVANSYS=m
+CONFIG_SCSI_ARCMSR=m
+# CONFIG_SCSI_ARCMSR_AER is not set
+CONFIG_MEGARAID_NEWGEN=y
+CONFIG_MEGARAID_MM=m
+CONFIG_MEGARAID_MAILBOX=m
+CONFIG_MEGARAID_LEGACY=m
+CONFIG_MEGARAID_SAS=m
+CONFIG_SCSI_HPTIOP=m
+CONFIG_SCSI_BUSLOGIC=m
+CONFIG_SCSI_DMX3191D=m
+CONFIG_SCSI_EATA=m
+CONFIG_SCSI_EATA_TAGGED_QUEUE=y
+CONFIG_SCSI_EATA_LINKED_COMMANDS=y
+CONFIG_SCSI_EATA_MAX_TAGS=16
+CONFIG_SCSI_FUTURE_DOMAIN=m
+CONFIG_SCSI_GDTH=m
+CONFIG_SCSI_IPS=m
+CONFIG_SCSI_INITIO=m
+CONFIG_SCSI_INIA100=m
+CONFIG_SCSI_PPA=m
+CONFIG_SCSI_IMM=m
+# CONFIG_SCSI_IZIP_EPP16 is not set
+# CONFIG_SCSI_IZIP_SLOW_CTR is not set
+CONFIG_SCSI_MVSAS=m
+CONFIG_SCSI_STEX=m
+CONFIG_SCSI_SYM53C8XX_2=m
+CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1
+CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
+CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
+CONFIG_SCSI_SYM53C8XX_MMIO=y
+CONFIG_SCSI_IPR=m
+# CONFIG_SCSI_IPR_TRACE is not set
+# CONFIG_SCSI_IPR_DUMP is not set
+CONFIG_SCSI_QLOGIC_1280=m
+CONFIG_SCSI_QLA_FC=m
+CONFIG_SCSI_QLA_ISCSI=m
+CONFIG_SCSI_LPFC=m
+CONFIG_SCSI_DC395x=m
+CONFIG_SCSI_DC390T=m
+CONFIG_SCSI_DEBUG=m
+CONFIG_SCSI_SRP=m
+CONFIG_SCSI_LOWLEVEL_PCMCIA=y
+CONFIG_PCMCIA_FDOMAIN=m
+CONFIG_PCMCIA_QLOGIC=m
+CONFIG_PCMCIA_SYM53C500=m
+CONFIG_SCSI_DH=m
+CONFIG_SCSI_DH_RDAC=m
+CONFIG_SCSI_DH_HP_SW=m
+CONFIG_SCSI_DH_EMC=m
+CONFIG_SCSI_DH_ALUA=m
+CONFIG_ATA=m
+# CONFIG_ATA_NONSTANDARD is not set
+CONFIG_ATA_ACPI=y
+CONFIG_SATA_PMP=y
+CONFIG_SATA_AHCI=m
+CONFIG_SATA_SIL24=m
+CONFIG_ATA_SFF=y
+CONFIG_SATA_SVW=m
+CONFIG_ATA_PIIX=m
+# CONFIG_SATA_MV is not set
+CONFIG_SATA_NV=m
+CONFIG_PDC_ADMA=m
+CONFIG_SATA_QSTOR=m
+CONFIG_SATA_PROMISE=m
+CONFIG_SATA_SX4=m
+CONFIG_SATA_SIL=m
+CONFIG_SATA_SIS=m
+CONFIG_SATA_ULI=m
+CONFIG_SATA_VIA=m
+CONFIG_SATA_VITESSE=m
+CONFIG_SATA_INIC162X=m
+CONFIG_PATA_ACPI=m
+CONFIG_PATA_ALI=m
+CONFIG_PATA_AMD=m
+CONFIG_PATA_ARTOP=m
+CONFIG_PATA_ATIIXP=m
+CONFIG_PATA_CMD640_PCI=m
+# CONFIG_PATA_CMD64X is not set
+CONFIG_PATA_CS5520=m
+CONFIG_PATA_CS5530=m
+# CONFIG_PATA_CYPRESS is not set
+CONFIG_PATA_EFAR=m
+CONFIG_ATA_GENERIC=m
+CONFIG_PATA_HPT366=m
+CONFIG_PATA_HPT37X=m
+CONFIG_PATA_HPT3X2N=m
+CONFIG_PATA_HPT3X3=m
+# CONFIG_PATA_HPT3X3_DMA is not set
+CONFIG_PATA_IT821X=m
+CONFIG_PATA_IT8213=m
+CONFIG_PATA_JMICRON=m
+CONFIG_PATA_TRIFLEX=m
+CONFIG_PATA_MARVELL=m
+CONFIG_PATA_MPIIX=m
+CONFIG_PATA_OLDPIIX=m
+CONFIG_PATA_NETCELL=m
+CONFIG_PATA_NINJA32=m
+CONFIG_PATA_NS87410=m
+CONFIG_PATA_NS87415=m
+# CONFIG_PATA_OPTI is not set
+# CONFIG_PATA_OPTIDMA is not set
+CONFIG_PATA_PCMCIA=m
+# CONFIG_PATA_PDC_OLD is not set
+# CONFIG_PATA_RADISYS is not set
+CONFIG_PATA_RZ1000=m
+CONFIG_PATA_SC1200=m
+CONFIG_PATA_SERVERWORKS=m
+CONFIG_PATA_PDC2027X=m
+CONFIG_PATA_SIL680=m
+CONFIG_PATA_SIS=m
+CONFIG_PATA_VIA=m
+CONFIG_PATA_WINBOND=m
+CONFIG_PATA_SCH=m
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=y
+CONFIG_MD_AUTODETECT=y
+CONFIG_MD_LINEAR=m
+CONFIG_MD_RAID0=m
+CONFIG_MD_RAID1=m
+CONFIG_MD_RAID10=m
+CONFIG_MD_RAID456=m
+# CONFIG_MD_RAID5_RESHAPE is not set
+CONFIG_MD_MULTIPATH=m
+CONFIG_MD_FAULTY=m
+CONFIG_BLK_DEV_DM=m
+# CONFIG_DM_DEBUG is not set
+CONFIG_DM_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
+CONFIG_DM_MULTIPATH=m
+# CONFIG_DM_DELAY is not set
+CONFIG_DM_UEVENT=y
+CONFIG_FUSION=y
+CONFIG_FUSION_SPI=m
+CONFIG_FUSION_FC=m
+CONFIG_FUSION_SAS=m
+CONFIG_FUSION_MAX_SGE=128
+CONFIG_FUSION_CTL=m
+CONFIG_FUSION_LAN=m
+# CONFIG_FUSION_LOGGING is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# Enable only one of the two stacks, unless you know what you are doing
+#
+# CONFIG_FIREWIRE is not set
+CONFIG_IEEE1394=m
+CONFIG_IEEE1394_OHCI1394=m
+CONFIG_IEEE1394_PCILYNX=m
+CONFIG_IEEE1394_SBP2=m
+# CONFIG_IEEE1394_SBP2_PHYS_DMA is not set
+CONFIG_IEEE1394_ETH1394_ROM_ENTRY=y
+CONFIG_IEEE1394_ETH1394=m
+CONFIG_IEEE1394_RAWIO=m
+CONFIG_IEEE1394_VIDEO1394=m
+CONFIG_IEEE1394_DV1394=m
+# CONFIG_IEEE1394_VERBOSEDEBUG is not set
+CONFIG_I2O=m
+CONFIG_I2O_LCT_NOTIFY_ON_CHANGES=y
+CONFIG_I2O_EXT_ADAPTEC=y
+CONFIG_I2O_EXT_ADAPTEC_DMA64=y
+CONFIG_I2O_CONFIG=m
+CONFIG_I2O_CONFIG_OLD_IOCTL=y
+CONFIG_I2O_BUS=m
+CONFIG_I2O_BLOCK=m
+CONFIG_I2O_SCSI=m
+CONFIG_I2O_PROC=m
+CONFIG_MACINTOSH_DRIVERS=y
+CONFIG_MAC_EMUMOUSEBTN=y
+CONFIG_NETDEVICES=y
+# CONFIG_IFB is not set
+CONFIG_DUMMY=m
+CONFIG_BONDING=m
+# CONFIG_MACVLAN is not set
+CONFIG_EQUALIZER=m
+CONFIG_TUN=m
+CONFIG_VETH=m
+CONFIG_NET_SB1000=m
+CONFIG_ARCNET=m
+CONFIG_ARCNET_1201=m
+CONFIG_ARCNET_1051=m
+CONFIG_ARCNET_RAW=m
+CONFIG_ARCNET_CAP=m
+CONFIG_ARCNET_COM90xx=m
+CONFIG_ARCNET_COM90xxIO=m
+CONFIG_ARCNET_RIM_I=m
+# CONFIG_ARCNET_COM20020 is not set
+CONFIG_PHYLIB=m
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=m
+CONFIG_DAVICOM_PHY=m
+CONFIG_QSEMI_PHY=m
+CONFIG_LXT_PHY=m
+CONFIG_CICADA_PHY=m
+CONFIG_VITESSE_PHY=m
+CONFIG_SMSC_PHY=m
+CONFIG_BROADCOM_PHY=m
+CONFIG_ICPLUS_PHY=m
+CONFIG_REALTEK_PHY=m
+# CONFIG_MDIO_BITBANG is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=m
+CONFIG_HAPPYMEAL=m
+CONFIG_SUNGEM=m
+CONFIG_CASSINI=m
+CONFIG_NET_VENDOR_3COM=y
+CONFIG_VORTEX=m
+CONFIG_TYPHOON=m
+CONFIG_ENC28J60=m
+# CONFIG_ENC28J60_WRITEVERIFY is not set
+CONFIG_NET_TULIP=y
+CONFIG_DE2104X=m
+CONFIG_TULIP=m
+# CONFIG_TULIP_MWI is not set
+# CONFIG_TULIP_MMIO is not set
+CONFIG_TULIP_NAPI=y
+CONFIG_TULIP_NAPI_HW_MITIGATION=y
+CONFIG_DE4X5=m
+CONFIG_WINBOND_840=m
+CONFIG_DM9102=m
+CONFIG_ULI526X=m
+CONFIG_PCMCIA_XIRCOM=m
+CONFIG_HP100=m
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+CONFIG_NET_PCI=y
+CONFIG_PCNET32=m
+CONFIG_AMD8111_ETH=m
+CONFIG_ADAPTEC_STARFIRE=m
+CONFIG_B44=m
+CONFIG_B44_PCI_AUTOSELECT=y
+CONFIG_B44_PCICORE_AUTOSELECT=y
+CONFIG_B44_PCI=y
+CONFIG_FORCEDETH=m
+# CONFIG_FORCEDETH_NAPI is not set
+CONFIG_EEPRO100=m
+CONFIG_E100=m
+CONFIG_FEALNX=m
+CONFIG_NATSEMI=m
+CONFIG_NE2K_PCI=m
+CONFIG_8139CP=m
+CONFIG_8139TOO=m
+# CONFIG_8139TOO_PIO is not set
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+CONFIG_8139TOO_8129=y
+# CONFIG_8139_OLD_RX_RESET is not set
+CONFIG_R6040=m
+CONFIG_SIS900=m
+CONFIG_EPIC100=m
+CONFIG_SUNDANCE=m
+# CONFIG_SUNDANCE_MMIO is not set
+CONFIG_TLAN=m
+CONFIG_VIA_RHINE=m
+# CONFIG_VIA_RHINE_MMIO is not set
+CONFIG_SC92031=m
+CONFIG_NET_POCKET=y
+CONFIG_ATP=m
+CONFIG_DE600=m
+CONFIG_DE620=m
+CONFIG_ATL2=m
+CONFIG_NETDEV_1000=y
+CONFIG_ACENIC=m
+# CONFIG_ACENIC_OMIT_TIGON_I is not set
+CONFIG_DL2K=m
+CONFIG_E1000=m
+CONFIG_E1000E=m
+CONFIG_IP1000=m
+CONFIG_IGB=m
+# CONFIG_IGB_LRO is not set
+CONFIG_IGB_DCA=y
+CONFIG_NS83820=m
+CONFIG_HAMACHI=m
+CONFIG_YELLOWFIN=m
+CONFIG_R8169=m
+CONFIG_R8169_VLAN=y
+CONFIG_SIS190=m
+CONFIG_SKGE=m
+# CONFIG_SKGE_DEBUG is not set
+# CONFIG_SKY2 is not set
+CONFIG_VIA_VELOCITY=m
+CONFIG_TIGON3=m
+CONFIG_BNX2=m
+CONFIG_QLA3XXX=m
+CONFIG_ATL1=m
+CONFIG_ATL1E=m
+CONFIG_JME=m
+CONFIG_NETDEV_10000=y
+CONFIG_CHELSIO_T1=m
+CONFIG_CHELSIO_T1_1G=y
+CONFIG_CHELSIO_T3=m
+CONFIG_ENIC=m
+CONFIG_IXGBE=m
+CONFIG_IXGBE_DCA=y
+CONFIG_IXGB=m
+CONFIG_S2IO=m
+CONFIG_MYRI10GE=m
+CONFIG_MYRI10GE_DCA=y
+CONFIG_NETXEN_NIC=m
+CONFIG_NIU=m
+CONFIG_MLX4_EN=m
+CONFIG_MLX4_CORE=m
+CONFIG_MLX4_DEBUG=y
+CONFIG_TEHUTI=m
+CONFIG_BNX2X=m
+CONFIG_QLGE=m
+CONFIG_SFC=m
+CONFIG_TR=y
+CONFIG_IBMOL=m
+CONFIG_3C359=m
+CONFIG_TMS380TR=m
+CONFIG_TMSPCI=m
+CONFIG_ABYSS=m
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+CONFIG_WLAN_80211=y
+CONFIG_PCMCIA_RAYCS=m
+CONFIG_IPW2100=m
+CONFIG_IPW2100_MONITOR=y
+# CONFIG_IPW2100_DEBUG is not set
+CONFIG_IPW2200=m
+CONFIG_IPW2200_MONITOR=y
+CONFIG_IPW2200_RADIOTAP=y
+CONFIG_IPW2200_PROMISCUOUS=y
+CONFIG_IPW2200_QOS=y
+# CONFIG_IPW2200_DEBUG is not set
+CONFIG_LIBERTAS=m
+CONFIG_LIBERTAS_USB=m
+CONFIG_LIBERTAS_CS=m
+CONFIG_LIBERTAS_SDIO=m
+# CONFIG_LIBERTAS_DEBUG is not set
+CONFIG_LIBERTAS_THINFIRM=m
+CONFIG_LIBERTAS_THINFIRM_USB=m
+CONFIG_AIRO=m
+CONFIG_HERMES=m
+CONFIG_PLX_HERMES=m
+CONFIG_TMD_HERMES=m
+CONFIG_NORTEL_HERMES=m
+CONFIG_PCI_HERMES=m
+CONFIG_PCMCIA_HERMES=m
+CONFIG_PCMCIA_SPECTRUM=m
+CONFIG_ATMEL=m
+CONFIG_PCI_ATMEL=m
+CONFIG_PCMCIA_ATMEL=m
+CONFIG_AIRO_CS=m
+CONFIG_PCMCIA_WL3501=m
+CONFIG_PRISM54=m
+CONFIG_USB_ZD1201=m
+CONFIG_USB_NET_RNDIS_WLAN=m
+CONFIG_RTL8180=m
+CONFIG_RTL8187=m
+CONFIG_ADM8211=m
+# CONFIG_MAC80211_HWSIM is not set
+CONFIG_P54_COMMON=m
+CONFIG_P54_USB=m
+CONFIG_P54_PCI=m
+CONFIG_ATH5K=m
+# CONFIG_ATH5K_DEBUG is not set
+CONFIG_ATH9K=m
+CONFIG_IWLWIFI=m
+CONFIG_IWLCORE=m
+CONFIG_IWLWIFI_LEDS=y
+CONFIG_IWLWIFI_RFKILL=y
+# CONFIG_IWLWIFI_DEBUG is not set
+CONFIG_IWLAGN=m
+CONFIG_IWLAGN_SPECTRUM_MEASUREMENT=y
+CONFIG_IWLAGN_LEDS=y
+CONFIG_IWL4965=y
+CONFIG_IWL5000=y
+CONFIG_IWL3945=m
+CONFIG_IWL3945_RFKILL=y
+# CONFIG_IWL3945_SPECTRUM_MEASUREMENT is not set
+CONFIG_IWL3945_LEDS=y
+# CONFIG_IWL3945_DEBUG is not set
+CONFIG_HOSTAP=m
+CONFIG_HOSTAP_FIRMWARE=y
+CONFIG_HOSTAP_FIRMWARE_NVRAM=y
+CONFIG_HOSTAP_PLX=m
+CONFIG_HOSTAP_PCI=m
+CONFIG_HOSTAP_CS=m
+CONFIG_B43=m
+CONFIG_B43_PCI_AUTOSELECT=y
+CONFIG_B43_PCICORE_AUTOSELECT=y
+CONFIG_B43_PCMCIA=y
+CONFIG_B43_PIO=y
+CONFIG_B43_LEDS=y
+CONFIG_B43_RFKILL=y
+# CONFIG_B43_DEBUG is not set
+CONFIG_B43LEGACY=m
+CONFIG_B43LEGACY_PCI_AUTOSELECT=y
+CONFIG_B43LEGACY_PCICORE_AUTOSELECT=y
+CONFIG_B43LEGACY_LEDS=y
+CONFIG_B43LEGACY_RFKILL=y
+CONFIG_B43LEGACY_DEBUG=y
+CONFIG_B43LEGACY_DMA=y
+CONFIG_B43LEGACY_PIO=y
+CONFIG_B43LEGACY_DMA_AND_PIO_MODE=y
+# CONFIG_B43LEGACY_DMA_MODE is not set
+# CONFIG_B43LEGACY_PIO_MODE is not set
+CONFIG_ZD1211RW=m
+# CONFIG_ZD1211RW_DEBUG is not set
+CONFIG_RT2X00=m
+CONFIG_RT2400PCI=m
+CONFIG_RT2500PCI=m
+CONFIG_RT61PCI=m
+CONFIG_RT2500USB=m
+CONFIG_RT73USB=m
+CONFIG_RT2X00_LIB_PCI=m
+CONFIG_RT2X00_LIB_USB=m
+CONFIG_RT2X00_LIB=m
+CONFIG_RT2X00_LIB_FIRMWARE=y
+CONFIG_RT2X00_LIB_CRYPTO=y
+CONFIG_RT2X00_LIB_RFKILL=y
+CONFIG_RT2X00_LIB_LEDS=y
+# CONFIG_RT2X00_DEBUG is not set
+
+#
+# USB Network Adapters
+#
+CONFIG_USB_CATC=m
+CONFIG_USB_KAWETH=m
+CONFIG_USB_PEGASUS=m
+CONFIG_USB_RTL8150=m
+CONFIG_USB_USBNET=m
+CONFIG_USB_NET_AX8817X=m
+CONFIG_USB_NET_CDCETHER=m
+CONFIG_USB_NET_DM9601=m
+CONFIG_USB_NET_SMSC95XX=m
+CONFIG_USB_NET_GL620A=m
+CONFIG_USB_NET_NET1080=m
+CONFIG_USB_NET_PLUSB=m
+CONFIG_USB_NET_MCS7830=m
+CONFIG_USB_NET_RNDIS_HOST=m
+CONFIG_USB_NET_CDC_SUBSET=m
+CONFIG_USB_ALI_M5632=y
+CONFIG_USB_AN2720=y
+CONFIG_USB_BELKIN=y
+CONFIG_USB_ARMLINUX=y
+# CONFIG_USB_EPSON2888 is not set
+# CONFIG_USB_KC2190 is not set
+CONFIG_USB_NET_ZAURUS=m
+CONFIG_USB_HSO=m
+CONFIG_NET_PCMCIA=y
+CONFIG_PCMCIA_3C589=m
+CONFIG_PCMCIA_3C574=m
+CONFIG_PCMCIA_FMVJ18X=m
+CONFIG_PCMCIA_PCNET=m
+CONFIG_PCMCIA_NMCLAN=m
+CONFIG_PCMCIA_SMC91C92=m
+CONFIG_PCMCIA_XIRC2PS=m
+CONFIG_PCMCIA_AXNET=m
+CONFIG_PCMCIA_IBMTR=m
+CONFIG_WAN=y
+CONFIG_LANMEDIA=m
+CONFIG_HDLC=m
+CONFIG_HDLC_RAW=m
+CONFIG_HDLC_RAW_ETH=m
+CONFIG_HDLC_CISCO=m
+CONFIG_HDLC_FR=m
+CONFIG_HDLC_PPP=m
+CONFIG_HDLC_X25=m
+CONFIG_PCI200SYN=m
+CONFIG_WANXL=m
+# CONFIG_PC300TOO is not set
+CONFIG_FARSYNC=m
+# CONFIG_DSCC4 is not set
+CONFIG_DLCI=m
+CONFIG_DLCI_MAX=8
+# CONFIG_WAN_ROUTER_DRIVERS is not set
+CONFIG_LAPBETHER=m
+CONFIG_X25_ASY=m
+# CONFIG_SBNI is not set
+CONFIG_ATM_DRIVERS=y
+# CONFIG_ATM_DUMMY is not set
+CONFIG_ATM_TCP=m
+CONFIG_ATM_LANAI=m
+CONFIG_ATM_ENI=m
+# CONFIG_ATM_ENI_DEBUG is not set
+# CONFIG_ATM_ENI_TUNE_BURST is not set
+CONFIG_ATM_FIRESTREAM=m
+CONFIG_ATM_ZATM=m
+# CONFIG_ATM_ZATM_DEBUG is not set
+CONFIG_ATM_IDT77252=m
+# CONFIG_ATM_IDT77252_DEBUG is not set
+CONFIG_ATM_IDT77252_RCV_ALL=y
+CONFIG_ATM_IDT77252_USE_SUNI=y
+# CONFIG_ATM_AMBASSADOR is not set
+CONFIG_ATM_HORIZON=m
+# CONFIG_ATM_HORIZON_DEBUG is not set
+CONFIG_ATM_IA=m
+# CONFIG_ATM_IA_DEBUG is not set
+CONFIG_ATM_FORE200E=m
+CONFIG_ATM_FORE200E_USE_TASKLET=y
+CONFIG_ATM_FORE200E_TX_RETRY=16
+CONFIG_ATM_FORE200E_DEBUG=0
+CONFIG_ATM_HE=m
+CONFIG_ATM_HE_USE_SUNI=y
+CONFIG_XEN_NETDEV_FRONTEND=m
+CONFIG_FDDI=y
+CONFIG_DEFXX=m
+# CONFIG_DEFXX_MMIO is not set
+CONFIG_SKFP=m
+CONFIG_HIPPI=y
+CONFIG_ROADRUNNER=m
+CONFIG_ROADRUNNER_LARGE_RINGS=y
+CONFIG_PLIP=m
+CONFIG_PPP=m
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_MPPE=m
+CONFIG_PPPOE=m
+CONFIG_PPPOATM=m
+# CONFIG_PPPOL2TP is not set
+CONFIG_SLIP=m
+CONFIG_SLIP_COMPRESSED=y
+CONFIG_SLHC=m
+CONFIG_SLIP_SMART=y
+CONFIG_SLIP_MODE_SLIP6=y
+CONFIG_NET_FC=y
+CONFIG_NETCONSOLE=m
+# CONFIG_NETCONSOLE_DYNAMIC is not set
+CONFIG_NETPOLL=y
+CONFIG_NETPOLL_TRAP=y
+CONFIG_NET_POLL_CONTROLLER=y
+CONFIG_VIRTIO_NET=m
+# CONFIG_ISDN is not set
+CONFIG_PHONE=m
+CONFIG_PHONE_IXJ=m
+CONFIG_PHONE_IXJ_PCMCIA=m
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+CONFIG_INPUT_FF_MEMLESS=m
+CONFIG_INPUT_POLLDEV=m
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+CONFIG_INPUT_JOYDEV=m
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+CONFIG_XEN_KBDDEV_FRONTEND=m
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+CONFIG_KEYBOARD_SUNKBD=m
+# CONFIG_KEYBOARD_LKKBD is not set
+CONFIG_KEYBOARD_XTKBD=m
+CONFIG_KEYBOARD_NEWTON=m
+CONFIG_KEYBOARD_STOWAWAY=m
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_PS2_ALPS=y
+CONFIG_MOUSE_PS2_LOGIPS2PP=y
+CONFIG_MOUSE_PS2_SYNAPTICS=y
+CONFIG_MOUSE_PS2_LIFEBOOK=y
+CONFIG_MOUSE_PS2_TRACKPOINT=y
+CONFIG_MOUSE_PS2_ELANTECH=y
+# CONFIG_MOUSE_PS2_TOUCHKIT is not set
+CONFIG_MOUSE_SERIAL=m
+CONFIG_MOUSE_APPLETOUCH=m
+CONFIG_MOUSE_BCM5974=m
+# CONFIG_MOUSE_VSXXXAA is not set
+CONFIG_INPUT_JOYSTICK=y
+CONFIG_JOYSTICK_ANALOG=m
+CONFIG_JOYSTICK_A3D=m
+CONFIG_JOYSTICK_ADI=m
+CONFIG_JOYSTICK_COBRA=m
+CONFIG_JOYSTICK_GF2K=m
+CONFIG_JOYSTICK_GRIP=m
+CONFIG_JOYSTICK_GRIP_MP=m
+CONFIG_JOYSTICK_GUILLEMOT=m
+CONFIG_JOYSTICK_INTERACT=m
+CONFIG_JOYSTICK_SIDEWINDER=m
+CONFIG_JOYSTICK_TMDC=m
+CONFIG_JOYSTICK_IFORCE=m
+CONFIG_JOYSTICK_IFORCE_USB=y
+CONFIG_JOYSTICK_IFORCE_232=y
+CONFIG_JOYSTICK_WARRIOR=m
+CONFIG_JOYSTICK_MAGELLAN=m
+CONFIG_JOYSTICK_SPACEORB=m
+CONFIG_JOYSTICK_SPACEBALL=m
+CONFIG_JOYSTICK_STINGER=m
+CONFIG_JOYSTICK_TWIDJOY=m
+# CONFIG_JOYSTICK_ZHENHUA is not set
+CONFIG_JOYSTICK_DB9=m
+CONFIG_JOYSTICK_GAMECON=m
+CONFIG_JOYSTICK_TURBOGRAFX=m
+CONFIG_JOYSTICK_JOYDUMP=m
+CONFIG_JOYSTICK_XPAD=m
+CONFIG_JOYSTICK_XPAD_FF=y
+CONFIG_JOYSTICK_XPAD_LEDS=y
+CONFIG_INPUT_TABLET=y
+CONFIG_TABLET_USB_ACECAD=m
+CONFIG_TABLET_USB_AIPTEK=m
+CONFIG_TABLET_USB_GTCO=m
+CONFIG_TABLET_USB_KBTAB=m
+CONFIG_TABLET_USB_WACOM=m
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_ADS7846=m
+CONFIG_TOUCHSCREEN_FUJITSU=m
+CONFIG_TOUCHSCREEN_GUNZE=m
+CONFIG_TOUCHSCREEN_ELO=m
+CONFIG_TOUCHSCREEN_MTOUCH=m
+CONFIG_TOUCHSCREEN_INEXIO=m
+CONFIG_TOUCHSCREEN_MK712=m
+CONFIG_TOUCHSCREEN_PENMOUNT=m
+CONFIG_TOUCHSCREEN_TOUCHRIGHT=m
+CONFIG_TOUCHSCREEN_TOUCHWIN=m
+CONFIG_TOUCHSCREEN_WM97XX=m
+CONFIG_TOUCHSCREEN_WM9705=y
+CONFIG_TOUCHSCREEN_WM9712=y
+CONFIG_TOUCHSCREEN_WM9713=y
+CONFIG_TOUCHSCREEN_USB_COMPOSITE=m
+CONFIG_TOUCHSCREEN_USB_EGALAX=y
+CONFIG_TOUCHSCREEN_USB_PANJIT=y
+CONFIG_TOUCHSCREEN_USB_3M=y
+CONFIG_TOUCHSCREEN_USB_ITM=y
+CONFIG_TOUCHSCREEN_USB_ETURBO=y
+CONFIG_TOUCHSCREEN_USB_GUNZE=y
+CONFIG_TOUCHSCREEN_USB_DMC_TSC10=y
+CONFIG_TOUCHSCREEN_USB_IRTOUCH=y
+CONFIG_TOUCHSCREEN_USB_IDEALTEK=y
+CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH=y
+CONFIG_TOUCHSCREEN_USB_GOTOP=y
+CONFIG_TOUCHSCREEN_TOUCHIT213=m
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_PCSPKR=y
+CONFIG_INPUT_APANEL=m
+CONFIG_INPUT_ATLAS_BTNS=m
+CONFIG_INPUT_ATI_REMOTE=m
+CONFIG_INPUT_ATI_REMOTE2=m
+CONFIG_INPUT_KEYSPAN_REMOTE=m
+CONFIG_INPUT_POWERMATE=m
+CONFIG_INPUT_YEALINK=m
+CONFIG_INPUT_CM109=m
+CONFIG_INPUT_UINPUT=m
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=m
+CONFIG_SERIO_CT82C710=m
+CONFIG_SERIO_PARKBD=m
+CONFIG_SERIO_PCIPS2=m
+CONFIG_SERIO_LIBPS2=y
+CONFIG_SERIO_RAW=m
+CONFIG_GAMEPORT=m
+CONFIG_GAMEPORT_NS558=m
+CONFIG_GAMEPORT_L4=m
+CONFIG_GAMEPORT_EMU10K1=m
+CONFIG_GAMEPORT_FM801=m
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_DEVKMEM=y
+CONFIG_SERIAL_NONSTANDARD=y
+# CONFIG_COMPUTONE is not set
+CONFIG_ROCKETPORT=m
+CONFIG_CYCLADES=m
+# CONFIG_CYZ_INTR is not set
+CONFIG_DIGIEPCA=m
+# CONFIG_MOXA_INTELLIO is not set
+CONFIG_MOXA_SMARTIO=m
+# CONFIG_ISI is not set
+CONFIG_SYNCLINK=m
+CONFIG_SYNCLINKMP=m
+CONFIG_SYNCLINK_GT=m
+CONFIG_N_HDLC=m
+CONFIG_RISCOM8=m
+# CONFIG_SPECIALIX is not set
+CONFIG_SX=m
+CONFIG_RIO=m
+CONFIG_RIO_OLDPCI=y
+CONFIG_STALDRV=y
+CONFIG_STALLION=m
+CONFIG_ISTALLION=m
+CONFIG_NOZOMI=m
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_FIX_EARLYCON_MEM=y
+CONFIG_SERIAL_8250_PCI=y
+CONFIG_SERIAL_8250_PNP=y
+CONFIG_SERIAL_8250_CS=m
+CONFIG_SERIAL_8250_NR_UARTS=8
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+CONFIG_SERIAL_8250_RSA=y
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_JSM=m
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+CONFIG_PRINTER=m
+# CONFIG_LP_CONSOLE is not set
+CONFIG_PPDEV=m
+CONFIG_HVC_DRIVER=y
+CONFIG_HVC_IRQ=y
+CONFIG_HVC_XEN=y
+CONFIG_VIRTIO_CONSOLE=m
+CONFIG_IPMI_HANDLER=m
+CONFIG_IPMI_PANIC_EVENT=y
+CONFIG_IPMI_PANIC_STRING=y
+CONFIG_IPMI_DEVICE_INTERFACE=m
+CONFIG_IPMI_SI=m
+CONFIG_IPMI_WATCHDOG=m
+CONFIG_IPMI_POWEROFF=m
+CONFIG_HW_RANDOM=y
+CONFIG_HW_RANDOM_INTEL=m
+CONFIG_HW_RANDOM_AMD=m
+CONFIG_HW_RANDOM_VIRTIO=m
+CONFIG_NVRAM=m
+CONFIG_R3964=m
+CONFIG_APPLICOM=m
+
+#
+# PCMCIA character devices
+#
+CONFIG_SYNCLINK_CS=m
+CONFIG_CARDMAN_4000=m
+CONFIG_CARDMAN_4040=m
+CONFIG_IPWIRELESS=m
+CONFIG_MWAVE=m
+CONFIG_PC8736x_GPIO=m
+CONFIG_NSC_GPIO=m
+CONFIG_RAW_DRIVER=m
+CONFIG_MAX_RAW_DEVS=4096
+CONFIG_HPET=y
+CONFIG_HPET_MMAP=y
+CONFIG_HANGCHECK_TIMER=m
+CONFIG_TCG_TPM=m
+CONFIG_TCG_TIS=m
+CONFIG_TCG_NSC=m
+CONFIG_TCG_ATMEL=m
+CONFIG_TCG_INFINEON=m
+CONFIG_TELCLOCK=m
+CONFIG_DEVPORT=y
+CONFIG_I2C=m
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=m
+CONFIG_I2C_HELPER_AUTO=y
+CONFIG_I2C_ALGOBIT=m
+CONFIG_I2C_ALGOPCA=m
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# PC SMBus host controller drivers
+#
+CONFIG_I2C_ALI1535=m
+CONFIG_I2C_ALI1563=m
+CONFIG_I2C_ALI15X3=m
+CONFIG_I2C_AMD756=m
+CONFIG_I2C_AMD756_S4882=m
+CONFIG_I2C_AMD8111=m
+CONFIG_I2C_I801=m
+CONFIG_I2C_ISCH=m
+CONFIG_I2C_PIIX4=m
+CONFIG_I2C_NFORCE2=m
+CONFIG_I2C_NFORCE2_S4985=m
+CONFIG_I2C_SIS5595=m
+CONFIG_I2C_SIS630=m
+CONFIG_I2C_SIS96X=m
+CONFIG_I2C_VIA=m
+CONFIG_I2C_VIAPRO=m
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+CONFIG_I2C_OCORES=m
+CONFIG_I2C_SIMTEC=m
+
+#
+# External I2C/SMBus adapter drivers
+#
+CONFIG_I2C_PARPORT=m
+CONFIG_I2C_PARPORT_LIGHT=m
+CONFIG_I2C_TAOS_EVM=m
+CONFIG_I2C_TINY_USB=m
+
+#
+# Graphics adapter I2C/DDC channel drivers
+#
+CONFIG_I2C_VOODOO3=m
+
+#
+# Other I2C/SMBus bus drivers
+#
+CONFIG_I2C_PCA_PLATFORM=m
+CONFIG_I2C_STUB=m
+
+#
+# Miscellaneous I2C Chip support
+#
+CONFIG_DS1682=m
+CONFIG_AT24=m
+CONFIG_SENSORS_EEPROM=m
+CONFIG_SENSORS_PCF8574=m
+CONFIG_PCF8575=m
+# CONFIG_SENSORS_PCA9539 is not set
+CONFIG_SENSORS_PCF8591=m
+CONFIG_SENSORS_MAX6875=m
+CONFIG_SENSORS_TSL2550=m
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+CONFIG_SPI=y
+# CONFIG_SPI_DEBUG is not set
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+CONFIG_SPI_BITBANG=m
+# CONFIG_SPI_BUTTERFLY is not set
+CONFIG_SPI_LM70_LLP=m
+
+#
+# SPI Protocol Masters
+#
+CONFIG_SPI_AT25=m
+CONFIG_SPI_SPIDEV=m
+CONFIG_SPI_TLE62X0=m
+CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
+# CONFIG_GPIOLIB is not set
+CONFIG_W1=m
+CONFIG_W1_CON=y
+
+#
+# 1-wire Bus Masters
+#
+CONFIG_W1_MASTER_MATROX=m
+CONFIG_W1_MASTER_DS2490=m
+CONFIG_W1_MASTER_DS2482=m
+
+#
+# 1-wire Slaves
+#
+CONFIG_W1_SLAVE_THERM=m
+CONFIG_W1_SLAVE_SMEM=m
+CONFIG_W1_SLAVE_DS2433=m
+# CONFIG_W1_SLAVE_DS2433_CRC is not set
+CONFIG_W1_SLAVE_DS2760=m
+CONFIG_W1_SLAVE_BQ27000=m
+CONFIG_POWER_SUPPLY=y
+# CONFIG_POWER_SUPPLY_DEBUG is not set
+# CONFIG_PDA_POWER is not set
+# CONFIG_BATTERY_DS2760 is not set
+CONFIG_BATTERY_BQ27x00=m
+CONFIG_HWMON=m
+CONFIG_HWMON_VID=m
+CONFIG_SENSORS_ABITUGURU=m
+CONFIG_SENSORS_ABITUGURU3=m
+CONFIG_SENSORS_AD7414=m
+CONFIG_SENSORS_AD7418=m
+CONFIG_SENSORS_ADCXX=m
+CONFIG_SENSORS_ADM1021=m
+CONFIG_SENSORS_ADM1025=m
+CONFIG_SENSORS_ADM1026=m
+CONFIG_SENSORS_ADM1029=m
+CONFIG_SENSORS_ADM1031=m
+CONFIG_SENSORS_ADM9240=m
+CONFIG_SENSORS_ADT7462=m
+CONFIG_SENSORS_ADT7470=m
+CONFIG_SENSORS_ADT7473=m
+CONFIG_SENSORS_K8TEMP=m
+CONFIG_SENSORS_ASB100=m
+CONFIG_SENSORS_ATXP1=m
+CONFIG_SENSORS_DS1621=m
+CONFIG_SENSORS_I5K_AMB=m
+CONFIG_SENSORS_F71805F=m
+CONFIG_SENSORS_F71882FG=m
+CONFIG_SENSORS_F75375S=m
+CONFIG_SENSORS_FSCHER=m
+CONFIG_SENSORS_FSCPOS=m
+CONFIG_SENSORS_FSCHMD=m
+CONFIG_SENSORS_GL518SM=m
+CONFIG_SENSORS_GL520SM=m
+CONFIG_SENSORS_CORETEMP=m
+CONFIG_SENSORS_IBMAEM=m
+CONFIG_SENSORS_IBMPEX=m
+CONFIG_SENSORS_IT87=m
+CONFIG_SENSORS_LM63=m
+CONFIG_SENSORS_LM70=m
+CONFIG_SENSORS_LM75=m
+CONFIG_SENSORS_LM77=m
+CONFIG_SENSORS_LM78=m
+CONFIG_SENSORS_LM80=m
+CONFIG_SENSORS_LM83=m
+CONFIG_SENSORS_LM85=m
+CONFIG_SENSORS_LM87=m
+CONFIG_SENSORS_LM90=m
+CONFIG_SENSORS_LM92=m
+CONFIG_SENSORS_LM93=m
+CONFIG_SENSORS_MAX1111=m
+CONFIG_SENSORS_MAX1619=m
+CONFIG_SENSORS_MAX6650=m
+CONFIG_SENSORS_PC87360=m
+CONFIG_SENSORS_PC87427=m
+CONFIG_SENSORS_SIS5595=m
+CONFIG_SENSORS_DME1737=m
+CONFIG_SENSORS_SMSC47M1=m
+CONFIG_SENSORS_SMSC47M192=m
+CONFIG_SENSORS_SMSC47B397=m
+CONFIG_SENSORS_ADS7828=m
+CONFIG_SENSORS_THMC50=m
+CONFIG_SENSORS_VIA686A=m
+CONFIG_SENSORS_VT1211=m
+CONFIG_SENSORS_VT8231=m
+CONFIG_SENSORS_W83781D=m
+CONFIG_SENSORS_W83791D=m
+CONFIG_SENSORS_W83792D=m
+CONFIG_SENSORS_W83793=m
+CONFIG_SENSORS_W83L785TS=m
+CONFIG_SENSORS_W83L786NG=m
+CONFIG_SENSORS_W83627HF=m
+CONFIG_SENSORS_W83627EHF=m
+CONFIG_SENSORS_HDAPS=m
+CONFIG_SENSORS_LIS3LV02D=m
+CONFIG_SENSORS_APPLESMC=m
+# CONFIG_HWMON_DEBUG_CHIP is not set
+CONFIG_THERMAL=y
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+CONFIG_SOFT_WATCHDOG=m
+CONFIG_ACQUIRE_WDT=m
+CONFIG_ADVANTECH_WDT=m
+CONFIG_ALIM1535_WDT=m
+CONFIG_ALIM7101_WDT=m
+CONFIG_SC520_WDT=m
+CONFIG_EUROTECH_WDT=m
+CONFIG_IB700_WDT=m
+CONFIG_IBMASR=m
+CONFIG_WAFER_WDT=m
+CONFIG_I6300ESB_WDT=m
+CONFIG_ITCO_WDT=m
+CONFIG_ITCO_VENDOR_SUPPORT=y
+CONFIG_IT8712F_WDT=m
+CONFIG_IT87_WDT=m
+CONFIG_HP_WATCHDOG=m
+CONFIG_SC1200_WDT=m
+CONFIG_PC87413_WDT=m
+CONFIG_60XX_WDT=m
+CONFIG_SBC8360_WDT=m
+CONFIG_CPU5_WDT=m
+CONFIG_SMSC37B787_WDT=m
+CONFIG_W83627HF_WDT=m
+CONFIG_W83697HF_WDT=m
+CONFIG_W83697UG_WDT=m
+CONFIG_W83877F_WDT=m
+CONFIG_W83977F_WDT=m
+CONFIG_MACHZ_WDT=m
+CONFIG_SBC_EPX_C3_WATCHDOG=m
+
+#
+# PCI-based Watchdog Cards
+#
+CONFIG_PCIPCWATCHDOG=m
+CONFIG_WDTPCI=m
+CONFIG_WDT_501_PCI=y
+
+#
+# USB-based Watchdog Cards
+#
+CONFIG_USBPCWATCHDOG=m
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+CONFIG_SSB=m
+CONFIG_SSB_SPROM=y
+CONFIG_SSB_BLOCKIO=y
+CONFIG_SSB_PCIHOST_POSSIBLE=y
+CONFIG_SSB_PCIHOST=y
+CONFIG_SSB_B43_PCI_BRIDGE=y
+CONFIG_SSB_PCMCIAHOST_POSSIBLE=y
+CONFIG_SSB_PCMCIAHOST=y
+# CONFIG_SSB_DEBUG is not set
+CONFIG_SSB_DRIVER_PCICORE_POSSIBLE=y
+CONFIG_SSB_DRIVER_PCICORE=y
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+CONFIG_MFD_SM501=m
+CONFIG_HTC_PASIC3=m
+# CONFIG_MFD_TMIO is not set
+CONFIG_MFD_WM8400=m
+CONFIG_MFD_WM8350=m
+CONFIG_MFD_WM8350_I2C=m
+CONFIG_REGULATOR=y
+# CONFIG_REGULATOR_DEBUG is not set
+# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
+# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
+CONFIG_REGULATOR_BQ24022=m
+CONFIG_REGULATOR_WM8350=m
+CONFIG_REGULATOR_WM8400=m
+
+#
+# Multimedia devices
+#
+
+#
+# Multimedia core support
+#
+CONFIG_VIDEO_DEV=m
+CONFIG_VIDEO_V4L2_COMMON=m
+CONFIG_VIDEO_ALLOW_V4L1=y
+CONFIG_VIDEO_V4L1_COMPAT=y
+CONFIG_DVB_CORE=m
+CONFIG_VIDEO_MEDIA=m
+
+#
+# Multimedia drivers
+#
+CONFIG_VIDEO_SAA7146=m
+CONFIG_VIDEO_SAA7146_VV=m
+CONFIG_MEDIA_ATTACH=y
+CONFIG_MEDIA_TUNER=m
+# CONFIG_MEDIA_TUNER_CUSTOMIZE is not set
+CONFIG_MEDIA_TUNER_SIMPLE=m
+CONFIG_MEDIA_TUNER_TDA8290=m
+CONFIG_MEDIA_TUNER_TDA827X=m
+CONFIG_MEDIA_TUNER_TDA18271=m
+CONFIG_MEDIA_TUNER_TDA9887=m
+CONFIG_MEDIA_TUNER_TEA5761=m
+CONFIG_MEDIA_TUNER_TEA5767=m
+CONFIG_MEDIA_TUNER_MT20XX=m
+CONFIG_MEDIA_TUNER_MT2060=m
+CONFIG_MEDIA_TUNER_MT2266=m
+CONFIG_MEDIA_TUNER_MT2131=m
+CONFIG_MEDIA_TUNER_QT1010=m
+CONFIG_MEDIA_TUNER_XC2028=m
+CONFIG_MEDIA_TUNER_XC5000=m
+CONFIG_MEDIA_TUNER_MXL5005S=m
+CONFIG_MEDIA_TUNER_MXL5007T=m
+CONFIG_VIDEO_V4L2=m
+CONFIG_VIDEO_V4L1=m
+CONFIG_VIDEOBUF_GEN=m
+CONFIG_VIDEOBUF_DMA_SG=m
+CONFIG_VIDEOBUF_VMALLOC=m
+CONFIG_VIDEOBUF_DMA_CONTIG=m
+CONFIG_VIDEOBUF_DVB=m
+CONFIG_VIDEO_BTCX=m
+CONFIG_VIDEO_IR=m
+CONFIG_VIDEO_TVEEPROM=m
+CONFIG_VIDEO_TUNER=m
+CONFIG_VIDEO_CAPTURE_DRIVERS=y
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set
+CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
+CONFIG_VIDEO_IR_I2C=m
+CONFIG_VIDEO_TVAUDIO=m
+CONFIG_VIDEO_TDA7432=m
+CONFIG_VIDEO_TDA9840=m
+CONFIG_VIDEO_TDA9875=m
+CONFIG_VIDEO_TEA6415C=m
+CONFIG_VIDEO_TEA6420=m
+CONFIG_VIDEO_MSP3400=m
+CONFIG_VIDEO_CS5345=m
+CONFIG_VIDEO_CS53L32A=m
+CONFIG_VIDEO_M52790=m
+CONFIG_VIDEO_WM8775=m
+CONFIG_VIDEO_WM8739=m
+CONFIG_VIDEO_VP27SMPX=m
+CONFIG_VIDEO_BT819=m
+CONFIG_VIDEO_BT856=m
+CONFIG_VIDEO_OV7670=m
+CONFIG_VIDEO_SAA7110=m
+CONFIG_VIDEO_SAA7111=m
+CONFIG_VIDEO_SAA7114=m
+CONFIG_VIDEO_SAA711X=m
+CONFIG_VIDEO_SAA717X=m
+CONFIG_VIDEO_TVP5150=m
+CONFIG_VIDEO_VPX3220=m
+CONFIG_VIDEO_CX25840=m
+CONFIG_VIDEO_CX2341X=m
+CONFIG_VIDEO_SAA7127=m
+CONFIG_VIDEO_SAA7185=m
+CONFIG_VIDEO_ADV7170=m
+CONFIG_VIDEO_ADV7175=m
+CONFIG_VIDEO_UPD64031A=m
+CONFIG_VIDEO_UPD64083=m
+CONFIG_VIDEO_VIVI=m
+CONFIG_VIDEO_BT848=m
+CONFIG_VIDEO_BT848_DVB=y
+CONFIG_VIDEO_SAA6588=m
+CONFIG_VIDEO_BWQCAM=m
+CONFIG_VIDEO_CQCAM=m
+CONFIG_VIDEO_W9966=m
+CONFIG_VIDEO_CPIA=m
+CONFIG_VIDEO_CPIA_PP=m
+CONFIG_VIDEO_CPIA_USB=m
+# CONFIG_VIDEO_CPIA2 is not set
+CONFIG_VIDEO_SAA5246A=m
+CONFIG_VIDEO_SAA5249=m
+CONFIG_VIDEO_STRADIS=m
+CONFIG_VIDEO_ZORAN=m
+CONFIG_VIDEO_ZORAN_DC30=m
+CONFIG_VIDEO_ZORAN_ZR36060=m
+CONFIG_VIDEO_ZORAN_BUZ=m
+CONFIG_VIDEO_ZORAN_DC10=m
+CONFIG_VIDEO_ZORAN_LML33=m
+CONFIG_VIDEO_ZORAN_LML33R10=m
+# CONFIG_VIDEO_ZORAN_AVS6EYES is not set
+CONFIG_VIDEO_MEYE=m
+CONFIG_VIDEO_SAA7134=m
+CONFIG_VIDEO_SAA7134_ALSA=m
+CONFIG_VIDEO_SAA7134_DVB=m
+CONFIG_VIDEO_MXB=m
+CONFIG_VIDEO_HEXIUM_ORION=m
+CONFIG_VIDEO_HEXIUM_GEMINI=m
+CONFIG_VIDEO_CX88=m
+CONFIG_VIDEO_CX88_ALSA=m
+CONFIG_VIDEO_CX88_BLACKBIRD=m
+CONFIG_VIDEO_CX88_DVB=m
+CONFIG_VIDEO_CX88_VP3054=m
+CONFIG_VIDEO_CX23885=m
+CONFIG_VIDEO_AU0828=m
+CONFIG_VIDEO_IVTV=m
+CONFIG_VIDEO_FB_IVTV=m
+CONFIG_VIDEO_CX18=m
+CONFIG_VIDEO_CAFE_CCIC=m
+CONFIG_SOC_CAMERA=m
+CONFIG_SOC_CAMERA_MT9M001=m
+CONFIG_SOC_CAMERA_MT9M111=m
+CONFIG_SOC_CAMERA_MT9V022=m
+CONFIG_SOC_CAMERA_PLATFORM=m
+CONFIG_VIDEO_SH_MOBILE_CEU=m
+CONFIG_V4L_USB_DRIVERS=y
+CONFIG_USB_VIDEO_CLASS=m
+CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y
+CONFIG_USB_GSPCA=m
+CONFIG_USB_M5602=m
+CONFIG_USB_GSPCA_CONEX=m
+CONFIG_USB_GSPCA_ETOMS=m
+CONFIG_USB_GSPCA_FINEPIX=m
+CONFIG_USB_GSPCA_MARS=m
+CONFIG_USB_GSPCA_OV519=m
+CONFIG_USB_GSPCA_PAC207=m
+CONFIG_USB_GSPCA_PAC7311=m
+CONFIG_USB_GSPCA_SONIXB=m
+CONFIG_USB_GSPCA_SONIXJ=m
+CONFIG_USB_GSPCA_SPCA500=m
+CONFIG_USB_GSPCA_SPCA501=m
+CONFIG_USB_GSPCA_SPCA505=m
+CONFIG_USB_GSPCA_SPCA506=m
+CONFIG_USB_GSPCA_SPCA508=m
+CONFIG_USB_GSPCA_SPCA561=m
+CONFIG_USB_GSPCA_STK014=m
+CONFIG_USB_GSPCA_SUNPLUS=m
+CONFIG_USB_GSPCA_T613=m
+CONFIG_USB_GSPCA_TV8532=m
+CONFIG_USB_GSPCA_VC032X=m
+CONFIG_USB_GSPCA_ZC3XX=m
+CONFIG_VIDEO_PVRUSB2=m
+CONFIG_VIDEO_PVRUSB2_SYSFS=y
+CONFIG_VIDEO_PVRUSB2_DVB=y
+# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set
+CONFIG_VIDEO_EM28XX=m
+CONFIG_VIDEO_EM28XX_ALSA=m
+CONFIG_VIDEO_EM28XX_DVB=m
+CONFIG_VIDEO_USBVISION=m
+CONFIG_VIDEO_USBVIDEO=m
+CONFIG_USB_VICAM=m
+CONFIG_USB_IBMCAM=m
+CONFIG_USB_KONICAWC=m
+CONFIG_USB_QUICKCAM_MESSENGER=m
+CONFIG_USB_ET61X251=m
+CONFIG_VIDEO_OVCAMCHIP=m
+CONFIG_USB_W9968CF=m
+CONFIG_USB_OV511=m
+CONFIG_USB_SE401=m
+CONFIG_USB_SN9C102=m
+CONFIG_USB_STV680=m
+CONFIG_USB_ZC0301=m
+CONFIG_USB_PWC=m
+# CONFIG_USB_PWC_DEBUG is not set
+CONFIG_USB_ZR364XX=m
+CONFIG_USB_STKWEBCAM=m
+CONFIG_USB_S2255=m
+CONFIG_RADIO_ADAPTERS=y
+CONFIG_RADIO_GEMTEK_PCI=m
+CONFIG_RADIO_MAXIRADIO=m
+CONFIG_RADIO_MAESTRO=m
+CONFIG_USB_DSBR=m
+CONFIG_USB_SI470X=m
+CONFIG_USB_MR800=m
+CONFIG_DVB_CAPTURE_DRIVERS=y
+
+#
+# Supported SAA7146 based PCI Adapters
+#
+CONFIG_TTPCI_EEPROM=m
+CONFIG_DVB_AV7110=m
+# CONFIG_DVB_AV7110_FIRMWARE is not set
+CONFIG_DVB_AV7110_OSD=y
+CONFIG_DVB_BUDGET_CORE=m
+CONFIG_DVB_BUDGET=m
+CONFIG_DVB_BUDGET_CI=m
+CONFIG_DVB_BUDGET_AV=m
+CONFIG_DVB_BUDGET_PATCH=m
+
+#
+# Supported USB Adapters
+#
+CONFIG_DVB_USB=m
+# CONFIG_DVB_USB_DEBUG is not set
+CONFIG_DVB_USB_A800=m
+CONFIG_DVB_USB_DIBUSB_MB=m
+# CONFIG_DVB_USB_DIBUSB_MB_FAULTY is not set
+CONFIG_DVB_USB_DIBUSB_MC=m
+CONFIG_DVB_USB_DIB0700=m
+CONFIG_DVB_USB_UMT_010=m
+CONFIG_DVB_USB_CXUSB=m
+CONFIG_DVB_USB_M920X=m
+CONFIG_DVB_USB_GL861=m
+CONFIG_DVB_USB_AU6610=m
+CONFIG_DVB_USB_DIGITV=m
+CONFIG_DVB_USB_VP7045=m
+CONFIG_DVB_USB_VP702X=m
+CONFIG_DVB_USB_GP8PSK=m
+CONFIG_DVB_USB_NOVA_T_USB2=m
+CONFIG_DVB_USB_TTUSB2=m
+CONFIG_DVB_USB_DTT200U=m
+CONFIG_DVB_USB_OPERA1=m
+CONFIG_DVB_USB_AF9005=m
+CONFIG_DVB_USB_AF9005_REMOTE=m
+CONFIG_DVB_USB_DW2102=m
+CONFIG_DVB_USB_CINERGY_T2=m
+CONFIG_DVB_USB_ANYSEE=m
+CONFIG_DVB_USB_DTV5100=m
+CONFIG_DVB_USB_AF9015=m
+CONFIG_DVB_TTUSB_BUDGET=m
+CONFIG_DVB_TTUSB_DEC=m
+CONFIG_DVB_SIANO_SMS1XXX=m
+CONFIG_DVB_SIANO_SMS1XXX_SMS_IDS=y
+
+#
+# Supported FlexCopII (B2C2) Adapters
+#
+CONFIG_DVB_B2C2_FLEXCOP=m
+CONFIG_DVB_B2C2_FLEXCOP_PCI=m
+CONFIG_DVB_B2C2_FLEXCOP_USB=m
+# CONFIG_DVB_B2C2_FLEXCOP_DEBUG is not set
+
+#
+# Supported BT878 Adapters
+#
+CONFIG_DVB_BT8XX=m
+
+#
+# Supported Pluto2 Adapters
+#
+# CONFIG_DVB_PLUTO2 is not set
+
+#
+# Supported SDMC DM1105 Adapters
+#
+CONFIG_DVB_DM1105=m
+
+#
+# Supported DVB Frontends
+#
+
+#
+# Customise DVB Frontends
+#
+# CONFIG_DVB_FE_CUSTOMISE is not set
+
+#
+# DVB-S (satellite) frontends
+#
+CONFIG_DVB_CX24110=m
+CONFIG_DVB_CX24123=m
+CONFIG_DVB_MT312=m
+CONFIG_DVB_S5H1420=m
+CONFIG_DVB_STV0288=m
+CONFIG_DVB_STB6000=m
+CONFIG_DVB_STV0299=m
+CONFIG_DVB_TDA8083=m
+CONFIG_DVB_TDA10086=m
+CONFIG_DVB_VES1X93=m
+CONFIG_DVB_TUNER_ITD1000=m
+CONFIG_DVB_TDA826X=m
+CONFIG_DVB_TUA6100=m
+CONFIG_DVB_CX24116=m
+CONFIG_DVB_SI21XX=m
+
+#
+# DVB-T (terrestrial) frontends
+#
+CONFIG_DVB_SP8870=m
+CONFIG_DVB_SP887X=m
+CONFIG_DVB_CX22700=m
+CONFIG_DVB_CX22702=m
+CONFIG_DVB_DRX397XD=m
+CONFIG_DVB_L64781=m
+CONFIG_DVB_TDA1004X=m
+CONFIG_DVB_NXT6000=m
+CONFIG_DVB_MT352=m
+CONFIG_DVB_ZL10353=m
+CONFIG_DVB_DIB3000MB=m
+CONFIG_DVB_DIB3000MC=m
+CONFIG_DVB_DIB7000M=m
+CONFIG_DVB_DIB7000P=m
+CONFIG_DVB_TDA10048=m
+
+#
+# DVB-C (cable) frontends
+#
+CONFIG_DVB_VES1820=m
+CONFIG_DVB_TDA10021=m
+CONFIG_DVB_TDA10023=m
+CONFIG_DVB_STV0297=m
+
+#
+# ATSC (North American/Korean Terrestrial/Cable DTV) frontends
+#
+CONFIG_DVB_NXT200X=m
+CONFIG_DVB_OR51211=m
+CONFIG_DVB_OR51132=m
+CONFIG_DVB_BCM3510=m
+CONFIG_DVB_LGDT330X=m
+CONFIG_DVB_S5H1409=m
+CONFIG_DVB_AU8522=m
+CONFIG_DVB_S5H1411=m
+
+#
+# Digital terrestrial only tuners/PLL
+#
+CONFIG_DVB_PLL=m
+CONFIG_DVB_TUNER_DIB0070=m
+
+#
+# SEC control devices for DVB-S
+#
+CONFIG_DVB_LNBP21=m
+CONFIG_DVB_ISL6405=m
+CONFIG_DVB_ISL6421=m
+CONFIG_DVB_LGS8GL5=m
+
+#
+# Tools to develop new frontends
+#
+# CONFIG_DVB_DUMMY_FE is not set
+CONFIG_DVB_AF9013=m
+CONFIG_DAB=y
+CONFIG_USB_DABUSB=m
+
+#
+# Graphics support
+#
+CONFIG_AGP=y
+CONFIG_AGP_AMD64=y
+CONFIG_AGP_INTEL=m
+CONFIG_AGP_SIS=m
+CONFIG_AGP_VIA=m
+CONFIG_DRM=m
+CONFIG_DRM_TDFX=m
+CONFIG_DRM_R128=m
+CONFIG_DRM_RADEON=m
+CONFIG_DRM_I810=m
+CONFIG_DRM_I830=m
+CONFIG_DRM_I915=m
+CONFIG_DRM_MGA=m
+CONFIG_DRM_SIS=m
+CONFIG_DRM_VIA=m
+CONFIG_DRM_SAVAGE=m
+CONFIG_VGASTATE=m
+CONFIG_VIDEO_OUTPUT_CONTROL=m
+CONFIG_FB=y
+CONFIG_FIRMWARE_EDID=y
+CONFIG_FB_DDC=m
+CONFIG_FB_BOOT_VESA_SUPPORT=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+CONFIG_FB_SYS_FILLRECT=m
+CONFIG_FB_SYS_COPYAREA=m
+CONFIG_FB_SYS_IMAGEBLIT=m
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+CONFIG_FB_SYS_FOPS=m
+CONFIG_FB_DEFERRED_IO=y
+CONFIG_FB_HECUBA=m
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+CONFIG_FB_BACKLIGHT=y
+CONFIG_FB_MODE_HELPERS=y
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+CONFIG_FB_CIRRUS=m
+CONFIG_FB_PM2=m
+CONFIG_FB_PM2_FIFO_DISCONNECT=y
+CONFIG_FB_CYBER2000=m
+CONFIG_FB_ARC=m
+# CONFIG_FB_ASILIANT is not set
+CONFIG_FB_IMSTT=y
+CONFIG_FB_VGA16=m
+CONFIG_FB_UVESA=m
+CONFIG_FB_VESA=y
+# CONFIG_FB_EFI is not set
+CONFIG_FB_N411=m
+CONFIG_FB_HGA=m
+CONFIG_FB_HGA_ACCEL=y
+CONFIG_FB_S1D13XXX=m
+CONFIG_FB_NVIDIA=m
+CONFIG_FB_NVIDIA_I2C=y
+# CONFIG_FB_NVIDIA_DEBUG is not set
+CONFIG_FB_NVIDIA_BACKLIGHT=y
+CONFIG_FB_RIVA=m
+CONFIG_FB_RIVA_I2C=y
+# CONFIG_FB_RIVA_DEBUG is not set
+CONFIG_FB_RIVA_BACKLIGHT=y
+CONFIG_FB_LE80578=m
+CONFIG_FB_CARILLO_RANCH=m
+CONFIG_FB_INTEL=m
+# CONFIG_FB_INTEL_DEBUG is not set
+CONFIG_FB_INTEL_I2C=y
+# CONFIG_FB_MATROX is not set
+CONFIG_FB_RADEON=m
+CONFIG_FB_RADEON_I2C=y
+CONFIG_FB_RADEON_BACKLIGHT=y
+# CONFIG_FB_RADEON_DEBUG is not set
+# CONFIG_FB_ATY128 is not set
+CONFIG_FB_ATY=m
+CONFIG_FB_ATY_CT=y
+CONFIG_FB_ATY_GENERIC_LCD=y
+CONFIG_FB_ATY_GX=y
+CONFIG_FB_ATY_BACKLIGHT=y
+# CONFIG_FB_S3 is not set
+CONFIG_FB_SAVAGE=m
+CONFIG_FB_SAVAGE_I2C=y
+CONFIG_FB_SAVAGE_ACCEL=y
+CONFIG_FB_SIS=m
+CONFIG_FB_SIS_300=y
+CONFIG_FB_SIS_315=y
+CONFIG_FB_VIA=m
+CONFIG_FB_NEOMAGIC=m
+CONFIG_FB_KYRO=m
+CONFIG_FB_3DFX=m
+CONFIG_FB_3DFX_ACCEL=y
+CONFIG_FB_VOODOO1=m
+# CONFIG_FB_VT8623 is not set
+CONFIG_FB_TRIDENT=m
+CONFIG_FB_TRIDENT_ACCEL=y
+# CONFIG_FB_ARK is not set
+CONFIG_FB_PM3=m
+CONFIG_FB_CARMINE=m
+CONFIG_FB_CARMINE_DRAM_EVAL=y
+# CONFIG_CARMINE_DRAM_CUSTOM is not set
+CONFIG_FB_GEODE=y
+CONFIG_FB_GEODE_LX=m
+CONFIG_FB_GEODE_GX=m
+CONFIG_FB_GEODE_GX1=m
+CONFIG_FB_SM501=m
+# CONFIG_FB_VIRTUAL is not set
+CONFIG_XEN_FBDEV_FRONTEND=m
+CONFIG_FB_METRONOME=m
+CONFIG_FB_MB862XX=m
+CONFIG_FB_MB862XX_PCI_GDC=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_LCD_CLASS_DEVICE=m
+CONFIG_LCD_LTV350QV=m
+CONFIG_LCD_ILI9320=m
+CONFIG_LCD_TDO24M=m
+CONFIG_LCD_VGG2432A4=m
+CONFIG_LCD_PLATFORM=m
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_CORGI=m
+CONFIG_BACKLIGHT_PROGEAR=m
+CONFIG_BACKLIGHT_CARILLO_RANCH=m
+CONFIG_BACKLIGHT_MBP_NVIDIA=m
+CONFIG_BACKLIGHT_SAHARA=m
+
+#
+# Display device support
+#
+CONFIG_DISPLAY_SUPPORT=m
+
+#
+# Display hardware drivers
+#
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+# CONFIG_VGACON_SOFT_SCROLLBACK is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+# CONFIG_LOGO is not set
+CONFIG_SOUND=m
+CONFIG_SOUND_OSS_CORE=y
+CONFIG_SND=m
+CONFIG_SND_TIMER=m
+CONFIG_SND_PCM=m
+CONFIG_SND_HWDEP=m
+CONFIG_SND_RAWMIDI=m
+CONFIG_SND_SEQUENCER=m
+CONFIG_SND_SEQ_DUMMY=m
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+CONFIG_SND_PCM_OSS_PLUGINS=y
+CONFIG_SND_SEQUENCER_OSS=y
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
+CONFIG_SND_VERBOSE_PRINTK=y
+CONFIG_SND_DEBUG=y
+# CONFIG_SND_DEBUG_VERBOSE is not set
+# CONFIG_SND_PCM_XRUN_DEBUG is not set
+CONFIG_SND_VMASTER=y
+CONFIG_SND_MPU401_UART=m
+CONFIG_SND_OPL3_LIB=m
+CONFIG_SND_VX_LIB=m
+CONFIG_SND_AC97_CODEC=m
+CONFIG_SND_DRIVERS=y
+CONFIG_SND_PCSP=m
+CONFIG_SND_DUMMY=m
+CONFIG_SND_VIRMIDI=m
+CONFIG_SND_MTPAV=m
+CONFIG_SND_MTS64=m
+CONFIG_SND_SERIAL_U16550=m
+CONFIG_SND_MPU401=m
+CONFIG_SND_PORTMAN2X4=m
+CONFIG_SND_AC97_POWER_SAVE=y
+CONFIG_SND_AC97_POWER_SAVE_DEFAULT=0
+CONFIG_SND_SB_COMMON=m
+CONFIG_SND_SB16_DSP=m
+CONFIG_SND_PCI=y
+CONFIG_SND_AD1889=m
+CONFIG_SND_ALS300=m
+CONFIG_SND_ALS4000=m
+CONFIG_SND_ALI5451=m
+CONFIG_SND_ATIIXP=m
+CONFIG_SND_ATIIXP_MODEM=m
+CONFIG_SND_AU8810=m
+CONFIG_SND_AU8820=m
+CONFIG_SND_AU8830=m
+CONFIG_SND_AW2=m
+CONFIG_SND_AZT3328=m
+CONFIG_SND_BT87X=m
+# CONFIG_SND_BT87X_OVERCLOCK is not set
+CONFIG_SND_CA0106=m
+CONFIG_SND_CMIPCI=m
+CONFIG_SND_OXYGEN_LIB=m
+CONFIG_SND_OXYGEN=m
+CONFIG_SND_CS4281=m
+CONFIG_SND_CS46XX=m
+CONFIG_SND_CS46XX_NEW_DSP=y
+CONFIG_SND_CS5530=m
+CONFIG_SND_DARLA20=m
+CONFIG_SND_GINA20=m
+CONFIG_SND_LAYLA20=m
+CONFIG_SND_DARLA24=m
+CONFIG_SND_GINA24=m
+CONFIG_SND_LAYLA24=m
+CONFIG_SND_MONA=m
+CONFIG_SND_MIA=m
+CONFIG_SND_ECHO3G=m
+CONFIG_SND_INDIGO=m
+CONFIG_SND_INDIGOIO=m
+CONFIG_SND_INDIGODJ=m
+CONFIG_SND_EMU10K1=m
+CONFIG_SND_EMU10K1X=m
+CONFIG_SND_ENS1370=m
+CONFIG_SND_ENS1371=m
+CONFIG_SND_ES1938=m
+CONFIG_SND_ES1968=m
+CONFIG_SND_FM801=m
+CONFIG_SND_FM801_TEA575X_BOOL=y
+CONFIG_SND_FM801_TEA575X=m
+CONFIG_SND_HDA_INTEL=m
+# CONFIG_SND_HDA_HWDEP is not set
+CONFIG_SND_HDA_INPUT_BEEP=y
+CONFIG_SND_HDA_CODEC_REALTEK=y
+CONFIG_SND_HDA_CODEC_ANALOG=y
+CONFIG_SND_HDA_CODEC_SIGMATEL=y
+CONFIG_SND_HDA_CODEC_VIA=y
+CONFIG_SND_HDA_CODEC_ATIHDMI=y
+CONFIG_SND_HDA_CODEC_NVHDMI=y
+CONFIG_SND_HDA_CODEC_CONEXANT=y
+CONFIG_SND_HDA_CODEC_CMEDIA=y
+CONFIG_SND_HDA_CODEC_SI3054=y
+CONFIG_SND_HDA_GENERIC=y
+# CONFIG_SND_HDA_POWER_SAVE is not set
+CONFIG_SND_HDSP=m
+CONFIG_SND_HDSPM=m
+CONFIG_SND_HIFIER=m
+CONFIG_SND_ICE1712=m
+CONFIG_SND_ICE1724=m
+CONFIG_SND_INTEL8X0=m
+CONFIG_SND_INTEL8X0M=m
+CONFIG_SND_KORG1212=m
+CONFIG_SND_MAESTRO3=m
+CONFIG_SND_MIXART=m
+CONFIG_SND_NM256=m
+CONFIG_SND_PCXHR=m
+CONFIG_SND_RIPTIDE=m
+CONFIG_SND_RME32=m
+CONFIG_SND_RME96=m
+CONFIG_SND_RME9652=m
+CONFIG_SND_SONICVIBES=m
+CONFIG_SND_TRIDENT=m
+CONFIG_SND_VIA82XX=m
+CONFIG_SND_VIA82XX_MODEM=m
+CONFIG_SND_VIRTUOSO=m
+CONFIG_SND_VX222=m
+CONFIG_SND_YMFPCI=m
+CONFIG_SND_SPI=y
+CONFIG_SND_USB=y
+CONFIG_SND_USB_AUDIO=m
+CONFIG_SND_USB_USX2Y=m
+CONFIG_SND_USB_CAIAQ=m
+CONFIG_SND_USB_CAIAQ_INPUT=y
+CONFIG_SND_USB_US122L=m
+CONFIG_SND_PCMCIA=y
+CONFIG_SND_VXPOCKET=m
+CONFIG_SND_PDAUDIOCF=m
+# CONFIG_SND_SOC is not set
+CONFIG_SOUND_PRIME=m
+CONFIG_SOUND_OSS=m
+CONFIG_SOUND_TRACEINIT=y
+CONFIG_SOUND_DMAP=y
+CONFIG_SOUND_SSCAPE=m
+CONFIG_SOUND_VMIDI=m
+CONFIG_SOUND_TRIX=m
+CONFIG_SOUND_MSS=m
+CONFIG_SOUND_MPU401=m
+CONFIG_SOUND_PAS=m
+CONFIG_SOUND_PSS=m
+CONFIG_PSS_MIXER=y
+# CONFIG_PSS_HAVE_BOOT is not set
+CONFIG_SOUND_SB=m
+CONFIG_SOUND_YM3812=m
+CONFIG_SOUND_UART6850=m
+CONFIG_SOUND_AEDSP16=m
+CONFIG_SC6600=y
+CONFIG_SC6600_JOY=y
+CONFIG_SC6600_CDROM=4
+CONFIG_SC6600_CDROMBASE=0x0
+CONFIG_SOUND_KAHLUA=m
+CONFIG_AC97_BUS=m
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+CONFIG_HIDRAW=y
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=m
+CONFIG_HID_PID=y
+CONFIG_USB_HIDDEV=y
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+
+#
+# Special HID drivers
+#
+# CONFIG_HID_COMPAT is not set
+CONFIG_HID_A4TECH=m
+CONFIG_HID_APPLE=m
+CONFIG_HID_BELKIN=m
+CONFIG_HID_BRIGHT=m
+CONFIG_HID_CHERRY=m
+CONFIG_HID_CHICONY=m
+CONFIG_HID_CYPRESS=m
+CONFIG_HID_DELL=m
+CONFIG_HID_EZKEY=m
+CONFIG_HID_GYRATION=m
+CONFIG_HID_LOGITECH=m
+CONFIG_LOGITECH_FF=y
+CONFIG_LOGIRUMBLEPAD2_FF=y
+CONFIG_HID_MICROSOFT=m
+CONFIG_HID_MONTEREY=m
+CONFIG_HID_PANTHERLORD=m
+CONFIG_PANTHERLORD_FF=y
+CONFIG_HID_PETALYNX=m
+CONFIG_HID_SAMSUNG=m
+CONFIG_HID_SONY=m
+CONFIG_HID_SUNPLUS=m
+CONFIG_THRUSTMASTER_FF=m
+CONFIG_ZEROPLUS_FF=m
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=m
+# CONFIG_USB_DEBUG is not set
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+CONFIG_USB_DEVICE_CLASS=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+CONFIG_USB_SUSPEND=y
+# CONFIG_USB_OTG is not set
+CONFIG_USB_MON=y
+CONFIG_USB_WUSB=m
+CONFIG_USB_WUSB_CBAF=m
+# CONFIG_USB_WUSB_CBAF_DEBUG is not set
+
+#
+# USB Host Controller Drivers
+#
+CONFIG_USB_C67X00_HCD=m
+CONFIG_USB_EHCI_HCD=m
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+CONFIG_USB_ISP116X_HCD=m
+CONFIG_USB_ISP1760_HCD=m
+CONFIG_USB_OHCI_HCD=m
+CONFIG_USB_OHCI_HCD_SSB=y
+# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_UHCI_HCD=m
+CONFIG_USB_U132_HCD=m
+CONFIG_USB_SL811_HCD=m
+CONFIG_USB_SL811_CS=m
+CONFIG_USB_R8A66597_HCD=m
+CONFIG_USB_WHCI_HCD=m
+CONFIG_USB_HWA_HCD=m
+
+#
+# Enable Host or Gadget support to see Inventra options
+#
+
+#
+# USB Device Class drivers
+#
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+CONFIG_USB_WDM=m
+CONFIG_USB_TMC=m
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
+#
+
+#
+# see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+CONFIG_USB_STORAGE_ISD200=y
+CONFIG_USB_STORAGE_DPCM=y
+CONFIG_USB_STORAGE_USBAT=y
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+# CONFIG_USB_STORAGE_ALAUDA is not set
+CONFIG_USB_STORAGE_ONETOUCH=y
+CONFIG_USB_STORAGE_KARMA=y
+CONFIG_USB_STORAGE_CYPRESS_ATACB=y
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Imaging devices
+#
+CONFIG_USB_MDC800=m
+CONFIG_USB_MICROTEK=m
+
+#
+# USB port drivers
+#
+CONFIG_USB_USS720=m
+CONFIG_USB_SERIAL=m
+CONFIG_USB_EZUSB=y
+CONFIG_USB_SERIAL_GENERIC=y
+# CONFIG_USB_SERIAL_AIRCABLE is not set
+CONFIG_USB_SERIAL_ARK3116=m
+CONFIG_USB_SERIAL_BELKIN=m
+CONFIG_USB_SERIAL_CH341=m
+CONFIG_USB_SERIAL_WHITEHEAT=m
+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
+CONFIG_USB_SERIAL_CP2101=m
+CONFIG_USB_SERIAL_CYPRESS_M8=m
+CONFIG_USB_SERIAL_EMPEG=m
+CONFIG_USB_SERIAL_FTDI_SIO=m
+# CONFIG_USB_SERIAL_FUNSOFT is not set
+CONFIG_USB_SERIAL_VISOR=m
+CONFIG_USB_SERIAL_IPAQ=m
+CONFIG_USB_SERIAL_IR=m
+CONFIG_USB_SERIAL_EDGEPORT=m
+CONFIG_USB_SERIAL_EDGEPORT_TI=m
+CONFIG_USB_SERIAL_GARMIN=m
+CONFIG_USB_SERIAL_IPW=m
+CONFIG_USB_SERIAL_IUU=m
+CONFIG_USB_SERIAL_KEYSPAN_PDA=m
+CONFIG_USB_SERIAL_KEYSPAN=m
+CONFIG_USB_SERIAL_KEYSPAN_MPR=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19=y
+CONFIG_USB_SERIAL_KEYSPAN_USA18X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y
+CONFIG_USB_SERIAL_KLSI=m
+CONFIG_USB_SERIAL_KOBIL_SCT=m
+CONFIG_USB_SERIAL_MCT_U232=m
+CONFIG_USB_SERIAL_MOS7720=m
+CONFIG_USB_SERIAL_MOS7840=m
+CONFIG_USB_SERIAL_MOTOROLA=m
+CONFIG_USB_SERIAL_NAVMAN=m
+CONFIG_USB_SERIAL_PL2303=m
+CONFIG_USB_SERIAL_OTI6858=m
+CONFIG_USB_SERIAL_SPCP8X5=m
+CONFIG_USB_SERIAL_HP4X=m
+CONFIG_USB_SERIAL_SAFE=m
+CONFIG_USB_SERIAL_SAFE_PADDED=y
+CONFIG_USB_SERIAL_SIERRAWIRELESS=m
+CONFIG_USB_SERIAL_TI=m
+CONFIG_USB_SERIAL_CYBERJACK=m
+CONFIG_USB_SERIAL_XIRCOM=m
+CONFIG_USB_SERIAL_OPTION=m
+CONFIG_USB_SERIAL_OMNINET=m
+# CONFIG_USB_SERIAL_DEBUG is not set
+
+#
+# USB Miscellaneous drivers
+#
+CONFIG_USB_EMI62=m
+CONFIG_USB_EMI26=m
+CONFIG_USB_ADUTUX=m
+CONFIG_USB_SEVSEG=m
+CONFIG_USB_RIO500=m
+CONFIG_USB_LEGOTOWER=m
+CONFIG_USB_LCD=m
+CONFIG_USB_BERRY_CHARGE=m
+CONFIG_USB_LED=m
+CONFIG_USB_CYPRESS_CY7C63=m
+CONFIG_USB_CYTHERM=m
+CONFIG_USB_PHIDGET=m
+CONFIG_USB_PHIDGETKIT=m
+CONFIG_USB_PHIDGETMOTORCONTROL=m
+CONFIG_USB_PHIDGETSERVO=m
+CONFIG_USB_IDMOUSE=m
+CONFIG_USB_FTDI_ELAN=m
+CONFIG_USB_APPLEDISPLAY=m
+CONFIG_USB_SISUSBVGA=m
+# CONFIG_USB_SISUSBVGA_CON is not set
+CONFIG_USB_LD=m
+CONFIG_USB_TRANCEVIBRATOR=m
+CONFIG_USB_IOWARRIOR=m
+# CONFIG_USB_TEST is not set
+CONFIG_USB_ISIGHTFW=m
+CONFIG_USB_VST=m
+CONFIG_USB_ATM=m
+CONFIG_USB_SPEEDTOUCH=m
+CONFIG_USB_CXACRU=m
+CONFIG_USB_UEAGLEATM=m
+CONFIG_USB_XUSBATM=m
+# CONFIG_USB_GADGET is not set
+CONFIG_UWB=m
+CONFIG_UWB_HWA=m
+CONFIG_UWB_WHCI=m
+CONFIG_UWB_WLP=m
+CONFIG_UWB_I1480U=m
+CONFIG_UWB_I1480U_WLP=m
+CONFIG_MMC=m
+# CONFIG_MMC_DEBUG is not set
+# CONFIG_MMC_UNSAFE_RESUME is not set
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=m
+CONFIG_MMC_BLOCK_BOUNCE=y
+CONFIG_SDIO_UART=m
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+# CONFIG_MMC_SDHCI is not set
+CONFIG_MMC_WBSD=m
+CONFIG_MMC_TIFM_SD=m
+# CONFIG_MMC_SPI is not set
+CONFIG_MMC_SDRICOH_CS=m
+CONFIG_MEMSTICK=m
+# CONFIG_MEMSTICK_DEBUG is not set
+
+#
+# MemoryStick drivers
+#
+# CONFIG_MEMSTICK_UNSAFE_RESUME is not set
+CONFIG_MSPRO_BLOCK=m
+
+#
+# MemoryStick Host Controller Drivers
+#
+CONFIG_MEMSTICK_TIFM_MS=m
+CONFIG_MEMSTICK_JMICRON_38X=m
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=m
+
+#
+# LED drivers
+#
+CONFIG_LEDS_PCA9532=m
+CONFIG_LEDS_HP_DISK=m
+CONFIG_LEDS_CLEVO_MAIL=m
+CONFIG_LEDS_PCA955X=m
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=m
+CONFIG_LEDS_TRIGGER_IDE_DISK=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=m
+CONFIG_LEDS_TRIGGER_BACKLIGHT=m
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=m
+CONFIG_ACCESSIBILITY=y
+# CONFIG_A11Y_BRAILLE_CONSOLE is not set
+CONFIG_INFINIBAND=m
+CONFIG_INFINIBAND_USER_MAD=m
+CONFIG_INFINIBAND_USER_ACCESS=m
+CONFIG_INFINIBAND_USER_MEM=y
+CONFIG_INFINIBAND_ADDR_TRANS=y
+CONFIG_INFINIBAND_MTHCA=m
+CONFIG_INFINIBAND_MTHCA_DEBUG=y
+CONFIG_INFINIBAND_IPATH=m
+CONFIG_INFINIBAND_AMSO1100=m
+# CONFIG_INFINIBAND_AMSO1100_DEBUG is not set
+CONFIG_INFINIBAND_CXGB3=m
+# CONFIG_INFINIBAND_CXGB3_DEBUG is not set
+CONFIG_MLX4_INFINIBAND=m
+CONFIG_INFINIBAND_NES=m
+# CONFIG_INFINIBAND_NES_DEBUG is not set
+CONFIG_INFINIBAND_IPOIB=m
+# CONFIG_INFINIBAND_IPOIB_CM is not set
+CONFIG_INFINIBAND_IPOIB_DEBUG=y
+# CONFIG_INFINIBAND_IPOIB_DEBUG_DATA is not set
+# CONFIG_INFINIBAND_SRP is not set
+# CONFIG_INFINIBAND_ISER is not set
+# CONFIG_EDAC is not set
+CONFIG_RTC_LIB=m
+CONFIG_RTC_CLASS=m
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+CONFIG_RTC_INTF_DEV_UIE_EMUL=y
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+CONFIG_RTC_DRV_DS1307=m
+CONFIG_RTC_DRV_DS1374=m
+CONFIG_RTC_DRV_DS1672=m
+CONFIG_RTC_DRV_MAX6900=m
+CONFIG_RTC_DRV_RS5C372=m
+CONFIG_RTC_DRV_ISL1208=m
+CONFIG_RTC_DRV_X1205=m
+CONFIG_RTC_DRV_PCF8563=m
+CONFIG_RTC_DRV_PCF8583=m
+CONFIG_RTC_DRV_M41T80=m
+CONFIG_RTC_DRV_M41T80_WDT=y
+CONFIG_RTC_DRV_S35390A=m
+CONFIG_RTC_DRV_FM3130=m
+CONFIG_RTC_DRV_RX8581=m
+
+#
+# SPI RTC drivers
+#
+CONFIG_RTC_DRV_M41T94=m
+CONFIG_RTC_DRV_DS1305=m
+CONFIG_RTC_DRV_DS1390=m
+CONFIG_RTC_DRV_MAX6902=m
+CONFIG_RTC_DRV_R9701=m
+CONFIG_RTC_DRV_RS5C348=m
+CONFIG_RTC_DRV_DS3234=m
+
+#
+# Platform RTC drivers
+#
+CONFIG_RTC_DRV_CMOS=m
+CONFIG_RTC_DRV_DS1286=m
+CONFIG_RTC_DRV_DS1511=m
+CONFIG_RTC_DRV_DS1553=m
+CONFIG_RTC_DRV_DS1742=m
+CONFIG_RTC_DRV_STK17TA8=m
+CONFIG_RTC_DRV_M48T86=m
+CONFIG_RTC_DRV_M48T35=m
+CONFIG_RTC_DRV_M48T59=m
+CONFIG_RTC_DRV_BQ4802=m
+CONFIG_RTC_DRV_V3020=m
+CONFIG_RTC_DRV_WM8350=m
+
+#
+# on-CPU RTC drivers
+#
+CONFIG_DMADEVICES=y
+
+#
+# DMA Devices
+#
+CONFIG_INTEL_IOATDMA=m
+CONFIG_DMA_ENGINE=y
+
+#
+# DMA Clients
+#
+CONFIG_NET_DMA=y
+# CONFIG_DMATEST is not set
+CONFIG_DCA=m
+CONFIG_AUXDISPLAY=y
+CONFIG_KS0108=m
+CONFIG_KS0108_PORT=0x378
+CONFIG_KS0108_DELAY=2
+# CONFIG_CFAG12864B is not set
+CONFIG_UIO=m
+CONFIG_UIO_CIF=m
+CONFIG_UIO_PDRV=m
+CONFIG_UIO_PDRV_GENIRQ=m
+# CONFIG_UIO_SMX is not set
+CONFIG_UIO_SERCOS3=m
+CONFIG_XEN_BALLOON=y
+CONFIG_XEN_SCRUB_PAGES=y
+# CONFIG_STAGING is not set
+
+#
+# Firmware Drivers
+#
+CONFIG_EDD=m
+# CONFIG_EDD_OFF is not set
+CONFIG_FIRMWARE_MEMMAP=y
+CONFIG_EFI_VARS=m
+CONFIG_DELL_RBU=m
+CONFIG_DCDBAS=m
+CONFIG_DMIID=y
+CONFIG_ISCSI_IBFT_FIND=y
+CONFIG_ISCSI_IBFT=m
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+CONFIG_EXT2_FS_XIP=y
+CONFIG_EXT3_FS=m
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_EXT4_FS=m
+# CONFIG_EXT4DEV_COMPAT is not set
+CONFIG_EXT4_FS_XATTR=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
+CONFIG_FS_XIP=y
+CONFIG_JBD=m
+CONFIG_JBD_DEBUG=y
+CONFIG_JBD2=m
+# CONFIG_JBD2_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+CONFIG_REISERFS_FS_XATTR=y
+CONFIG_REISERFS_FS_POSIX_ACL=y
+CONFIG_REISERFS_FS_SECURITY=y
+CONFIG_JFS_FS=m
+CONFIG_JFS_POSIX_ACL=y
+CONFIG_JFS_SECURITY=y
+# CONFIG_JFS_DEBUG is not set
+CONFIG_JFS_STATISTICS=y
+CONFIG_FS_POSIX_ACL=y
+CONFIG_FILE_LOCKING=y
+CONFIG_XFS_FS=m
+CONFIG_XFS_QUOTA=y
+CONFIG_XFS_POSIX_ACL=y
+CONFIG_XFS_RT=y
+# CONFIG_XFS_DEBUG is not set
+CONFIG_GFS2_FS=m
+CONFIG_GFS2_FS_LOCKING_DLM=m
+CONFIG_OCFS2_FS=m
+CONFIG_OCFS2_FS_O2CB=m
+CONFIG_OCFS2_FS_USERSPACE_CLUSTER=m
+CONFIG_OCFS2_FS_STATS=y
+# CONFIG_OCFS2_DEBUG_MASKLOG is not set
+# CONFIG_OCFS2_DEBUG_FS is not set
+# CONFIG_OCFS2_COMPAT_JBD is not set
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+CONFIG_QUOTA=y
+CONFIG_QUOTA_NETLINK_INTERFACE=y
+CONFIG_PRINT_QUOTA_WARNING=y
+CONFIG_QFMT_V1=m
+CONFIG_QFMT_V2=m
+CONFIG_QUOTACTL=y
+CONFIG_AUTOFS_FS=m
+CONFIG_AUTOFS4_FS=m
+CONFIG_FUSE_FS=m
+CONFIG_GENERIC_ACL=y
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+CONFIG_NTFS_FS=m
+# CONFIG_NTFS_DEBUG is not set
+CONFIG_NTFS_RW=y
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_HUGETLBFS=y
+CONFIG_HUGETLB_PAGE=y
+CONFIG_CONFIGFS_FS=m
+
+#
+# Miscellaneous filesystems
+#
+CONFIG_ADFS_FS=m
+# CONFIG_ADFS_FS_RW is not set
+CONFIG_AFFS_FS=m
+CONFIG_ECRYPT_FS=m
+CONFIG_HFS_FS=m
+CONFIG_HFSPLUS_FS=m
+CONFIG_BEFS_FS=m
+# CONFIG_BEFS_DEBUG is not set
+CONFIG_BFS_FS=m
+CONFIG_EFS_FS=m
+CONFIG_JFFS2_FS=m
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_LZO=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_JFFS2_CMODE_NONE is not set
+CONFIG_JFFS2_CMODE_PRIORITY=y
+# CONFIG_JFFS2_CMODE_SIZE is not set
+# CONFIG_JFFS2_CMODE_FAVOURLZO is not set
+CONFIG_UBIFS_FS=m
+CONFIG_UBIFS_FS_XATTR=y
+CONFIG_UBIFS_FS_ADVANCED_COMPR=y
+CONFIG_UBIFS_FS_LZO=y
+CONFIG_UBIFS_FS_ZLIB=y
+# CONFIG_UBIFS_FS_DEBUG is not set
+CONFIG_CRAMFS=m
+CONFIG_VXFS_FS=m
+CONFIG_MINIX_FS=y
+CONFIG_OMFS_FS=m
+CONFIG_HPFS_FS=m
+CONFIG_QNX4FS_FS=m
+CONFIG_ROMFS_FS=m
+CONFIG_SYSV_FS=m
+CONFIG_UFS_FS=m
+# CONFIG_UFS_FS_WRITE is not set
+# CONFIG_UFS_DEBUG is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_NFSD=m
+CONFIG_NFSD_V2_ACL=y
+CONFIG_NFSD_V3=y
+CONFIG_NFSD_V3_ACL=y
+CONFIG_NFSD_V4=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_NFS_ACL_SUPPORT=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+CONFIG_SUNRPC_XPRT_RDMA=m
+# CONFIG_SUNRPC_REGISTER_V4 is not set
+CONFIG_RPCSEC_GSS_KRB5=y
+CONFIG_RPCSEC_GSS_SPKM3=m
+CONFIG_SMB_FS=m
+CONFIG_SMB_NLS_DEFAULT=y
+CONFIG_SMB_NLS_REMOTE="cp850"
+CONFIG_CIFS=m
+CONFIG_CIFS_STATS=y
+# CONFIG_CIFS_STATS2 is not set
+CONFIG_CIFS_WEAK_PW_HASH=y
+CONFIG_CIFS_UPCALL=y
+CONFIG_CIFS_XATTR=y
+CONFIG_CIFS_POSIX=y
+# CONFIG_CIFS_DEBUG2 is not set
+# CONFIG_CIFS_EXPERIMENTAL is not set
+CONFIG_NCP_FS=m
+CONFIG_NCPFS_PACKET_SIGNING=y
+CONFIG_NCPFS_IOCTL_LOCKING=y
+CONFIG_NCPFS_STRONG=y
+CONFIG_NCPFS_NFS_NS=y
+CONFIG_NCPFS_OS2_NS=y
+CONFIG_NCPFS_SMALLDOS=y
+CONFIG_NCPFS_NLS=y
+CONFIG_NCPFS_EXTRAS=y
+CONFIG_CODA_FS=m
+CONFIG_AFS_FS=m
+# CONFIG_AFS_DEBUG is not set
+CONFIG_9P_FS=m
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+CONFIG_OSF_PARTITION=y
+# CONFIG_AMIGA_PARTITION is not set
+CONFIG_ATARI_PARTITION=y
+CONFIG_MAC_PARTITION=y
+CONFIG_MSDOS_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+# CONFIG_MINIX_SUBPARTITION is not set
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+CONFIG_LDM_PARTITION=y
+# CONFIG_LDM_DEBUG is not set
+CONFIG_SGI_PARTITION=y
+CONFIG_ULTRIX_PARTITION=y
+CONFIG_SUN_PARTITION=y
+CONFIG_KARMA_PARTITION=y
+CONFIG_EFI_PARTITION=y
+CONFIG_SYSV68_PARTITION=y
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="utf8"
+CONFIG_NLS_CODEPAGE_437=m
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=m
+CONFIG_NLS_ISO8859_1=m
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_UTF8=m
+CONFIG_DLM=m
+CONFIG_DLM_DEBUG=y
+
+#
+# Kernel hacking
+#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=2048
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_UNUSED_SYMBOLS=y
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC=y
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=1
+CONFIG_SCHED_DEBUG=y
+# CONFIG_SCHEDSTATS is not set
+CONFIG_TIMER_STATS=y
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_VIRTUAL is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+CONFIG_DEBUG_MEMORY_INIT=y
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_FRAME_POINTER is not set
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_SYSPROF_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_PROVIDE_OHCI1394_DMA_INIT is not set
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+CONFIG_STRICT_DEVMEM=y
+CONFIG_X86_VERBOSE_BOOTUP=y
+CONFIG_EARLY_PRINTK=y
+# CONFIG_EARLY_PRINTK_DBGP is not set
+CONFIG_DEBUG_STACKOVERFLOW=y
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
+# CONFIG_DEBUG_PER_CPU_MAPS is not set
+# CONFIG_X86_PTDUMP is not set
+# CONFIG_DEBUG_RODATA is not set
+# CONFIG_DIRECT_GBPAGES is not set
+# CONFIG_DEBUG_NX_TEST is not set
+# CONFIG_IOMMU_DEBUG is not set
+# CONFIG_MMIOTRACE is not set
+CONFIG_IO_DELAY_TYPE_0X80=0
+CONFIG_IO_DELAY_TYPE_0XED=1
+CONFIG_IO_DELAY_TYPE_UDELAY=2
+CONFIG_IO_DELAY_TYPE_NONE=3
+CONFIG_IO_DELAY_0X80=y
+# CONFIG_IO_DELAY_0XED is not set
+# CONFIG_IO_DELAY_UDELAY is not set
+# CONFIG_IO_DELAY_NONE is not set
+CONFIG_DEFAULT_IO_DELAY_TYPE=0
+# CONFIG_DEBUG_BOOT_PARAMS is not set
+# CONFIG_CPA_DEBUG is not set
+# CONFIG_OPTIMIZE_INLINING is not set
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+# CONFIG_KEYS_DEBUG_PROC_KEYS is not set
+CONFIG_SECURITY=y
+CONFIG_SECURITYFS=y
+CONFIG_SECURITY_NETWORK=y
+# CONFIG_SECURITY_NETWORK_XFRM is not set
+CONFIG_SECURITY_FILE_CAPABILITIES=y
+CONFIG_SECURITY_DEFAULT_MMAP_MIN_ADDR=0
+CONFIG_SECURITY_SELINUX=y
+CONFIG_SECURITY_SELINUX_BOOTPARAM=y
+CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=0
+CONFIG_SECURITY_SELINUX_DISABLE=y
+CONFIG_SECURITY_SELINUX_DEVELOP=y
+CONFIG_SECURITY_SELINUX_AVC_STATS=y
+CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1
+# CONFIG_SECURITY_SELINUX_ENABLE_SECMARK_DEFAULT is not set
+# CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX is not set
+CONFIG_XOR_BLOCKS=m
+CONFIG_ASYNC_CORE=m
+CONFIG_ASYNC_MEMCPY=m
+CONFIG_ASYNC_XOR=m
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_FIPS=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD=m
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG=m
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+CONFIG_CRYPTO_GF128MUL=m
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_CRYPTD=m
+CONFIG_CRYPTO_AUTHENC=m
+CONFIG_CRYPTO_TEST=m
+
+#
+# Authenticated Encryption with Associated Data
+#
+CONFIG_CRYPTO_CCM=m
+CONFIG_CRYPTO_GCM=m
+CONFIG_CRYPTO_SEQIV=m
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_CTR=m
+CONFIG_CRYPTO_CTS=m
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_LRW=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_XTS=m
+
+#
+# Hash modes
+#
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_XCBC=m
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=m
+CONFIG_CRYPTO_CRC32C_INTEL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_RMD128=m
+CONFIG_CRYPTO_RMD160=m
+CONFIG_CRYPTO_RMD256=m
+CONFIG_CRYPTO_RMD320=m
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_WP512=m
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_AES_X86_64=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_CAMELLIA=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_DES=y
+CONFIG_CRYPTO_FCRYPT=m
+CONFIG_CRYPTO_KHAZAD=m
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SALSA20_X86_64 is not set
+CONFIG_CRYPTO_SEED=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_TWOFISH_COMMON=m
+CONFIG_CRYPTO_TWOFISH_X86_64=m
+
+#
+# Compression
+#
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_LZO=m
+
+#
+# Random Number Generation
+#
+CONFIG_CRYPTO_ANSI_CPRNG=m
+CONFIG_CRYPTO_HW=y
+CONFIG_CRYPTO_DEV_HIFN_795X=m
+# CONFIG_CRYPTO_DEV_HIFN_795X_RNG is not set
+CONFIG_HAVE_KVM=y
+CONFIG_VIRTUALIZATION=y
+CONFIG_KVM=m
+CONFIG_KVM_INTEL=m
+CONFIG_KVM_AMD=m
+CONFIG_VIRTIO=m
+CONFIG_VIRTIO_RING=m
+CONFIG_VIRTIO_PCI=m
+CONFIG_VIRTIO_BALLOON=m
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_FIRST_BIT=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_CRC_CCITT=m
+CONFIG_CRC16=m
+CONFIG_CRC_T10DIF=m
+CONFIG_CRC_ITU_T=m
+CONFIG_CRC32=y
+CONFIG_CRC7=m
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=m
+CONFIG_LZO_COMPRESS=m
+CONFIG_LZO_DECOMPRESS=m
+CONFIG_GENERIC_ALLOCATOR=y
+CONFIG_REED_SOLOMON=m
+CONFIG_REED_SOLOMON_DEC16=y
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=m
+CONFIG_TEXTSEARCH_BM=m
+CONFIG_TEXTSEARCH_FSM=m
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_CHECK_SIGNATURE=y
diff --git a/pkgs/os-specific/linux/kernel/linux-2.6.21_ck.nix b/pkgs/os-specific/linux/kernel/generic.nix
index 55748d3e9f54e..11bac64ced7cb 100644
--- a/pkgs/os-specific/linux/kernel/linux-2.6.21_ck.nix
+++ b/pkgs/os-specific/linux/kernel/generic.nix
@@ -1,22 +1,36 @@
 { stdenv, fetchurl, perl, mktemp, module_init_tools
 
-  # A list of patches to apply to the kernel.  Each element of this list
+, # The kernel source tarball.
+  src
+
+, # The kernel version.
+  version
+
+, # The kernel configuration.
+  config
+
+, # An attribute set whose attributes express the availability of
+  # certain features in this kernel.  E.g. `{iwlwifi = true;}'
+  # indicates a kernel that provides Intel wireless support.  Used in
+  # NixOS to implement kernel-specific behaviour.
+  features ? {}
+
+, # A list of patches to apply to the kernel.  Each element of this list
   # should be an attribute set {name, patch} where `name' is a
   # symbolic name and `patch' is the actual patch.  The patch may
   # optionally be compressed with gzip or bzip2.
-, kernelPatches ? []
+  kernelPatches ? []
 
 , # Whether to build a User-Mode Linux kernel.
   userModeLinux ? false
 
+, # Whether to build a Xen kernel.
+  xen ? false
+
 , # Allows you to set your own kernel version suffix (e.g.,
   # "-my-kernel").
   localVersion ? ""
 
-, # Your own kernel configuration file, if you don't want to use the
-  # default. 
-  kernelConfig ? null
-
 , # A list of additional statements to be appended to the
   # configuration file.
   extraConfig ? []
@@ -26,38 +40,35 @@ assert stdenv.system == "i686-linux" || stdenv.system == "x86_64-linux";
 
 let
 
-  lib = import ../../../lib;
-
-  version = "2.6.21";
+  lib = stdenv.lib;
 
 in
 
 stdenv.mkDerivation {
   name = if userModeLinux then "user-mode-linux-${version}" else "linux-${version}";
-  builder = ./builder.sh;
-  
-  src = fetchurl {
-    url = "http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.21.tar.bz2";
-    sha256 = "f187b12d70e0a48ce81f0472dfe9504fb5f0f966be339ac9d57dd2b991a74942";
+
+  passthru = {
+    inherit version;
+    # Combine the `features' attribute sets of all the kernel patches.
+    features = lib.fold (x: y: (if x ? features then x.features else {}) // y) features kernelPatches;
   };
   
+  builder = ./builder.sh;
+
+  inherit src config;
+  
   patches = map (p: p.patch) kernelPatches;
+  
   extraConfig =
     let addNewlines = map (s: "\n" + s + "\n");
         configFromPatches =
           map (p: if p ? extraConfig then p.extraConfig else "") kernelPatches;
     in lib.concatStrings (addNewlines (configFromPatches ++ extraConfig));
 
-  config =
-    if kernelConfig != null then kernelConfig else
-    if userModeLinux then ./config-2.6.21-uml else
-    if stdenv.system == "i686-linux" then ./config-2.6.21-i686-smp else
-    if stdenv.system == "x86_64-linux" then ./config-2.6.21-x86_64-smp else
-    abort "No kernel configuration for your platform!";
-  
   buildInputs = [perl mktemp];
   
   arch =
+    if xen then "xen" else
     if userModeLinux then "um" else
     if stdenv.system == "i686-linux" then "i386" else
     if stdenv.system == "x86_64-linux" then "x86_64" else
diff --git a/pkgs/os-specific/linux/kernel/linux-2.6.20.3-ext3cow.patch b/pkgs/os-specific/linux/kernel/linux-2.6.20.3-ext3cow.patch
deleted file mode 100644
index 22704f1a1db78..0000000000000
--- a/pkgs/os-specific/linux/kernel/linux-2.6.20.3-ext3cow.patch
+++ /dev/null
@@ -1,18494 +0,0 @@
-diff -ruN linux-2.6.20.3/fs/ext3cow/acl.c linux-2.6.20.3-ext3cow/fs/ext3cow/acl.c
---- linux-2.6.20.3/fs/ext3cow/acl.c	1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.20.3-ext3cow/fs/ext3cow/acl.c	2008-03-09 11:14:49.000000000 -0400
-@@ -0,0 +1,551 @@
-+/*
-+ * linux/fs/ext3cow/acl.c
-+ *
-+ * Copyright (C) 2001-2003 Andreas Gruenbacher, <agruen@suse.de>
-+ */
-+
-+#include <linux/init.h>
-+#include <linux/sched.h>
-+#include <linux/slab.h>
-+#include <linux/capability.h>
-+#include <linux/fs.h>
-+#include <linux/ext3cow_jbd.h>
-+#include <linux/ext3cow_fs.h>
-+#include "xattr.h"
-+#include "acl.h"
-+
-+/*
-+ * Convert from filesystem to in-memory representation.
-+ */
-+static struct posix_acl *
-+ext3cow_acl_from_disk(const void *value, size_t size)
-+{
-+	const char *end = (char *)value + size;
-+	int n, count;
-+	struct posix_acl *acl;
-+
-+	if (!value)
-+		return NULL;
-+	if (size < sizeof(ext3cow_acl_header))
-+		 return ERR_PTR(-EINVAL);
-+	if (((ext3cow_acl_header *)value)->a_version !=
-+	    cpu_to_le32(EXT3COW_ACL_VERSION))
-+		return ERR_PTR(-EINVAL);
-+	value = (char *)value + sizeof(ext3cow_acl_header);
-+	count = ext3cow_acl_count(size);
-+	if (count < 0)
-+		return ERR_PTR(-EINVAL);
-+	if (count == 0)
-+		return NULL;
-+	acl = posix_acl_alloc(count, GFP_KERNEL);
-+	if (!acl)
-+		return ERR_PTR(-ENOMEM);
-+	for (n=0; n < count; n++) {
-+		ext3cow_acl_entry *entry =
-+			(ext3cow_acl_entry *)value;
-+		if ((char *)value + sizeof(ext3cow_acl_entry_short) > end)
-+			goto fail;
-+		acl->a_entries[n].e_tag  = le16_to_cpu(entry->e_tag);
-+		acl->a_entries[n].e_perm = le16_to_cpu(entry->e_perm);
-+		switch(acl->a_entries[n].e_tag) {
-+			case ACL_USER_OBJ:
-+			case ACL_GROUP_OBJ:
-+			case ACL_MASK:
-+			case ACL_OTHER:
-+				value = (char *)value +
-+					sizeof(ext3cow_acl_entry_short);
-+				acl->a_entries[n].e_id = ACL_UNDEFINED_ID;
-+				break;
-+
-+			case ACL_USER:
-+			case ACL_GROUP:
-+				value = (char *)value + sizeof(ext3cow_acl_entry);
-+				if ((char *)value > end)
-+					goto fail;
-+				acl->a_entries[n].e_id =
-+					le32_to_cpu(entry->e_id);
-+				break;
-+
-+			default:
-+				goto fail;
-+		}
-+	}
-+	if (value != end)
-+		goto fail;
-+	return acl;
-+
-+fail:
-+	posix_acl_release(acl);
-+	return ERR_PTR(-EINVAL);
-+}
-+
-+/*
-+ * Convert from in-memory to filesystem representation.
-+ */
-+static void *
-+ext3cow_acl_to_disk(const struct posix_acl *acl, size_t *size)
-+{
-+	ext3cow_acl_header *ext_acl;
-+	char *e;
-+	size_t n;
-+
-+	*size = ext3cow_acl_size(acl->a_count);
-+	ext_acl = kmalloc(sizeof(ext3cow_acl_header) + acl->a_count *
-+			sizeof(ext3cow_acl_entry), GFP_KERNEL);
-+	if (!ext_acl)
-+		return ERR_PTR(-ENOMEM);
-+	ext_acl->a_version = cpu_to_le32(EXT3COW_ACL_VERSION);
-+	e = (char *)ext_acl + sizeof(ext3cow_acl_header);
-+	for (n=0; n < acl->a_count; n++) {
-+		ext3cow_acl_entry *entry = (ext3cow_acl_entry *)e;
-+		entry->e_tag  = cpu_to_le16(acl->a_entries[n].e_tag);
-+		entry->e_perm = cpu_to_le16(acl->a_entries[n].e_perm);
-+		switch(acl->a_entries[n].e_tag) {
-+			case ACL_USER:
-+			case ACL_GROUP:
-+				entry->e_id =
-+					cpu_to_le32(acl->a_entries[n].e_id);
-+				e += sizeof(ext3cow_acl_entry);
-+				break;
-+
-+			case ACL_USER_OBJ:
-+			case ACL_GROUP_OBJ:
-+			case ACL_MASK:
-+			case ACL_OTHER:
-+				e += sizeof(ext3cow_acl_entry_short);
-+				break;
-+
-+			default:
-+				goto fail;
-+		}
-+	}
-+	return (char *)ext_acl;
-+
-+fail:
-+	kfree(ext_acl);
-+	return ERR_PTR(-EINVAL);
-+}
-+
-+static inline struct posix_acl *
-+ext3cow_iget_acl(struct inode *inode, struct posix_acl **i_acl)
-+{
-+	struct posix_acl *acl = EXT3COW_ACL_NOT_CACHED;
-+
-+	spin_lock(&inode->i_lock);
-+	if (*i_acl != EXT3COW_ACL_NOT_CACHED)
-+		acl = posix_acl_dup(*i_acl);
-+	spin_unlock(&inode->i_lock);
-+
-+	return acl;
-+}
-+
-+static inline void
-+ext3cow_iset_acl(struct inode *inode, struct posix_acl **i_acl,
-+                  struct posix_acl *acl)
-+{
-+	spin_lock(&inode->i_lock);
-+	if (*i_acl != EXT3COW_ACL_NOT_CACHED)
-+		posix_acl_release(*i_acl);
-+	*i_acl = posix_acl_dup(acl);
-+	spin_unlock(&inode->i_lock);
-+}
-+
-+/*
-+ * Inode operation get_posix_acl().
-+ *
-+ * inode->i_mutex: don't care
-+ */
-+static struct posix_acl *
-+ext3cow_get_acl(struct inode *inode, int type)
-+{
-+	struct ext3cow_inode_info *ei = EXT3COW_I(inode);
-+	int name_index;
-+	char *value = NULL;
-+	struct posix_acl *acl;
-+	int retval;
-+
-+	if (!test_opt(inode->i_sb, POSIX_ACL))
-+		return NULL;
-+
-+	switch(type) {
-+		case ACL_TYPE_ACCESS:
-+			acl = ext3cow_iget_acl(inode, &ei->i_acl);
-+			if (acl != EXT3COW_ACL_NOT_CACHED)
-+				return acl;
-+			name_index = EXT3COW_XATTR_INDEX_POSIX_ACL_ACCESS;
-+			break;
-+
-+		case ACL_TYPE_DEFAULT:
-+			acl = ext3cow_iget_acl(inode, &ei->i_default_acl);
-+			if (acl != EXT3COW_ACL_NOT_CACHED)
-+				return acl;
-+			name_index = EXT3COW_XATTR_INDEX_POSIX_ACL_DEFAULT;
-+			break;
-+
-+		default:
-+			return ERR_PTR(-EINVAL);
-+	}
-+	retval = ext3cow_xattr_get(inode, name_index, "", NULL, 0);
-+	if (retval > 0) {
-+		value = kmalloc(retval, GFP_KERNEL);
-+		if (!value)
-+			return ERR_PTR(-ENOMEM);
-+		retval = ext3cow_xattr_get(inode, name_index, "", value, retval);
-+	}
-+	if (retval > 0)
-+		acl = ext3cow_acl_from_disk(value, retval);
-+	else if (retval == -ENODATA || retval == -ENOSYS)
-+		acl = NULL;
-+	else
-+		acl = ERR_PTR(retval);
-+	kfree(value);
-+
-+	if (!IS_ERR(acl)) {
-+		switch(type) {
-+			case ACL_TYPE_ACCESS:
-+				ext3cow_iset_acl(inode, &ei->i_acl, acl);
-+				break;
-+
-+			case ACL_TYPE_DEFAULT:
-+				ext3cow_iset_acl(inode, &ei->i_default_acl, acl);
-+				break;
-+		}
-+	}
-+	return acl;
-+}
-+
-+/*
-+ * Set the access or default ACL of an inode.
-+ *
-+ * inode->i_mutex: down unless called from ext3cow_new_inode
-+ */
-+static int
-+ext3cow_set_acl(handle_t *handle, struct inode *inode, int type,
-+	     struct posix_acl *acl)
-+{
-+	struct ext3cow_inode_info *ei = EXT3COW_I(inode);
-+	int name_index;
-+	void *value = NULL;
-+	size_t size = 0;
-+	int error;
-+
-+	if (S_ISLNK(inode->i_mode))
-+		return -EOPNOTSUPP;
-+
-+	switch(type) {
-+		case ACL_TYPE_ACCESS:
-+			name_index = EXT3COW_XATTR_INDEX_POSIX_ACL_ACCESS;
-+			if (acl) {
-+				mode_t mode = inode->i_mode;
-+				error = posix_acl_equiv_mode(acl, &mode);
-+				if (error < 0)
-+					return error;
-+				else {
-+					inode->i_mode = mode;
-+					ext3cow_mark_inode_dirty(handle, inode);
-+					if (error == 0)
-+						acl = NULL;
-+				}
-+			}
-+			break;
-+
-+		case ACL_TYPE_DEFAULT:
-+			name_index = EXT3COW_XATTR_INDEX_POSIX_ACL_DEFAULT;
-+			if (!S_ISDIR(inode->i_mode))
-+				return acl ? -EACCES : 0;
-+			break;
-+
-+		default:
-+			return -EINVAL;
-+	}
-+	if (acl) {
-+		value = ext3cow_acl_to_disk(acl, &size);
-+		if (IS_ERR(value))
-+			return (int)PTR_ERR(value);
-+	}
-+
-+	error = ext3cow_xattr_set_handle(handle, inode, name_index, "",
-+				      value, size, 0);
-+
-+	kfree(value);
-+	if (!error) {
-+		switch(type) {
-+			case ACL_TYPE_ACCESS:
-+				ext3cow_iset_acl(inode, &ei->i_acl, acl);
-+				break;
-+
-+			case ACL_TYPE_DEFAULT:
-+				ext3cow_iset_acl(inode, &ei->i_default_acl, acl);
-+				break;
-+		}
-+	}
-+	return error;
-+}
-+
-+static int
-+ext3cow_check_acl(struct inode *inode, int mask)
-+{
-+	struct posix_acl *acl = ext3cow_get_acl(inode, ACL_TYPE_ACCESS);
-+
-+	if (IS_ERR(acl))
-+		return PTR_ERR(acl);
-+	if (acl) {
-+		int error = posix_acl_permission(inode, acl, mask);
-+		posix_acl_release(acl);
-+		return error;
-+	}
-+
-+	return -EAGAIN;
-+}
-+
-+int
-+ext3cow_permission(struct inode *inode, int mask, struct nameidata *nd)
-+{
-+	return generic_permission(inode, mask, ext3cow_check_acl);
-+}
-+
-+/*
-+ * Initialize the ACLs of a new inode. Called from ext3cow_new_inode.
-+ *
-+ * dir->i_mutex: down
-+ * inode->i_mutex: up (access to inode is still exclusive)
-+ */
-+int
-+ext3cow_init_acl(handle_t *handle, struct inode *inode, struct inode *dir)
-+{
-+	struct posix_acl *acl = NULL;
-+	int error = 0;
-+
-+	if (!S_ISLNK(inode->i_mode)) {
-+		if (test_opt(dir->i_sb, POSIX_ACL)) {
-+			acl = ext3cow_get_acl(dir, ACL_TYPE_DEFAULT);
-+			if (IS_ERR(acl))
-+				return PTR_ERR(acl);
-+		}
-+		if (!acl)
-+			inode->i_mode &= ~current->fs->umask;
-+	}
-+	if (test_opt(inode->i_sb, POSIX_ACL) && acl) {
-+		struct posix_acl *clone;
-+		mode_t mode;
-+
-+		if (S_ISDIR(inode->i_mode)) {
-+			error = ext3cow_set_acl(handle, inode,
-+					     ACL_TYPE_DEFAULT, acl);
-+			if (error)
-+				goto cleanup;
-+		}
-+		clone = posix_acl_clone(acl, GFP_KERNEL);
-+		error = -ENOMEM;
-+		if (!clone)
-+			goto cleanup;
-+
-+		mode = inode->i_mode;
-+		error = posix_acl_create_masq(clone, &mode);
-+		if (error >= 0) {
-+			inode->i_mode = mode;
-+			if (error > 0) {
-+				/* This is an extended ACL */
-+				error = ext3cow_set_acl(handle, inode,
-+						     ACL_TYPE_ACCESS, clone);
-+			}
-+		}
-+		posix_acl_release(clone);
-+	}
-+cleanup:
-+	posix_acl_release(acl);
-+	return error;
-+}
-+
-+/*
-+ * Does chmod for an inode that may have an Access Control List. The
-+ * inode->i_mode field must be updated to the desired value by the caller
-+ * before calling this function.
-+ * Returns 0 on success, or a negative error number.
-+ *
-+ * We change the ACL rather than storing some ACL entries in the file
-+ * mode permission bits (which would be more efficient), because that
-+ * would break once additional permissions (like  ACL_APPEND, ACL_DELETE
-+ * for directories) are added. There are no more bits available in the
-+ * file mode.
-+ *
-+ * inode->i_mutex: down
-+ */
-+int
-+ext3cow_acl_chmod(struct inode *inode)
-+{
-+	struct posix_acl *acl, *clone;
-+        int error;
-+
-+	if (S_ISLNK(inode->i_mode))
-+		return -EOPNOTSUPP;
-+	if (!test_opt(inode->i_sb, POSIX_ACL))
-+		return 0;
-+	acl = ext3cow_get_acl(inode, ACL_TYPE_ACCESS);
-+	if (IS_ERR(acl) || !acl)
-+		return PTR_ERR(acl);
-+	clone = posix_acl_clone(acl, GFP_KERNEL);
-+	posix_acl_release(acl);
-+	if (!clone)
-+		return -ENOMEM;
-+	error = posix_acl_chmod_masq(clone, inode->i_mode);
-+	if (!error) {
-+		handle_t *handle;
-+		int retries = 0;
-+
-+	retry:
-+		handle = ext3cow_journal_start(inode,
-+				EXT3COW_DATA_TRANS_BLOCKS(inode->i_sb));
-+		if (IS_ERR(handle)) {
-+			error = PTR_ERR(handle);
-+			ext3cow_std_error(inode->i_sb, error);
-+			goto out;
-+		}
-+		error = ext3cow_set_acl(handle, inode, ACL_TYPE_ACCESS, clone);
-+		ext3cow_journal_stop(handle);
-+		if (error == -ENOSPC &&
-+		    ext3cow_should_retry_alloc(inode->i_sb, &retries))
-+			goto retry;
-+	}
-+out:
-+	posix_acl_release(clone);
-+	return error;
-+}
-+
-+/*
-+ * Extended attribute handlers
-+ */
-+static size_t
-+ext3cow_xattr_list_acl_access(struct inode *inode, char *list, size_t list_len,
-+			   const char *name, size_t name_len)
-+{
-+	const size_t size = sizeof(POSIX_ACL_XATTR_ACCESS);
-+
-+	if (!test_opt(inode->i_sb, POSIX_ACL))
-+		return 0;
-+	if (list && size <= list_len)
-+		memcpy(list, POSIX_ACL_XATTR_ACCESS, size);
-+	return size;
-+}
-+
-+static size_t
-+ext3cow_xattr_list_acl_default(struct inode *inode, char *list, size_t list_len,
-+			    const char *name, size_t name_len)
-+{
-+	const size_t size = sizeof(POSIX_ACL_XATTR_DEFAULT);
-+
-+	if (!test_opt(inode->i_sb, POSIX_ACL))
-+		return 0;
-+	if (list && size <= list_len)
-+		memcpy(list, POSIX_ACL_XATTR_DEFAULT, size);
-+	return size;
-+}
-+
-+static int
-+ext3cow_xattr_get_acl(struct inode *inode, int type, void *buffer, size_t size)
-+{
-+	struct posix_acl *acl;
-+	int error;
-+
-+	if (!test_opt(inode->i_sb, POSIX_ACL))
-+		return -EOPNOTSUPP;
-+
-+	acl = ext3cow_get_acl(inode, type);
-+	if (IS_ERR(acl))
-+		return PTR_ERR(acl);
-+	if (acl == NULL)
-+		return -ENODATA;
-+	error = posix_acl_to_xattr(acl, buffer, size);
-+	posix_acl_release(acl);
-+
-+	return error;
-+}
-+
-+static int
-+ext3cow_xattr_get_acl_access(struct inode *inode, const char *name,
-+			  void *buffer, size_t size)
-+{
-+	if (strcmp(name, "") != 0)
-+		return -EINVAL;
-+	return ext3cow_xattr_get_acl(inode, ACL_TYPE_ACCESS, buffer, size);
-+}
-+
-+static int
-+ext3cow_xattr_get_acl_default(struct inode *inode, const char *name,
-+			   void *buffer, size_t size)
-+{
-+	if (strcmp(name, "") != 0)
-+		return -EINVAL;
-+	return ext3cow_xattr_get_acl(inode, ACL_TYPE_DEFAULT, buffer, size);
-+}
-+
-+static int
-+ext3cow_xattr_set_acl(struct inode *inode, int type, const void *value,
-+		   size_t size)
-+{
-+	handle_t *handle;
-+	struct posix_acl *acl;
-+	int error, retries = 0;
-+
-+	if (!test_opt(inode->i_sb, POSIX_ACL))
-+		return -EOPNOTSUPP;
-+	if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
-+		return -EPERM;
-+
-+	if (value) {
-+		acl = posix_acl_from_xattr(value, size);
-+		if (IS_ERR(acl))
-+			return PTR_ERR(acl);
-+		else if (acl) {
-+			error = posix_acl_valid(acl);
-+			if (error)
-+				goto release_and_out;
-+		}
-+	} else
-+		acl = NULL;
-+
-+retry:
-+	handle = ext3cow_journal_start(inode, EXT3COW_DATA_TRANS_BLOCKS(inode->i_sb));
-+	if (IS_ERR(handle))
-+		return PTR_ERR(handle);
-+	error = ext3cow_set_acl(handle, inode, type, acl);
-+	ext3cow_journal_stop(handle);
-+	if (error == -ENOSPC && ext3cow_should_retry_alloc(inode->i_sb, &retries))
-+		goto retry;
-+
-+release_and_out:
-+	posix_acl_release(acl);
-+	return error;
-+}
-+
-+static int
-+ext3cow_xattr_set_acl_access(struct inode *inode, const char *name,
-+			  const void *value, size_t size, int flags)
-+{
-+	if (strcmp(name, "") != 0)
-+		return -EINVAL;
-+	return ext3cow_xattr_set_acl(inode, ACL_TYPE_ACCESS, value, size);
-+}
-+
-+static int
-+ext3cow_xattr_set_acl_default(struct inode *inode, const char *name,
-+			   const void *value, size_t size, int flags)
-+{
-+	if (strcmp(name, "") != 0)
-+		return -EINVAL;
-+	return ext3cow_xattr_set_acl(inode, ACL_TYPE_DEFAULT, value, size);
-+}
-+
-+struct xattr_handler ext3cow_xattr_acl_access_handler = {
-+	.prefix	= POSIX_ACL_XATTR_ACCESS,
-+	.list	= ext3cow_xattr_list_acl_access,
-+	.get	= ext3cow_xattr_get_acl_access,
-+	.set	= ext3cow_xattr_set_acl_access,
-+};
-+
-+struct xattr_handler ext3cow_xattr_acl_default_handler = {
-+	.prefix	= POSIX_ACL_XATTR_DEFAULT,
-+	.list	= ext3cow_xattr_list_acl_default,
-+	.get	= ext3cow_xattr_get_acl_default,
-+	.set	= ext3cow_xattr_set_acl_default,
-+};
-diff -ruN linux-2.6.20.3/fs/ext3cow/acl.h linux-2.6.20.3-ext3cow/fs/ext3cow/acl.h
---- linux-2.6.20.3/fs/ext3cow/acl.h	1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.20.3-ext3cow/fs/ext3cow/acl.h	2008-03-09 11:14:48.000000000 -0400
-@@ -0,0 +1,81 @@
-+/*
-+  File: fs/ext3cow/acl.h
-+
-+  (C) 2001 Andreas Gruenbacher, <a.gruenbacher@computer.org>
-+*/
-+
-+#include <linux/posix_acl_xattr.h>
-+
-+#define EXT3COW_ACL_VERSION	0x0001
-+
-+typedef struct {
-+	__le16		e_tag;
-+	__le16		e_perm;
-+	__le32		e_id;
-+} ext3cow_acl_entry;
-+
-+typedef struct {
-+	__le16		e_tag;
-+	__le16		e_perm;
-+} ext3cow_acl_entry_short;
-+
-+typedef struct {
-+	__le32		a_version;
-+} ext3cow_acl_header;
-+
-+static inline size_t ext3cow_acl_size(int count)
-+{
-+	if (count <= 4) {
-+		return sizeof(ext3cow_acl_header) +
-+		       count * sizeof(ext3cow_acl_entry_short);
-+	} else {
-+		return sizeof(ext3cow_acl_header) +
-+		       4 * sizeof(ext3cow_acl_entry_short) +
-+		       (count - 4) * sizeof(ext3cow_acl_entry);
-+	}
-+}
-+
-+static inline int ext3cow_acl_count(size_t size)
-+{
-+	ssize_t s;
-+	size -= sizeof(ext3cow_acl_header);
-+	s = size - 4 * sizeof(ext3cow_acl_entry_short);
-+	if (s < 0) {
-+		if (size % sizeof(ext3cow_acl_entry_short))
-+			return -1;
-+		return size / sizeof(ext3cow_acl_entry_short);
-+	} else {
-+		if (s % sizeof(ext3cow_acl_entry))
-+			return -1;
-+		return s / sizeof(ext3cow_acl_entry) + 4;
-+	}
-+}
-+
-+#ifdef CONFIG_EXT3COW_FS_POSIX_ACL
-+
-+/* Value for inode->u.ext3cow_i.i_acl and inode->u.ext3cow_i.i_default_acl
-+   if the ACL has not been cached */
-+#define EXT3COW_ACL_NOT_CACHED ((void *)-1)
-+
-+/* acl.c */
-+extern int ext3cow_permission (struct inode *, int, struct nameidata *);
-+extern int ext3cow_acl_chmod (struct inode *);
-+extern int ext3cow_init_acl (handle_t *, struct inode *, struct inode *);
-+
-+#else  /* CONFIG_EXT3COW_FS_POSIX_ACL */
-+#include <linux/sched.h>
-+#define ext3cow_permission NULL
-+
-+static inline int
-+ext3cow_acl_chmod(struct inode *inode)
-+{
-+	return 0;
-+}
-+
-+static inline int
-+ext3cow_init_acl(handle_t *handle, struct inode *inode, struct inode *dir)
-+{
-+	return 0;
-+}
-+#endif  /* CONFIG_EXT3COW_FS_POSIX_ACL */
-+
-diff -ruN linux-2.6.20.3/fs/ext3cow/balloc.c linux-2.6.20.3-ext3cow/fs/ext3cow/balloc.c
---- linux-2.6.20.3/fs/ext3cow/balloc.c	1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.20.3-ext3cow/fs/ext3cow/balloc.c	2008-03-09 11:14:48.000000000 -0400
-@@ -0,0 +1,1823 @@
-+/*
-+ *  linux/fs/ext3cow/balloc.c
-+ *
-+ * Copyright (C) 1992, 1993, 1994, 1995
-+ * Remy Card (card@masi.ibp.fr)
-+ * Laboratoire MASI - Institut Blaise Pascal
-+ * Universite Pierre et Marie Curie (Paris VI)
-+ *
-+ *  Enhanced block allocation by Stephen Tweedie (sct@redhat.com), 1993
-+ *  Big-endian to little-endian byte-swapping/bitmaps by
-+ *        David S. Miller (davem@caip.rutgers.edu), 1995
-+ */
-+
-+#include <linux/time.h>
-+#include <linux/capability.h>
-+#include <linux/fs.h>
-+#include <linux/jbd.h>
-+#include <linux/ext3cow_fs.h>
-+#include <linux/ext3cow_jbd.h>
-+#include <linux/quotaops.h>
-+#include <linux/buffer_head.h>
-+
-+/*
-+ * balloc.c contains the blocks allocation and deallocation routines
-+ */
-+
-+/*
-+ * The free blocks are managed by bitmaps.  A file system contains several
-+ * blocks groups.  Each group contains 1 bitmap block for blocks, 1 bitmap
-+ * block for inodes, N blocks for the inode table and data blocks.
-+ *
-+ * The file system contains group descriptors which are located after the
-+ * super block.  Each descriptor contains the number of the bitmap block and
-+ * the free blocks count in the block.  The descriptors are loaded in memory
-+ * when a file system is mounted (see ext3cow_read_super).
-+ */
-+
-+
-+#define in_range(b, first, len)	((b) >= (first) && (b) <= (first) + (len) - 1)
-+
-+/**
-+ * ext3cow_get_group_desc() -- load group descriptor from disk
-+ * @sb:			super block
-+ * @block_group:	given block group
-+ * @bh:			pointer to the buffer head to store the block
-+ *			group descriptor
-+ */
-+struct ext3cow_group_desc * ext3cow_get_group_desc(struct super_block * sb,
-+					     unsigned int block_group,
-+					     struct buffer_head ** bh)
-+{
-+	unsigned long group_desc;
-+	unsigned long offset;
-+	struct ext3cow_group_desc * desc;
-+	struct ext3cow_sb_info *sbi = EXT3COW_SB(sb);
-+
-+	if (block_group >= sbi->s_groups_count) {
-+		ext3cow_error (sb, "ext3cow_get_group_desc",
-+			    "block_group >= groups_count - "
-+			    "block_group = %d, groups_count = %lu",
-+			    block_group, sbi->s_groups_count);
-+
-+		return NULL;
-+	}
-+	smp_rmb();
-+
-+	group_desc = block_group >> EXT3COW_DESC_PER_BLOCK_BITS(sb);
-+	offset = block_group & (EXT3COW_DESC_PER_BLOCK(sb) - 1);
-+	if (!sbi->s_group_desc[group_desc]) {
-+		ext3cow_error (sb, "ext3cow_get_group_desc",
-+			    "Group descriptor not loaded - "
-+			    "block_group = %d, group_desc = %lu, desc = %lu",
-+			     block_group, group_desc, offset);
-+		return NULL;
-+	}
-+
-+	desc = (struct ext3cow_group_desc *) sbi->s_group_desc[group_desc]->b_data;
-+	if (bh)
-+		*bh = sbi->s_group_desc[group_desc];
-+	return desc + offset;
-+}
-+
-+/**
-+ * read_block_bitmap()
-+ * @sb:			super block
-+ * @block_group:	given block group
-+ *
-+ * Read the bitmap for a given block_group, reading into the specified
-+ * slot in the superblock's bitmap cache.
-+ *
-+ * Return buffer_head on success or NULL in case of failure.
-+ */
-+static struct buffer_head *
-+read_block_bitmap(struct super_block *sb, unsigned int block_group)
-+{
-+	struct ext3cow_group_desc * desc;
-+	struct buffer_head * bh = NULL;
-+
-+	desc = ext3cow_get_group_desc (sb, block_group, NULL);
-+	if (!desc)
-+		goto error_out;
-+	bh = sb_bread(sb, le32_to_cpu(desc->bg_block_bitmap));
-+	if (!bh)
-+		ext3cow_error (sb, "read_block_bitmap",
-+			    "Cannot read block bitmap - "
-+			    "block_group = %d, block_bitmap = %u",
-+			    block_group, le32_to_cpu(desc->bg_block_bitmap));
-+error_out:
-+	return bh;
-+}
-+/*
-+ * The reservation window structure operations
-+ * --------------------------------------------
-+ * Operations include:
-+ * dump, find, add, remove, is_empty, find_next_reservable_window, etc.
-+ *
-+ * We use a red-black tree to represent per-filesystem reservation
-+ * windows.
-+ *
-+ */
-+
-+/**
-+ * __rsv_window_dump() -- Dump the filesystem block allocation reservation map
-+ * @rb_root:		root of per-filesystem reservation rb tree
-+ * @verbose:		verbose mode
-+ * @fn:			function which wishes to dump the reservation map
-+ *
-+ * If verbose is turned on, it will print the whole block reservation
-+ * windows(start, end).	Otherwise, it will only print out the "bad" windows,
-+ * those windows that overlap with their immediate neighbors.
-+ */
-+#if 1
-+static void __rsv_window_dump(struct rb_root *root, int verbose,
-+			      const char *fn)
-+{
-+	struct rb_node *n;
-+	struct ext3cow_reserve_window_node *rsv, *prev;
-+	int bad;
-+
-+restart:
-+	n = rb_first(root);
-+	bad = 0;
-+	prev = NULL;
-+
-+	printk("Block Allocation Reservation Windows Map (%s):\n", fn);
-+	while (n) {
-+		rsv = rb_entry(n, struct ext3cow_reserve_window_node, rsv_node);
-+		if (verbose)
-+			printk("reservation window 0x%p "
-+			       "start:  %lu, end:  %lu\n",
-+			       rsv, rsv->rsv_start, rsv->rsv_end);
-+		if (rsv->rsv_start && rsv->rsv_start >= rsv->rsv_end) {
-+			printk("Bad reservation %p (start >= end)\n",
-+			       rsv);
-+			bad = 1;
-+		}
-+		if (prev && prev->rsv_end >= rsv->rsv_start) {
-+			printk("Bad reservation %p (prev->end >= start)\n",
-+			       rsv);
-+			bad = 1;
-+		}
-+		if (bad) {
-+			if (!verbose) {
-+				printk("Restarting reservation walk in verbose mode\n");
-+				verbose = 1;
-+				goto restart;
-+			}
-+		}
-+		n = rb_next(n);
-+		prev = rsv;
-+	}
-+	printk("Window map complete.\n");
-+	if (bad)
-+		BUG();
-+}
-+#define rsv_window_dump(root, verbose) \
-+	__rsv_window_dump((root), (verbose), __FUNCTION__)
-+#else
-+#define rsv_window_dump(root, verbose) do {} while (0)
-+#endif
-+
-+/**
-+ * goal_in_my_reservation()
-+ * @rsv:		inode's reservation window
-+ * @grp_goal:		given goal block relative to the allocation block group
-+ * @group:		the current allocation block group
-+ * @sb:			filesystem super block
-+ *
-+ * Test if the given goal block (group relative) is within the file's
-+ * own block reservation window range.
-+ *
-+ * If the reservation window is outside the goal allocation group, return 0;
-+ * grp_goal (given goal block) could be -1, which means no specific
-+ * goal block. In this case, always return 1.
-+ * If the goal block is within the reservation window, return 1;
-+ * otherwise, return 0;
-+ */
-+static int
-+goal_in_my_reservation(struct ext3cow_reserve_window *rsv, ext3cow_grpblk_t grp_goal,
-+			unsigned int group, struct super_block * sb)
-+{
-+	ext3cow_fsblk_t group_first_block, group_last_block;
-+
-+	group_first_block = ext3cow_group_first_block_no(sb, group);
-+	group_last_block = group_first_block + (EXT3COW_BLOCKS_PER_GROUP(sb) - 1);
-+
-+	if ((rsv->_rsv_start > group_last_block) ||
-+	    (rsv->_rsv_end < group_first_block))
-+		return 0;
-+	if ((grp_goal >= 0) && ((grp_goal + group_first_block < rsv->_rsv_start)
-+		|| (grp_goal + group_first_block > rsv->_rsv_end)))
-+		return 0;
-+	return 1;
-+}
-+
-+/**
-+ * search_reserve_window()
-+ * @rb_root:		root of reservation tree
-+ * @goal:		target allocation block
-+ *
-+ * Find the reserved window which includes the goal, or the previous one
-+ * if the goal is not in any window.
-+ * Returns NULL if there are no windows or if all windows start after the goal.
-+ */
-+static struct ext3cow_reserve_window_node *
-+search_reserve_window(struct rb_root *root, ext3cow_fsblk_t goal)
-+{
-+	struct rb_node *n = root->rb_node;
-+	struct ext3cow_reserve_window_node *rsv;
-+
-+	if (!n)
-+		return NULL;
-+
-+	do {
-+		rsv = rb_entry(n, struct ext3cow_reserve_window_node, rsv_node);
-+
-+		if (goal < rsv->rsv_start)
-+			n = n->rb_left;
-+		else if (goal > rsv->rsv_end)
-+			n = n->rb_right;
-+		else
-+			return rsv;
-+	} while (n);
-+	/*
-+	 * We've fallen off the end of the tree: the goal wasn't inside
-+	 * any particular node.  OK, the previous node must be to one
-+	 * side of the interval containing the goal.  If it's the RHS,
-+	 * we need to back up one.
-+	 */
-+	if (rsv->rsv_start > goal) {
-+		n = rb_prev(&rsv->rsv_node);
-+		rsv = rb_entry(n, struct ext3cow_reserve_window_node, rsv_node);
-+	}
-+	return rsv;
-+}
-+
-+/**
-+ * ext3cow_rsv_window_add() -- Insert a window to the block reservation rb tree.
-+ * @sb:			super block
-+ * @rsv:		reservation window to add
-+ *
-+ * Must be called with rsv_lock hold.
-+ */
-+void ext3cow_rsv_window_add(struct super_block *sb,
-+		    struct ext3cow_reserve_window_node *rsv)
-+{
-+	struct rb_root *root = &EXT3COW_SB(sb)->s_rsv_window_root;
-+	struct rb_node *node = &rsv->rsv_node;
-+	ext3cow_fsblk_t start = rsv->rsv_start;
-+
-+	struct rb_node ** p = &root->rb_node;
-+	struct rb_node * parent = NULL;
-+	struct ext3cow_reserve_window_node *this;
-+
-+	while (*p)
-+	{
-+		parent = *p;
-+		this = rb_entry(parent, struct ext3cow_reserve_window_node, rsv_node);
-+
-+		if (start < this->rsv_start)
-+			p = &(*p)->rb_left;
-+		else if (start > this->rsv_end)
-+			p = &(*p)->rb_right;
-+		else {
-+			rsv_window_dump(root, 1);
-+			BUG();
-+		}
-+	}
-+
-+	rb_link_node(node, parent, p);
-+	rb_insert_color(node, root);
-+}
-+
-+/**
-+ * ext3cow_rsv_window_remove() -- unlink a window from the reservation rb tree
-+ * @sb:			super block
-+ * @rsv:		reservation window to remove
-+ *
-+ * Mark the block reservation window as not allocated, and unlink it
-+ * from the filesystem reservation window rb tree. Must be called with
-+ * rsv_lock hold.
-+ */
-+static void rsv_window_remove(struct super_block *sb,
-+			      struct ext3cow_reserve_window_node *rsv)
-+{
-+	rsv->rsv_start = EXT3COW_RESERVE_WINDOW_NOT_ALLOCATED;
-+	rsv->rsv_end = EXT3COW_RESERVE_WINDOW_NOT_ALLOCATED;
-+	rsv->rsv_alloc_hit = 0;
-+	rb_erase(&rsv->rsv_node, &EXT3COW_SB(sb)->s_rsv_window_root);
-+}
-+
-+/*
-+ * rsv_is_empty() -- Check if the reservation window is allocated.
-+ * @rsv:		given reservation window to check
-+ *
-+ * returns 1 if the end block is EXT3COW_RESERVE_WINDOW_NOT_ALLOCATED.
-+ */
-+static inline int rsv_is_empty(struct ext3cow_reserve_window *rsv)
-+{
-+	/* a valid reservation end block could not be 0 */
-+	return rsv->_rsv_end == EXT3COW_RESERVE_WINDOW_NOT_ALLOCATED;
-+}
-+
-+/**
-+ * ext3cow_init_block_alloc_info()
-+ * @inode:		file inode structure
-+ *
-+ * Allocate and initialize the	reservation window structure, and
-+ * link the window to the ext3cow inode structure at last
-+ *
-+ * The reservation window structure is only dynamically allocated
-+ * and linked to ext3cow inode the first time the open file
-+ * needs a new block. So, before every ext3cow_new_block(s) call, for
-+ * regular files, we should check whether the reservation window
-+ * structure exists or not. In the latter case, this function is called.
-+ * Fail to do so will result in block reservation being turned off for that
-+ * open file.
-+ *
-+ * This function is called from ext3cow_get_blocks_handle(), also called
-+ * when setting the reservation window size through ioctl before the file
-+ * is open for write (needs block allocation).
-+ *
-+ * Needs truncate_mutex protection prior to call this function.
-+ */
-+void ext3cow_init_block_alloc_info(struct inode *inode)
-+{
-+	struct ext3cow_inode_info *ei = EXT3COW_I(inode);
-+	struct ext3cow_block_alloc_info *block_i = ei->i_block_alloc_info;
-+	struct super_block *sb = inode->i_sb;
-+
-+	block_i = kmalloc(sizeof(*block_i), GFP_NOFS);
-+	if (block_i) {
-+		struct ext3cow_reserve_window_node *rsv = &block_i->rsv_window_node;
-+
-+		rsv->rsv_start = EXT3COW_RESERVE_WINDOW_NOT_ALLOCATED;
-+		rsv->rsv_end = EXT3COW_RESERVE_WINDOW_NOT_ALLOCATED;
-+
-+		/*
-+		 * if filesystem is mounted with NORESERVATION, the goal
-+		 * reservation window size is set to zero to indicate
-+		 * block reservation is off
-+		 */
-+		if (!test_opt(sb, RESERVATION))
-+			rsv->rsv_goal_size = 0;
-+		else
-+			rsv->rsv_goal_size = EXT3COW_DEFAULT_RESERVE_BLOCKS;
-+		rsv->rsv_alloc_hit = 0;
-+		block_i->last_alloc_logical_block = 0;
-+		block_i->last_alloc_physical_block = 0;
-+	}
-+	ei->i_block_alloc_info = block_i;
-+}
-+
-+/**
-+ * ext3cow_discard_reservation()
-+ * @inode:		inode
-+ *
-+ * Discard(free) block reservation window on last file close, or truncate
-+ * or at last iput().
-+ *
-+ * It is being called in three cases:
-+ *	ext3cow_release_file(): last writer close the file
-+ *	ext3cow_clear_inode(): last iput(), when nobody link to this file.
-+ *	ext3cow_truncate(): when the block indirect map is about to change.
-+ *
-+ */
-+void ext3cow_discard_reservation(struct inode *inode)
-+{
-+	struct ext3cow_inode_info *ei = EXT3COW_I(inode);
-+	struct ext3cow_block_alloc_info *block_i = ei->i_block_alloc_info;
-+	struct ext3cow_reserve_window_node *rsv;
-+	spinlock_t *rsv_lock = &EXT3COW_SB(inode->i_sb)->s_rsv_window_lock;
-+
-+	if (!block_i)
-+		return;
-+
-+	rsv = &block_i->rsv_window_node;
-+	if (!rsv_is_empty(&rsv->rsv_window)) {
-+		spin_lock(rsv_lock);
-+		if (!rsv_is_empty(&rsv->rsv_window))
-+			rsv_window_remove(inode->i_sb, rsv);
-+		spin_unlock(rsv_lock);
-+	}
-+}
-+
-+/**
-+ * ext3cow_free_blocks_sb() -- Free given blocks and update quota
-+ * @handle:			handle to this transaction
-+ * @sb:				super block
-+ * @block:			start physcial block to free
-+ * @count:			number of blocks to free
-+ * @pdquot_freed_blocks:	pointer to quota
-+ */
-+void ext3cow_free_blocks_sb(handle_t *handle, struct super_block *sb,
-+			 ext3cow_fsblk_t block, unsigned long count,
-+			 unsigned long *pdquot_freed_blocks)
-+{
-+	struct buffer_head *bitmap_bh = NULL;
-+	struct buffer_head *gd_bh;
-+	unsigned long block_group;
-+	ext3cow_grpblk_t bit;
-+	unsigned long i;
-+	unsigned long overflow;
-+	struct ext3cow_group_desc * desc;
-+	struct ext3cow_super_block * es;
-+	struct ext3cow_sb_info *sbi;
-+	int err = 0, ret;
-+	ext3cow_grpblk_t group_freed;
-+
-+	*pdquot_freed_blocks = 0;
-+	sbi = EXT3COW_SB(sb);
-+	es = sbi->s_es;
-+	if (block < le32_to_cpu(es->s_first_data_block) ||
-+	    block + count < block ||
-+	    block + count > le32_to_cpu(es->s_blocks_count)) {
-+		ext3cow_error (sb, "ext3cow_free_blocks",
-+			    "Freeing blocks not in datazone - "
-+			    "block = "E3FSBLK", count = %lu", block, count);
-+		goto error_return;
-+	}
-+
-+  //TODO: Remove:
-+  printk(KERN_INFO "freeing block(s) %lu-%lu\n", block, block + count - 1);
-+	ext3cow_debug ("freeing block(s) %lu-%lu\n", block, block + count - 1);
-+
-+do_more:
-+	overflow = 0;
-+	block_group = (block - le32_to_cpu(es->s_first_data_block)) /
-+		      EXT3COW_BLOCKS_PER_GROUP(sb);
-+	bit = (block - le32_to_cpu(es->s_first_data_block)) %
-+		      EXT3COW_BLOCKS_PER_GROUP(sb);
-+	/*
-+	 * Check to see if we are freeing blocks across a group
-+	 * boundary.
-+	 */
-+	if (bit + count > EXT3COW_BLOCKS_PER_GROUP(sb)) {
-+		overflow = bit + count - EXT3COW_BLOCKS_PER_GROUP(sb);
-+		count -= overflow;
-+	}
-+	brelse(bitmap_bh);
-+	bitmap_bh = read_block_bitmap(sb, block_group);
-+	if (!bitmap_bh)
-+		goto error_return;
-+	desc = ext3cow_get_group_desc (sb, block_group, &gd_bh);
-+	if (!desc)
-+		goto error_return;
-+
-+	if (in_range (le32_to_cpu(desc->bg_block_bitmap), block, count) ||
-+	    in_range (le32_to_cpu(desc->bg_inode_bitmap), block, count) ||
-+	    in_range (block, le32_to_cpu(desc->bg_inode_table),
-+		      sbi->s_itb_per_group) ||
-+	    in_range (block + count - 1, le32_to_cpu(desc->bg_inode_table),
-+		      sbi->s_itb_per_group))
-+		ext3cow_error (sb, "ext3cow_free_blocks",
-+			    "Freeing blocks in system zones - "
-+			    "Block = "E3FSBLK", count = %lu",
-+			    block, count);
-+
-+	/*
-+	 * We are about to start releasing blocks in the bitmap,
-+	 * so we need undo access.
-+	 */
-+	/* @@@ check errors */
-+	BUFFER_TRACE(bitmap_bh, "getting undo access");
-+	err = ext3cow_journal_get_undo_access(handle, bitmap_bh);
-+	if (err)
-+		goto error_return;
-+
-+	/*
-+	 * We are about to modify some metadata.  Call the journal APIs
-+	 * to unshare ->b_data if a currently-committing transaction is
-+	 * using it
-+	 */
-+	BUFFER_TRACE(gd_bh, "get_write_access");
-+	err = ext3cow_journal_get_write_access(handle, gd_bh);
-+	if (err)
-+		goto error_return;
-+
-+	jbd_lock_bh_state(bitmap_bh);
-+
-+	for (i = 0, group_freed = 0; i < count; i++) {
-+		/*
-+		 * An HJ special.  This is expensive...
-+		 */
-+#ifdef CONFIG_JBD_DEBUG
-+		jbd_unlock_bh_state(bitmap_bh);
-+		{
-+			struct buffer_head *debug_bh;
-+			debug_bh = sb_find_get_block(sb, block + i);
-+			if (debug_bh) {
-+				BUFFER_TRACE(debug_bh, "Deleted!");
-+				if (!bh2jh(bitmap_bh)->b_committed_data)
-+					BUFFER_TRACE(debug_bh,
-+						"No commited data in bitmap");
-+				BUFFER_TRACE2(debug_bh, bitmap_bh, "bitmap");
-+				__brelse(debug_bh);
-+			}
-+		}
-+		jbd_lock_bh_state(bitmap_bh);
-+#endif
-+		if (need_resched()) {
-+			jbd_unlock_bh_state(bitmap_bh);
-+			cond_resched();
-+			jbd_lock_bh_state(bitmap_bh);
-+		}
-+		/* @@@ This prevents newly-allocated data from being
-+		 * freed and then reallocated within the same
-+		 * transaction.
-+		 *
-+		 * Ideally we would want to allow that to happen, but to
-+		 * do so requires making journal_forget() capable of
-+		 * revoking the queued write of a data block, which
-+		 * implies blocking on the journal lock.  *forget()
-+		 * cannot block due to truncate races.
-+		 *
-+		 * Eventually we can fix this by making journal_forget()
-+		 * return a status indicating whether or not it was able
-+		 * to revoke the buffer.  On successful revoke, it is
-+		 * safe not to set the allocation bit in the committed
-+		 * bitmap, because we know that there is no outstanding
-+		 * activity on the buffer any more and so it is safe to
-+		 * reallocate it.
-+		 */
-+		BUFFER_TRACE(bitmap_bh, "set in b_committed_data");
-+		J_ASSERT_BH(bitmap_bh,
-+				bh2jh(bitmap_bh)->b_committed_data != NULL);
-+		ext3cow_set_bit_atomic(sb_bgl_lock(sbi, block_group), bit + i,
-+				bh2jh(bitmap_bh)->b_committed_data);
-+
-+		/*
-+		 * We clear the bit in the bitmap after setting the committed
-+		 * data bit, because this is the reverse order to that which
-+		 * the allocator uses.
-+		 */
-+		BUFFER_TRACE(bitmap_bh, "clear bit");
-+		if (!ext3cow_clear_bit_atomic(sb_bgl_lock(sbi, block_group),
-+						bit + i, bitmap_bh->b_data)) {
-+			jbd_unlock_bh_state(bitmap_bh);
-+			ext3cow_error(sb, __FUNCTION__,
-+				"bit already cleared for block "E3FSBLK,
-+				 block + i);
-+			jbd_lock_bh_state(bitmap_bh);
-+			BUFFER_TRACE(bitmap_bh, "bit already cleared");
-+		} else {
-+			group_freed++;
-+		}
-+	}
-+	jbd_unlock_bh_state(bitmap_bh);
-+
-+	spin_lock(sb_bgl_lock(sbi, block_group));
-+	desc->bg_free_blocks_count =
-+		cpu_to_le16(le16_to_cpu(desc->bg_free_blocks_count) +
-+			group_freed);
-+	spin_unlock(sb_bgl_lock(sbi, block_group));
-+	percpu_counter_mod(&sbi->s_freeblocks_counter, count);
-+
-+	/* We dirtied the bitmap block */
-+	BUFFER_TRACE(bitmap_bh, "dirtied bitmap block");
-+	err = ext3cow_journal_dirty_metadata(handle, bitmap_bh);
-+
-+	/* And the group descriptor block */
-+	BUFFER_TRACE(gd_bh, "dirtied group descriptor block");
-+	ret = ext3cow_journal_dirty_metadata(handle, gd_bh);
-+	if (!err) err = ret;
-+	*pdquot_freed_blocks += group_freed;
-+
-+	if (overflow && !err) {
-+		block += count;
-+		count = overflow;
-+		goto do_more;
-+	}
-+	sb->s_dirt = 1;
-+error_return:
-+	brelse(bitmap_bh);
-+	ext3cow_std_error(sb, err);
-+	return;
-+}
-+
-+/**
-+ * ext3cow_free_blocks() -- Free given blocks and update quota
-+ * @handle:		handle for this transaction
-+ * @inode:		inode
-+ * @block:		start physical block to free
-+ * @count:		number of blocks to count
-+ */
-+void ext3cow_free_blocks(handle_t *handle, struct inode *inode,
-+			ext3cow_fsblk_t block, unsigned long count)
-+{
-+	struct super_block * sb;
-+	unsigned long dquot_freed_blocks;
-+
-+	sb = inode->i_sb;
-+	if (!sb) {
-+		printk ("ext3cow_free_blocks: nonexistent device");
-+		return;
-+	}
-+	ext3cow_free_blocks_sb(handle, sb, block, count, &dquot_freed_blocks);
-+	if (dquot_freed_blocks)
-+		DQUOT_FREE_BLOCK(inode, dquot_freed_blocks);
-+	return;
-+}
-+
-+/**
-+ * ext3cow_test_allocatable()
-+ * @nr:			given allocation block group
-+ * @bh:			bufferhead contains the bitmap of the given block group
-+ *
-+ * For ext3cow allocations, we must not reuse any blocks which are
-+ * allocated in the bitmap buffer's "last committed data" copy.  This
-+ * prevents deletes from freeing up the page for reuse until we have
-+ * committed the delete transaction.
-+ *
-+ * If we didn't do this, then deleting something and reallocating it as
-+ * data would allow the old block to be overwritten before the
-+ * transaction committed (because we force data to disk before commit).
-+ * This would lead to corruption if we crashed between overwriting the
-+ * data and committing the delete.
-+ *
-+ * @@@ We may want to make this allocation behaviour conditional on
-+ * data-writes at some point, and disable it for metadata allocations or
-+ * sync-data inodes.
-+ */
-+static int ext3cow_test_allocatable(ext3cow_grpblk_t nr, struct buffer_head *bh)
-+{
-+	int ret;
-+	struct journal_head *jh = bh2jh(bh);
-+
-+	if (ext3cow_test_bit(nr, bh->b_data))
-+		return 0;
-+
-+	jbd_lock_bh_state(bh);
-+	if (!jh->b_committed_data)
-+		ret = 1;
-+	else
-+		ret = !ext3cow_test_bit(nr, jh->b_committed_data);
-+	jbd_unlock_bh_state(bh);
-+	return ret;
-+}
-+
-+/**
-+ * bitmap_search_next_usable_block()
-+ * @start:		the starting block (group relative) of the search
-+ * @bh:			bufferhead contains the block group bitmap
-+ * @maxblocks:		the ending block (group relative) of the reservation
-+ *
-+ * The bitmap search --- search forward alternately through the actual
-+ * bitmap on disk and the last-committed copy in journal, until we find a
-+ * bit free in both bitmaps.
-+ */
-+static ext3cow_grpblk_t
-+bitmap_search_next_usable_block(ext3cow_grpblk_t start, struct buffer_head *bh,
-+					ext3cow_grpblk_t maxblocks)
-+{
-+	ext3cow_grpblk_t next;
-+	struct journal_head *jh = bh2jh(bh);
-+
-+	while (start < maxblocks) {
-+		next = ext3cow_find_next_zero_bit(bh->b_data, maxblocks, start);
-+		if (next >= maxblocks)
-+			return -1;
-+		if (ext3cow_test_allocatable(next, bh))
-+			return next;
-+		jbd_lock_bh_state(bh);
-+		if (jh->b_committed_data)
-+			start = ext3cow_find_next_zero_bit(jh->b_committed_data,
-+							maxblocks, next);
-+		jbd_unlock_bh_state(bh);
-+	}
-+	return -1;
-+}
-+
-+/**
-+ * find_next_usable_block()
-+ * @start:		the starting block (group relative) to find next
-+ *			allocatable block in bitmap.
-+ * @bh:			bufferhead contains the block group bitmap
-+ * @maxblocks:		the ending block (group relative) for the search
-+ *
-+ * Find an allocatable block in a bitmap.  We honor both the bitmap and
-+ * its last-committed copy (if that exists), and perform the "most
-+ * appropriate allocation" algorithm of looking for a free block near
-+ * the initial goal; then for a free byte somewhere in the bitmap; then
-+ * for any free bit in the bitmap.
-+ */
-+static ext3cow_grpblk_t
-+find_next_usable_block(ext3cow_grpblk_t start, struct buffer_head *bh,
-+			ext3cow_grpblk_t maxblocks)
-+{
-+	ext3cow_grpblk_t here, next;
-+	char *p, *r;
-+
-+	if (start > 0) {
-+		/*
-+		 * The goal was occupied; search forward for a free
-+		 * block within the next XX blocks.
-+		 *
-+		 * end_goal is more or less random, but it has to be
-+		 * less than EXT3COW_BLOCKS_PER_GROUP. Aligning up to the
-+		 * next 64-bit boundary is simple..
-+		 */
-+		ext3cow_grpblk_t end_goal = (start + 63) & ~63;
-+		if (end_goal > maxblocks)
-+			end_goal = maxblocks;
-+		here = ext3cow_find_next_zero_bit(bh->b_data, end_goal, start);
-+		if (here < end_goal && ext3cow_test_allocatable(here, bh))
-+			return here;
-+		ext3cow_debug("Bit not found near goal\n");
-+	}
-+
-+	here = start;
-+	if (here < 0)
-+		here = 0;
-+
-+	p = ((char *)bh->b_data) + (here >> 3);
-+	r = memscan(p, 0, ((maxblocks + 7) >> 3) - (here >> 3));
-+	next = (r - ((char *)bh->b_data)) << 3;
-+
-+	if (next < maxblocks && next >= start && ext3cow_test_allocatable(next, bh))
-+		return next;
-+
-+	/*
-+	 * The bitmap search --- search forward alternately through the actual
-+	 * bitmap and the last-committed copy until we find a bit free in
-+	 * both
-+	 */
-+	here = bitmap_search_next_usable_block(here, bh, maxblocks);
-+	return here;
-+}
-+
-+/**
-+ * claim_block()
-+ * @block:		the free block (group relative) to allocate
-+ * @bh:			the bufferhead containts the block group bitmap
-+ *
-+ * We think we can allocate this block in this bitmap.  Try to set the bit.
-+ * If that succeeds then check that nobody has allocated and then freed the
-+ * block since we saw that is was not marked in b_committed_data.  If it _was_
-+ * allocated and freed then clear the bit in the bitmap again and return
-+ * zero (failure).
-+ */
-+static inline int
-+claim_block(spinlock_t *lock, ext3cow_grpblk_t block, struct buffer_head *bh)
-+{
-+	struct journal_head *jh = bh2jh(bh);
-+	int ret;
-+
-+	if (ext3cow_set_bit_atomic(lock, block, bh->b_data))
-+		return 0;
-+	jbd_lock_bh_state(bh);
-+	if (jh->b_committed_data && ext3cow_test_bit(block,jh->b_committed_data)) {
-+		ext3cow_clear_bit_atomic(lock, block, bh->b_data);
-+		ret = 0;
-+	} else {
-+		ret = 1;
-+	}
-+	jbd_unlock_bh_state(bh);
-+	return ret;
-+}
-+
-+/**
-+ * ext3cow_try_to_allocate()
-+ * @sb:			superblock
-+ * @handle:		handle to this transaction
-+ * @group:		given allocation block group
-+ * @bitmap_bh:		bufferhead holds the block bitmap
-+ * @grp_goal:		given target block within the group
-+ * @count:		target number of blocks to allocate
-+ * @my_rsv:		reservation window
-+ *
-+ * Attempt to allocate blocks within a give range. Set the range of allocation
-+ * first, then find the first free bit(s) from the bitmap (within the range),
-+ * and at last, allocate the blocks by claiming the found free bit as allocated.
-+ *
-+ * To set the range of this allocation:
-+ *	if there is a reservation window, only try to allocate block(s) from the
-+ *	file's own reservation window;
-+ *	Otherwise, the allocation range starts from the give goal block, ends at
-+ *	the block group's last block.
-+ *
-+ * If we failed to allocate the desired block then we may end up crossing to a
-+ * new bitmap.  In that case we must release write access to the old one via
-+ * ext3cow_journal_release_buffer(), else we'll run out of credits.
-+ */
-+static ext3cow_grpblk_t
-+ext3cow_try_to_allocate(struct super_block *sb, handle_t *handle, int group,
-+			struct buffer_head *bitmap_bh, ext3cow_grpblk_t grp_goal,
-+			unsigned long *count, struct ext3cow_reserve_window *my_rsv)
-+{
-+	ext3cow_fsblk_t group_first_block;
-+	ext3cow_grpblk_t start, end;
-+	unsigned long num = 0;
-+
-+	/* we do allocation within the reservation window if we have a window */
-+	if (my_rsv) {
-+		group_first_block = ext3cow_group_first_block_no(sb, group);
-+		if (my_rsv->_rsv_start >= group_first_block)
-+			start = my_rsv->_rsv_start - group_first_block;
-+		else
-+			/* reservation window cross group boundary */
-+			start = 0;
-+		end = my_rsv->_rsv_end - group_first_block + 1;
-+		if (end > EXT3COW_BLOCKS_PER_GROUP(sb))
-+			/* reservation window crosses group boundary */
-+			end = EXT3COW_BLOCKS_PER_GROUP(sb);
-+		if ((start <= grp_goal) && (grp_goal < end))
-+			start = grp_goal;
-+		else
-+			grp_goal = -1;
-+	} else {
-+		if (grp_goal > 0)
-+			start = grp_goal;
-+		else
-+			start = 0;
-+		end = EXT3COW_BLOCKS_PER_GROUP(sb);
-+	}
-+
-+	BUG_ON(start > EXT3COW_BLOCKS_PER_GROUP(sb));
-+
-+repeat:
-+	if (grp_goal < 0 || !ext3cow_test_allocatable(grp_goal, bitmap_bh)) {
-+		grp_goal = find_next_usable_block(start, bitmap_bh, end);
-+		if (grp_goal < 0)
-+			goto fail_access;
-+		if (!my_rsv) {
-+			int i;
-+
-+			for (i = 0; i < 7 && grp_goal > start &&
-+					ext3cow_test_allocatable(grp_goal - 1,
-+								bitmap_bh);
-+					i++, grp_goal--)
-+				;
-+		}
-+	}
-+	start = grp_goal;
-+
-+	if (!claim_block(sb_bgl_lock(EXT3COW_SB(sb), group),
-+		grp_goal, bitmap_bh)) {
-+		/*
-+		 * The block was allocated by another thread, or it was
-+		 * allocated and then freed by another thread
-+		 */
-+		start++;
-+		grp_goal++;
-+		if (start >= end)
-+			goto fail_access;
-+		goto repeat;
-+	}
-+	num++;
-+	grp_goal++;
-+	while (num < *count && grp_goal < end
-+		&& ext3cow_test_allocatable(grp_goal, bitmap_bh)
-+		&& claim_block(sb_bgl_lock(EXT3COW_SB(sb), group),
-+				grp_goal, bitmap_bh)) {
-+		num++;
-+		grp_goal++;
-+	}
-+	*count = num;
-+	return grp_goal - num;
-+fail_access:
-+	*count = num;
-+	return -1;
-+}
-+
-+/**
-+ *	find_next_reservable_window():
-+ *		find a reservable space within the given range.
-+ *		It does not allocate the reservation window for now:
-+ *		alloc_new_reservation() will do the work later.
-+ *
-+ *	@search_head: the head of the searching list;
-+ *		This is not necessarily the list head of the whole filesystem
-+ *
-+ *		We have both head and start_block to assist the search
-+ *		for the reservable space. The list starts from head,
-+ *		but we will shift to the place where start_block is,
-+ *		then start from there, when looking for a reservable space.
-+ *
-+ *	@size: the target new reservation window size
-+ *
-+ *	@group_first_block: the first block we consider to start
-+ *			the real search from
-+ *
-+ *	@last_block:
-+ *		the maximum block number that our goal reservable space
-+ *		could start from. This is normally the last block in this
-+ *		group. The search will end when we found the start of next
-+ *		possible reservable space is out of this boundary.
-+ *		This could handle the cross boundary reservation window
-+ *		request.
-+ *
-+ *	basically we search from the given range, rather than the whole
-+ *	reservation double linked list, (start_block, last_block)
-+ *	to find a free region that is of my size and has not
-+ *	been reserved.
-+ *
-+ */
-+static int find_next_reservable_window(
-+				struct ext3cow_reserve_window_node *search_head,
-+				struct ext3cow_reserve_window_node *my_rsv,
-+				struct super_block * sb,
-+				ext3cow_fsblk_t start_block,
-+				ext3cow_fsblk_t last_block)
-+{
-+	struct rb_node *next;
-+	struct ext3cow_reserve_window_node *rsv, *prev;
-+	ext3cow_fsblk_t cur;
-+	int size = my_rsv->rsv_goal_size;
-+
-+	/* TODO: make the start of the reservation window byte-aligned */
-+	/* cur = *start_block & ~7;*/
-+	cur = start_block;
-+	rsv = search_head;
-+	if (!rsv)
-+		return -1;
-+
-+	while (1) {
-+		if (cur <= rsv->rsv_end)
-+			cur = rsv->rsv_end + 1;
-+
-+		/* TODO?
-+		 * in the case we could not find a reservable space
-+		 * that is what is expected, during the re-search, we could
-+		 * remember what's the largest reservable space we could have
-+		 * and return that one.
-+		 *
-+		 * For now it will fail if we could not find the reservable
-+		 * space with expected-size (or more)...
-+		 */
-+		if (cur > last_block)
-+			return -1;		/* fail */
-+
-+		prev = rsv;
-+		next = rb_next(&rsv->rsv_node);
-+		rsv = rb_entry(next,struct ext3cow_reserve_window_node,rsv_node);
-+
-+		/*
-+		 * Reached the last reservation, we can just append to the
-+		 * previous one.
-+		 */
-+		if (!next)
-+			break;
-+
-+		if (cur + size <= rsv->rsv_start) {
-+			/*
-+			 * Found a reserveable space big enough.  We could
-+			 * have a reservation across the group boundary here
-+			 */
-+			break;
-+		}
-+	}
-+	/*
-+	 * we come here either :
-+	 * when we reach the end of the whole list,
-+	 * and there is empty reservable space after last entry in the list.
-+	 * append it to the end of the list.
-+	 *
-+	 * or we found one reservable space in the middle of the list,
-+	 * return the reservation window that we could append to.
-+	 * succeed.
-+	 */
-+
-+	if ((prev != my_rsv) && (!rsv_is_empty(&my_rsv->rsv_window)))
-+		rsv_window_remove(sb, my_rsv);
-+
-+	/*
-+	 * Let's book the whole avaliable window for now.  We will check the
-+	 * disk bitmap later and then, if there are free blocks then we adjust
-+	 * the window size if it's larger than requested.
-+	 * Otherwise, we will remove this node from the tree next time
-+	 * call find_next_reservable_window.
-+	 */
-+	my_rsv->rsv_start = cur;
-+	my_rsv->rsv_end = cur + size - 1;
-+	my_rsv->rsv_alloc_hit = 0;
-+
-+	if (prev != my_rsv)
-+		ext3cow_rsv_window_add(sb, my_rsv);
-+
-+	return 0;
-+}
-+
-+/**
-+ *	alloc_new_reservation()--allocate a new reservation window
-+ *
-+ *		To make a new reservation, we search part of the filesystem
-+ *		reservation list (the list that inside the group). We try to
-+ *		allocate a new reservation window near the allocation goal,
-+ *		or the beginning of the group, if there is no goal.
-+ *
-+ *		We first find a reservable space after the goal, then from
-+ *		there, we check the bitmap for the first free block after
-+ *		it. If there is no free block until the end of group, then the
-+ *		whole group is full, we failed. Otherwise, check if the free
-+ *		block is inside the expected reservable space, if so, we
-+ *		succeed.
-+ *		If the first free block is outside the reservable space, then
-+ *		start from the first free block, we search for next available
-+ *		space, and go on.
-+ *
-+ *	on succeed, a new reservation will be found and inserted into the list
-+ *	It contains at least one free block, and it does not overlap with other
-+ *	reservation windows.
-+ *
-+ *	failed: we failed to find a reservation window in this group
-+ *
-+ *	@rsv: the reservation
-+ *
-+ *	@grp_goal: The goal (group-relative).  It is where the search for a
-+ *		free reservable space should start from.
-+ *		if we have a grp_goal(grp_goal >0 ), then start from there,
-+ *		no grp_goal(grp_goal = -1), we start from the first block
-+ *		of the group.
-+ *
-+ *	@sb: the super block
-+ *	@group: the group we are trying to allocate in
-+ *	@bitmap_bh: the block group block bitmap
-+ *
-+ */
-+static int alloc_new_reservation(struct ext3cow_reserve_window_node *my_rsv,
-+		ext3cow_grpblk_t grp_goal, struct super_block *sb,
-+		unsigned int group, struct buffer_head *bitmap_bh)
-+{
-+	struct ext3cow_reserve_window_node *search_head;
-+	ext3cow_fsblk_t group_first_block, group_end_block, start_block;
-+	ext3cow_grpblk_t first_free_block;
-+	struct rb_root *fs_rsv_root = &EXT3COW_SB(sb)->s_rsv_window_root;
-+	unsigned long size;
-+	int ret;
-+	spinlock_t *rsv_lock = &EXT3COW_SB(sb)->s_rsv_window_lock;
-+
-+	group_first_block = ext3cow_group_first_block_no(sb, group);
-+	group_end_block = group_first_block + (EXT3COW_BLOCKS_PER_GROUP(sb) - 1);
-+
-+	if (grp_goal < 0)
-+		start_block = group_first_block;
-+	else
-+		start_block = grp_goal + group_first_block;
-+
-+	size = my_rsv->rsv_goal_size;
-+
-+	if (!rsv_is_empty(&my_rsv->rsv_window)) {
-+		/*
-+		 * if the old reservation is cross group boundary
-+		 * and if the goal is inside the old reservation window,
-+		 * we will come here when we just failed to allocate from
-+		 * the first part of the window. We still have another part
-+		 * that belongs to the next group. In this case, there is no
-+		 * point to discard our window and try to allocate a new one
-+		 * in this group(which will fail). we should
-+		 * keep the reservation window, just simply move on.
-+		 *
-+		 * Maybe we could shift the start block of the reservation
-+		 * window to the first block of next group.
-+		 */
-+
-+		if ((my_rsv->rsv_start <= group_end_block) &&
-+				(my_rsv->rsv_end > group_end_block) &&
-+				(start_block >= my_rsv->rsv_start))
-+			return -1;
-+
-+		if ((my_rsv->rsv_alloc_hit >
-+		     (my_rsv->rsv_end - my_rsv->rsv_start + 1) / 2)) {
-+			/*
-+			 * if the previously allocation hit ratio is
-+			 * greater than 1/2, then we double the size of
-+			 * the reservation window the next time,
-+			 * otherwise we keep the same size window
-+			 */
-+			size = size * 2;
-+			if (size > EXT3COW_MAX_RESERVE_BLOCKS)
-+				size = EXT3COW_MAX_RESERVE_BLOCKS;
-+			my_rsv->rsv_goal_size= size;
-+		}
-+	}
-+
-+	spin_lock(rsv_lock);
-+	/*
-+	 * shift the search start to the window near the goal block
-+	 */
-+	search_head = search_reserve_window(fs_rsv_root, start_block);
-+
-+	/*
-+	 * find_next_reservable_window() simply finds a reservable window
-+	 * inside the given range(start_block, group_end_block).
-+	 *
-+	 * To make sure the reservation window has a free bit inside it, we
-+	 * need to check the bitmap after we found a reservable window.
-+	 */
-+retry:
-+	ret = find_next_reservable_window(search_head, my_rsv, sb,
-+						start_block, group_end_block);
-+
-+	if (ret == -1) {
-+		if (!rsv_is_empty(&my_rsv->rsv_window))
-+			rsv_window_remove(sb, my_rsv);
-+		spin_unlock(rsv_lock);
-+		return -1;
-+	}
-+
-+	/*
-+	 * On success, find_next_reservable_window() returns the
-+	 * reservation window where there is a reservable space after it.
-+	 * Before we reserve this reservable space, we need
-+	 * to make sure there is at least a free block inside this region.
-+	 *
-+	 * searching the first free bit on the block bitmap and copy of
-+	 * last committed bitmap alternatively, until we found a allocatable
-+	 * block. Search start from the start block of the reservable space
-+	 * we just found.
-+	 */
-+	spin_unlock(rsv_lock);
-+	first_free_block = bitmap_search_next_usable_block(
-+			my_rsv->rsv_start - group_first_block,
-+			bitmap_bh, group_end_block - group_first_block + 1);
-+
-+	if (first_free_block < 0) {
-+		/*
-+		 * no free block left on the bitmap, no point
-+		 * to reserve the space. return failed.
-+		 */
-+		spin_lock(rsv_lock);
-+		if (!rsv_is_empty(&my_rsv->rsv_window))
-+			rsv_window_remove(sb, my_rsv);
-+		spin_unlock(rsv_lock);
-+		return -1;		/* failed */
-+	}
-+
-+	start_block = first_free_block + group_first_block;
-+	/*
-+	 * check if the first free block is within the
-+	 * free space we just reserved
-+	 */
-+	if (start_block >= my_rsv->rsv_start && start_block <= my_rsv->rsv_end)
-+		return 0;		/* success */
-+	/*
-+	 * if the first free bit we found is out of the reservable space
-+	 * continue search for next reservable space,
-+	 * start from where the free block is,
-+	 * we also shift the list head to where we stopped last time
-+	 */
-+	search_head = my_rsv;
-+	spin_lock(rsv_lock);
-+	goto retry;
-+}
-+
-+/**
-+ * try_to_extend_reservation()
-+ * @my_rsv:		given reservation window
-+ * @sb:			super block
-+ * @size:		the delta to extend
-+ *
-+ * Attempt to expand the reservation window large enough to have
-+ * required number of free blocks
-+ *
-+ * Since ext3cow_try_to_allocate() will always allocate blocks within
-+ * the reservation window range, if the window size is too small,
-+ * multiple blocks allocation has to stop at the end of the reservation
-+ * window. To make this more efficient, given the total number of
-+ * blocks needed and the current size of the window, we try to
-+ * expand the reservation window size if necessary on a best-effort
-+ * basis before ext3cow_new_blocks() tries to allocate blocks,
-+ */
-+static void try_to_extend_reservation(struct ext3cow_reserve_window_node *my_rsv,
-+			struct super_block *sb, int size)
-+{
-+	struct ext3cow_reserve_window_node *next_rsv;
-+	struct rb_node *next;
-+	spinlock_t *rsv_lock = &EXT3COW_SB(sb)->s_rsv_window_lock;
-+
-+	if (!spin_trylock(rsv_lock))
-+		return;
-+
-+	next = rb_next(&my_rsv->rsv_node);
-+
-+	if (!next)
-+		my_rsv->rsv_end += size;
-+	else {
-+		next_rsv = rb_entry(next, struct ext3cow_reserve_window_node, rsv_node);
-+
-+		if ((next_rsv->rsv_start - my_rsv->rsv_end - 1) >= size)
-+			my_rsv->rsv_end += size;
-+		else
-+			my_rsv->rsv_end = next_rsv->rsv_start - 1;
-+	}
-+	spin_unlock(rsv_lock);
-+}
-+
-+/**
-+ * ext3cow_try_to_allocate_with_rsv()
-+ * @sb:			superblock
-+ * @handle:		handle to this transaction
-+ * @group:		given allocation block group
-+ * @bitmap_bh:		bufferhead holds the block bitmap
-+ * @grp_goal:		given target block within the group
-+ * @count:		target number of blocks to allocate
-+ * @my_rsv:		reservation window
-+ * @errp:		pointer to store the error code
-+ *
-+ * This is the main function used to allocate a new block and its reservation
-+ * window.
-+ *
-+ * Each time when a new block allocation is need, first try to allocate from
-+ * its own reservation.  If it does not have a reservation window, instead of
-+ * looking for a free bit on bitmap first, then look up the reservation list to
-+ * see if it is inside somebody else's reservation window, we try to allocate a
-+ * reservation window for it starting from the goal first. Then do the block
-+ * allocation within the reservation window.
-+ *
-+ * This will avoid keeping on searching the reservation list again and
-+ * again when somebody is looking for a free block (without
-+ * reservation), and there are lots of free blocks, but they are all
-+ * being reserved.
-+ *
-+ * We use a red-black tree for the per-filesystem reservation list.
-+ *
-+ */
-+static ext3cow_grpblk_t
-+ext3cow_try_to_allocate_with_rsv(struct super_block *sb, handle_t *handle,
-+			unsigned int group, struct buffer_head *bitmap_bh,
-+			ext3cow_grpblk_t grp_goal,
-+			struct ext3cow_reserve_window_node * my_rsv,
-+			unsigned long *count, int *errp)
-+{
-+	ext3cow_fsblk_t group_first_block, group_last_block;
-+	ext3cow_grpblk_t ret = 0;
-+	int fatal;
-+	unsigned long num = *count;
-+
-+	*errp = 0;
-+
-+	/*
-+	 * Make sure we use undo access for the bitmap, because it is critical
-+	 * that we do the frozen_data COW on bitmap buffers in all cases even
-+	 * if the buffer is in BJ_Forget state in the committing transaction.
-+	 */
-+	BUFFER_TRACE(bitmap_bh, "get undo access for new block");
-+	fatal = ext3cow_journal_get_undo_access(handle, bitmap_bh);
-+	if (fatal) {
-+		*errp = fatal;
-+		return -1;
-+	}
-+
-+	/*
-+	 * we don't deal with reservation when
-+	 * filesystem is mounted without reservation
-+	 * or the file is not a regular file
-+	 * or last attempt to allocate a block with reservation turned on failed
-+	 */
-+	if (my_rsv == NULL ) {
-+		ret = ext3cow_try_to_allocate(sb, handle, group, bitmap_bh,
-+						grp_goal, count, NULL);
-+		goto out;
-+	}
-+	/*
-+	 * grp_goal is a group relative block number (if there is a goal)
-+	 * 0 <= grp_goal < EXT3COW_BLOCKS_PER_GROUP(sb)
-+	 * first block is a filesystem wide block number
-+	 * first block is the block number of the first block in this group
-+	 */
-+	group_first_block = ext3cow_group_first_block_no(sb, group);
-+	group_last_block = group_first_block + (EXT3COW_BLOCKS_PER_GROUP(sb) - 1);
-+
-+	/*
-+	 * Basically we will allocate a new block from inode's reservation
-+	 * window.
-+	 *
-+	 * We need to allocate a new reservation window, if:
-+	 * a) inode does not have a reservation window; or
-+	 * b) last attempt to allocate a block from existing reservation
-+	 *    failed; or
-+	 * c) we come here with a goal and with a reservation window
-+	 *
-+	 * We do not need to allocate a new reservation window if we come here
-+	 * at the beginning with a goal and the goal is inside the window, or
-+	 * we don't have a goal but already have a reservation window.
-+	 * then we could go to allocate from the reservation window directly.
-+	 */
-+	while (1) {
-+		if (rsv_is_empty(&my_rsv->rsv_window) || (ret < 0) ||
-+			!goal_in_my_reservation(&my_rsv->rsv_window,
-+						grp_goal, group, sb)) {
-+			if (my_rsv->rsv_goal_size < *count)
-+				my_rsv->rsv_goal_size = *count;
-+			ret = alloc_new_reservation(my_rsv, grp_goal, sb,
-+							group, bitmap_bh);
-+			if (ret < 0)
-+				break;			/* failed */
-+
-+			if (!goal_in_my_reservation(&my_rsv->rsv_window,
-+							grp_goal, group, sb))
-+				grp_goal = -1;
-+		} else if (grp_goal >= 0) {
-+			int curr = my_rsv->rsv_end -
-+					(grp_goal + group_first_block) + 1;
-+
-+			if (curr < *count)
-+				try_to_extend_reservation(my_rsv, sb,
-+							*count - curr);
-+		}
-+
-+		if ((my_rsv->rsv_start > group_last_block) ||
-+				(my_rsv->rsv_end < group_first_block)) {
-+			rsv_window_dump(&EXT3COW_SB(sb)->s_rsv_window_root, 1);
-+			BUG();
-+		}
-+		ret = ext3cow_try_to_allocate(sb, handle, group, bitmap_bh,
-+					   grp_goal, &num, &my_rsv->rsv_window);
-+		if (ret >= 0) {
-+			my_rsv->rsv_alloc_hit += num;
-+			*count = num;
-+			break;				/* succeed */
-+		}
-+		num = *count;
-+	}
-+out:
-+	if (ret >= 0) {
-+		BUFFER_TRACE(bitmap_bh, "journal_dirty_metadata for "
-+					"bitmap block");
-+		fatal = ext3cow_journal_dirty_metadata(handle, bitmap_bh);
-+		if (fatal) {
-+			*errp = fatal;
-+			return -1;
-+		}
-+		return ret;
-+	}
-+
-+	BUFFER_TRACE(bitmap_bh, "journal_release_buffer");
-+	ext3cow_journal_release_buffer(handle, bitmap_bh);
-+	return ret;
-+}
-+
-+/**
-+ * ext3cow_has_free_blocks()
-+ * @sbi:		in-core super block structure.
-+ *
-+ * Check if filesystem has at least 1 free block available for allocation.
-+ */
-+static int ext3cow_has_free_blocks(struct ext3cow_sb_info *sbi)
-+{
-+	ext3cow_fsblk_t free_blocks, root_blocks;
-+
-+	free_blocks = percpu_counter_read_positive(&sbi->s_freeblocks_counter);
-+	root_blocks = le32_to_cpu(sbi->s_es->s_r_blocks_count);
-+	if (free_blocks < root_blocks + 1 && !capable(CAP_SYS_RESOURCE) &&
-+		sbi->s_resuid != current->fsuid &&
-+		(sbi->s_resgid == 0 || !in_group_p (sbi->s_resgid))) {
-+		return 0;
-+	}
-+	return 1;
-+}
-+
-+/**
-+ * ext3cow_should_retry_alloc()
-+ * @sb:			super block
-+ * @retries		number of attemps has been made
-+ *
-+ * ext3cow_should_retry_alloc() is called when ENOSPC is returned, and if
-+ * it is profitable to retry the operation, this function will wait
-+ * for the current or commiting transaction to complete, and then
-+ * return TRUE.
-+ *
-+ * if the total number of retries exceed three times, return FALSE.
-+ */
-+int ext3cow_should_retry_alloc(struct super_block *sb, int *retries)
-+{
-+	if (!ext3cow_has_free_blocks(EXT3COW_SB(sb)) || (*retries)++ > 3)
-+		return 0;
-+
-+	jbd_debug(1, "%s: retrying operation after ENOSPC\n", sb->s_id);
-+
-+	return journal_force_commit_nested(EXT3COW_SB(sb)->s_journal);
-+}
-+
-+/**
-+ * ext3cow_new_blocks() -- core block(s) allocation function
-+ * @handle:		handle to this transaction
-+ * @inode:		file inode
-+ * @goal:		given target block(filesystem wide)
-+ * @count:		target number of blocks to allocate
-+ * @errp:		error code
-+ *
-+ * ext3cow_new_blocks uses a goal block to assist allocation.  It tries to
-+ * allocate block(s) from the block group contains the goal block first. If that
-+ * fails, it will try to allocate block(s) from other block groups without
-+ * any specific goal block.
-+ *
-+ */
-+ext3cow_fsblk_t ext3cow_new_blocks(handle_t *handle, struct inode *inode,
-+			ext3cow_fsblk_t goal, unsigned long *count, int *errp)
-+{
-+	struct buffer_head *bitmap_bh = NULL;
-+	struct buffer_head *gdp_bh;
-+	int group_no;
-+	int goal_group;
-+	ext3cow_grpblk_t grp_target_blk;	/* blockgroup relative goal block */
-+	ext3cow_grpblk_t grp_alloc_blk;	/* blockgroup-relative allocated block*/
-+	ext3cow_fsblk_t ret_block;		/* filesyetem-wide allocated block */
-+	int bgi;			/* blockgroup iteration index */
-+	int fatal = 0, err;
-+	int performed_allocation = 0;
-+	ext3cow_grpblk_t free_blocks;	/* number of free blocks in a group */
-+	struct super_block *sb;
-+	struct ext3cow_group_desc *gdp;
-+	struct ext3cow_super_block *es;
-+	struct ext3cow_sb_info *sbi;
-+	struct ext3cow_reserve_window_node *my_rsv = NULL;
-+	struct ext3cow_block_alloc_info *block_i;
-+	unsigned short windowsz = 0;
-+#ifdef EXT3COWFS_DEBUG
-+	static int goal_hits, goal_attempts;
-+#endif
-+	unsigned long ngroups;
-+	unsigned long num = *count;
-+
-+	*errp = -ENOSPC;
-+	sb = inode->i_sb;
-+	if (!sb) {
-+		printk("ext3cow_new_block: nonexistent device");
-+		return 0;
-+	}
-+
-+	/*
-+	 * Check quota for allocation of this block.
-+	 */
-+	if (DQUOT_ALLOC_BLOCK(inode, num)) {
-+		*errp = -EDQUOT;
-+		return 0;
-+	}
-+
-+	sbi = EXT3COW_SB(sb);
-+	es = EXT3COW_SB(sb)->s_es;
-+	ext3cow_debug("goal=%lu.\n", goal);
-+	/*
-+	 * Allocate a block from reservation only when
-+	 * filesystem is mounted with reservation(default,-o reservation), and
-+	 * it's a regular file, and
-+	 * the desired window size is greater than 0 (One could use ioctl
-+	 * command EXT3COW_IOC_SETRSVSZ to set the window size to 0 to turn off
-+	 * reservation on that particular file)
-+	 */
-+	block_i = EXT3COW_I(inode)->i_block_alloc_info;
-+	if (block_i && ((windowsz = block_i->rsv_window_node.rsv_goal_size) > 0))
-+		my_rsv = &block_i->rsv_window_node;
-+
-+	if (!ext3cow_has_free_blocks(sbi)) {
-+		*errp = -ENOSPC;
-+		goto out;
-+	}
-+
-+	/*
-+	 * First, test whether the goal block is free.
-+	 */
-+	if (goal < le32_to_cpu(es->s_first_data_block) ||
-+	    goal >= le32_to_cpu(es->s_blocks_count))
-+		goal = le32_to_cpu(es->s_first_data_block);
-+	group_no = (goal - le32_to_cpu(es->s_first_data_block)) /
-+			EXT3COW_BLOCKS_PER_GROUP(sb);
-+	goal_group = group_no;
-+retry_alloc:
-+	gdp = ext3cow_get_group_desc(sb, group_no, &gdp_bh);
-+	if (!gdp)
-+		goto io_error;
-+
-+	free_blocks = le16_to_cpu(gdp->bg_free_blocks_count);
-+	/*
-+	 * if there is not enough free blocks to make a new resevation
-+	 * turn off reservation for this allocation
-+	 */
-+	if (my_rsv && (free_blocks < windowsz)
-+		&& (rsv_is_empty(&my_rsv->rsv_window)))
-+		my_rsv = NULL;
-+
-+	if (free_blocks > 0) {
-+		grp_target_blk = ((goal - le32_to_cpu(es->s_first_data_block)) %
-+				EXT3COW_BLOCKS_PER_GROUP(sb));
-+		bitmap_bh = read_block_bitmap(sb, group_no);
-+		if (!bitmap_bh)
-+			goto io_error;
-+		grp_alloc_blk = ext3cow_try_to_allocate_with_rsv(sb, handle,
-+					group_no, bitmap_bh, grp_target_blk,
-+					my_rsv,	&num, &fatal);
-+		if (fatal)
-+			goto out;
-+		if (grp_alloc_blk >= 0)
-+			goto allocated;
-+	}
-+
-+	ngroups = EXT3COW_SB(sb)->s_groups_count;
-+	smp_rmb();
-+
-+	/*
-+	 * Now search the rest of the groups.  We assume that
-+	 * i and gdp correctly point to the last group visited.
-+	 */
-+	for (bgi = 0; bgi < ngroups; bgi++) {
-+		group_no++;
-+		if (group_no >= ngroups)
-+			group_no = 0;
-+		gdp = ext3cow_get_group_desc(sb, group_no, &gdp_bh);
-+		if (!gdp)
-+			goto io_error;
-+		free_blocks = le16_to_cpu(gdp->bg_free_blocks_count);
-+		/*
-+		 * skip this group if the number of
-+		 * free blocks is less than half of the reservation
-+		 * window size.
-+		 */
-+		if (free_blocks <= (windowsz/2))
-+			continue;
-+
-+		brelse(bitmap_bh);
-+		bitmap_bh = read_block_bitmap(sb, group_no);
-+		if (!bitmap_bh)
-+			goto io_error;
-+		/*
-+		 * try to allocate block(s) from this group, without a goal(-1).
-+		 */
-+		grp_alloc_blk = ext3cow_try_to_allocate_with_rsv(sb, handle,
-+					group_no, bitmap_bh, -1, my_rsv,
-+					&num, &fatal);
-+		if (fatal)
-+			goto out;
-+		if (grp_alloc_blk >= 0)
-+			goto allocated;
-+	}
-+	/*
-+	 * We may end up a bogus ealier ENOSPC error due to
-+	 * filesystem is "full" of reservations, but
-+	 * there maybe indeed free blocks avaliable on disk
-+	 * In this case, we just forget about the reservations
-+	 * just do block allocation as without reservations.
-+	 */
-+	if (my_rsv) {
-+		my_rsv = NULL;
-+		windowsz = 0;
-+		group_no = goal_group;
-+		goto retry_alloc;
-+	}
-+	/* No space left on the device */
-+	*errp = -ENOSPC;
-+	goto out;
-+
-+allocated:
-+
-+	ext3cow_debug("using block group %d(%d)\n",
-+			group_no, gdp->bg_free_blocks_count);
-+
-+	BUFFER_TRACE(gdp_bh, "get_write_access");
-+	fatal = ext3cow_journal_get_write_access(handle, gdp_bh);
-+	if (fatal)
-+		goto out;
-+
-+	ret_block = grp_alloc_blk + ext3cow_group_first_block_no(sb, group_no);
-+
-+	if (in_range(le32_to_cpu(gdp->bg_block_bitmap), ret_block, num) ||
-+	    in_range(le32_to_cpu(gdp->bg_inode_bitmap), ret_block, num) ||
-+	    in_range(ret_block, le32_to_cpu(gdp->bg_inode_table),
-+		      EXT3COW_SB(sb)->s_itb_per_group) ||
-+	    in_range(ret_block + num - 1, le32_to_cpu(gdp->bg_inode_table),
-+		      EXT3COW_SB(sb)->s_itb_per_group))
-+		ext3cow_error(sb, "ext3cow_new_block",
-+			    "Allocating block in system zone - "
-+			    "blocks from "E3FSBLK", length %lu",
-+			     ret_block, num);
-+
-+	performed_allocation = 1;
-+
-+#ifdef CONFIG_JBD_DEBUG
-+	{
-+		struct buffer_head *debug_bh;
-+
-+		/* Record bitmap buffer state in the newly allocated block */
-+		debug_bh = sb_find_get_block(sb, ret_block);
-+		if (debug_bh) {
-+			BUFFER_TRACE(debug_bh, "state when allocated");
-+			BUFFER_TRACE2(debug_bh, bitmap_bh, "bitmap state");
-+			brelse(debug_bh);
-+		}
-+	}
-+	jbd_lock_bh_state(bitmap_bh);
-+	spin_lock(sb_bgl_lock(sbi, group_no));
-+	if (buffer_jbd(bitmap_bh) && bh2jh(bitmap_bh)->b_committed_data) {
-+		int i;
-+
-+		for (i = 0; i < num; i++) {
-+			if (ext3cow_test_bit(grp_alloc_blk+i,
-+					bh2jh(bitmap_bh)->b_committed_data)) {
-+				printk("%s: block was unexpectedly set in "
-+					"b_committed_data\n", __FUNCTION__);
-+			}
-+		}
-+	}
-+	ext3cow_debug("found bit %d\n", grp_alloc_blk);
-+	spin_unlock(sb_bgl_lock(sbi, group_no));
-+	jbd_unlock_bh_state(bitmap_bh);
-+#endif
-+
-+	if (ret_block + num - 1 >= le32_to_cpu(es->s_blocks_count)) {
-+		ext3cow_error(sb, "ext3cow_new_block",
-+			    "block("E3FSBLK") >= blocks count(%d) - "
-+			    "block_group = %d, es == %p ", ret_block,
-+			le32_to_cpu(es->s_blocks_count), group_no, es);
-+		goto out;
-+	}
-+
-+	/*
-+	 * It is up to the caller to add the new buffer to a journal
-+	 * list of some description.  We don't know in advance whether
-+	 * the caller wants to use it as metadata or data.
-+	 */
-+	ext3cow_debug("allocating block %lu. Goal hits %d of %d.\n",
-+			ret_block, goal_hits, goal_attempts);
-+
-+	spin_lock(sb_bgl_lock(sbi, group_no));
-+	gdp->bg_free_blocks_count =
-+			cpu_to_le16(le16_to_cpu(gdp->bg_free_blocks_count)-num);
-+	spin_unlock(sb_bgl_lock(sbi, group_no));
-+	percpu_counter_mod(&sbi->s_freeblocks_counter, -num);
-+
-+	BUFFER_TRACE(gdp_bh, "journal_dirty_metadata for group descriptor");
-+	err = ext3cow_journal_dirty_metadata(handle, gdp_bh);
-+	if (!fatal)
-+		fatal = err;
-+
-+	sb->s_dirt = 1;
-+	if (fatal)
-+		goto out;
-+
-+	*errp = 0;
-+	brelse(bitmap_bh);
-+	DQUOT_FREE_BLOCK(inode, *count-num);
-+	*count = num;
-+	return ret_block;
-+
-+io_error:
-+	*errp = -EIO;
-+out:
-+	if (fatal) {
-+		*errp = fatal;
-+		ext3cow_std_error(sb, fatal);
-+	}
-+	/*
-+	 * Undo the block allocation
-+	 */
-+	if (!performed_allocation)
-+		DQUOT_FREE_BLOCK(inode, *count);
-+	brelse(bitmap_bh);
-+	return 0;
-+}
-+
-+ext3cow_fsblk_t ext3cow_new_block(handle_t *handle, struct inode *inode,
-+			ext3cow_fsblk_t goal, int *errp)
-+{
-+	unsigned long count = 1;
-+
-+	return ext3cow_new_blocks(handle, inode, goal, &count, errp);
-+}
-+
-+/**
-+ * ext3cow_count_free_blocks() -- count filesystem free blocks
-+ * @sb:		superblock
-+ *
-+ * Adds up the number of free blocks from each block group.
-+ */
-+ext3cow_fsblk_t ext3cow_count_free_blocks(struct super_block *sb)
-+{
-+	ext3cow_fsblk_t desc_count;
-+	struct ext3cow_group_desc *gdp;
-+	int i;
-+	unsigned long ngroups = EXT3COW_SB(sb)->s_groups_count;
-+#ifdef EXT3COWFS_DEBUG
-+	struct ext3cow_super_block *es;
-+	ext3cow_fsblk_t bitmap_count;
-+	unsigned long x;
-+	struct buffer_head *bitmap_bh = NULL;
-+
-+	es = EXT3COW_SB(sb)->s_es;
-+	desc_count = 0;
-+	bitmap_count = 0;
-+	gdp = NULL;
-+
-+	smp_rmb();
-+	for (i = 0; i < ngroups; i++) {
-+		gdp = ext3cow_get_group_desc(sb, i, NULL);
-+		if (!gdp)
-+			continue;
-+		desc_count += le16_to_cpu(gdp->bg_free_blocks_count);
-+		brelse(bitmap_bh);
-+		bitmap_bh = read_block_bitmap(sb, i);
-+		if (bitmap_bh == NULL)
-+			continue;
-+
-+		x = ext3cow_count_free(bitmap_bh, sb->s_blocksize);
-+		printk("group %d: stored = %d, counted = %lu\n",
-+			i, le16_to_cpu(gdp->bg_free_blocks_count), x);
-+		bitmap_count += x;
-+	}
-+	brelse(bitmap_bh);
-+	printk("ext3cow_count_free_blocks: stored = "E3FSBLK
-+		", computed = "E3FSBLK", "E3FSBLK"\n",
-+	       le32_to_cpu(es->s_free_blocks_count),
-+		desc_count, bitmap_count);
-+	return bitmap_count;
-+#else
-+	desc_count = 0;
-+	smp_rmb();
-+	for (i = 0; i < ngroups; i++) {
-+		gdp = ext3cow_get_group_desc(sb, i, NULL);
-+		if (!gdp)
-+			continue;
-+		desc_count += le16_to_cpu(gdp->bg_free_blocks_count);
-+	}
-+
-+	return desc_count;
-+#endif
-+}
-+
-+static inline int
-+block_in_use(ext3cow_fsblk_t block, struct super_block *sb, unsigned char *map)
-+{
-+	return ext3cow_test_bit ((block -
-+		le32_to_cpu(EXT3COW_SB(sb)->s_es->s_first_data_block)) %
-+			 EXT3COW_BLOCKS_PER_GROUP(sb), map);
-+}
-+
-+static inline int test_root(int a, int b)
-+{
-+	int num = b;
-+
-+	while (a > num)
-+		num *= b;
-+	return num == a;
-+}
-+
-+static int ext3cow_group_sparse(int group)
-+{
-+	if (group <= 1)
-+		return 1;
-+	if (!(group & 1))
-+		return 0;
-+	return (test_root(group, 7) || test_root(group, 5) ||
-+		test_root(group, 3));
-+}
-+
-+/**
-+ *	ext3cow_bg_has_super - number of blocks used by the superblock in group
-+ *	@sb: superblock for filesystem
-+ *	@group: group number to check
-+ *
-+ *	Return the number of blocks used by the superblock (primary or backup)
-+ *	in this group.  Currently this will be only 0 or 1.
-+ */
-+int ext3cow_bg_has_super(struct super_block *sb, int group)
-+{
-+	if (EXT3COW_HAS_RO_COMPAT_FEATURE(sb,
-+				EXT3COW_FEATURE_RO_COMPAT_SPARSE_SUPER) &&
-+			!ext3cow_group_sparse(group))
-+		return 0;
-+	return 1;
-+}
-+
-+static unsigned long ext3cow_bg_num_gdb_meta(struct super_block *sb, int group)
-+{
-+	unsigned long metagroup = group / EXT3COW_DESC_PER_BLOCK(sb);
-+	unsigned long first = metagroup * EXT3COW_DESC_PER_BLOCK(sb);
-+	unsigned long last = first + EXT3COW_DESC_PER_BLOCK(sb) - 1;
-+
-+	if (group == first || group == first + 1 || group == last)
-+		return 1;
-+	return 0;
-+}
-+
-+static unsigned long ext3cow_bg_num_gdb_nometa(struct super_block *sb, int group)
-+{
-+	if (EXT3COW_HAS_RO_COMPAT_FEATURE(sb,
-+				EXT3COW_FEATURE_RO_COMPAT_SPARSE_SUPER) &&
-+			!ext3cow_group_sparse(group))
-+		return 0;
-+	return EXT3COW_SB(sb)->s_gdb_count;
-+}
-+
-+/**
-+ *	ext3cow_bg_num_gdb - number of blocks used by the group table in group
-+ *	@sb: superblock for filesystem
-+ *	@group: group number to check
-+ *
-+ *	Return the number of blocks used by the group descriptor table
-+ *	(primary or backup) in this group.  In the future there may be a
-+ *	different number of descriptor blocks in each group.
-+ */
-+unsigned long ext3cow_bg_num_gdb(struct super_block *sb, int group)
-+{
-+	unsigned long first_meta_bg =
-+			le32_to_cpu(EXT3COW_SB(sb)->s_es->s_first_meta_bg);
-+	unsigned long metagroup = group / EXT3COW_DESC_PER_BLOCK(sb);
-+
-+	if (!EXT3COW_HAS_INCOMPAT_FEATURE(sb,EXT3COW_FEATURE_INCOMPAT_META_BG) ||
-+			metagroup < first_meta_bg)
-+		return ext3cow_bg_num_gdb_nometa(sb,group);
-+
-+	return ext3cow_bg_num_gdb_meta(sb,group);
-+
-+}
-diff -ruN linux-2.6.20.3/fs/ext3cow/bitmap.c linux-2.6.20.3-ext3cow/fs/ext3cow/bitmap.c
---- linux-2.6.20.3/fs/ext3cow/bitmap.c	1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.20.3-ext3cow/fs/ext3cow/bitmap.c	2008-03-09 11:14:48.000000000 -0400
-@@ -0,0 +1,32 @@
-+/*
-+ *  linux/fs/ext3/bitmap.c
-+ *
-+ * Copyright (C) 1992, 1993, 1994, 1995
-+ * Remy Card (card@masi.ibp.fr)
-+ * Laboratoire MASI - Institut Blaise Pascal
-+ * Universite Pierre et Marie Curie (Paris VI)
-+ */
-+
-+#include <linux/buffer_head.h>
-+#include <linux/jbd.h>
-+#include <linux/ext3cow_fs.h>
-+
-+#ifdef EXT3COWFS_DEBUG
-+
-+static int nibblemap[] = {4, 3, 3, 2, 3, 2, 2, 1, 3, 2, 2, 1, 2, 1, 1, 0};
-+
-+unsigned long ext3cow_count_free (struct buffer_head * map, unsigned int numchars)
-+{
-+	unsigned int i;
-+	unsigned long sum = 0;
-+
-+	if (!map)
-+		return (0);
-+	for (i = 0; i < numchars; i++)
-+		sum += nibblemap[map->b_data[i] & 0xf] +
-+			nibblemap[(map->b_data[i] >> 4) & 0xf];
-+	return (sum);
-+}
-+
-+#endif  /*  EXT3COWFS_DEBUG  */
-+
-diff -ruN linux-2.6.20.3/fs/ext3cow/CHANGELOG linux-2.6.20.3-ext3cow/fs/ext3cow/CHANGELOG
---- linux-2.6.20.3/fs/ext3cow/CHANGELOG	1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.20.3-ext3cow/fs/ext3cow/CHANGELOG	2008-03-09 11:27:12.000000000 -0400
-@@ -0,0 +1,12 @@
-+3-9-08
-+- Fixed a bug that resulted in the first block in a newly allocated indirect block to be allocated over and over again.
-+- Fixed a bug that resulted in COW bitmaps not to be reset after truncate.
-+- Bug e2fsprogs that caused aborting journal fixed.
-+
-+6-20-97
-+- Finished the rollback code for inode chains in case of error.
-+
-+6-18-07
-+- Added support for 32-bit uid's and gid's back in again
-+- Took out support for block fragmentation
-+- Hopefully fixed the non-sticking uid/gid bug.
-\ No newline at end of file
-diff -ruN linux-2.6.20.3/fs/ext3cow/dir.c linux-2.6.20.3-ext3cow/fs/ext3cow/dir.c
---- linux-2.6.20.3/fs/ext3cow/dir.c	1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.20.3-ext3cow/fs/ext3cow/dir.c	2008-03-09 11:14:49.000000000 -0400
-@@ -0,0 +1,732 @@
-+/*
-+ *  linux/fs/ext3cow/dir.c
-+ *
-+ * Copyright (C) 1992, 1993, 1994, 1995
-+ * Remy Card (card@masi.ibp.fr)
-+ * Laboratoire MASI - Institut Blaise Pascal
-+ * Universite Pierre et Marie Curie (Paris VI)
-+ *
-+ *  from
-+ *
-+ *  linux/fs/minix/dir.c
-+ *
-+ *  Copyright (C) 1991, 1992  Linus Torvalds
-+ *
-+ *  ext3cow directory handling functions
-+ *
-+ *  Big-endian to little-endian byte-swapping/bitmaps by
-+ *        David S. Miller (davem@caip.rutgers.edu), 1995
-+ *
-+ * Hash Tree Directory indexing (c) 2001  Daniel Phillips
-+ *
-+ */
-+
-+#include <linux/fs.h>
-+#include <linux/jbd.h>
-+#include <linux/ext3cow_fs.h>
-+#include <linux/buffer_head.h>
-+#include <linux/smp_lock.h>
-+#include <linux/slab.h>
-+#include <linux/rbtree.h>
-+
-+static unsigned char ext3cow_filetype_table[] = {
-+	DT_UNKNOWN, DT_REG, DT_DIR, DT_CHR, DT_BLK, DT_FIFO, DT_SOCK, DT_LNK
-+};
-+
-+static int ext3cow_readdir(struct file *, void *, filldir_t);
-+static int ext3cow_dx_readdir(struct file * filp,
-+			   void * dirent, filldir_t filldir);
-+static int ext3cow_release_dir (struct inode * inode,
-+				struct file * filp);
-+
-+const struct file_operations ext3cow_dir_operations = {
-+	.llseek		= generic_file_llseek,
-+	.read		= generic_read_dir,
-+	.readdir	= ext3cow_readdir,		/* we take BKL. needed?*/
-+	.ioctl		= ext3cow_ioctl,		/* BKL held */
-+#ifdef CONFIG_COMPAT
-+	.compat_ioctl	= ext3cow_compat_ioctl,
-+#endif
-+	.fsync		= ext3cow_sync_file,	/* BKL held */
-+#ifdef CONFIG_EXT3COW_INDEX
-+	.release	= ext3cow_release_dir,
-+#endif
-+};
-+
-+
-+static unsigned char get_dtype(struct super_block *sb, int filetype)
-+{
-+	if (!EXT3COW_HAS_INCOMPAT_FEATURE(sb, EXT3COW_FEATURE_INCOMPAT_FILETYPE) ||
-+	    (filetype >= EXT3COW_FT_MAX))
-+		return DT_UNKNOWN;
-+
-+	return (ext3cow_filetype_table[filetype]);
-+}
-+
-+static int ext3cow_readversions(struct file * filp, void * dirent, 
-+                                filldir_t filldir)
-+{
-+  int error = 0;
-+  unsigned long offset;
-+  int i, stored;
-+  struct buffer_head *bh;
-+  struct ext3cow_dir_entry_2 * de;
-+  struct super_block * sb;
-+  int err;
-+  struct inode *dir = filp->f_dentry->d_inode;
-+  char *at;
-+  unsigned long ino;
-+  int ref_len = filp->f_dentry->d_name.len -1;
-+  
-+  sb = dir->i_sb;
-+  
-+  stored = 0;
-+  bh = NULL;
-+  offset = filp->f_pos & (sb->s_blocksize - 1);
-+  
-+  at = strrchr(filp->f_dentry->d_name.name, EXT3COW_FLUX_TOKEN);
-+  
-+  while (!error && !stored && filp->f_pos < dir->i_size) {
-+    unsigned long blk = (filp->f_pos) >> EXT3COW_BLOCK_SIZE_BITS(sb);
-+    struct buffer_head map_bh;
-+
-+    bh = NULL;
-+    map_bh.b_state = 0;
-+		err = ext3cow_get_blocks_handle(NULL, dir, blk, 1,
-+						&map_bh, 0, 0);
-+		if (err > 0) {
-+			page_cache_readahead(sb->s_bdev->bd_inode->i_mapping,
-+				&filp->f_ra,
-+				filp,
-+				map_bh.b_blocknr >>
-+					(PAGE_CACHE_SHIFT - dir->i_blkbits),
-+				1);
-+			bh = ext3cow_bread(NULL, dir, blk, 0, &err);
-+		}
-+
-+		/*
-+		 * We ignore I/O errors on directories so users have a chance
-+		 * of recovering data when there's a bad sector
-+		 */
-+    if (!bh) {
-+      ext3cow_error (sb, "ext3cow_versions",
-+                     "directory #%lu contains a hole at offset %lu",
-+                     dir->i_ino, (unsigned long)filp->f_pos);
-+      /* corrupt size?  Maybe no more blocks to read */
-+			if (filp->f_pos > dir->i_blocks << 9)
-+				break;
-+      filp->f_pos += sb->s_blocksize - offset;
-+      continue;
-+    }
-+    
-+  ver_revalidate:
-+    /* If the dir block has changed since the last call to
-+     * readdir(2), then we might be pointing to an invalid
-+     * dirent right now.  Scan from the start of the block
-+     * to make sure. */
-+    if (filp->f_version != dir->i_version) {
-+      for (i = 0; i < sb->s_blocksize && i < offset; ) {
-+        de = (struct ext3cow_dir_entry_2 *) 
-+          (bh->b_data + i);
-+				/* It's too expensive to do a full
-+				 * dirent test each time round this
-+				 * loop, but we do have to test at
-+				 * least that it is non-zero.  A
-+				 * failure will be detected in the
-+				 * dirent test below. */
-+        if (le16_to_cpu(de->rec_len) <
-+            EXT3COW_DIR_REC_LEN(1))
-+          break;
-+        i += le16_to_cpu(de->rec_len);
-+      }
-+      offset = i;
-+      filp->f_pos = (filp->f_pos & ~(sb->s_blocksize - 1))
-+        | offset;
-+      filp->f_version = dir->i_version;
-+    }
-+    
-+    while (!error && filp->f_pos < dir->i_size 
-+           && offset < sb->s_blocksize) {
-+      de = (struct ext3cow_dir_entry_2 *) (bh->b_data + offset);
-+      if (!ext3cow_check_dir_entry ("ext3cow_readversions", dir, de,
-+                                    bh, offset)) {
-+				/* On error, skip the f_pos to the
-+           next block. */
-+        filp->f_pos = (filp->f_pos |
-+                       (sb->s_blocksize - 1)) + 1;
-+        brelse (bh);
-+        return stored;
-+      }
-+      offset += le16_to_cpu(de->rec_len);
-+      
-+      if (le32_to_cpu(de->inode)){
-+        unsigned long version = filp->f_version;
-+        unsigned char d_type = DT_UNKNOWN;
-+        
-+        /* We might block in the next section
-+         * if the data destination is
-+         * currently swapped out.  So, use a
-+         * version stamp to detect whether or
-+         * not the directory has been modified
-+         * during the copy operation.
-+         */
-+        
-+        if (EXT3COW_HAS_INCOMPAT_FEATURE(sb,
-+                                         EXT3COW_FEATURE_INCOMPAT_FILETYPE)
-+            && de->file_type < EXT3COW_FT_MAX)
-+          d_type =
-+            ext3cow_filetype_table[de->file_type];
-+        if (de->name_len == ref_len
-+            && strncmp(filp->f_dentry->d_name.name, de->name, ref_len)==0) {
-+          
-+          struct inode * inde;
-+          char * name;
-+          
-+          name = kmalloc(EXT3COW_NAME_LEN, GFP_KERNEL);
-+          strncpy(name, de->name, de->name_len);
-+          inde = iget(dir->i_sb, de->inode);
-+          
-+          if (de->death_epoch!=0 && de->birth_epoch!=de->death_epoch) {
-+            name[de->name_len]='\0';
-+            sprintf(name,"%s@%d",name, de->death_epoch);
-+            error = filldir(dirent, name,
-+                            strlen(name),
-+                            filp->f_pos,
-+                            le32_to_cpu(inde->i_ino),
-+                            d_type);
-+            stored++;
-+          }
-+          
-+          while (EXT3COW_I(inde)->i_next_inode!=0) {
-+            name[de->name_len]='\0';
-+            sprintf(name,"%s@%d",name, EXT3COW_I_EPOCHNUMBER(inde));
-+            error = filldir(dirent, name,
-+                            strlen(name),
-+                            filp->f_pos,
-+                            le32_to_cpu(inde->i_ino),
-+                            d_type);
-+            ino = EXT3COW_I(inde)->i_next_inode;
-+            iput(inde);
-+            inde = iget(dir->i_sb, ino);
-+            stored++;
-+          }
-+          
-+          kfree(name);
-+          iput(inde);
-+                    
-+          if (error)
-+            break;
-+          
-+          if (!stored && 
-+              EXT3COW_IS_DIRENT_SCOPED(de, EXT3COW_I_EPOCHNUMBER(dir))) {
-+            error = filldir(dirent, de->name,
-+                            de->name_len,
-+                            filp->f_pos,
-+                            le32_to_cpu(de->inode),
-+                            d_type);
-+          }
-+            
-+          if (error)
-+            break;
-+          if (version != filp->f_version)
-+            goto ver_revalidate;
-+          stored ++;
-+        }
-+      }
-+      
-+      filp->f_pos += le16_to_cpu(de->rec_len);
-+    }
-+    offset = 0;
-+    brelse (bh);
-+  }
-+  return 0;
-+}
-+
-+
-+int ext3cow_check_dir_entry (const char * function, struct inode * dir,
-+			  struct ext3cow_dir_entry_2 * de,
-+			  struct buffer_head * bh,
-+			  unsigned long offset)
-+{
-+	const char * error_msg = NULL;
-+	const int rlen = le16_to_cpu(de->rec_len);
-+  unsigned int current_epoch = EXT3COW_S_EPOCHNUMBER(dir->i_sb);
-+
-+	if (rlen < EXT3COW_DIR_REC_LEN(1))
-+		error_msg = "rec_len is smaller than minimal";
-+	else if (rlen % 4 != 0)
-+		error_msg = "rec_len % 4 != 0";
-+	else if (rlen < EXT3COW_DIR_REC_LEN(de->name_len))
-+		error_msg = "rec_len is too small for name_len";
-+	else if (((char *) de - bh->b_data) + rlen > dir->i_sb->s_blocksize)
-+		error_msg = "directory entry across blocks";
-+	else if (le32_to_cpu(de->inode) >
-+			le32_to_cpu(EXT3COW_SB(dir->i_sb)->s_es->s_inodes_count))
-+		error_msg = "inode out of bounds";
-+  /* Some bounds on versioned entries -znjp*/
-+  else if (le32_to_cpu(de->death_epoch) != EXT3COW_DIRENT_ALIVE && 
-+           le32_to_cpu(de->birth_epoch) > le32_to_cpu(de->death_epoch))
-+    error_msg = "entry died before it was born";
-+  else if (le32_to_cpu(de->birth_epoch) > current_epoch)
-+    error_msg = "entry was born in the future";
-+  else if (le32_to_cpu(de->death_epoch) > current_epoch)
-+    error_msg = "entry has already died in the future";
-+
-+	if (error_msg != NULL)
-+		ext3cow_error (dir->i_sb, function,
-+			"bad entry in directory #%lu: %s - "
-+			"offset=%lu, inode=%lu, rec_len=%d, name_len=%d, "
-+      "birth_epoch=%d death_epoch=%d",
-+			dir->i_ino, error_msg, offset,
-+			(unsigned long) le32_to_cpu(de->inode),
-+                   rlen, de->name_len, de->birth_epoch, de->death_epoch);
-+	return error_msg == NULL ? 1 : 0;
-+}
-+
-+static int ext3cow_readdir(struct file * filp,
-+			 void * dirent, filldir_t filldir)
-+{
-+	int error = 0;
-+	unsigned long offset;
-+	int i, stored;
-+	struct ext3cow_dir_entry_2 *de;
-+	struct super_block *sb;
-+	int err;
-+	struct inode *inode = filp->f_path.dentry->d_inode;
-+	int ret = 0;
-+  
-+  /* is this a version listing? */
-+  if (filp->f_dentry->d_name.name[filp->f_dentry->d_name.len-1] ==  
-+      EXT3COW_FLUX_TOKEN)
-+    return ext3cow_readversions(filp, dirent, filldir);
-+  
-+	sb = inode->i_sb;
-+
-+#ifdef CONFIG_EXT3COW_INDEX
-+	if (EXT3COW_HAS_COMPAT_FEATURE(inode->i_sb, 
-+                                 EXT3COW_FEATURE_COMPAT_DIR_INDEX) &&
-+	    ((EXT3COW_I(inode)->i_flags & EXT3COW_INDEX_FL) ||
-+	     ((inode->i_size >> sb->s_blocksize_bits) == 1))) {
-+
-+		err = ext3cow_dx_readdir(filp, dirent, filldir);
-+		if (err != ERR_BAD_DX_DIR) {
-+			ret = err;
-+			goto out;
-+		}
-+		/*
-+		 * We don't set the inode dirty flag since it's not
-+		 * critical that it get flushed back to the disk.
-+		 */
-+		EXT3COW_I(filp->f_path.dentry->d_inode)->i_flags &= ~EXT3COW_INDEX_FL;
-+	}
-+#endif
-+	stored = 0;
-+	offset = filp->f_pos & (sb->s_blocksize - 1);
-+
-+	while (!error && !stored && filp->f_pos < inode->i_size) {
-+		unsigned long blk = filp->f_pos >> EXT3COW_BLOCK_SIZE_BITS(sb);
-+		struct buffer_head map_bh;
-+		struct buffer_head *bh = NULL;
-+
-+		map_bh.b_state = 0;
-+		err = ext3cow_get_blocks_handle(NULL, inode, blk, 1,
-+						&map_bh, 0, 0);
-+		if (err > 0) {
-+			page_cache_readahead(sb->s_bdev->bd_inode->i_mapping,
-+				&filp->f_ra,
-+				filp,
-+				map_bh.b_blocknr >>
-+					(PAGE_CACHE_SHIFT - inode->i_blkbits),
-+				1);
-+			bh = ext3cow_bread(NULL, inode, blk, 0, &err);
-+		}
-+
-+		/*
-+		 * We ignore I/O errors on directories so users have a chance
-+		 * of recovering data when there's a bad sector
-+		 */
-+		if (!bh) {
-+			ext3cow_error (sb, "ext3cow_readdir",
-+				"directory #%lu contains a hole at offset %lu",
-+				inode->i_ino, (unsigned long)filp->f_pos);
-+			/* corrupt size?  Maybe no more blocks to read */
-+			if (filp->f_pos > inode->i_blocks << 9)
-+				break;
-+			filp->f_pos += sb->s_blocksize - offset;
-+			continue;
-+		}
-+
-+revalidate:
-+		/* If the dir block has changed since the last call to
-+		 * readdir(2), then we might be pointing to an invalid
-+		 * dirent right now.  Scan from the start of the block
-+		 * to make sure. */
-+		if (filp->f_version != inode->i_version) {
-+			for (i = 0; i < sb->s_blocksize && i < offset; ) {
-+				de = (struct ext3cow_dir_entry_2 *)
-+					(bh->b_data + i);
-+				/* It's too expensive to do a full
-+				 * dirent test each time round this
-+				 * loop, but we do have to test at
-+				 * least that it is non-zero.  A
-+				 * failure will be detected in the
-+				 * dirent test below. */
-+				if (le16_to_cpu(de->rec_len) <
-+						EXT3COW_DIR_REC_LEN(1))
-+					break;
-+				i += le16_to_cpu(de->rec_len);
-+			}
-+			offset = i;
-+			filp->f_pos = (filp->f_pos & ~(sb->s_blocksize - 1))
-+				| offset;
-+			filp->f_version = inode->i_version;
-+		}
-+
-+		while (!error && filp->f_pos < inode->i_size
-+		       && offset < sb->s_blocksize) {
-+			de = (struct ext3cow_dir_entry_2 *) (bh->b_data + offset);
-+			if (!ext3cow_check_dir_entry ("ext3cow_readdir", inode, de,
-+						   bh, offset)) {
-+				/* On error, skip the f_pos to the
-+                                   next block. */
-+				filp->f_pos = (filp->f_pos |
-+						(sb->s_blocksize - 1)) + 1;
-+				brelse (bh);
-+				ret = stored;
-+				goto out;
-+			}
-+			offset += le16_to_cpu(de->rec_len);
-+    /*
-+        printk("Inode %ld Epoch number %u: is 
-+        dir %d -> %s be %d de %d scoped? %d\n",
-+        dir->i_ino,
-+        EXT3COW_I_EPOCHNUMBER(dir),
-+        de->inode,
-+        de->name,
-+        de->birth_epoch,
-+        de->death_epoch,
-+        EXT3COW_IS_DIRENT_SCOPED(de, EXT3COW_I_EPOCHNUMBER(dir)));
-+      */
-+
-+      /* Only add scoped dirents - znjp */
-+			if (le32_to_cpu(de->inode)  && 
-+          EXT3COW_IS_DIRENT_SCOPED(de, EXT3COW_I_EPOCHNUMBER(inode))) {
-+				/* We might block in the next section
-+				 * if the data destination is
-+				 * currently swapped out.  So, use a
-+				 * version stamp to detect whether or
-+				 * not the directory has been modified
-+				 * during the copy operation.
-+				 */
-+				unsigned long version = filp->f_version;
-+
-+				error = filldir(dirent, de->name,
-+						de->name_len,
-+						filp->f_pos,
-+						le32_to_cpu(de->inode),
-+						get_dtype(sb, de->file_type));
-+				if (error)
-+					break;
-+				if (version != filp->f_version)
-+					goto revalidate;
-+				stored ++;
-+			}
-+			filp->f_pos += le16_to_cpu(de->rec_len);
-+		}
-+		offset = 0;
-+		brelse (bh);
-+	}
-+out:
-+	return ret;
-+}
-+
-+#ifdef CONFIG_EXT3COW_INDEX
-+/*
-+ * These functions convert from the major/minor hash to an f_pos
-+ * value.
-+ *
-+ * Currently we only use major hash numer.  This is unfortunate, but
-+ * on 32-bit machines, the same VFS interface is used for lseek and
-+ * llseek, so if we use the 64 bit offset, then the 32-bit versions of
-+ * lseek/telldir/seekdir will blow out spectacularly, and from within
-+ * the ext2 low-level routine, we don't know if we're being called by
-+ * a 64-bit version of the system call or the 32-bit version of the
-+ * system call.  Worse yet, NFSv2 only allows for a 32-bit readdir
-+ * cookie.  Sigh.
-+ */
-+#define hash2pos(major, minor)	(major >> 1)
-+#define pos2maj_hash(pos)	((pos << 1) & 0xffffffff)
-+#define pos2min_hash(pos)	(0)
-+
-+/*
-+ * This structure holds the nodes of the red-black tree used to store
-+ * the directory entry in hash order.
-+ */
-+struct fname {
-+	__u32		hash;
-+	__u32		minor_hash;
-+	struct rb_node	rb_hash;
-+	struct fname	*next;
-+	__u32		inode;
-+	__u8		name_len;
-+	__u8		file_type;
-+	char		name[0];
-+};
-+
-+/*
-+ * This functoin implements a non-recursive way of freeing all of the
-+ * nodes in the red-black tree.
-+ */
-+static void free_rb_tree_fname(struct rb_root *root)
-+{
-+	struct rb_node	*n = root->rb_node;
-+	struct rb_node	*parent;
-+	struct fname	*fname;
-+
-+	while (n) {
-+		/* Do the node's children first */
-+		if ((n)->rb_left) {
-+			n = n->rb_left;
-+			continue;
-+		}
-+		if (n->rb_right) {
-+			n = n->rb_right;
-+			continue;
-+		}
-+		/*
-+		 * The node has no children; free it, and then zero
-+		 * out parent's link to it.  Finally go to the
-+		 * beginning of the loop and try to free the parent
-+		 * node.
-+		 */
-+		parent = rb_parent(n);
-+		fname = rb_entry(n, struct fname, rb_hash);
-+		while (fname) {
-+			struct fname * old = fname;
-+			fname = fname->next;
-+			kfree (old);
-+		}
-+		if (!parent)
-+			root->rb_node = NULL;
-+		else if (parent->rb_left == n)
-+			parent->rb_left = NULL;
-+		else if (parent->rb_right == n)
-+			parent->rb_right = NULL;
-+		n = parent;
-+	}
-+	root->rb_node = NULL;
-+}
-+
-+
-+static struct dir_private_info *create_dir_info(loff_t pos)
-+{
-+	struct dir_private_info *p;
-+
-+	p = kmalloc(sizeof(struct dir_private_info), GFP_KERNEL);
-+	if (!p)
-+		return NULL;
-+	p->root.rb_node = NULL;
-+	p->curr_node = NULL;
-+	p->extra_fname = NULL;
-+	p->last_pos = 0;
-+	p->curr_hash = pos2maj_hash(pos);
-+	p->curr_minor_hash = pos2min_hash(pos);
-+	p->next_hash = 0;
-+	return p;
-+}
-+
-+void ext3cow_htree_free_dir_info(struct dir_private_info *p)
-+{
-+	free_rb_tree_fname(&p->root);
-+	kfree(p);
-+}
-+
-+/*
-+ * Given a directory entry, enter it into the fname rb tree.
-+ */
-+int ext3cow_htree_store_dirent(struct file *dir_file, __u32 hash,
-+			     __u32 minor_hash,
-+			     struct ext3cow_dir_entry_2 *dirent)
-+{
-+	struct rb_node **p, *parent = NULL;
-+	struct fname * fname, *new_fn;
-+	struct dir_private_info *info;
-+	int len;
-+
-+	info = (struct dir_private_info *) dir_file->private_data;
-+	p = &info->root.rb_node;
-+
-+	/* Create and allocate the fname structure */
-+	len = sizeof(struct fname) + dirent->name_len + 1;
-+	new_fn = kzalloc(len, GFP_KERNEL);
-+	if (!new_fn)
-+		return -ENOMEM;
-+	new_fn->hash = hash;
-+	new_fn->minor_hash = minor_hash;
-+	new_fn->inode = le32_to_cpu(dirent->inode);
-+	new_fn->name_len = dirent->name_len;
-+	new_fn->file_type = dirent->file_type;
-+	memcpy(new_fn->name, dirent->name, dirent->name_len);
-+	new_fn->name[dirent->name_len] = 0;
-+
-+	while (*p) {
-+		parent = *p;
-+		fname = rb_entry(parent, struct fname, rb_hash);
-+
-+		/*
-+		 * If the hash and minor hash match up, then we put
-+		 * them on a linked list.  This rarely happens...
-+		 */
-+		if ((new_fn->hash == fname->hash) &&
-+		    (new_fn->minor_hash == fname->minor_hash)) {
-+			new_fn->next = fname->next;
-+			fname->next = new_fn;
-+			return 0;
-+		}
-+
-+		if (new_fn->hash < fname->hash)
-+			p = &(*p)->rb_left;
-+		else if (new_fn->hash > fname->hash)
-+			p = &(*p)->rb_right;
-+		else if (new_fn->minor_hash < fname->minor_hash)
-+			p = &(*p)->rb_left;
-+		else /* if (new_fn->minor_hash > fname->minor_hash) */
-+			p = &(*p)->rb_right;
-+	}
-+
-+	rb_link_node(&new_fn->rb_hash, parent, p);
-+	rb_insert_color(&new_fn->rb_hash, &info->root);
-+	return 0;
-+}
-+
-+
-+
-+/*
-+ * This is a helper function for ext3cow_dx_readdir.  It calls filldir
-+ * for all entres on the fname linked list.  (Normally there is only
-+ * one entry on the linked list, unless there are 62 bit hash collisions.)
-+ */
-+static int call_filldir(struct file * filp, void * dirent,
-+			filldir_t filldir, struct fname *fname)
-+{
-+	struct dir_private_info *info = filp->private_data;
-+	loff_t	curr_pos;
-+	struct inode *inode = filp->f_path.dentry->d_inode;
-+	struct super_block * sb;
-+	int error;
-+
-+	sb = inode->i_sb;
-+
-+  printk(KERN_INFO, "Got %s\n", filp->f_path.dentry->d_name.name);
-+
-+	if (!fname) {
-+		printk("call_filldir: called with null fname?!?\n");
-+		return 0;
-+	}
-+	curr_pos = hash2pos(fname->hash, fname->minor_hash);
-+	while (fname) {
-+		error = filldir(dirent, fname->name,
-+				fname->name_len, curr_pos,
-+				fname->inode,
-+				get_dtype(sb, fname->file_type));
-+		if (error) {
-+			filp->f_pos = curr_pos;
-+			info->extra_fname = fname->next;
-+			return error;
-+		}
-+		fname = fname->next;
-+	}
-+	return 0;
-+}
-+
-+static int ext3cow_dx_readdir(struct file * filp,
-+			 void * dirent, filldir_t filldir)
-+{
-+	struct dir_private_info *info = filp->private_data;
-+	struct inode *inode = filp->f_path.dentry->d_inode;
-+	struct fname *fname;
-+	int	ret;
-+
-+	if (!info) {
-+		info = create_dir_info(filp->f_pos);
-+		if (!info)
-+			return -ENOMEM;
-+		filp->private_data = info;
-+	}
-+
-+	if (filp->f_pos == EXT3COW_HTREE_EOF)
-+		return 0;	/* EOF */
-+
-+	/* Some one has messed with f_pos; reset the world */
-+	if (info->last_pos != filp->f_pos) {
-+		free_rb_tree_fname(&info->root);
-+		info->curr_node = NULL;
-+		info->extra_fname = NULL;
-+		info->curr_hash = pos2maj_hash(filp->f_pos);
-+		info->curr_minor_hash = pos2min_hash(filp->f_pos);
-+	}
-+
-+	/*
-+	 * If there are any leftover names on the hash collision
-+	 * chain, return them first.
-+	 */
-+	if (info->extra_fname &&
-+	    call_filldir(filp, dirent, filldir, info->extra_fname))
-+		goto finished;
-+
-+	if (!info->curr_node)
-+		info->curr_node = rb_first(&info->root);
-+
-+	while (1) {
-+		/*
-+		 * Fill the rbtree if we have no more entries,
-+		 * or the inode has changed since we last read in the
-+		 * cached entries.
-+		 */
-+		if ((!info->curr_node) ||
-+		    (filp->f_version != inode->i_version)) {
-+			info->curr_node = NULL;
-+			free_rb_tree_fname(&info->root);
-+			filp->f_version = inode->i_version;
-+			ret = ext3cow_htree_fill_tree(filp, info->curr_hash,
-+						   info->curr_minor_hash,
-+						   &info->next_hash);
-+			if (ret < 0)
-+				return ret;
-+			if (ret == 0) {
-+				filp->f_pos = EXT3COW_HTREE_EOF;
-+				break;
-+			}
-+			info->curr_node = rb_first(&info->root);
-+		}
-+
-+		fname = rb_entry(info->curr_node, struct fname, rb_hash);
-+		info->curr_hash = fname->hash;
-+		info->curr_minor_hash = fname->minor_hash;
-+		if (call_filldir(filp, dirent, filldir, fname))
-+			break;
-+
-+		info->curr_node = rb_next(info->curr_node);
-+		if (!info->curr_node) {
-+			if (info->next_hash == ~0) {
-+				filp->f_pos = EXT3COW_HTREE_EOF;
-+				break;
-+			}
-+			info->curr_hash = info->next_hash;
-+			info->curr_minor_hash = 0;
-+		}
-+	}
-+finished:
-+	info->last_pos = filp->f_pos;
-+	return 0;
-+}
-+
-+static int ext3cow_release_dir (struct inode * inode, struct file * filp)
-+{
-+       if (filp->private_data)
-+		ext3cow_htree_free_dir_info(filp->private_data);
-+
-+	return 0;
-+}
-+
-+#endif
-diff -ruN linux-2.6.20.3/fs/ext3cow/ext3cow_jbd.c linux-2.6.20.3-ext3cow/fs/ext3cow/ext3cow_jbd.c
---- linux-2.6.20.3/fs/ext3cow/ext3cow_jbd.c	1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.20.3-ext3cow/fs/ext3cow/ext3cow_jbd.c	2008-03-09 11:14:48.000000000 -0400
-@@ -0,0 +1,59 @@
-+/*
-+ * Interface between ext3cow and JBD
-+ */
-+
-+#include <linux/ext3cow_jbd.h>
-+
-+int __ext3cow_journal_get_undo_access(const char *where, handle_t *handle,
-+				struct buffer_head *bh)
-+{
-+	int err = journal_get_undo_access(handle, bh);
-+	if (err)
-+		ext3cow_journal_abort_handle(where, __FUNCTION__, bh, handle,err);
-+	return err;
-+}
-+
-+int __ext3cow_journal_get_write_access(const char *where, handle_t *handle,
-+				struct buffer_head *bh)
-+{
-+	int err = journal_get_write_access(handle, bh);
-+	if (err)
-+		ext3cow_journal_abort_handle(where, __FUNCTION__, bh, handle,err);
-+	return err;
-+}
-+
-+int __ext3cow_journal_forget(const char *where, handle_t *handle,
-+				struct buffer_head *bh)
-+{
-+	int err = journal_forget(handle, bh);
-+	if (err)
-+		ext3cow_journal_abort_handle(where, __FUNCTION__, bh, handle,err);
-+	return err;
-+}
-+
-+int __ext3cow_journal_revoke(const char *where, handle_t *handle,
-+				unsigned long blocknr, struct buffer_head *bh)
-+{
-+	int err = journal_revoke(handle, blocknr, bh);
-+	if (err)
-+		ext3cow_journal_abort_handle(where, __FUNCTION__, bh, handle,err);
-+	return err;
-+}
-+
-+int __ext3cow_journal_get_create_access(const char *where,
-+				handle_t *handle, struct buffer_head *bh)
-+{
-+	int err = journal_get_create_access(handle, bh);
-+	if (err)
-+		ext3cow_journal_abort_handle(where, __FUNCTION__, bh, handle,err);
-+	return err;
-+}
-+
-+int __ext3cow_journal_dirty_metadata(const char *where,
-+				handle_t *handle, struct buffer_head *bh)
-+{
-+	int err = journal_dirty_metadata(handle, bh);
-+	if (err)
-+		ext3cow_journal_abort_handle(where, __FUNCTION__, bh, handle,err);
-+	return err;
-+}
-diff -ruN linux-2.6.20.3/fs/ext3cow/file.c linux-2.6.20.3-ext3cow/fs/ext3cow/file.c
---- linux-2.6.20.3/fs/ext3cow/file.c	1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.20.3-ext3cow/fs/ext3cow/file.c	2008-03-09 11:14:48.000000000 -0400
-@@ -0,0 +1,147 @@
-+/*
-+ *  linux/fs/ext3cow/file.c
-+ *
-+ * Copyright (C) 1992, 1993, 1994, 1995
-+ * Remy Card (card@masi.ibp.fr)
-+ * Laboratoire MASI - Institut Blaise Pascal
-+ * Universite Pierre et Marie Curie (Paris VI)
-+ *
-+ *  from
-+ *
-+ *  linux/fs/minix/file.c
-+ *
-+ *  Copyright (C) 1991, 1992  Linus Torvalds
-+ *
-+ *  ext3cow fs regular file handling primitives
-+ *
-+ *  64-bit file support on 64-bit platforms by Jakub Jelinek
-+ *	(jj@sunsite.ms.mff.cuni.cz)
-+ */
-+
-+#include <linux/time.h>
-+#include <linux/fs.h>
-+#include <linux/jbd.h>
-+#include <linux/ext3cow_fs.h>
-+#include <linux/ext3cow_jbd.h>
-+#include "xattr.h"
-+#include "acl.h"
-+
-+/*
-+ * Called when an inode is released. Note that this is different
-+ * from ext3cow_file_open: open gets called at every open, but release
-+ * gets called only when /all/ the files are closed.
-+ */
-+static int ext3cow_release_file (struct inode * inode, struct file * filp)
-+{
-+	/* if we are the last writer on the inode, drop the block reservation */
-+	if ((filp->f_mode & FMODE_WRITE) &&
-+			(atomic_read(&inode->i_writecount) == 1))
-+	{
-+		mutex_lock(&EXT3COW_I(inode)->truncate_mutex);
-+		ext3cow_discard_reservation(inode);
-+		mutex_unlock(&EXT3COW_I(inode)->truncate_mutex);
-+	}
-+	if (is_dx(inode) && filp->private_data)
-+		ext3cow_htree_free_dir_info(filp->private_data);
-+
-+	return 0;
-+}
-+
-+static ssize_t
-+ext3cow_file_write(struct kiocb *iocb, const struct iovec *iov,
-+		unsigned long nr_segs, loff_t pos)
-+{
-+	struct file *file = iocb->ki_filp;
-+	struct inode *inode = file->f_path.dentry->d_inode;
-+  struct inode *dir   = file->f_path.dentry->d_parent->d_inode;
-+	ssize_t ret = 0;
-+	int err = 0;
-+  
-+  /* This is the place where we create a new version on write -znjp */
-+  if(EXT3COW_S_EPOCHNUMBER(inode->i_sb) > EXT3COW_I_EPOCHNUMBER(inode)){
-+    err = ext3cow_dup_inode(dir, inode);
-+    if(err)
-+      return err;
-+  }
-+
-+	ret = generic_file_aio_write(iocb, iov, nr_segs, pos);
-+
-+	/*
-+	 * Skip flushing if there was an error, or if nothing was written.
-+	 */
-+	if (ret <= 0)
-+		return ret;
-+
-+	/*
-+	 * If the inode is IS_SYNC, or is O_SYNC and we are doing data
-+	 * journalling then we need to make sure that we force the transaction
-+	 * to disk to keep all metadata uptodate synchronously.
-+	 */
-+	if (file->f_flags & O_SYNC) {
-+		/*
-+		 * If we are non-data-journaled, then the dirty data has
-+		 * already been flushed to backing store by generic_osync_inode,
-+		 * and the inode has been flushed too if there have been any
-+		 * modifications other than mere timestamp updates.
-+		 *
-+		 * Open question --- do we care about flushing timestamps too
-+		 * if the inode is IS_SYNC?
-+		 */
-+		if (!ext3cow_should_journal_data(inode))
-+			return ret;
-+
-+		goto force_commit;
-+	}
-+
-+	/*
-+	 * So we know that there has been no forced data flush.  If the inode
-+	 * is marked IS_SYNC, we need to force one ourselves.
-+	 */
-+	if (!IS_SYNC(inode))
-+		return ret;
-+
-+	/*
-+	 * Open question #2 --- should we force data to disk here too?  If we
-+	 * don't, the only impact is that data=writeback filesystems won't
-+	 * flush data to disk automatically on IS_SYNC, only metadata (but
-+	 * historically, that is what ext2 has done.)
-+	 */
-+
-+force_commit:
-+	err = ext3cow_force_commit(inode->i_sb);
-+	if (err)
-+		return err;
-+	return ret;
-+}
-+
-+const struct file_operations ext3cow_file_operations = {
-+	.llseek		= generic_file_llseek,
-+	.read		= do_sync_read,
-+	.write		= do_sync_write,
-+	.aio_read	= generic_file_aio_read,
-+	.aio_write	= ext3cow_file_write,
-+	.ioctl		= ext3cow_ioctl,
-+#ifdef CONFIG_COMPAT
-+	.compat_ioctl	= ext3cow_compat_ioctl,
-+#endif
-+	.mmap		= generic_file_mmap,
-+	.open		= generic_file_open,
-+	.release	= ext3cow_release_file,
-+	.fsync		= ext3cow_sync_file,
-+	.sendfile	= generic_file_sendfile,
-+	.splice_read	= generic_file_splice_read,
-+	.splice_write	= generic_file_splice_write,
-+};
-+
-+struct inode_operations ext3cow_file_inode_operations = {
-+	.truncate	= ext3cow_truncate,
-+	.setattr	= ext3cow_setattr,
-+#ifdef CONFIG_EXT3COW_FS_XATTR
-+	.setxattr	= generic_setxattr,
-+	.getxattr	= generic_getxattr,
-+	.listxattr	= ext3cow_listxattr,
-+	.removexattr	= generic_removexattr,
-+#endif
-+	.permission	= ext3cow_permission,
-+};
-+
-diff -ruN linux-2.6.20.3/fs/ext3cow/fsync.c linux-2.6.20.3-ext3cow/fs/ext3cow/fsync.c
---- linux-2.6.20.3/fs/ext3cow/fsync.c	1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.20.3-ext3cow/fs/ext3cow/fsync.c	2008-03-09 11:14:48.000000000 -0400
-@@ -0,0 +1,88 @@
-+/*
-+ *  linux/fs/ext3cow/fsync.c
-+ *
-+ *  Copyright (C) 1993  Stephen Tweedie (sct@redhat.com)
-+ *  from
-+ *  Copyright (C) 1992  Remy Card (card@masi.ibp.fr)
-+ *                      Laboratoire MASI - Institut Blaise Pascal
-+ *                      Universite Pierre et Marie Curie (Paris VI)
-+ *  from
-+ *  linux/fs/minix/truncate.c   Copyright (C) 1991, 1992  Linus Torvalds
-+ *
-+ *  ext3cowfs fsync primitive
-+ *
-+ *  Big-endian to little-endian byte-swapping/bitmaps by
-+ *        David S. Miller (davem@caip.rutgers.edu), 1995
-+ *
-+ *  Removed unnecessary code duplication for little endian machines
-+ *  and excessive __inline__s.
-+ *        Andi Kleen, 1997
-+ *
-+ * Major simplications and cleanup - we only need to do the metadata, because
-+ * we can depend on generic_block_fdatasync() to sync the data blocks.
-+ */
-+
-+#include <linux/time.h>
-+#include <linux/fs.h>
-+#include <linux/sched.h>
-+#include <linux/writeback.h>
-+#include <linux/jbd.h>
-+#include <linux/ext3cow_fs.h>
-+#include <linux/ext3cow_jbd.h>
-+
-+/*
-+ * akpm: A new design for ext3cow_sync_file().
-+ *
-+ * This is only called from sys_fsync(), sys_fdatasync() and sys_msync().
-+ * There cannot be a transaction open by this task.
-+ * Another task could have dirtied this inode.  Its data can be in any
-+ * state in the journalling system.
-+ *
-+ * What we do is just kick off a commit and wait on it.  This will snapshot the
-+ * inode to disk.
-+ */
-+
-+int ext3cow_sync_file(struct file * file, struct dentry *dentry, int datasync)
-+{
-+	struct inode *inode = dentry->d_inode;
-+	int ret = 0;
-+
-+	J_ASSERT(ext3cow_journal_current_handle() == 0);
-+
-+	/*
-+	 * data=writeback:
-+	 *  The caller's filemap_fdatawrite()/wait will sync the data.
-+	 *  sync_inode() will sync the metadata
-+	 *
-+	 * data=ordered:
-+	 *  The caller's filemap_fdatawrite() will write the data and
-+	 *  sync_inode() will write the inode if it is dirty.  Then the caller's
-+	 *  filemap_fdatawait() will wait on the pages.
-+	 *
-+	 * data=journal:
-+	 *  filemap_fdatawrite won't do anything (the buffers are clean).
-+	 *  ext3cow_force_commit will write the file data into the journal and
-+	 *  will wait on that.
-+	 *  filemap_fdatawait() will encounter a ton of newly-dirtied pages
-+	 *  (they were dirtied by commit).  But that's OK - the blocks are
-+	 *  safe in-journal, which is all fsync() needs to ensure.
-+	 */
-+	if (ext3cow_should_journal_data(inode)) {
-+		ret = ext3cow_force_commit(inode->i_sb);
-+		goto out;
-+	}
-+
-+	/*
-+	 * The VFS has written the file data.  If the inode is unaltered
-+	 * then we need not start a commit.
-+	 */
-+	if (inode->i_state & (I_DIRTY_SYNC|I_DIRTY_DATASYNC)) {
-+		struct writeback_control wbc = {
-+			.sync_mode = WB_SYNC_ALL,
-+			.nr_to_write = 0, /* sys_fsync did this */
-+		};
-+		ret = sync_inode(inode, &wbc);
-+	}
-+out:
-+	return ret;
-+}
-diff -ruN linux-2.6.20.3/fs/ext3cow/hash.c linux-2.6.20.3-ext3cow/fs/ext3cow/hash.c
---- linux-2.6.20.3/fs/ext3cow/hash.c	1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.20.3-ext3cow/fs/ext3cow/hash.c	2008-03-09 11:14:48.000000000 -0400
-@@ -0,0 +1,152 @@
-+/*
-+ *  linux/fs/ext3cow/hash.c
-+ *
-+ * Copyright (C) 2002 by Theodore Ts'o
-+ *
-+ * This file is released under the GPL v2.
-+ *
-+ * This file may be redistributed under the terms of the GNU Public
-+ * License.
-+ */
-+
-+#include <linux/fs.h>
-+#include <linux/jbd.h>
-+#include <linux/sched.h>
-+#include <linux/ext3cow_fs.h>
-+#include <linux/cryptohash.h>
-+
-+#define DELTA 0x9E3779B9
-+
-+static void TEA_transform(__u32 buf[4], __u32 const in[])
-+{
-+	__u32	sum = 0;
-+	__u32	b0 = buf[0], b1 = buf[1];
-+	__u32	a = in[0], b = in[1], c = in[2], d = in[3];
-+	int	n = 16;
-+
-+	do {
-+		sum += DELTA;
-+		b0 += ((b1 << 4)+a) ^ (b1+sum) ^ ((b1 >> 5)+b);
-+		b1 += ((b0 << 4)+c) ^ (b0+sum) ^ ((b0 >> 5)+d);
-+	} while(--n);
-+
-+	buf[0] += b0;
-+	buf[1] += b1;
-+}
-+
-+
-+/* The old legacy hash */
-+static __u32 dx_hack_hash (const char *name, int len)
-+{
-+	__u32 hash0 = 0x12a3fe2d, hash1 = 0x37abe8f9;
-+	while (len--) {
-+		__u32 hash = hash1 + (hash0 ^ (*name++ * 7152373));
-+
-+		if (hash & 0x80000000) hash -= 0x7fffffff;
-+		hash1 = hash0;
-+		hash0 = hash;
-+	}
-+	return (hash0 << 1);
-+}
-+
-+static void str2hashbuf(const char *msg, int len, __u32 *buf, int num)
-+{
-+	__u32	pad, val;
-+	int	i;
-+
-+	pad = (__u32)len | ((__u32)len << 8);
-+	pad |= pad << 16;
-+
-+	val = pad;
-+	if (len > num*4)
-+		len = num * 4;
-+	for (i=0; i < len; i++) {
-+		if ((i % 4) == 0)
-+			val = pad;
-+		val = msg[i] + (val << 8);
-+		if ((i % 4) == 3) {
-+			*buf++ = val;
-+			val = pad;
-+			num--;
-+		}
-+	}
-+	if (--num >= 0)
-+		*buf++ = val;
-+	while (--num >= 0)
-+		*buf++ = pad;
-+}
-+
-+/*
-+ * Returns the hash of a filename.  If len is 0 and name is NULL, then
-+ * this function can be used to test whether or not a hash version is
-+ * supported.
-+ *
-+ * The seed is an 4 longword (32 bits) "secret" which can be used to
-+ * uniquify a hash.  If the seed is all zero's, then some default seed
-+ * may be used.
-+ *
-+ * A particular hash version specifies whether or not the seed is
-+ * represented, and whether or not the returned hash is 32 bits or 64
-+ * bits.  32 bit hashes will return 0 for the minor hash.
-+ */
-+int ext3cowfs_dirhash(const char *name, int len, struct dx_hash_info *hinfo)
-+{
-+	__u32	hash;
-+	__u32	minor_hash = 0;
-+	const char	*p;
-+	int		i;
-+	__u32		in[8], buf[4];
-+
-+	/* Initialize the default seed for the hash checksum functions */
-+	buf[0] = 0x67452301;
-+	buf[1] = 0xefcdab89;
-+	buf[2] = 0x98badcfe;
-+	buf[3] = 0x10325476;
-+
-+	/* Check to see if the seed is all zero's */
-+	if (hinfo->seed) {
-+		for (i=0; i < 4; i++) {
-+			if (hinfo->seed[i])
-+				break;
-+		}
-+		if (i < 4)
-+			memcpy(buf, hinfo->seed, sizeof(buf));
-+	}
-+
-+	switch (hinfo->hash_version) {
-+	case DX_HASH_LEGACY:
-+		hash = dx_hack_hash(name, len);
-+		break;
-+	case DX_HASH_HALF_MD4:
-+		p = name;
-+		while (len > 0) {
-+			str2hashbuf(p, len, in, 8);
-+			half_md4_transform(buf, in);
-+			len -= 32;
-+			p += 32;
-+		}
-+		minor_hash = buf[2];
-+		hash = buf[1];
-+		break;
-+	case DX_HASH_TEA:
-+		p = name;
-+		while (len > 0) {
-+			str2hashbuf(p, len, in, 4);
-+			TEA_transform(buf, in);
-+			len -= 16;
-+			p += 16;
-+		}
-+		hash = buf[0];
-+		minor_hash = buf[1];
-+		break;
-+	default:
-+		hinfo->hash = 0;
-+		return -1;
-+	}
-+	hash = hash & ~1;
-+	if (hash == (EXT3COW_HTREE_EOF << 1))
-+		hash = (EXT3COW_HTREE_EOF-1) << 1;
-+	hinfo->hash = hash;
-+	hinfo->minor_hash = minor_hash;
-+	return 0;
-+}
-diff -ruN linux-2.6.20.3/fs/ext3cow/ialloc.c linux-2.6.20.3-ext3cow/fs/ext3cow/ialloc.c
---- linux-2.6.20.3/fs/ext3cow/ialloc.c	1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.20.3-ext3cow/fs/ext3cow/ialloc.c	2008-03-09 11:14:48.000000000 -0400
-@@ -0,0 +1,764 @@
-+/*
-+ *  linux/fs/ext3cow/ialloc.c
-+ *
-+ * Copyright (C) 1992, 1993, 1994, 1995
-+ * Remy Card (card@masi.ibp.fr)
-+ * Laboratoire MASI - Institut Blaise Pascal
-+ * Universite Pierre et Marie Curie (Paris VI)
-+ *
-+ *  BSD ufs-inspired inode and directory allocation by
-+ *  Stephen Tweedie (sct@redhat.com), 1993
-+ *  Big-endian to little-endian byte-swapping/bitmaps by
-+ *        David S. Miller (davem@caip.rutgers.edu), 1995
-+ */
-+
-+#include <linux/time.h>
-+#include <linux/fs.h>
-+#include <linux/jbd.h>
-+#include <linux/ext3cow_fs.h>
-+#include <linux/ext3cow_jbd.h>
-+#include <linux/stat.h>
-+#include <linux/string.h>
-+#include <linux/quotaops.h>
-+#include <linux/buffer_head.h>
-+#include <linux/random.h>
-+#include <linux/bitops.h>
-+
-+#include <asm/byteorder.h>
-+
-+#include "xattr.h"
-+#include "acl.h"
-+
-+/*
-+ * ialloc.c contains the inodes allocation and deallocation routines
-+ */
-+
-+/*
-+ * The free inodes are managed by bitmaps.  A file system contains several
-+ * blocks groups.  Each group contains 1 bitmap block for blocks, 1 bitmap
-+ * block for inodes, N blocks for the inode table and data blocks.
-+ *
-+ * The file system contains group descriptors which are located after the
-+ * super block.  Each descriptor contains the number of the bitmap block and
-+ * the free blocks count in the block.
-+ */
-+
-+
-+/*
-+ * Read the inode allocation bitmap for a given block_group, reading
-+ * into the specified slot in the superblock's bitmap cache.
-+ *
-+ * Return buffer_head of bitmap on success or NULL.
-+ */
-+static struct buffer_head *
-+read_inode_bitmap(struct super_block * sb, unsigned long block_group)
-+{
-+	struct ext3cow_group_desc *desc;
-+	struct buffer_head *bh = NULL;
-+
-+	desc = ext3cow_get_group_desc(sb, block_group, NULL);
-+	if (!desc)
-+		goto error_out;
-+
-+	bh = sb_bread(sb, le32_to_cpu(desc->bg_inode_bitmap));
-+	if (!bh)
-+		ext3cow_error(sb, "read_inode_bitmap",
-+			    "Cannot read inode bitmap - "
-+			    "block_group = %lu, inode_bitmap = %u",
-+			    block_group, le32_to_cpu(desc->bg_inode_bitmap));
-+error_out:
-+	return bh;
-+}
-+
-+/*
-+ * NOTE! When we get the inode, we're the only people
-+ * that have access to it, and as such there are no
-+ * race conditions we have to worry about. The inode
-+ * is not on the hash-lists, and it cannot be reached
-+ * through the filesystem because the directory entry
-+ * has been deleted earlier.
-+ *
-+ * HOWEVER: we must make sure that we get no aliases,
-+ * which means that we have to call "clear_inode()"
-+ * _before_ we mark the inode not in use in the inode
-+ * bitmaps. Otherwise a newly created file might use
-+ * the same inode number (not actually the same pointer
-+ * though), and then we'd have two inodes sharing the
-+ * same inode number and space on the harddisk.
-+ */
-+void ext3cow_free_inode (handle_t *handle, struct inode * inode)
-+{
-+	struct super_block * sb = inode->i_sb;
-+	int is_directory;
-+	unsigned long ino;
-+	struct buffer_head *bitmap_bh = NULL;
-+	struct buffer_head *bh2;
-+	unsigned long block_group;
-+	unsigned long bit;
-+	struct ext3cow_group_desc * gdp;
-+	struct ext3cow_super_block * es;
-+	struct ext3cow_sb_info *sbi;
-+	int fatal = 0, err;
-+
-+	if (atomic_read(&inode->i_count) > 1) {
-+		printk ("ext3cow_free_inode: inode has count=%d\n",
-+					atomic_read(&inode->i_count));
-+		return;
-+	}
-+	if (inode->i_nlink) {
-+		printk ("ext3cow_free_inode: inode has nlink=%d\n",
-+			inode->i_nlink);
-+		return;
-+	}
-+	if (!sb) {
-+		printk("ext3cow_free_inode: inode on nonexistent device\n");
-+		return;
-+	}
-+	sbi = EXT3COW_SB(sb);
-+
-+	ino = inode->i_ino;
-+	ext3cow_debug ("freeing inode %lu\n", ino);
-+
-+	/*
-+	 * Note: we must free any quota before locking the superblock,
-+	 * as writing the quota to disk may need the lock as well.
-+	 */
-+	DQUOT_INIT(inode);
-+	ext3cow_xattr_delete_inode(handle, inode);
-+	DQUOT_FREE_INODE(inode);
-+	DQUOT_DROP(inode);
-+
-+	is_directory = S_ISDIR(inode->i_mode);
-+
-+	/* Do this BEFORE marking the inode not in use or returning an error */
-+	clear_inode (inode);
-+
-+	es = EXT3COW_SB(sb)->s_es;
-+	if (ino < EXT3COW_FIRST_INO(sb) || ino > le32_to_cpu(es->s_inodes_count)) {
-+		ext3cow_error (sb, "ext3cow_free_inode",
-+			    "reserved or nonexistent inode %lu", ino);
-+		goto error_return;
-+	}
-+	block_group = (ino - 1) / EXT3COW_INODES_PER_GROUP(sb);
-+	bit = (ino - 1) % EXT3COW_INODES_PER_GROUP(sb);
-+	bitmap_bh = read_inode_bitmap(sb, block_group);
-+	if (!bitmap_bh)
-+		goto error_return;
-+
-+	BUFFER_TRACE(bitmap_bh, "get_write_access");
-+	fatal = ext3cow_journal_get_write_access(handle, bitmap_bh);
-+	if (fatal)
-+		goto error_return;
-+
-+	/* Ok, now we can actually update the inode bitmaps.. */
-+	if (!ext3cow_clear_bit_atomic(sb_bgl_lock(sbi, block_group),
-+					bit, bitmap_bh->b_data))
-+		ext3cow_error (sb, "ext3cow_free_inode",
-+			      "bit already cleared for inode %lu", ino);
-+	else {
-+		gdp = ext3cow_get_group_desc (sb, block_group, &bh2);
-+
-+		BUFFER_TRACE(bh2, "get_write_access");
-+		fatal = ext3cow_journal_get_write_access(handle, bh2);
-+		if (fatal) goto error_return;
-+
-+		if (gdp) {
-+			spin_lock(sb_bgl_lock(sbi, block_group));
-+			gdp->bg_free_inodes_count = cpu_to_le16(
-+				le16_to_cpu(gdp->bg_free_inodes_count) + 1);
-+			if (is_directory)
-+				gdp->bg_used_dirs_count = cpu_to_le16(
-+				  le16_to_cpu(gdp->bg_used_dirs_count) - 1);
-+			spin_unlock(sb_bgl_lock(sbi, block_group));
-+			percpu_counter_inc(&sbi->s_freeinodes_counter);
-+			if (is_directory)
-+				percpu_counter_dec(&sbi->s_dirs_counter);
-+
-+		}
-+		BUFFER_TRACE(bh2, "call ext3cow_journal_dirty_metadata");
-+		err = ext3cow_journal_dirty_metadata(handle, bh2);
-+		if (!fatal) fatal = err;
-+	}
-+	BUFFER_TRACE(bitmap_bh, "call ext3cow_journal_dirty_metadata");
-+	err = ext3cow_journal_dirty_metadata(handle, bitmap_bh);
-+	if (!fatal)
-+		fatal = err;
-+	sb->s_dirt = 1;
-+error_return:
-+	brelse(bitmap_bh);
-+	ext3cow_std_error(sb, fatal);
-+}
-+
-+/*
-+ * There are two policies for allocating an inode.  If the new inode is
-+ * a directory, then a forward search is made for a block group with both
-+ * free space and a low directory-to-inode ratio; if that fails, then of
-+ * the groups with above-average free space, that group with the fewest
-+ * directories already is chosen.
-+ *
-+ * For other inodes, search forward from the parent directory\'s block
-+ * group to find a free inode.
-+ */
-+static int find_group_dir(struct super_block *sb, struct inode *parent)
-+{
-+	int ngroups = EXT3COW_SB(sb)->s_groups_count;
-+	unsigned int freei, avefreei;
-+	struct ext3cow_group_desc *desc, *best_desc = NULL;
-+	struct buffer_head *bh;
-+	int group, best_group = -1;
-+
-+	freei = percpu_counter_read_positive(&EXT3COW_SB(sb)->s_freeinodes_counter);
-+	avefreei = freei / ngroups;
-+
-+	for (group = 0; group < ngroups; group++) {
-+		desc = ext3cow_get_group_desc (sb, group, &bh);
-+		if (!desc || !desc->bg_free_inodes_count)
-+			continue;
-+		if (le16_to_cpu(desc->bg_free_inodes_count) < avefreei)
-+			continue;
-+		if (!best_desc ||
-+		    (le16_to_cpu(desc->bg_free_blocks_count) >
-+		     le16_to_cpu(best_desc->bg_free_blocks_count))) {
-+			best_group = group;
-+			best_desc = desc;
-+		}
-+	}
-+	return best_group;
-+}
-+
-+/*
-+ * Orlov's allocator for directories.
-+ *
-+ * We always try to spread first-level directories.
-+ *
-+ * If there are blockgroups with both free inodes and free blocks counts
-+ * not worse than average we return one with smallest directory count.
-+ * Otherwise we simply return a random group.
-+ *
-+ * For the rest rules look so:
-+ *
-+ * It's OK to put directory into a group unless
-+ * it has too many directories already (max_dirs) or
-+ * it has too few free inodes left (min_inodes) or
-+ * it has too few free blocks left (min_blocks) or
-+ * it's already running too large debt (max_debt).
-+ * Parent's group is prefered, if it doesn't satisfy these
-+ * conditions we search cyclically through the rest. If none
-+ * of the groups look good we just look for a group with more
-+ * free inodes than average (starting at parent's group).
-+ *
-+ * Debt is incremented each time we allocate a directory and decremented
-+ * when we allocate an inode, within 0--255.
-+ */
-+
-+#define INODE_COST 64
-+#define BLOCK_COST 256
-+
-+static int find_group_orlov(struct super_block *sb, struct inode *parent)
-+{
-+	int parent_group = EXT3COW_I(parent)->i_block_group;
-+	struct ext3cow_sb_info *sbi = EXT3COW_SB(sb);
-+	struct ext3cow_super_block *es = sbi->s_es;
-+	int ngroups = sbi->s_groups_count;
-+	int inodes_per_group = EXT3COW_INODES_PER_GROUP(sb);
-+	unsigned int freei, avefreei;
-+	ext3cow_fsblk_t freeb, avefreeb;
-+	ext3cow_fsblk_t blocks_per_dir;
-+	unsigned int ndirs;
-+	int max_debt, max_dirs, min_inodes;
-+	ext3cow_grpblk_t min_blocks;
-+	int group = -1, i;
-+	struct ext3cow_group_desc *desc;
-+	struct buffer_head *bh;
-+
-+	freei = percpu_counter_read_positive(&sbi->s_freeinodes_counter);
-+	avefreei = freei / ngroups;
-+	freeb = percpu_counter_read_positive(&sbi->s_freeblocks_counter);
-+	avefreeb = freeb / ngroups;
-+	ndirs = percpu_counter_read_positive(&sbi->s_dirs_counter);
-+
-+	if ((parent == sb->s_root->d_inode) ||
-+	    (EXT3COW_I(parent)->i_flags & EXT3COW_TOPDIR_FL)) {
-+		int best_ndir = inodes_per_group;
-+		int best_group = -1;
-+
-+		get_random_bytes(&group, sizeof(group));
-+		parent_group = (unsigned)group % ngroups;
-+		for (i = 0; i < ngroups; i++) {
-+			group = (parent_group + i) % ngroups;
-+			desc = ext3cow_get_group_desc (sb, group, &bh);
-+			if (!desc || !desc->bg_free_inodes_count)
-+				continue;
-+			if (le16_to_cpu(desc->bg_used_dirs_count) >= best_ndir)
-+				continue;
-+			if (le16_to_cpu(desc->bg_free_inodes_count) < avefreei)
-+				continue;
-+			if (le16_to_cpu(desc->bg_free_blocks_count) < avefreeb)
-+				continue;
-+			best_group = group;
-+			best_ndir = le16_to_cpu(desc->bg_used_dirs_count);
-+		}
-+		if (best_group >= 0)
-+			return best_group;
-+		goto fallback;
-+	}
-+
-+	blocks_per_dir = (le32_to_cpu(es->s_blocks_count) - freeb) / ndirs;
-+
-+	max_dirs = ndirs / ngroups + inodes_per_group / 16;
-+	min_inodes = avefreei - inodes_per_group / 4;
-+	min_blocks = avefreeb - EXT3COW_BLOCKS_PER_GROUP(sb) / 4;
-+
-+	max_debt = EXT3COW_BLOCKS_PER_GROUP(sb) / max(blocks_per_dir, (ext3cow_fsblk_t)BLOCK_COST);
-+	if (max_debt * INODE_COST > inodes_per_group)
-+		max_debt = inodes_per_group / INODE_COST;
-+	if (max_debt > 255)
-+		max_debt = 255;
-+	if (max_debt == 0)
-+		max_debt = 1;
-+
-+	for (i = 0; i < ngroups; i++) {
-+		group = (parent_group + i) % ngroups;
-+		desc = ext3cow_get_group_desc (sb, group, &bh);
-+		if (!desc || !desc->bg_free_inodes_count)
-+			continue;
-+		if (le16_to_cpu(desc->bg_used_dirs_count) >= max_dirs)
-+			continue;
-+		if (le16_to_cpu(desc->bg_free_inodes_count) < min_inodes)
-+			continue;
-+		if (le16_to_cpu(desc->bg_free_blocks_count) < min_blocks)
-+			continue;
-+		return group;
-+	}
-+
-+fallback:
-+	for (i = 0; i < ngroups; i++) {
-+		group = (parent_group + i) % ngroups;
-+		desc = ext3cow_get_group_desc (sb, group, &bh);
-+		if (!desc || !desc->bg_free_inodes_count)
-+			continue;
-+		if (le16_to_cpu(desc->bg_free_inodes_count) >= avefreei)
-+			return group;
-+	}
-+
-+	if (avefreei) {
-+		/*
-+		 * The free-inodes counter is approximate, and for really small
-+		 * filesystems the above test can fail to find any blockgroups
-+		 */
-+		avefreei = 0;
-+		goto fallback;
-+	}
-+
-+	return -1;
-+}
-+
-+static int find_group_other(struct super_block *sb, struct inode *parent)
-+{
-+	int parent_group = EXT3COW_I(parent)->i_block_group;
-+	int ngroups = EXT3COW_SB(sb)->s_groups_count;
-+	struct ext3cow_group_desc *desc;
-+	struct buffer_head *bh;
-+	int group, i;
-+
-+	/*
-+	 * Try to place the inode in its parent directory
-+	 */
-+	group = parent_group;
-+	desc = ext3cow_get_group_desc (sb, group, &bh);
-+	if (desc && le16_to_cpu(desc->bg_free_inodes_count) &&
-+			le16_to_cpu(desc->bg_free_blocks_count))
-+		return group;
-+
-+	/*
-+	 * We're going to place this inode in a different blockgroup from its
-+	 * parent.  We want to cause files in a common directory to all land in
-+	 * the same blockgroup.  But we want files which are in a different
-+	 * directory which shares a blockgroup with our parent to land in a
-+	 * different blockgroup.
-+	 *
-+	 * So add our directory's i_ino into the starting point for the hash.
-+	 */
-+	group = (group + parent->i_ino) % ngroups;
-+
-+	/*
-+	 * Use a quadratic hash to find a group with a free inode and some free
-+	 * blocks.
-+	 */
-+	for (i = 1; i < ngroups; i <<= 1) {
-+		group += i;
-+		if (group >= ngroups)
-+			group -= ngroups;
-+		desc = ext3cow_get_group_desc (sb, group, &bh);
-+		if (desc && le16_to_cpu(desc->bg_free_inodes_count) &&
-+				le16_to_cpu(desc->bg_free_blocks_count))
-+			return group;
-+	}
-+
-+	/*
-+	 * That failed: try linear search for a free inode, even if that group
-+	 * has no free blocks.
-+	 */
-+	group = parent_group;
-+	for (i = 0; i < ngroups; i++) {
-+		if (++group >= ngroups)
-+			group = 0;
-+		desc = ext3cow_get_group_desc (sb, group, &bh);
-+		if (desc && le16_to_cpu(desc->bg_free_inodes_count))
-+			return group;
-+	}
-+
-+	return -1;
-+}
-+
-+/*
-+ * There are two policies for allocating an inode.  If the new inode is
-+ * a directory, then a forward search is made for a block group with both
-+ * free space and a low directory-to-inode ratio; if that fails, then of
-+ * the groups with above-average free space, that group with the fewest
-+ * directories already is chosen.
-+ *
-+ * For other inodes, search forward from the parent directory's block
-+ * group to find a free inode.
-+ */
-+struct inode *ext3cow_new_inode(handle_t *handle, struct inode * dir, int mode)
-+{
-+	struct super_block *sb;
-+	struct buffer_head *bitmap_bh = NULL;
-+	struct buffer_head *bh2;
-+	int group;
-+	unsigned long ino = 0;
-+	struct inode * inode;
-+	struct ext3cow_group_desc * gdp = NULL;
-+	struct ext3cow_super_block * es;
-+	struct ext3cow_inode_info *ei;
-+	struct ext3cow_sb_info *sbi;
-+	int err = 0;
-+	struct inode *ret;
-+	int i;
-+
-+	/* Cannot create files in a deleted directory */
-+	if (!dir || !dir->i_nlink)
-+		return ERR_PTR(-EPERM);
-+
-+	sb = dir->i_sb;
-+	inode = new_inode(sb);
-+	if (!inode)
-+		return ERR_PTR(-ENOMEM);
-+	ei = EXT3COW_I(inode);
-+
-+	sbi = EXT3COW_SB(sb);
-+	es = sbi->s_es;
-+	if (S_ISDIR(mode)) {
-+		if (test_opt (sb, OLDALLOC))
-+			group = find_group_dir(sb, dir);
-+		else
-+			group = find_group_orlov(sb, dir);
-+	} else
-+		group = find_group_other(sb, dir);
-+
-+	err = -ENOSPC;
-+	if (group == -1)
-+		goto out;
-+
-+	for (i = 0; i < sbi->s_groups_count; i++) {
-+		err = -EIO;
-+
-+		gdp = ext3cow_get_group_desc(sb, group, &bh2);
-+		if (!gdp)
-+			goto fail;
-+
-+		brelse(bitmap_bh);
-+		bitmap_bh = read_inode_bitmap(sb, group);
-+		if (!bitmap_bh)
-+			goto fail;
-+
-+		ino = 0;
-+
-+repeat_in_this_group:
-+		ino = ext3cow_find_next_zero_bit((unsigned long *)
-+				bitmap_bh->b_data, EXT3COW_INODES_PER_GROUP(sb), ino);
-+		if (ino < EXT3COW_INODES_PER_GROUP(sb)) {
-+
-+			BUFFER_TRACE(bitmap_bh, "get_write_access");
-+			err = ext3cow_journal_get_write_access(handle, bitmap_bh);
-+			if (err)
-+				goto fail;
-+
-+			if (!ext3cow_set_bit_atomic(sb_bgl_lock(sbi, group),
-+						ino, bitmap_bh->b_data)) {
-+				/* we won it */
-+				BUFFER_TRACE(bitmap_bh,
-+					"call ext3cow_journal_dirty_metadata");
-+				err = ext3cow_journal_dirty_metadata(handle,
-+								bitmap_bh);
-+				if (err)
-+					goto fail;
-+				goto got;
-+			}
-+			/* we lost it */
-+			journal_release_buffer(handle, bitmap_bh);
-+
-+			if (++ino < EXT3COW_INODES_PER_GROUP(sb))
-+				goto repeat_in_this_group;
-+		}
-+
-+		/*
-+		 * This case is possible in concurrent environment.  It is very
-+		 * rare.  We cannot repeat the find_group_xxx() call because
-+		 * that will simply return the same blockgroup, because the
-+		 * group descriptor metadata has not yet been updated.
-+		 * So we just go onto the next blockgroup.
-+		 */
-+		if (++group == sbi->s_groups_count)
-+			group = 0;
-+	}
-+	err = -ENOSPC;
-+	goto out;
-+
-+got:
-+	ino += group * EXT3COW_INODES_PER_GROUP(sb) + 1;
-+	if (ino < EXT3COW_FIRST_INO(sb) || ino > le32_to_cpu(es->s_inodes_count)) {
-+		ext3cow_error (sb, "ext3cow_new_inode",
-+			    "reserved inode or inode > inodes count - "
-+			    "block_group = %d, inode=%lu", group, ino);
-+		err = -EIO;
-+		goto fail;
-+	}
-+
-+	BUFFER_TRACE(bh2, "get_write_access");
-+	err = ext3cow_journal_get_write_access(handle, bh2);
-+	if (err) goto fail;
-+	spin_lock(sb_bgl_lock(sbi, group));
-+	gdp->bg_free_inodes_count =
-+		cpu_to_le16(le16_to_cpu(gdp->bg_free_inodes_count) - 1);
-+	if (S_ISDIR(mode)) {
-+		gdp->bg_used_dirs_count =
-+			cpu_to_le16(le16_to_cpu(gdp->bg_used_dirs_count) + 1);
-+	}
-+	spin_unlock(sb_bgl_lock(sbi, group));
-+	BUFFER_TRACE(bh2, "call ext3cow_journal_dirty_metadata");
-+	err = ext3cow_journal_dirty_metadata(handle, bh2);
-+	if (err) goto fail;
-+
-+	percpu_counter_dec(&sbi->s_freeinodes_counter);
-+	if (S_ISDIR(mode))
-+		percpu_counter_inc(&sbi->s_dirs_counter);
-+	sb->s_dirt = 1;
-+
-+	inode->i_uid = current->fsuid;
-+	if (test_opt (sb, GRPID))
-+		inode->i_gid = dir->i_gid;
-+	else if (dir->i_mode & S_ISGID) {
-+		inode->i_gid = dir->i_gid;
-+		if (S_ISDIR(mode))
-+			mode |= S_ISGID;
-+	} else
-+		inode->i_gid = current->fsgid;
-+	inode->i_mode = mode;
-+
-+	inode->i_ino = ino;
-+	/* This is the optimal IO size (for stat), not the fs block size */
-+	inode->i_blocks = 0;
-+	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
-+
-+  /* For versioning -znjp */
-+  ei->i_cow_bitmap   = 0x0000;
-+  ei->i_epoch_number = EXT3COW_S_EPOCHNUMBER(dir->i_sb);
-+  ei->i_next_inode   = 0;
-+
-+	memset(ei->i_data, 0, sizeof(ei->i_data));
-+	ei->i_dir_start_lookup = 0;
-+	ei->i_disksize = 0;
-+
-+	ei->i_flags = EXT3COW_I(dir)->i_flags & ~EXT3COW_INDEX_FL;
-+	if (S_ISLNK(mode))
-+		ei->i_flags &= ~(EXT3COW_IMMUTABLE_FL|EXT3COW_APPEND_FL);
-+	/* dirsync only applies to directories */
-+	if (!S_ISDIR(mode))
-+		ei->i_flags &= ~EXT3COW_DIRSYNC_FL;
-+#ifdef EXT3COW_FRAGMENTS
-+  /* Taken out for versioning -znjp */
-+	//ei->i_faddr = 0;
-+	//ei->i_frag_no = 0;
-+	//ei->i_frag_size = 0;
-+#endif
-+	ei->i_file_acl = 0;
-+	ei->i_dir_acl = 0;
-+	ei->i_dtime = 0;
-+	ei->i_block_alloc_info = NULL;
-+	ei->i_block_group = group;
-+
-+	ext3cow_set_inode_flags(inode);
-+	if (IS_DIRSYNC(inode))
-+		handle->h_sync = 1;
-+	insert_inode_hash(inode);
-+	spin_lock(&sbi->s_next_gen_lock);
-+	inode->i_generation = sbi->s_next_generation++;
-+	spin_unlock(&sbi->s_next_gen_lock);
-+
-+	ei->i_state = EXT3COW_STATE_NEW;
-+	ei->i_extra_isize =
-+		(EXT3COW_INODE_SIZE(inode->i_sb) > EXT3COW_GOOD_OLD_INODE_SIZE) ?
-+		sizeof(struct ext3cow_inode) - EXT3COW_GOOD_OLD_INODE_SIZE : 0;
-+
-+	ret = inode;
-+	if(DQUOT_ALLOC_INODE(inode)) {
-+		err = -EDQUOT;
-+		goto fail_drop;
-+	}
-+
-+	err = ext3cow_init_acl(handle, inode, dir);
-+	if (err)
-+		goto fail_free_drop;
-+
-+	err = ext3cow_init_security(handle,inode, dir);
-+	if (err)
-+		goto fail_free_drop;
-+
-+	err = ext3cow_mark_inode_dirty(handle, inode);
-+	if (err) {
-+		ext3cow_std_error(sb, err);
-+		goto fail_free_drop;
-+	}
-+
-+	ext3cow_debug("allocating inode %lu\n", inode->i_ino);
-+	goto really_out;
-+fail:
-+	ext3cow_std_error(sb, err);
-+out:
-+	iput(inode);
-+	ret = ERR_PTR(err);
-+really_out:
-+	brelse(bitmap_bh);
-+	return ret;
-+
-+fail_free_drop:
-+	DQUOT_FREE_INODE(inode);
-+
-+fail_drop:
-+	DQUOT_DROP(inode);
-+	inode->i_flags |= S_NOQUOTA;
-+	inode->i_nlink = 0;
-+	iput(inode);
-+	brelse(bitmap_bh);
-+	return ERR_PTR(err);
-+}
-+
-+/* Verify that we are loading a valid orphan from disk */
-+struct inode *ext3cow_orphan_get(struct super_block *sb, unsigned long ino)
-+{
-+	unsigned long max_ino = le32_to_cpu(EXT3COW_SB(sb)->s_es->s_inodes_count);
-+	unsigned long block_group;
-+	int bit;
-+	struct buffer_head *bitmap_bh = NULL;
-+	struct inode *inode = NULL;
-+
-+	/* Error cases - e2fsck has already cleaned up for us */
-+	if (ino > max_ino) {
-+		ext3cow_warning(sb, __FUNCTION__,
-+			     "bad orphan ino %lu!  e2fsck was run?", ino);
-+		goto out;
-+	}
-+
-+	block_group = (ino - 1) / EXT3COW_INODES_PER_GROUP(sb);
-+	bit = (ino - 1) % EXT3COW_INODES_PER_GROUP(sb);
-+	bitmap_bh = read_inode_bitmap(sb, block_group);
-+	if (!bitmap_bh) {
-+		ext3cow_warning(sb, __FUNCTION__,
-+			     "inode bitmap error for orphan %lu", ino);
-+		goto out;
-+	}
-+
-+	/* Having the inode bit set should be a 100% indicator that this
-+	 * is a valid orphan (no e2fsck run on fs).  Orphans also include
-+	 * inodes that were being truncated, so we can't check i_nlink==0.
-+	 */
-+	if (!ext3cow_test_bit(bit, bitmap_bh->b_data) ||
-+			!(inode = iget(sb, ino)) || is_bad_inode(inode) ||
-+			NEXT_ORPHAN(inode) > max_ino) {
-+		ext3cow_warning(sb, __FUNCTION__,
-+			     "bad orphan inode %lu!  e2fsck was run?", ino);
-+		printk(KERN_NOTICE "ext3cow_test_bit(bit=%d, block=%llu) = %d\n",
-+		       bit, (unsigned long long)bitmap_bh->b_blocknr,
-+		       ext3cow_test_bit(bit, bitmap_bh->b_data));
-+		printk(KERN_NOTICE "inode=%p\n", inode);
-+		if (inode) {
-+			printk(KERN_NOTICE "is_bad_inode(inode)=%d\n",
-+			       is_bad_inode(inode));
-+			printk(KERN_NOTICE "NEXT_ORPHAN(inode)=%u\n",
-+			       NEXT_ORPHAN(inode));
-+			printk(KERN_NOTICE "max_ino=%lu\n", max_ino);
-+		}
-+		/* Avoid freeing blocks if we got a bad deleted inode */
-+		if (inode && inode->i_nlink == 0)
-+			inode->i_blocks = 0;
-+		iput(inode);
-+		inode = NULL;
-+	}
-+out:
-+	brelse(bitmap_bh);
-+	return inode;
-+}
-+
-+unsigned long ext3cow_count_free_inodes (struct super_block * sb)
-+{
-+	unsigned long desc_count;
-+	struct ext3cow_group_desc *gdp;
-+	int i;
-+#ifdef EXT3COWFS_DEBUG
-+	struct ext3cow_super_block *es;
-+	unsigned long bitmap_count, x;
-+	struct buffer_head *bitmap_bh = NULL;
-+
-+	es = EXT3COW_SB(sb)->s_es;
-+	desc_count = 0;
-+	bitmap_count = 0;
-+	gdp = NULL;
-+	for (i = 0; i < EXT3COW_SB(sb)->s_groups_count; i++) {
-+		gdp = ext3cow_get_group_desc (sb, i, NULL);
-+		if (!gdp)
-+			continue;
-+		desc_count += le16_to_cpu(gdp->bg_free_inodes_count);
-+		brelse(bitmap_bh);
-+		bitmap_bh = read_inode_bitmap(sb, i);
-+		if (!bitmap_bh)
-+			continue;
-+
-+		x = ext3cow_count_free(bitmap_bh, EXT3COW_INODES_PER_GROUP(sb) / 8);
-+		printk("group %d: stored = %d, counted = %lu\n",
-+			i, le16_to_cpu(gdp->bg_free_inodes_count), x);
-+		bitmap_count += x;
-+	}
-+	brelse(bitmap_bh);
-+	printk("ext3cow_count_free_inodes: stored = %u, computed = %lu, %lu\n",
-+		le32_to_cpu(es->s_free_inodes_count), desc_count, bitmap_count);
-+	return desc_count;
-+#else
-+	desc_count = 0;
-+	for (i = 0; i < EXT3COW_SB(sb)->s_groups_count; i++) {
-+		gdp = ext3cow_get_group_desc (sb, i, NULL);
-+		if (!gdp)
-+			continue;
-+		desc_count += le16_to_cpu(gdp->bg_free_inodes_count);
-+		cond_resched();
-+	}
-+	return desc_count;
-+#endif
-+}
-+
-+/* Called at mount-time, super-block is locked */
-+unsigned long ext3cow_count_dirs (struct super_block * sb)
-+{
-+	unsigned long count = 0;
-+	int i;
-+
-+	for (i = 0; i < EXT3COW_SB(sb)->s_groups_count; i++) {
-+		struct ext3cow_group_desc *gdp = ext3cow_get_group_desc (sb, i, NULL);
-+		if (!gdp)
-+			continue;
-+		count += le16_to_cpu(gdp->bg_used_dirs_count);
-+	}
-+	return count;
-+}
-+
-diff -ruN linux-2.6.20.3/fs/ext3cow/inode.c linux-2.6.20.3-ext3cow/fs/ext3cow/inode.c
---- linux-2.6.20.3/fs/ext3cow/inode.c	1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.20.3-ext3cow/fs/ext3cow/inode.c	2008-03-09 11:14:48.000000000 -0400
-@@ -0,0 +1,3502 @@
-+/*
-+ *  linux/fs/ext3cow/inode.c
-+ *
-+ * Copyright (C) 1992, 1993, 1994, 1995
-+ * Remy Card (card@masi.ibp.fr)
-+ * Laboratoire MASI - Institut Blaise Pascal
-+ * Universite Pierre et Marie Curie (Paris VI)
-+ *
-+ *  from
-+ *
-+ *  linux/fs/minix/inode.c
-+ *
-+ *  Copyright (C) 1991, 1992  Linus Torvalds
-+ *
-+ *  Goal-directed block allocation by Stephen Tweedie
-+ *	(sct@redhat.com), 1993, 1998
-+ *  Big-endian to little-endian byte-swapping/bitmaps by
-+ *        David S. Miller (davem@caip.rutgers.edu), 1995
-+ *  64-bit file support on 64-bit platforms by Jakub Jelinek
-+ *	(jj@sunsite.ms.mff.cuni.cz)
-+ *
-+ *  Assorted race fixes, rewrite of ext3cow_get_block() by Al Viro, 2000
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/fs.h>
-+#include <linux/time.h>
-+#include <linux/ext3cow_jbd.h>
-+#include <linux/jbd.h>
-+#include <linux/smp_lock.h>
-+#include <linux/highuid.h>
-+#include <linux/pagemap.h>
-+#include <linux/quotaops.h>
-+#include <linux/string.h>
-+#include <linux/buffer_head.h>
-+#include <linux/writeback.h>
-+#include <linux/mpage.h>
-+#include <linux/uio.h>
-+#include <linux/bio.h>
-+#include "xattr.h"
-+#include "acl.h"
-+
-+static int ext3cow_writepage_trans_blocks(struct inode *inode);
-+
-+/*
-+ * Test whether an inode is a fast symlink.
-+ */
-+static int ext3cow_inode_is_fast_symlink(struct inode *inode)
-+{
-+	int ea_blocks = EXT3COW_I(inode)->i_file_acl ?
-+		(inode->i_sb->s_blocksize >> 9) : 0;
-+
-+	return (S_ISLNK(inode->i_mode) && inode->i_blocks - ea_blocks == 0);
-+}
-+
-+/*
-+ * The ext3cow forget function must perform a revoke if we are freeing data
-+ * which has been journaled.  Metadata (eg. indirect blocks) must be
-+ * revoked in all cases.
-+ *
-+ * "bh" may be NULL: a metadata block may have been freed from memory
-+ * but there may still be a record of it in the journal, and that record
-+ * still needs to be revoked.
-+ */
-+int ext3cow_forget(handle_t *handle, int is_metadata, struct inode *inode,
-+			struct buffer_head *bh, ext3cow_fsblk_t blocknr)
-+{
-+	int err;
-+
-+	might_sleep();
-+
-+	BUFFER_TRACE(bh, "enter");
-+
-+	jbd_debug(4, "forgetting bh %p: is_metadata = %d, mode %o, "
-+		  "data mode %lx\n",
-+		  bh, is_metadata, inode->i_mode,
-+		  test_opt(inode->i_sb, DATA_FLAGS));
-+
-+	/* Never use the revoke function if we are doing full data
-+	 * journaling: there is no need to, and a V1 superblock won't
-+	 * support it.  Otherwise, only skip the revoke on un-journaled
-+	 * data blocks. */
-+
-+	if (test_opt(inode->i_sb, DATA_FLAGS) == EXT3COW_MOUNT_JOURNAL_DATA ||
-+	    (!is_metadata && !ext3cow_should_journal_data(inode))) {
-+		if (bh) {
-+			BUFFER_TRACE(bh, "call journal_forget");
-+			return ext3cow_journal_forget(handle, bh);
-+		}
-+		return 0;
-+	}
-+
-+	/*
-+	 * data!=journal && (is_metadata || should_journal_data(inode))
-+	 */
-+	BUFFER_TRACE(bh, "call ext3cow_journal_revoke");
-+	err = ext3cow_journal_revoke(handle, blocknr, bh);
-+	if (err)
-+		ext3cow_abort(inode->i_sb, __FUNCTION__,
-+			   "error %d when attempting revoke", err);
-+	BUFFER_TRACE(bh, "exit");
-+	return err;
-+}
-+
-+/*
-+ * Work out how many blocks we need to proceed with the next chunk of a
-+ * truncate transaction.
-+ */
-+static unsigned long blocks_for_truncate(struct inode *inode)
-+{
-+	unsigned long needed;
-+
-+	needed = inode->i_blocks >> (inode->i_sb->s_blocksize_bits - 9);
-+
-+	/* Give ourselves just enough room to cope with inodes in which
-+	 * i_blocks is corrupt: we've seen disk corruptions in the past
-+	 * which resulted in random data in an inode which looked enough
-+	 * like a regular file for ext3cow to try to delete it.  Things
-+	 * will go a bit crazy if that happens, but at least we should
-+	 * try not to panic the whole kernel. */
-+	if (needed < 2)
-+		needed = 2;
-+
-+	/* But we need to bound the transaction so we don't overflow the
-+	 * journal. */
-+	if (needed > EXT3COW_MAX_TRANS_DATA)
-+		needed = EXT3COW_MAX_TRANS_DATA;
-+
-+	return EXT3COW_DATA_TRANS_BLOCKS(inode->i_sb) + needed;
-+}
-+
-+/*
-+ * Truncate transactions can be complex and absolutely huge.  So we need to
-+ * be able to restart the transaction at a conventient checkpoint to make
-+ * sure we don't overflow the journal.
-+ *
-+ * start_transaction gets us a new handle for a truncate transaction,
-+ * and extend_transaction tries to extend the existing one a bit.  If
-+ * extend fails, we need to propagate the failure up and restart the
-+ * transaction in the top-level truncate loop. --sct
-+ */
-+static handle_t *start_transaction(struct inode *inode)
-+{
-+	handle_t *result;
-+
-+	result = ext3cow_journal_start(inode, blocks_for_truncate(inode));
-+	if (!IS_ERR(result))
-+		return result;
-+
-+	ext3cow_std_error(inode->i_sb, PTR_ERR(result));
-+	return result;
-+}
-+
-+/*
-+ * Try to extend this transaction for the purposes of truncation.
-+ *
-+ * Returns 0 if we managed to create more room.  If we can't create more
-+ * room, and the transaction must be restarted we return 1.
-+ */
-+static int try_to_extend_transaction(handle_t *handle, struct inode *inode)
-+{
-+	if (handle->h_buffer_credits > EXT3COW_RESERVE_TRANS_BLOCKS)
-+		return 0;
-+	if (!ext3cow_journal_extend(handle, blocks_for_truncate(inode)))
-+		return 0;
-+	return 1;
-+}
-+
-+/*
-+ * Restart the transaction associated with *handle.  This does a commit,
-+ * so before we call here everything must be consistently dirtied against
-+ * this transaction.
-+ */
-+static int ext3cow_journal_test_restart(handle_t *handle, struct inode *inode)
-+{
-+	jbd_debug(2, "restarting handle %p\n", handle);
-+	return ext3cow_journal_restart(handle, blocks_for_truncate(inode));
-+}
-+
-+/*
-+ * Called at the last iput() if i_nlink is zero.
-+ */
-+void ext3cow_delete_inode (struct inode * inode)
-+{
-+	handle_t *handle;
-+
-+	truncate_inode_pages(&inode->i_data, 0);
-+
-+	if (is_bad_inode(inode))
-+		goto no_delete;
-+
-+	handle = start_transaction(inode);
-+	if (IS_ERR(handle)) {
-+		/*
-+		 * If we're going to skip the normal cleanup, we still need to
-+		 * make sure that the in-core orphan linked list is properly
-+		 * cleaned up.
-+		 */
-+		ext3cow_orphan_del(NULL, inode);
-+		goto no_delete;
-+	}
-+
-+	if (IS_SYNC(inode))
-+		handle->h_sync = 1;
-+	inode->i_size = 0;
-+	if (inode->i_blocks)
-+		ext3cow_truncate(inode);
-+	/*
-+	 * Kill off the orphan record which ext3cow_truncate created.
-+	 * AKPM: I think this can be inside the above `if'.
-+	 * Note that ext3cow_orphan_del() has to be able to cope with the
-+	 * deletion of a non-existent orphan - this is because we don't
-+	 * know if ext3cow_truncate() actually created an orphan record.
-+	 * (Well, we could do this if we need to, but heck - it works)
-+	 */
-+	ext3cow_orphan_del(handle, inode);
-+	EXT3COW_I(inode)->i_dtime	= get_seconds();
-+
-+	/*
-+	 * One subtle ordering requirement: if anything has gone wrong
-+	 * (transaction abort, IO errors, whatever), then we can still
-+	 * do these next steps (the fs will already have been marked as
-+	 * having errors), but we can't free the inode if the mark_dirty
-+	 * fails.
-+	 */
-+	if (ext3cow_mark_inode_dirty(handle, inode))
-+		/* If that failed, just do the required in-core inode clear. */
-+		clear_inode(inode);
-+	else
-+		ext3cow_free_inode(handle, inode);
-+	ext3cow_journal_stop(handle);
-+	return;
-+no_delete:
-+	clear_inode(inode);	/* We must guarantee clearing of inode... */
-+}
-+
-+typedef struct {
-+	__le32	*p;
-+	__le32	key;
-+	struct buffer_head *bh;
-+} Indirect;
-+
-+static inline void add_chain(Indirect *p, struct buffer_head *bh, __le32 *v)
-+{
-+	p->key = *(p->p = v);
-+	p->bh = bh;
-+}
-+
-+static int verify_chain(Indirect *from, Indirect *to)
-+{
-+	while (from <= to && from->key == *from->p)
-+		from++;
-+	return (from > to);
-+}
-+
-+//TODO: Delete at some point
-+/* znjp - used for bitmap testing */
-+
-+ static void printbin(u32 val, int size) {
-+  u32 mask;
-+  
-+  mask=(1UL << (size-1));
-+  while (mask) {
-+    if (mask & val) 
-+      printk("1");
-+    else 
-+      printk("0");
-+    mask /= 2;
-+  }
-+  printk("\n");
-+ 
-+ }
-+
-+
-+/**
-+ *	ext3cow_block_to_path - parse the block number into array of offsets
-+ *	@inode: inode in question (we are only interested in its superblock)
-+ *	@i_block: block number to be parsed
-+ *	@offsets: array to store the offsets in
-+ *      @boundary: set this non-zero if the referred-to block is likely to be
-+ *             followed (on disk) by an indirect block.
-+ *
-+ *	To store the locations of file's data ext3cow uses a data structure common
-+ *	for UNIX filesystems - tree of pointers anchored in the inode, with
-+ *	data blocks at leaves and indirect blocks in intermediate nodes.
-+ *	This function translates the block number into path in that tree -
-+ *	return value is the path length and @offsets[n] is the offset of
-+ *	pointer to (n+1)th node in the nth one. If @block is out of range
-+ *	(negative or too large) warning is printed and zero returned.
-+ *
-+ *	Note: function doesn't find node addresses, so no IO is needed. All
-+ *	we need to know is the capacity of indirect blocks (taken from the
-+ *	inode->i_sb).
-+ */
-+
-+/*
-+ * Portability note: the last comparison (check that we fit into triple
-+ * indirect block) is spelled differently, because otherwise on an
-+ * architecture with 32-bit longs and 8Kb pages we might get into trouble
-+ * if our filesystem had 8Kb blocks. We might use long long, but that would
-+ * kill us on x86. Oh, well, at least the sign propagation does not matter -
-+ * i_block would have to be negative in the very beginning, so we would not
-+ * get there at all.
-+ */
-+
-+static int ext3cow_block_to_path(struct inode *inode,
-+			long i_block, int offsets[4], int *boundary)
-+{
-+  /* TODO: Check for efficientcy -znjp */
-+	int ptrs = EXT3COW_ADDR_PER_BLOCK(inode->i_sb);
-+	const long direct_blocks = EXT3COW_NDIR_BLOCKS,
-+		indirect_blocks = ptrs,
-+    double_blocks = (ptrs * ptrs);
-+		//double_blocks = (1 << (ptrs_bits * 2));
-+	int n = 0;
-+	int final = 0;
-+
-+	if (i_block < 0) {
-+		ext3cow_warning (inode->i_sb, "ext3cow_block_to_path", "block < 0");
-+	} else if (i_block < direct_blocks) {
-+		offsets[n++] = i_block;
-+		final = direct_blocks;
-+	} else if ( (i_block -= direct_blocks) < indirect_blocks) {
-+		offsets[n++] = EXT3COW_IND_BLOCK;
-+		offsets[n++] = i_block;
-+		final = ptrs;
-+	} else if ((i_block -= indirect_blocks) < double_blocks) {
-+		offsets[n++] = EXT3COW_DIND_BLOCK;
-+		offsets[n++] = (i_block/ptrs); //i_block >> ptrs_bits;
-+		offsets[n++] = (i_block%ptrs); //i_block & (ptrs - 1);
-+		final = ptrs;
-+	} else if (((i_block -= double_blocks)/(double_blocks)) < ptrs) {
-+    //	} else if (((i_block -= double_blocks) >> (ptrs_bits * 2)) < ptrs) {
-+		offsets[n++] = EXT3COW_TIND_BLOCK;
-+		offsets[n++] = (i_block/double_blocks); //i_block >> (ptrs_bits * 2);
-+		offsets[n++] = (i_block/double_blocks)%ptrs; //(i_block >> ptrs_bits) & (ptrs - 1);
-+		offsets[n++] = i_block%ptrs; //i_block & (ptrs - 1);
-+		final = ptrs;
-+	} else {
-+		ext3cow_warning(inode->i_sb, "ext3cow_block_to_path", "block > big");
-+	}
-+	if (boundary)
-+		*boundary = final - 1 - (i_block & (ptrs - 1));
-+	return n;
-+}
-+
-+/**
-+ *	ext3cow_get_branch - read the chain of indirect blocks leading to data
-+ *	@inode: inode in question
-+ *	@depth: depth of the chain (1 - direct pointer, etc.)
-+ *	@offsets: offsets of pointers in inode/indirect blocks
-+ *	@chain: place to store the result
-+ *	@err: here we store the error value
-+ *
-+ *	Function fills the array of triples <key, p, bh> and returns %NULL
-+ *	if everything went OK or the pointer to the last filled triple
-+ *	(incomplete one) otherwise. Upon the return chain[i].key contains
-+ *	the number of (i+1)-th block in the chain (as it is stored in memory,
-+ *	i.e. little-endian 32-bit), chain[i].p contains the address of that
-+ *	number (it points into struct inode for i==0 and into the bh->b_data
-+ *	for i>0) and chain[i].bh points to the buffer_head of i-th indirect
-+ *	block for i>0 and NULL for i==0. In other words, it holds the block
-+ *	numbers of the chain, addresses they were taken from (and where we can
-+ *	verify that chain did not change) and buffer_heads hosting these
-+ *	numbers.
-+ *
-+ *	Function stops when it stumbles upon zero pointer (absent block)
-+ *		(pointer to last triple returned, *@err == 0)
-+ *	or when it gets an IO error reading an indirect block
-+ *		(ditto, *@err == -EIO)
-+ *	or when it notices that chain had been changed while it was reading
-+ *		(ditto, *@err == -EAGAIN)
-+ *	or when it reads all @depth-1 indirect blocks successfully and finds
-+ *	the whole chain, all way to the data (returns %NULL, *err == 0).
-+ *  If this is COW we set the cow field to 1.  We know if it's COW
-+ *  because there will already be a key.  We need this field so we
-+ *  zero out the data already in the buffer.
-+ *  The create flag let's us know if were just looking for a block
-+ *  to read, or a block to write.  We only set the bitmap when
-+ *  we're looking for a block to write, either on new allocation
-+ *  or on COWing. -znjp
-+ */
-+static Indirect *ext3cow_get_branch(struct inode *inode, int depth, 
-+                                    int *offsets,
-+                                    Indirect chain[4], int *err, int *cow,
-+                                    int create)
-+{
-+	struct super_block *sb = inode->i_sb;
-+	Indirect *p = chain;
-+	struct buffer_head *bh = NULL;
-+  u32 *bitmap_w = NULL;
-+  int ptrs = EXT3COW_ADDR_PER_BLOCK(inode->i_sb);
-+  int nbitsperword = (sizeof(u32) * 8);
-+
-+	*err = 0;
-+  *cow = 0;
-+
-+
-+	/* i_data is not going away, no lock needed */
-+	add_chain (chain, NULL, EXT3COW_I(inode)->i_data + *offsets);
-+	if (!p->key){
-+    /* Set the bitmap on allocation - znjp */
-+    if(create){
-+      EXT3COW_I(inode)->i_cow_bitmap |= (1UL << *offsets);
-+    }
-+		goto no_block;
-+  }
-+
-+  /* Are we writing and COWing any direct blocks? -znjp */
-+  if(create && !(EXT3COW_I(inode)->i_cow_bitmap & (1UL << *offsets))){    
-+    //printk(KERN_INFO "COWing direct block\n");
-+    *(p->p) = 0;
-+    p->key = 0;
-+    /* Set the bitamp when COWing -znjp */
-+    EXT3COW_I(inode)->i_cow_bitmap |= (1UL << *offsets);
-+    *cow = 1;
-+    goto no_block;
-+  }
-+
-+	while (--depth) {
-+
-+		bh = sb_bread(sb, le32_to_cpu(p->key));
-+		if (!bh)
-+			goto failure;
-+
-+		/* Reader: pointers */
-+		if (!verify_chain(chain, p))
-+			goto changed;
-+		add_chain(++p, bh, (__le32*)bh->b_data + *++offsets);
-+		/* Reader: end */
-+    /* Find correct bitmap word */
-+    bitmap_w = (u32*)bh->b_data + ptrs + (*offsets/nbitsperword);
-+		if (!p->key){
-+      /* Set the bitmap when allocating -znjp */
-+      if(create){
-+       *bitmap_w |= (u32)(1UL << (int)(*offsets%nbitsperword));
-+      }
-+			goto no_block;
-+    }
-+
-+    /* Are we COWing any indirect blocks? -znjp */
-+    if(create && !(*bitmap_w & (1UL << (int)(*offsets%nbitsperword)))){
-+      //printk(KERN_INFO "COWing indirect block\n");
-+      *(p->p) = 0;
-+      p->key = 0;
-+      /* Set the bitmap -znjp */
-+      *bitmap_w |= (u32)(1UL << (int)(*offsets%nbitsperword));
-+      *cow = 1;
-+      goto no_block;
-+    }
-+	}
-+	return NULL;
-+
-+changed:
-+	brelse(bh);
-+	*err = -EAGAIN;
-+	goto no_block;
-+failure:
-+	*err = -EIO;
-+no_block:
-+	return p;
-+}
-+
-+/**
-+ *	ext3cow_find_near - find a place for allocation with sufficient locality
-+ *	@inode: owner
-+ *	@ind: descriptor of indirect block.
-+ *
-+ *	This function returns the prefered place for block allocation.
-+ *	It is used when heuristic for sequential allocation fails.
-+ *	Rules are:
-+ *	  + if there is a block to the left of our position - allocate near it.
-+ *	  + if pointer will live in indirect block - allocate near that block.
-+ *	  + if pointer will live in inode - allocate in the same
-+ *	    cylinder group.
-+ *
-+ * In the latter case we colour the starting block by the callers PID to
-+ * prevent it from clashing with concurrent allocations for a different inode
-+ * in the same block group.   The PID is used here so that functionally related
-+ * files will be close-by on-disk.
-+ *
-+ *	Caller must make sure that @ind is valid and will stay that way.
-+ */
-+static ext3cow_fsblk_t ext3cow_find_near(struct inode *inode, Indirect *ind)
-+{
-+	struct ext3cow_inode_info *ei = EXT3COW_I(inode);
-+	__le32 *start = ind->bh ? (__le32*) ind->bh->b_data : ei->i_data;
-+	__le32 *p;
-+	ext3cow_fsblk_t bg_start;
-+	ext3cow_grpblk_t colour;
-+
-+	/* Try to find previous block */
-+	for (p = ind->p - 1; p >= start; p--) {
-+		if (*p)
-+			return le32_to_cpu(*p);
-+	}
-+
-+	/* No such thing, so let's try location of indirect block */
-+	if (ind->bh)
-+		return ind->bh->b_blocknr;
-+
-+	/*
-+	 * It is going to be referred to from the inode itself? OK, just put it
-+	 * into the same cylinder group then.
-+	 */
-+	bg_start = ext3cow_group_first_block_no(inode->i_sb, ei->i_block_group);
-+	colour = (current->pid % 16) *
-+			(EXT3COW_BLOCKS_PER_GROUP(inode->i_sb) / 16);
-+	return bg_start + colour;
-+}
-+
-+/**
-+ *	ext3cow_find_goal - find a prefered place for allocation.
-+ *	@inode: owner
-+ *	@block:  block we want
-+ *	@chain:  chain of indirect blocks
-+ *	@partial: pointer to the last triple within a chain
-+ *	@goal:	place to store the result.
-+ *
-+ *	Normally this function find the prefered place for block allocation,
-+ *	stores it in *@goal and returns zero.
-+ */
-+
-+static ext3cow_fsblk_t ext3cow_find_goal(struct inode *inode, long block,
-+		Indirect chain[4], Indirect *partial)
-+{
-+	struct ext3cow_block_alloc_info *block_i;
-+
-+	block_i =  EXT3COW_I(inode)->i_block_alloc_info;
-+
-+	/*
-+	 * try the heuristic for sequential allocation,
-+	 * failing that at least try to get decent locality.
-+	 */
-+	if (block_i && (block == block_i->last_alloc_logical_block + 1)
-+		&& (block_i->last_alloc_physical_block != 0)) {
-+		return block_i->last_alloc_physical_block + 1;
-+	}
-+
-+	return ext3cow_find_near(inode, partial);
-+}
-+
-+/**
-+ *	ext3cow_blks_to_allocate: Look up the block map and count the number
-+ *	of direct blocks need to be allocated for the given branch.
-+ *
-+ *	@branch: chain of indirect blocks
-+ *	@k: number of blocks need for indirect blocks
-+ *	@blks: number of data blocks to be mapped.
-+ *	@blocks_to_boundary:  the offset in the indirect block
-+ *
-+ *	return the total number of blocks to be allocate, including the
-+ *	direct and indirect blocks.
-+ */
-+static int ext3cow_blks_to_allocate(Indirect *branch, int k, unsigned long blks,
-+		int blocks_to_boundary)
-+{
-+	unsigned long count = 0;
-+
-+	/*
-+	 * Simple case, [t,d]Indirect block(s) has not allocated yet
-+	 * then it's clear blocks on that path have not allocated
-+	 */
-+	if (k > 0) {
-+		/* right now we don't handle cross boundary allocation */
-+		if (blks < blocks_to_boundary + 1)
-+			count += blks;
-+		else
-+			count += blocks_to_boundary + 1;
-+		return count;
-+	}
-+
-+	count++;
-+	while (count < blks && count <= blocks_to_boundary &&
-+		le32_to_cpu(*(branch[0].p + count)) == 0) {
-+		count++;
-+	}
-+	return count;
-+}
-+
-+/**
-+ *	ext3cow_alloc_blocks: multiple allocate blocks needed for a branch
-+ *	@indirect_blks: the number of blocks need to allocate for indirect
-+ *			blocks
-+ *
-+ *	@new_blocks: on return it will store the new block numbers for
-+ *	the indirect blocks(if needed) and the first direct block,
-+ *	@blks:	on return it will store the total number of allocated
-+ *		direct blocks
-+ */
-+static int ext3cow_alloc_blocks(handle_t *handle, struct inode *inode,
-+			ext3cow_fsblk_t goal, int indirect_blks, int blks,
-+			ext3cow_fsblk_t new_blocks[4], int *err)
-+{
-+	int target, i;
-+	unsigned long count = 0;
-+	int index = 0;
-+	ext3cow_fsblk_t current_block = 0;
-+	int ret = 0;
-+
-+	/*
-+	 * Here we try to allocate the requested multiple blocks at once,
-+	 * on a best-effort basis.
-+	 * To build a branch, we should allocate blocks for
-+	 * the indirect blocks(if not allocated yet), and at least
-+	 * the first direct block of this branch.  That's the
-+	 * minimum number of blocks need to allocate(required)
-+	 */
-+	target = blks + indirect_blks;
-+
-+	while (1) {
-+		count = target;
-+		/* allocating blocks for indirect blocks and direct blocks */
-+		current_block = ext3cow_new_blocks(handle,inode,goal,&count,err);
-+		if (*err)
-+			goto failed_out;
-+
-+		target -= count;
-+		/* allocate blocks for indirect blocks */
-+		while (index < indirect_blks && count) {
-+			new_blocks[index++] = current_block++;
-+			count--;
-+		}
-+
-+		if (count > 0)
-+			break;
-+	}
-+
-+	/* save the new block number for the first direct block */
-+	new_blocks[index] = current_block;
-+
-+	/* total number of blocks allocated for direct blocks */
-+	ret = count;
-+	*err = 0;
-+	return ret;
-+failed_out:
-+	for (i = 0; i <index; i++)
-+		ext3cow_free_blocks(handle, inode, new_blocks[i], 1);
-+	return ret;
-+}
-+
-+/**
-+ *	ext3cow_alloc_branch - allocate and set up a chain of blocks.
-+ *	@inode: owner
-+ *	@indirect_blks: number of allocated indirect blocks
-+ *	@blks: number of allocated direct blocks
-+ *	@offsets: offsets (in the blocks) to store the pointers to next.
-+ *	@branch: place to store the chain in.
-+ *
-+ *	This function allocates blocks, zeroes out all but the last one,
-+ *	links them into chain and (if we are synchronous) writes them to disk.
-+ *	In other words, it prepares a branch that can be spliced onto the
-+ *	inode. It stores the information about that chain in the branch[], in
-+ *	the same format as ext3cow_get_branch() would do. We are calling it after
-+ *	we had read the existing part of chain and partial points to the last
-+ *	triple of that (one with zero ->key). Upon the exit we have the same
-+ *	picture as after the successful ext3cow_get_block(), except that in one
-+ *	place chain is disconnected - *branch->p is still zero (we did not
-+ *	set the last link), but branch->key contains the number that should
-+ *	be placed into *branch->p to fill that gap.
-+ *
-+ *	If allocation fails we free all blocks we've allocated (and forget
-+ *	their buffer_heads) and return the error value the from failed
-+ *	ext3cow_alloc_block() (normally -ENOSPC). Otherwise we set the chain
-+ *	as described above and return 0.
-+ */
-+static int ext3cow_alloc_branch(handle_t *handle, struct inode *inode,
-+			int indirect_blks, int *blks, ext3cow_fsblk_t goal,
-+			int *offsets, Indirect *branch)
-+{
-+	int blocksize = inode->i_sb->s_blocksize;
-+	int i, n = 0;
-+	int err = 0;
-+	struct buffer_head *bh;
-+	int num;
-+	ext3cow_fsblk_t new_blocks[4];
-+	ext3cow_fsblk_t current_block;
-+
-+  u32 *bitmap_w = NULL;
-+  int ptrs = EXT3COW_ADDR_PER_BLOCK(inode->i_sb);
-+  int nbitsperword = (sizeof(u32) * 8);
-+
-+	num = ext3cow_alloc_blocks(handle, inode, goal, indirect_blks,
-+				*blks, new_blocks, &err);
-+	if (err)
-+		return err;
-+
-+	branch[0].key = cpu_to_le32(new_blocks[0]);
-+	/*
-+	 * metadata blocks and data blocks are allocated.
-+	 */
-+
-+	for (n = 1; n <= indirect_blks;  n++) {
-+		/*
-+		 * Get buffer_head for parent block, zero it out
-+		 * and set the pointer to new one, then send
-+		 * parent to disk.
-+		 */
-+		bh = sb_getblk(inode->i_sb, new_blocks[n-1]);
-+		branch[n].bh = bh;
-+		lock_buffer(bh);
-+		BUFFER_TRACE(bh, "call get_create_access");
-+		err = ext3cow_journal_get_create_access(handle, bh);
-+		if (err) {
-+			unlock_buffer(bh);
-+			brelse(bh);
-+			goto failed;
-+		}
-+
-+		memset(bh->b_data, 0, blocksize);
-+    /* Mark the cow bitmap for each new indirect block allocated.
-+     * We had to put this here, because get_branch was insufficient
-+     * when allocating an indirect block. -znjp
-+     */
-+    bitmap_w = (u32*)bh->b_data + ptrs + (offsets[n]/nbitsperword);
-+    *bitmap_w |= (u32)(1UL << (int)(offsets[n]%nbitsperword));
-+
-+		branch[n].p = (__le32 *) bh->b_data + offsets[n];
-+		branch[n].key = cpu_to_le32(new_blocks[n]);
-+		*branch[n].p = branch[n].key;
-+		if ( n == indirect_blks) {
-+			current_block = new_blocks[n];
-+			/*
-+			 * End of chain, update the last new metablock of
-+			 * the chain to point to the new allocated
-+			 * data blocks numbers
-+			 */
-+			for (i=1; i < num; i++)
-+				*(branch[n].p + i) = cpu_to_le32(++current_block);
-+		}
-+		BUFFER_TRACE(bh, "marking uptodate");
-+		set_buffer_uptodate(bh);
-+		unlock_buffer(bh);
-+
-+		BUFFER_TRACE(bh, "call ext3cow_journal_dirty_metadata");
-+		err = ext3cow_journal_dirty_metadata(handle, bh);
-+		if (err)
-+			goto failed;
-+	}
-+	*blks = num;
-+	return err;
-+failed:
-+	/* Allocation failed, free what we already allocated */
-+	for (i = 1; i <= n ; i++) {
-+		BUFFER_TRACE(branch[i].bh, "call journal_forget");
-+		ext3cow_journal_forget(handle, branch[i].bh);
-+	}
-+	for (i = 0; i <indirect_blks; i++)
-+		ext3cow_free_blocks(handle, inode, new_blocks[i], 1);
-+
-+	ext3cow_free_blocks(handle, inode, new_blocks[i], num);
-+
-+	return err;
-+}
-+
-+/**
-+ * ext3cow_splice_branch - splice the allocated branch onto inode.
-+ * @inode: owner
-+ * @block: (logical) number of block we are adding
-+ * @chain: chain of indirect blocks (with a missing link - see
-+ *	ext3cow_alloc_branch)
-+ * @where: location of missing link
-+ * @num:   number of indirect blocks we are adding
-+ * @blks:  number of direct blocks we are adding
-+ *
-+ * This function fills the missing link and does all housekeeping needed in
-+ * inode (->i_blocks, etc.). In case of success we end up with the full
-+ * chain to new block and return 0.
-+ */
-+static int ext3cow_splice_branch(handle_t *handle, struct inode *inode,
-+			long block, Indirect *where, int num, int blks)
-+{
-+	int i;
-+	int err = 0;
-+	struct ext3cow_block_alloc_info *block_i;
-+	ext3cow_fsblk_t current_block;
-+
-+	block_i = EXT3COW_I(inode)->i_block_alloc_info;
-+	/*
-+	 * If we're splicing into a [td]indirect block (as opposed to the
-+	 * inode) then we need to get write access to the [td]indirect block
-+	 * before the splice.
-+	 */
-+	if (where->bh) {
-+		BUFFER_TRACE(where->bh, "get_write_access");
-+		err = ext3cow_journal_get_write_access(handle, where->bh);
-+		if (err)
-+			goto err_out;
-+	}
-+	/* That's it */
-+
-+	*where->p = where->key;
-+
-+	/*
-+	 * Update the host buffer_head or inode to point to more just allocated
-+	 * direct blocks blocks
-+	 */
-+	if (num == 0 && blks > 1) {
-+		current_block = le32_to_cpu(where->key) + 1;
-+		for (i = 1; i < blks; i++)
-+			*(where->p + i ) = cpu_to_le32(current_block++);
-+	}
-+
-+	/*
-+	 * update the most recently allocated logical & physical block
-+	 * in i_block_alloc_info, to assist find the proper goal block for next
-+	 * allocation
-+	 */
-+	if (block_i) {
-+		block_i->last_alloc_logical_block = block + blks - 1;
-+		block_i->last_alloc_physical_block =
-+				le32_to_cpu(where[num].key) + blks - 1;
-+	}
-+
-+	/* We are done with atomic stuff, now do the rest of housekeeping */
-+
-+	inode->i_ctime = CURRENT_TIME_SEC;
-+	ext3cow_mark_inode_dirty(handle, inode);
-+
-+	/* had we spliced it onto indirect block? */
-+	if (where->bh) {
-+		/*
-+		 * If we spliced it onto an indirect block, we haven't
-+		 * altered the inode.  Note however that if it is being spliced
-+		 * onto an indirect block at the very end of the file (the
-+		 * file is growing) then we *will* alter the inode to reflect
-+		 * the new i_size.  But that is not done here - it is done in
-+		 * generic_commit_write->__mark_inode_dirty->ext3cow_dirty_inode.
-+		 */
-+		jbd_debug(5, "splicing indirect only\n");
-+		BUFFER_TRACE(where->bh, "call ext3cow_journal_dirty_metadata");
-+		err = ext3cow_journal_dirty_metadata(handle, where->bh);
-+		if (err)
-+			goto err_out;
-+	} else {
-+		/*
-+		 * OK, we spliced it into the inode itself on a direct block.
-+		 * Inode was dirtied above.
-+		 */
-+		jbd_debug(5, "splicing direct\n");
-+	}
-+	return err;
-+
-+err_out:
-+	for (i = 1; i <= num; i++) {
-+		BUFFER_TRACE(where[i].bh, "call journal_forget");
-+		ext3cow_journal_forget(handle, where[i].bh);
-+		ext3cow_free_blocks(handle,inode,le32_to_cpu(where[i-1].key),1);
-+	}
-+	ext3cow_free_blocks(handle, inode, le32_to_cpu(where[num].key), blks);
-+
-+	return err;
-+}
-+
-+/*
-+ * Allocation strategy is simple: if we have to allocate something, we will
-+ * have to go the whole way to leaf. So let's do it before attaching anything
-+ * to tree, set linkage between the newborn blocks, write them if sync is
-+ * required, recheck the path, free and repeat if check fails, otherwise
-+ * set the last missing link (that will protect us from any truncate-generated
-+ * removals - all blocks on the path are immune now) and possibly force the
-+ * write on the parent block.
-+ * That has a nice additional property: no special recovery from the failed
-+ * allocations is needed - we simply release blocks and do not touch anything
-+ * reachable from inode.
-+ *
-+ * `handle' can be NULL if create == 0.
-+ *
-+ * The BKL may not be held on entry here.  Be sure to take it early.
-+ * return > 0, # of blocks mapped or allocated.
-+ * return = 0, if plain lookup failed.
-+ * return < 0, error case.
-+ */
-+int ext3cow_get_blocks_handle(handle_t *handle, struct inode *inode,
-+		sector_t iblock, unsigned long maxblocks,
-+		struct buffer_head *bh_result,
-+		int create, int extend_disksize)
-+{
-+	int err = -EIO;
-+	int offsets[4];
-+	Indirect chain[4];
-+	Indirect *partial;
-+	ext3cow_fsblk_t goal;
-+	int indirect_blks;
-+	int blocks_to_boundary = 0;
-+	int depth;
-+	struct ext3cow_inode_info *ei = EXT3COW_I(inode);
-+	int count = 0;
-+	ext3cow_fsblk_t first_block = 0;
-+  int cow = 0; /* To determine wether we clear the buffer of not -znjp */
-+
-+
-+	J_ASSERT(handle != NULL || create == 0);
-+	depth = ext3cow_block_to_path(inode,iblock,offsets,&blocks_to_boundary);
-+
-+	if (depth == 0)
-+		goto out;
-+
-+	partial = ext3cow_get_branch(inode, depth, offsets, 
-+                               chain, &err, &cow, create);
-+
-+	/* Simplest case - block found, no allocation needed */
-+	if (!partial) {
-+		first_block = le32_to_cpu(chain[depth - 1].key);
-+    if(!cow) /* Don't clear the buffer if it's a COW allocation -znjp */
-+      clear_buffer_new(bh_result);
-+		count++;
-+		/*map more blocks*/
-+		while (count < maxblocks && count <= blocks_to_boundary) {
-+			ext3cow_fsblk_t blk;
-+
-+			if (!verify_chain(chain, partial)) {
-+				/*
-+				 * Indirect block might be removed by
-+				 * truncate while we were reading it.
-+				 * Handling of that case: forget what we've
-+				 * got now. Flag the err as EAGAIN, so it
-+				 * will reread.
-+				 */
-+				err = -EAGAIN;
-+				count = 0;
-+				break;
-+			}
-+			blk = le32_to_cpu(*(chain[depth-1].p + count));
-+
-+			if (blk == first_block + count)
-+				count++;
-+			else
-+				break;
-+		}
-+		if (err != -EAGAIN)
-+			goto got_it;
-+	}
-+
-+	/* Next simple case - plain lookup or failed read of indirect block */
-+	if (!create || err == -EIO)
-+		goto cleanup;
-+
-+	mutex_lock(&ei->truncate_mutex);
-+
-+	/*
-+	 * If the indirect block is missing while we are reading
-+	 * the chain(ext3cow_get_branch() returns -EAGAIN err), or
-+	 * if the chain has been changed after we grab the semaphore,
-+	 * (either because another process truncated this branch, or
-+	 * another get_block allocated this branch) re-grab the chain to see if
-+	 * the request block has been allocated or not.
-+	 *
-+	 * Since we already block the truncate/other get_block
-+	 * at this point, we will have the current copy of the chain when we
-+	 * splice the branch into the tree.
-+	 */
-+	if (err == -EAGAIN || !verify_chain(chain, partial)) {
-+		while (partial > chain) {
-+			brelse(partial->bh);
-+			partial--;
-+		}
-+		partial = ext3cow_get_branch(inode, depth, offsets, 
-+                                 chain, &err, &cow, create);
-+		if (!partial) {
-+			count++;
-+			mutex_unlock(&ei->truncate_mutex);
-+			if (err)
-+				goto cleanup;
-+      /* Don't clear the buffer if we're COWing it -znjp */
-+      if(!cow)
-+        clear_buffer_new(bh_result);
-+			goto got_it;
-+		}
-+	}
-+
-+	/*
-+	 * Okay, we need to do block allocation.  Lazily initialize the block
-+	 * allocation info here if necessary
-+	*/
-+	if (S_ISREG(inode->i_mode) && (!ei->i_block_alloc_info))
-+		ext3cow_init_block_alloc_info(inode);
-+
-+	goal = ext3cow_find_goal(inode, iblock, chain, partial);
-+
-+	/* the number of blocks need to allocate for [d,t]indirect blocks */
-+	indirect_blks = (chain + depth) - partial - 1;
-+
-+	/*
-+	 * Next look up the indirect map to count the totoal number of
-+	 * direct blocks to allocate for this branch.
-+	 */
-+	count = ext3cow_blks_to_allocate(partial, indirect_blks,
-+					maxblocks, blocks_to_boundary);
-+	/*
-+	 * Block out ext3cow_truncate while we alter the tree
-+	 */
-+	err = ext3cow_alloc_branch(handle, inode, indirect_blks, &count, goal,
-+				offsets + (partial - chain), partial);
-+
-+	/*
-+	 * The ext3cow_splice_branch call will free and forget any buffers
-+	 * on the new chain if there is a failure, but that risks using
-+	 * up transaction credits, especially for bitmaps where the
-+	 * credits cannot be returned.  Can we handle this somehow?  We
-+	 * may need to return -EAGAIN upwards in the worst case.  --sct
-+	 */
-+	if (!err)
-+		err = ext3cow_splice_branch(handle, inode, iblock,
-+					partial, indirect_blks, count);
-+	/*
-+	 * i_disksize growing is protected by truncate_mutex.  Don't forget to
-+	 * protect it if you're about to implement concurrent
-+	 * ext3cow_get_block() -bzzz
-+	*/
-+	if (!err && extend_disksize && inode->i_size > ei->i_disksize)
-+		ei->i_disksize = inode->i_size;
-+	mutex_unlock(&ei->truncate_mutex);
-+	if (err)
-+		goto cleanup;
-+
-+	set_buffer_new(bh_result);
-+got_it:
-+	map_bh(bh_result, inode->i_sb, le32_to_cpu(chain[depth-1].key));
-+	if (count > blocks_to_boundary)
-+		set_buffer_boundary(bh_result);
-+	err = count;
-+	/* Clean up and exit */
-+	partial = chain + depth - 1;	/* the whole chain */
-+cleanup:
-+	while (partial > chain) {
-+		BUFFER_TRACE(partial->bh, "call brelse");
-+		brelse(partial->bh);
-+		partial--;
-+	}
-+	BUFFER_TRACE(bh_result, "returned");
-+out:
-+	return err;
-+}
-+
-+#define DIO_CREDITS (EXT3COW_RESERVE_TRANS_BLOCKS + 32)
-+
-+static int ext3cow_get_block(struct inode *inode, sector_t iblock,
-+			struct buffer_head *bh_result, int create)
-+{
-+	handle_t *handle = journal_current_handle();
-+	int ret = 0;
-+	unsigned max_blocks = bh_result->b_size >> inode->i_blkbits;
-+
-+	if (!create)
-+		goto get_block;		/* A read */
-+
-+	if (max_blocks == 1)
-+		goto get_block;		/* A single block get */
-+
-+	if (handle->h_transaction->t_state == T_LOCKED) {
-+		/*
-+		 * Huge direct-io writes can hold off commits for long
-+		 * periods of time.  Let this commit run.
-+		 */
-+		ext3cow_journal_stop(handle);
-+		handle = ext3cow_journal_start(inode, DIO_CREDITS);
-+		if (IS_ERR(handle))
-+			ret = PTR_ERR(handle);
-+		goto get_block;
-+	}
-+
-+	if (handle->h_buffer_credits <= EXT3COW_RESERVE_TRANS_BLOCKS) {
-+		/*
-+		 * Getting low on buffer credits...
-+		 */
-+		ret = ext3cow_journal_extend(handle, DIO_CREDITS);
-+		if (ret > 0) {
-+			/*
-+			 * Couldn't extend the transaction.  Start a new one.
-+			 */
-+			ret = ext3cow_journal_restart(handle, DIO_CREDITS);
-+		}
-+	}
-+
-+get_block:
-+	if (ret == 0) {
-+		ret = ext3cow_get_blocks_handle(handle, inode, iblock,
-+					max_blocks, bh_result, create, 0);
-+		if (ret > 0) {
-+			bh_result->b_size = (ret << inode->i_blkbits);
-+			ret = 0;
-+		}
-+	}
-+	return ret;
-+}
-+
-+/*
-+ * `handle' can be NULL if create is zero
-+ */
-+struct buffer_head *ext3cow_getblk(handle_t *handle, struct inode *inode,
-+				long block, int create, int *errp)
-+{
-+	struct buffer_head dummy;
-+	int fatal = 0, err;
-+
-+	J_ASSERT(handle != NULL || create == 0);
-+
-+	dummy.b_state = 0;
-+	dummy.b_blocknr = -1000;
-+	buffer_trace_init(&dummy.b_history);
-+	err = ext3cow_get_blocks_handle(handle, inode, block, 1,
-+					&dummy, create, 1);
-+	/*
-+	 * ext3cow_get_blocks_handle() returns number of blocks
-+	 * mapped. 0 in case of a HOLE.
-+	 */
-+	if (err > 0) {
-+		if (err > 1)
-+			WARN_ON(1);
-+		err = 0;
-+	}
-+	*errp = err;
-+	if (!err && buffer_mapped(&dummy)) {
-+		struct buffer_head *bh;
-+		bh = sb_getblk(inode->i_sb, dummy.b_blocknr);
-+		if (!bh) {
-+			*errp = -EIO;
-+			goto err;
-+		}
-+		if (buffer_new(&dummy)) {
-+			J_ASSERT(create != 0);
-+			J_ASSERT(handle != 0);
-+
-+			/*
-+			 * Now that we do not always journal data, we should
-+			 * keep in mind whether this should always journal the
-+			 * new buffer as metadata.  For now, regular file
-+			 * writes use ext3cow_get_block instead, so it's not a
-+			 * problem.
-+			 */
-+			lock_buffer(bh);
-+			BUFFER_TRACE(bh, "call get_create_access");
-+			fatal = ext3cow_journal_get_create_access(handle, bh);
-+			if (!fatal && !buffer_uptodate(bh)) {
-+				memset(bh->b_data,0,inode->i_sb->s_blocksize);
-+				set_buffer_uptodate(bh);
-+			}
-+			unlock_buffer(bh);
-+			BUFFER_TRACE(bh, "call ext3cow_journal_dirty_metadata");
-+			err = ext3cow_journal_dirty_metadata(handle, bh);
-+			if (!fatal)
-+				fatal = err;
-+		} else {
-+			BUFFER_TRACE(bh, "not a new buffer");
-+		}
-+		if (fatal) {
-+			*errp = fatal;
-+			brelse(bh);
-+			bh = NULL;
-+		}
-+		return bh;
-+	}
-+err:
-+	return NULL;
-+}
-+
-+struct buffer_head *ext3cow_bread(handle_t *handle, struct inode *inode,
-+			       int block, int create, int *err)
-+{
-+	struct buffer_head * bh;
-+
-+	bh = ext3cow_getblk(handle, inode, block, create, err);
-+	if (!bh)
-+		return bh;
-+	if (buffer_uptodate(bh))
-+		return bh;
-+	ll_rw_block(READ_META, 1, &bh);
-+	wait_on_buffer(bh);
-+	if (buffer_uptodate(bh))
-+		return bh;
-+	put_bh(bh);
-+	*err = -EIO;
-+	return NULL;
-+}
-+
-+static int walk_page_buffers(	handle_t *handle,
-+				struct buffer_head *head,
-+				unsigned from,
-+				unsigned to,
-+				int *partial,
-+				int (*fn)(	handle_t *handle,
-+						struct buffer_head *bh))
-+{
-+	struct buffer_head *bh;
-+	unsigned block_start, block_end;
-+	unsigned blocksize = head->b_size;
-+	int err, ret = 0;
-+	struct buffer_head *next;
-+
-+	for (	bh = head, block_start = 0;
-+		ret == 0 && (bh != head || !block_start);
-+		block_start = block_end, bh = next)
-+	{
-+		next = bh->b_this_page;
-+		block_end = block_start + blocksize;
-+		if (block_end <= from || block_start >= to) {
-+			if (partial && !buffer_uptodate(bh))
-+				*partial = 1;
-+			continue;
-+		}
-+		err = (*fn)(handle, bh);
-+		if (!ret)
-+			ret = err;
-+	}
-+	return ret;
-+}
-+
-+/*
-+ * To preserve ordering, it is essential that the hole instantiation and
-+ * the data write be encapsulated in a single transaction.  We cannot
-+ * close off a transaction and start a new one between the ext3cow_get_block()
-+ * and the commit_write().  So doing the journal_start at the start of
-+ * prepare_write() is the right place.
-+ *
-+ * Also, this function can nest inside ext3cow_writepage() ->
-+ * block_write_full_page(). In that case, we *know* that ext3cow_writepage()
-+ * has generated enough buffer credits to do the whole page.  So we won't
-+ * block on the journal in that case, which is good, because the caller may
-+ * be PF_MEMALLOC.
-+ *
-+ * By accident, ext3cow can be reentered when a transaction is open via
-+ * quota file writes.  If we were to commit the transaction while thus
-+ * reentered, there can be a deadlock - we would be holding a quota
-+ * lock, and the commit would never complete if another thread had a
-+ * transaction open and was blocking on the quota lock - a ranking
-+ * violation.
-+ *
-+ * So what we do is to rely on the fact that journal_stop/journal_start
-+ * will _not_ run commit under these circumstances because handle->h_ref
-+ * is elevated.  We'll still have enough credits for the tiny quotafile
-+ * write.
-+ */
-+static int do_journal_get_write_access(handle_t *handle,
-+					struct buffer_head *bh)
-+{
-+	if (!buffer_mapped(bh) || buffer_freed(bh))
-+		return 0;
-+	return ext3cow_journal_get_write_access(handle, bh);
-+}
-+
-+/*
-+ * The idea of this helper function is following:
-+ * if prepare_write has allocated some blocks, but not all of them, the
-+ * transaction must include the content of the newly allocated blocks.
-+ * This content is expected to be set to zeroes by block_prepare_write().
-+ * 2006/10/14  SAW
-+ */
-+static int ext3cow_prepare_failure(struct file *file, struct page *page,
-+				unsigned from, unsigned to)
-+{
-+	struct address_space *mapping;
-+	struct buffer_head *bh, *head, *next;
-+	unsigned block_start, block_end;
-+	unsigned blocksize;
-+	int ret;
-+	handle_t *handle = ext3cow_journal_current_handle();
-+
-+	mapping = page->mapping;
-+	if (ext3cow_should_writeback_data(mapping->host)) {
-+		/* optimization: no constraints about data */
-+skip:
-+		return ext3cow_journal_stop(handle);
-+	}
-+
-+	head = page_buffers(page);
-+	blocksize = head->b_size;
-+	for (	bh = head, block_start = 0;
-+		bh != head || !block_start;
-+	    	block_start = block_end, bh = next)
-+	{
-+		next = bh->b_this_page;
-+		block_end = block_start + blocksize;
-+		if (block_end <= from)
-+			continue;
-+		if (block_start >= to) {
-+			block_start = to;
-+			break;
-+		}
-+		if (!buffer_mapped(bh))
-+		/* prepare_write failed on this bh */
-+			break;
-+		if (ext3cow_should_journal_data(mapping->host)) {
-+			ret = do_journal_get_write_access(handle, bh);
-+			if (ret) {
-+				ext3cow_journal_stop(handle);
-+				return ret;
-+			}
-+		}
-+	/*
-+	 * block_start here becomes the first block where the current iteration
-+	 * of prepare_write failed.
-+	 */
-+	}
-+	if (block_start <= from)
-+		goto skip;
-+
-+	/* commit allocated and zeroed buffers */
-+	return mapping->a_ops->commit_write(file, page, from, block_start);
-+}
-+
-+/* Used to quickly unmap all buffers in a page for COWing -znjp */
-+static int ext3cow_clear_buffer_mapped(handle_t *handle, 
-+                                       struct buffer_head *bh)
-+{
-+  clear_buffer_mapped(bh);
-+  return 0;
-+}
-+
-+static int ext3cow_prepare_write(struct file *file, struct page *page,
-+			      unsigned from, unsigned to)
-+{
-+	struct inode *inode = page->mapping->host;
-+	int ret, ret2;
-+	int needed_blocks = ext3cow_writepage_trans_blocks(inode);
-+	handle_t *handle;
-+	int retries = 0;
-+
-+retry:
-+	handle = ext3cow_journal_start(inode, needed_blocks);
-+	if (IS_ERR(handle))
-+		return PTR_ERR(handle);
-+  /* Unset the BH_Mapped flag so get_block is always called -znjp */
-+  if(page_has_buffers(page))
-+    ret = walk_page_buffers(handle, page_buffers(page),
-+                            from, to, NULL, ext3cow_clear_buffer_mapped);
-+
-+	if (test_opt(inode->i_sb, NOBH) && ext3cow_should_writeback_data(inode))
-+		ret = nobh_prepare_write(page, from, to, ext3cow_get_block);
-+	else
-+		ret = block_prepare_write(page, from, to, ext3cow_get_block);
-+	if (ret)
-+		goto failure;
-+
-+	if (ext3cow_should_journal_data(inode)) {
-+		ret = walk_page_buffers(handle, page_buffers(page),
-+				from, to, NULL, do_journal_get_write_access);
-+		if (ret)
-+			/* fatal error, just put the handle and return */
-+			journal_stop(handle);
-+	}
-+	return ret;
-+
-+failure:
-+	ret2 = ext3cow_prepare_failure(file, page, from, to);
-+	if (ret2 < 0)
-+		return ret2;
-+	if (ret == -ENOSPC && ext3cow_should_retry_alloc(inode->i_sb, &retries))
-+		goto retry;
-+	/* retry number exceeded, or other error like -EDQUOT */
-+	return ret;
-+}
-+
-+int ext3cow_journal_dirty_data(handle_t *handle, struct buffer_head *bh)
-+{
-+	int err = journal_dirty_data(handle, bh);
-+	if (err)
-+		ext3cow_journal_abort_handle(__FUNCTION__, __FUNCTION__,
-+						bh, handle,err);
-+	return err;
-+}
-+
-+/* For commit_write() in data=journal mode */
-+static int commit_write_fn(handle_t *handle, struct buffer_head *bh)
-+{
-+	if (!buffer_mapped(bh) || buffer_freed(bh))
-+		return 0;
-+	set_buffer_uptodate(bh);
-+	return ext3cow_journal_dirty_metadata(handle, bh);
-+}
-+
-+/*
-+ * We need to pick up the new inode size which generic_commit_write gave us
-+ * `file' can be NULL - eg, when called from page_symlink().
-+ *
-+ * ext3cow never places buffers on inode->i_mapping->private_list.  metadata
-+ * buffers are managed internally.
-+ */
-+static int ext3cow_ordered_commit_write(struct file *file, struct page *page,
-+			     unsigned from, unsigned to)
-+{
-+	handle_t *handle = ext3cow_journal_current_handle();
-+	struct inode *inode = page->mapping->host;
-+	int ret = 0, ret2;
-+
-+	ret = walk_page_buffers(handle, page_buffers(page),
-+		from, to, NULL, ext3cow_journal_dirty_data);
-+
-+	if (ret == 0) {
-+		/*
-+		 * generic_commit_write() will run mark_inode_dirty() if i_size
-+		 * changes.  So let's piggyback the i_disksize mark_inode_dirty
-+		 * into that.
-+		 */
-+		loff_t new_i_size;
-+
-+		new_i_size = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
-+		if (new_i_size > EXT3COW_I(inode)->i_disksize)
-+			EXT3COW_I(inode)->i_disksize = new_i_size;
-+		ret = generic_commit_write(file, page, from, to);
-+	}
-+	ret2 = ext3cow_journal_stop(handle);
-+	if (!ret)
-+		ret = ret2;
-+	return ret;
-+}
-+
-+static int ext3cow_writeback_commit_write(struct file *file, struct page *page,
-+			     unsigned from, unsigned to)
-+{
-+	handle_t *handle = ext3cow_journal_current_handle();
-+	struct inode *inode = page->mapping->host;
-+	int ret = 0, ret2;
-+	loff_t new_i_size;
-+
-+	new_i_size = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
-+	if (new_i_size > EXT3COW_I(inode)->i_disksize)
-+		EXT3COW_I(inode)->i_disksize = new_i_size;
-+
-+	if (test_opt(inode->i_sb, NOBH) && ext3cow_should_writeback_data(inode))
-+		ret = nobh_commit_write(file, page, from, to);
-+	else
-+		ret = generic_commit_write(file, page, from, to);
-+
-+	ret2 = ext3cow_journal_stop(handle);
-+	if (!ret)
-+		ret = ret2;
-+	return ret;
-+}
-+
-+static int ext3cow_journalled_commit_write(struct file *file,
-+			struct page *page, unsigned from, unsigned to)
-+{
-+	handle_t *handle = ext3cow_journal_current_handle();
-+	struct inode *inode = page->mapping->host;
-+	int ret = 0, ret2;
-+	int partial = 0;
-+	loff_t pos;
-+
-+	/*
-+	 * Here we duplicate the generic_commit_write() functionality
-+	 */
-+	pos = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
-+
-+	ret = walk_page_buffers(handle, page_buffers(page), from,
-+				to, &partial, commit_write_fn);
-+	if (!partial)
-+		SetPageUptodate(page);
-+	if (pos > inode->i_size)
-+		i_size_write(inode, pos);
-+	EXT3COW_I(inode)->i_state |= EXT3COW_STATE_JDATA;
-+	if (inode->i_size > EXT3COW_I(inode)->i_disksize) {
-+		EXT3COW_I(inode)->i_disksize = inode->i_size;
-+		ret2 = ext3cow_mark_inode_dirty(handle, inode);
-+		if (!ret)
-+			ret = ret2;
-+	}
-+	ret2 = ext3cow_journal_stop(handle);
-+	if (!ret)
-+		ret = ret2;
-+	return ret;
-+}
-+
-+/*
-+ * bmap() is special.  It gets used by applications such as lilo and by
-+ * the swapper to find the on-disk block of a specific piece of data.
-+ *
-+ * Naturally, this is dangerous if the block concerned is still in the
-+ * journal.  If somebody makes a swapfile on an ext3cow data-journaling
-+ * filesystem and enables swap, then they may get a nasty shock when the
-+ * data getting swapped to that swapfile suddenly gets overwritten by
-+ * the original zero's written out previously to the journal and
-+ * awaiting writeback in the kernel's buffer cache.
-+ *
-+ * So, if we see any bmap calls here on a modified, data-journaled file,
-+ * take extra steps to flush any blocks which might be in the cache.
-+ */
-+static sector_t ext3cow_bmap(struct address_space *mapping, sector_t block)
-+{
-+	struct inode *inode = mapping->host;
-+	journal_t *journal;
-+	int err;
-+
-+	if (EXT3COW_I(inode)->i_state & EXT3COW_STATE_JDATA) {
-+		/*
-+		 * This is a REALLY heavyweight approach, but the use of
-+		 * bmap on dirty files is expected to be extremely rare:
-+		 * only if we run lilo or swapon on a freshly made file
-+		 * do we expect this to happen.
-+		 *
-+		 * (bmap requires CAP_SYS_RAWIO so this does not
-+		 * represent an unprivileged user DOS attack --- we'd be
-+		 * in trouble if mortal users could trigger this path at
-+		 * will.)
-+		 *
-+		 * NB. EXT3COW_STATE_JDATA is not set on files other than
-+		 * regular files.  If somebody wants to bmap a directory
-+		 * or symlink and gets confused because the buffer
-+		 * hasn't yet been flushed to disk, they deserve
-+		 * everything they get.
-+		 */
-+
-+		EXT3COW_I(inode)->i_state &= ~EXT3COW_STATE_JDATA;
-+		journal = EXT3COW_JOURNAL(inode);
-+		journal_lock_updates(journal);
-+		err = journal_flush(journal);
-+		journal_unlock_updates(journal);
-+
-+		if (err)
-+			return 0;
-+	}
-+
-+	return generic_block_bmap(mapping,block,ext3cow_get_block);
-+}
-+
-+static int bget_one(handle_t *handle, struct buffer_head *bh)
-+{
-+	get_bh(bh);
-+	return 0;
-+}
-+
-+static int bput_one(handle_t *handle, struct buffer_head *bh)
-+{
-+	put_bh(bh);
-+	return 0;
-+}
-+
-+static int journal_dirty_data_fn(handle_t *handle, struct buffer_head *bh)
-+{
-+	if (buffer_mapped(bh))
-+		return ext3cow_journal_dirty_data(handle, bh);
-+	return 0;
-+}
-+
-+/*
-+ * Note that we always start a transaction even if we're not journalling
-+ * data.  This is to preserve ordering: any hole instantiation within
-+ * __block_write_full_page -> ext3cow_get_block() should be journalled
-+ * along with the data so we don't crash and then get metadata which
-+ * refers to old data.
-+ *
-+ * In all journalling modes block_write_full_page() will start the I/O.
-+ *
-+ * Problem:
-+ *
-+ *	ext3cow_writepage() -> kmalloc() -> __alloc_pages() -> page_launder() ->
-+ *		ext3cow_writepage()
-+ *
-+ * Similar for:
-+ *
-+ *	ext3cow_file_write() -> generic_file_write() -> __alloc_pages() -> ...
-+ *
-+ * Same applies to ext3cow_get_block().  We will deadlock on various things like
-+ * lock_journal and i_truncate_mutex.
-+ *
-+ * Setting PF_MEMALLOC here doesn't work - too many internal memory
-+ * allocations fail.
-+ *
-+ * 16May01: If we're reentered then journal_current_handle() will be
-+ *	    non-zero. We simply *return*.
-+ *
-+ * 1 July 2001: @@@ FIXME:
-+ *   In journalled data mode, a data buffer may be metadata against the
-+ *   current transaction.  But the same file is part of a shared mapping
-+ *   and someone does a writepage() on it.
-+ *
-+ *   We will move the buffer onto the async_data list, but *after* it has
-+ *   been dirtied. So there's a small window where we have dirty data on
-+ *   BJ_Metadata.
-+ *
-+ *   Note that this only applies to the last partial page in the file.  The
-+ *   bit which block_write_full_page() uses prepare/commit for.  (That's
-+ *   broken code anyway: it's wrong for msync()).
-+ *
-+ *   It's a rare case: affects the final partial page, for journalled data
-+ *   where the file is subject to bith write() and writepage() in the same
-+ *   transction.  To fix it we'll need a custom block_write_full_page().
-+ *   We'll probably need that anyway for journalling writepage() output.
-+ *
-+ * We don't honour synchronous mounts for writepage().  That would be
-+ * disastrous.  Any write() or metadata operation will sync the fs for
-+ * us.
-+ *
-+ * AKPM2: if all the page's buffers are mapped to disk and !data=journal,
-+ * we don't need to open a transaction here.
-+ */
-+static int ext3cow_ordered_writepage(struct page *page,
-+				struct writeback_control *wbc)
-+{
-+	struct inode *inode = page->mapping->host;
-+	struct buffer_head *page_bufs;
-+	handle_t *handle = NULL;
-+	int ret = 0;
-+	int err;
-+
-+	J_ASSERT(PageLocked(page));
-+
-+	/*
-+	 * We give up here if we're reentered, because it might be for a
-+	 * different filesystem.
-+	 */
-+	if (ext3cow_journal_current_handle())
-+		goto out_fail;
-+
-+	handle = ext3cow_journal_start(inode, ext3cow_writepage_trans_blocks(inode));
-+
-+	if (IS_ERR(handle)) {
-+		ret = PTR_ERR(handle);
-+		goto out_fail;
-+	}
-+
-+	if (!page_has_buffers(page)) {
-+		create_empty_buffers(page, inode->i_sb->s_blocksize,
-+				(1 << BH_Dirty)|(1 << BH_Uptodate));
-+	}
-+	page_bufs = page_buffers(page);
-+	walk_page_buffers(handle, page_bufs, 0,
-+			PAGE_CACHE_SIZE, NULL, bget_one);
-+
-+	ret = block_write_full_page(page, ext3cow_get_block, wbc);
-+
-+	/*
-+	 * The page can become unlocked at any point now, and
-+	 * truncate can then come in and change things.  So we
-+	 * can't touch *page from now on.  But *page_bufs is
-+	 * safe due to elevated refcount.
-+	 */
-+
-+	/*
-+	 * And attach them to the current transaction.  But only if
-+	 * block_write_full_page() succeeded.  Otherwise they are unmapped,
-+	 * and generally junk.
-+	 */
-+	if (ret == 0) {
-+		err = walk_page_buffers(handle, page_bufs, 0, PAGE_CACHE_SIZE,
-+					NULL, journal_dirty_data_fn);
-+		if (!ret)
-+			ret = err;
-+	}
-+	walk_page_buffers(handle, page_bufs, 0,
-+			PAGE_CACHE_SIZE, NULL, bput_one);
-+	err = ext3cow_journal_stop(handle);
-+	if (!ret)
-+		ret = err;
-+	return ret;
-+
-+out_fail:
-+	redirty_page_for_writepage(wbc, page);
-+	unlock_page(page);
-+	return ret;
-+}
-+
-+static int ext3cow_writeback_writepage(struct page *page,
-+				struct writeback_control *wbc)
-+{
-+	struct inode *inode = page->mapping->host;
-+	handle_t *handle = NULL;
-+	int ret = 0;
-+	int err;
-+
-+	if (ext3cow_journal_current_handle())
-+		goto out_fail;
-+
-+	handle = ext3cow_journal_start(inode, ext3cow_writepage_trans_blocks(inode));
-+	if (IS_ERR(handle)) {
-+		ret = PTR_ERR(handle);
-+		goto out_fail;
-+	}
-+
-+	if (test_opt(inode->i_sb, NOBH) && ext3cow_should_writeback_data(inode))
-+		ret = nobh_writepage(page, ext3cow_get_block, wbc);
-+	else
-+		ret = block_write_full_page(page, ext3cow_get_block, wbc);
-+
-+	err = ext3cow_journal_stop(handle);
-+	if (!ret)
-+		ret = err;
-+	return ret;
-+
-+out_fail:
-+	redirty_page_for_writepage(wbc, page);
-+	unlock_page(page);
-+	return ret;
-+}
-+
-+static int ext3cow_journalled_writepage(struct page *page,
-+				struct writeback_control *wbc)
-+{
-+	struct inode *inode = page->mapping->host;
-+	handle_t *handle = NULL;
-+	int ret = 0;
-+	int err;
-+
-+	if (ext3cow_journal_current_handle())
-+		goto no_write;
-+
-+	handle = ext3cow_journal_start(inode, ext3cow_writepage_trans_blocks(inode));
-+	if (IS_ERR(handle)) {
-+		ret = PTR_ERR(handle);
-+		goto no_write;
-+	}
-+
-+	if (!page_has_buffers(page) || PageChecked(page)) {
-+		/*
-+		 * It's mmapped pagecache.  Add buffers and journal it.  There
-+		 * doesn't seem much point in redirtying the page here.
-+		 */
-+		ClearPageChecked(page);
-+		ret = block_prepare_write(page, 0, PAGE_CACHE_SIZE,
-+					ext3cow_get_block);
-+		if (ret != 0) {
-+			ext3cow_journal_stop(handle);
-+			goto out_unlock;
-+		}
-+		ret = walk_page_buffers(handle, page_buffers(page), 0,
-+			PAGE_CACHE_SIZE, NULL, do_journal_get_write_access);
-+
-+		err = walk_page_buffers(handle, page_buffers(page), 0,
-+				PAGE_CACHE_SIZE, NULL, commit_write_fn);
-+		if (ret == 0)
-+			ret = err;
-+		EXT3COW_I(inode)->i_state |= EXT3COW_STATE_JDATA;
-+		unlock_page(page);
-+	} else {
-+		/*
-+		 * It may be a page full of checkpoint-mode buffers.  We don't
-+		 * really know unless we go poke around in the buffer_heads.
-+		 * But block_write_full_page will do the right thing.
-+		 */
-+		ret = block_write_full_page(page, ext3cow_get_block, wbc);
-+	}
-+	err = ext3cow_journal_stop(handle);
-+	if (!ret)
-+		ret = err;
-+out:
-+	return ret;
-+
-+no_write:
-+	redirty_page_for_writepage(wbc, page);
-+out_unlock:
-+	unlock_page(page);
-+	goto out;
-+}
-+
-+static int ext3cow_readpage(struct file *file, struct page *page)
-+{
-+	return mpage_readpage(page, ext3cow_get_block);
-+}
-+
-+static int
-+ext3cow_readpages(struct file *file, struct address_space *mapping,
-+		struct list_head *pages, unsigned nr_pages)
-+{
-+	return mpage_readpages(mapping, pages, nr_pages, ext3cow_get_block);
-+}
-+
-+static void ext3cow_invalidatepage(struct page *page, unsigned long offset)
-+{
-+	journal_t *journal = EXT3COW_JOURNAL(page->mapping->host);
-+
-+	/*
-+	 * If it's a full truncate we just forget about the pending dirtying
-+	 */
-+	if (offset == 0)
-+		ClearPageChecked(page);
-+
-+	journal_invalidatepage(journal, page, offset);
-+}
-+
-+static int ext3cow_releasepage(struct page *page, gfp_t wait)
-+{
-+	journal_t *journal = EXT3COW_JOURNAL(page->mapping->host);
-+
-+	WARN_ON(PageChecked(page));
-+	if (!page_has_buffers(page))
-+		return 0;
-+	return journal_try_to_free_buffers(journal, page, wait);
-+}
-+
-+/*
-+ * If the O_DIRECT write will extend the file then add this inode to the
-+ * orphan list.  So recovery will truncate it back to the original size
-+ * if the machine crashes during the write.
-+ *
-+ * If the O_DIRECT write is intantiating holes inside i_size and the machine
-+ * crashes then stale disk data _may_ be exposed inside the file.
-+ */
-+static ssize_t ext3cow_direct_IO(int rw, struct kiocb *iocb,
-+			const struct iovec *iov, loff_t offset,
-+			unsigned long nr_segs)
-+{
-+	struct file *file = iocb->ki_filp;
-+	struct inode *inode = file->f_mapping->host;
-+	struct ext3cow_inode_info *ei = EXT3COW_I(inode);
-+	handle_t *handle = NULL;
-+	ssize_t ret;
-+	int orphan = 0;
-+	size_t count = iov_length(iov, nr_segs);
-+
-+	if (rw == WRITE) {
-+		loff_t final_size = offset + count;
-+
-+		handle = ext3cow_journal_start(inode, DIO_CREDITS);
-+		if (IS_ERR(handle)) {
-+			ret = PTR_ERR(handle);
-+			goto out;
-+		}
-+		if (final_size > inode->i_size) {
-+			ret = ext3cow_orphan_add(handle, inode);
-+			if (ret)
-+				goto out_stop;
-+			orphan = 1;
-+			ei->i_disksize = inode->i_size;
-+		}
-+	}
-+
-+	ret = blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov,
-+				 offset, nr_segs,
-+				 ext3cow_get_block, NULL);
-+
-+	/*
-+	 * Reacquire the handle: ext3cow_get_block() can restart the transaction
-+	 */
-+	handle = journal_current_handle();
-+
-+out_stop:
-+	if (handle) {
-+		int err;
-+
-+		if (orphan && inode->i_nlink)
-+			ext3cow_orphan_del(handle, inode);
-+		if (orphan && ret > 0) {
-+			loff_t end = offset + ret;
-+			if (end > inode->i_size) {
-+				ei->i_disksize = end;
-+				i_size_write(inode, end);
-+				/*
-+				 * We're going to return a positive `ret'
-+				 * here due to non-zero-length I/O, so there's
-+				 * no way of reporting error returns from
-+				 * ext3cow_mark_inode_dirty() to userspace.  So
-+				 * ignore it.
-+				 */
-+				ext3cow_mark_inode_dirty(handle, inode);
-+			}
-+		}
-+		err = ext3cow_journal_stop(handle);
-+		if (ret == 0)
-+			ret = err;
-+	}
-+out:
-+	return ret;
-+}
-+
-+/*
-+ * Pages can be marked dirty completely asynchronously from ext3cow's journalling
-+ * activity.  By filemap_sync_pte(), try_to_unmap_one(), etc.  We cannot do
-+ * much here because ->set_page_dirty is called under VFS locks.  The page is
-+ * not necessarily locked.
-+ *
-+ * We cannot just dirty the page and leave attached buffers clean, because the
-+ * buffers' dirty state is "definitive".  We cannot just set the buffers dirty
-+ * or jbddirty because all the journalling code will explode.
-+ *
-+ * So what we do is to mark the page "pending dirty" and next time writepage
-+ * is called, propagate that into the buffers appropriately.
-+ */
-+static int ext3cow_journalled_set_page_dirty(struct page *page)
-+{
-+	SetPageChecked(page);
-+	return __set_page_dirty_nobuffers(page);
-+}
-+
-+static const struct address_space_operations ext3cow_ordered_aops = {
-+	.readpage	= ext3cow_readpage,
-+	.readpages	= ext3cow_readpages,
-+	.writepage	= ext3cow_ordered_writepage,
-+	.sync_page	= block_sync_page,
-+	.prepare_write	= ext3cow_prepare_write,
-+	.commit_write	= ext3cow_ordered_commit_write,
-+	.bmap		= ext3cow_bmap,
-+	.invalidatepage	= ext3cow_invalidatepage,
-+	.releasepage	= ext3cow_releasepage,
-+	.direct_IO	= ext3cow_direct_IO,
-+	.migratepage	= buffer_migrate_page,
-+};
-+
-+static const struct address_space_operations ext3cow_writeback_aops = {
-+	.readpage	= ext3cow_readpage,
-+	.readpages	= ext3cow_readpages,
-+	.writepage	= ext3cow_writeback_writepage,
-+	.sync_page	= block_sync_page,
-+	.prepare_write	= ext3cow_prepare_write,
-+	.commit_write	= ext3cow_writeback_commit_write,
-+	.bmap		= ext3cow_bmap,
-+	.invalidatepage	= ext3cow_invalidatepage,
-+	.releasepage	= ext3cow_releasepage,
-+	.direct_IO	= ext3cow_direct_IO,
-+	.migratepage	= buffer_migrate_page,
-+};
-+
-+static const struct address_space_operations ext3cow_journalled_aops = {
-+	.readpage	= ext3cow_readpage,
-+	.readpages	= ext3cow_readpages,
-+	.writepage	= ext3cow_journalled_writepage,
-+	.sync_page	= block_sync_page,
-+	.prepare_write	= ext3cow_prepare_write,
-+	.commit_write	= ext3cow_journalled_commit_write,
-+	.set_page_dirty	= ext3cow_journalled_set_page_dirty,
-+	.bmap		= ext3cow_bmap,
-+	.invalidatepage	= ext3cow_invalidatepage,
-+	.releasepage	= ext3cow_releasepage,
-+};
-+
-+void ext3cow_set_aops(struct inode *inode)
-+{
-+	if (ext3cow_should_order_data(inode))
-+		inode->i_mapping->a_ops = &ext3cow_ordered_aops;
-+	else if (ext3cow_should_writeback_data(inode))
-+		inode->i_mapping->a_ops = &ext3cow_writeback_aops;
-+	else
-+		inode->i_mapping->a_ops = &ext3cow_journalled_aops;
-+}
-+
-+/*
-+ * ext3cow_block_truncate_page() zeroes out a mapping from file offset `from'
-+ * up to the end of the block which corresponds to `from'.
-+ * This required during truncate. We need to physically zero the tail end
-+ * of that block so it doesn't yield old data if the file is later grown.
-+ */
-+static int ext3cow_block_truncate_page(handle_t *handle, struct page *page,
-+		struct address_space *mapping, loff_t from)
-+{
-+	ext3cow_fsblk_t index = from >> PAGE_CACHE_SHIFT;
-+	unsigned offset = from & (PAGE_CACHE_SIZE-1);
-+	unsigned blocksize, iblock, length, pos;
-+	struct inode *inode = mapping->host;
-+	struct buffer_head *bh;
-+	int err = 0;
-+	void *kaddr;
-+
-+	blocksize = inode->i_sb->s_blocksize;
-+	length = blocksize - (offset & (blocksize - 1));
-+	iblock = index << (PAGE_CACHE_SHIFT - inode->i_sb->s_blocksize_bits);
-+
-+	/*
-+	 * For "nobh" option,  we can only work if we don't need to
-+	 * read-in the page - otherwise we create buffers to do the IO.
-+	 */
-+	if (!page_has_buffers(page) && test_opt(inode->i_sb, NOBH) &&
-+	     ext3cow_should_writeback_data(inode) && PageUptodate(page)) {
-+		kaddr = kmap_atomic(page, KM_USER0);
-+		memset(kaddr + offset, 0, length);
-+		flush_dcache_page(page);
-+		kunmap_atomic(kaddr, KM_USER0);
-+		set_page_dirty(page);
-+		goto unlock;
-+	}
-+
-+	if (!page_has_buffers(page))
-+		create_empty_buffers(page, blocksize, 0);
-+
-+	/* Find the buffer that contains "offset" */
-+	bh = page_buffers(page);
-+	pos = blocksize;
-+	while (offset >= pos) {
-+		bh = bh->b_this_page;
-+		iblock++;
-+		pos += blocksize;
-+	}
-+
-+	err = 0;
-+	if (buffer_freed(bh)) {
-+		BUFFER_TRACE(bh, "freed: skip");
-+		goto unlock;
-+	}
-+
-+	if (!buffer_mapped(bh)) {
-+		BUFFER_TRACE(bh, "unmapped");
-+		ext3cow_get_block(inode, iblock, bh, 0);
-+		/* unmapped? It's a hole - nothing to do */
-+		if (!buffer_mapped(bh)) {
-+			BUFFER_TRACE(bh, "still unmapped");
-+			goto unlock;
-+		}
-+	}
-+
-+	/* Ok, it's mapped. Make sure it's up-to-date */
-+	if (PageUptodate(page))
-+		set_buffer_uptodate(bh);
-+
-+	if (!buffer_uptodate(bh)) {
-+		err = -EIO;
-+		ll_rw_block(READ, 1, &bh);
-+		wait_on_buffer(bh);
-+		/* Uhhuh. Read error. Complain and punt. */
-+		if (!buffer_uptodate(bh))
-+			goto unlock;
-+	}
-+
-+	if (ext3cow_should_journal_data(inode)) {
-+		BUFFER_TRACE(bh, "get write access");
-+		err = ext3cow_journal_get_write_access(handle, bh);
-+		if (err)
-+			goto unlock;
-+	}
-+
-+	kaddr = kmap_atomic(page, KM_USER0);
-+	memset(kaddr + offset, 0, length);
-+	flush_dcache_page(page);
-+	kunmap_atomic(kaddr, KM_USER0);
-+
-+	BUFFER_TRACE(bh, "zeroed end of block");
-+
-+	err = 0;
-+	if (ext3cow_should_journal_data(inode)) {
-+		err = ext3cow_journal_dirty_metadata(handle, bh);
-+	} else {
-+		if (ext3cow_should_order_data(inode))
-+			err = ext3cow_journal_dirty_data(handle, bh);
-+		mark_buffer_dirty(bh);
-+	}
-+
-+unlock:
-+	unlock_page(page);
-+	page_cache_release(page);
-+	return err;
-+}
-+
-+/*
-+ * Probably it should be a library function... search for first non-zero word
-+ * or memcmp with zero_page, whatever is better for particular architecture.
-+ * Linus?
-+ */
-+static inline int all_zeroes(__le32 *p, __le32 *q)
-+{
-+	while (p < q)
-+		if (*p++)
-+			return 0;
-+	return 1;
-+}
-+
-+/**
-+ *	ext3cow_find_shared - find the indirect blocks for partial truncation.
-+ *	@inode:	  inode in question
-+ *	@depth:	  depth of the affected branch
-+ *	@offsets: offsets of pointers in that branch (see ext3cow_block_to_path)
-+ *	@chain:	  place to store the pointers to partial indirect blocks
-+ *	@top:	  place to the (detached) top of branch
-+ *
-+ *	This is a helper function used by ext3cow_truncate().
-+ *
-+ *	When we do truncate() we may have to clean the ends of several
-+ *	indirect blocks but leave the blocks themselves alive. Block is
-+ *	partially truncated if some data below the new i_size is refered
-+ *	from it (and it is on the path to the first completely truncated
-+ *	data block, indeed).  We have to free the top of that path along
-+ *	with everything to the right of the path. Since no allocation
-+ *	past the truncation point is possible until ext3cow_truncate()
-+ *	finishes, we may safely do the latter, but top of branch may
-+ *	require special attention - pageout below the truncation point
-+ *	might try to populate it.
-+ *
-+ *	We atomically detach the top of branch from the tree, store the
-+ *	block number of its root in *@top, pointers to buffer_heads of
-+ *	partially truncated blocks - in @chain[].bh and pointers to
-+ *	their last elements that should not be removed - in
-+ *	@chain[].p. Return value is the pointer to last filled element
-+ *	of @chain.
-+ *
-+ *	The work left to caller to do the actual freeing of subtrees:
-+ *		a) free the subtree starting from *@top
-+ *		b) free the subtrees whose roots are stored in
-+ *			(@chain[i].p+1 .. end of @chain[i].bh->b_data)
-+ *		c) free the subtrees growing from the inode past the @chain[0].
-+ *			(no partially truncated stuff there).  */
-+
-+static Indirect *ext3cow_find_shared(struct inode *inode, int depth,
-+			int offsets[4], Indirect chain[4], __le32 *top)
-+{
-+	Indirect *partial, *p;
-+	int k, err, cow;
-+
-+	*top = 0;
-+	/* Make k index the deepest non-null offest + 1 */
-+	for (k = depth; k > 1 && !offsets[k-1]; k--)
-+		;
-+	partial = ext3cow_get_branch(inode, k, offsets, chain, &err, &cow, 0);
-+	/* Writer: pointers */
-+	if (!partial)
-+		partial = chain + k-1;
-+	/*
-+	 * If the branch acquired continuation since we've looked at it -
-+	 * fine, it should all survive and (new) top doesn't belong to us.
-+	 */
-+	if (!partial->key && *partial->p)
-+		/* Writer: end */
-+		goto no_top;
-+	for (p=partial; p>chain && all_zeroes((__le32*)p->bh->b_data,p->p); p--)
-+		;
-+	/*
-+	 * OK, we've found the last block that must survive. The rest of our
-+	 * branch should be detached before unlocking. However, if that rest
-+	 * of branch is all ours and does not grow immediately from the inode
-+	 * it's easier to cheat and just decrement partial->p.
-+	 */
-+	if (p == chain + k - 1 && p > chain) {
-+		p->p--;
-+	} else {
-+		*top = *p->p;
-+		/* Nope, don't do this in ext3cow.  Must leave the tree intact */
-+#if 0
-+		*p->p = 0;
-+#endif
-+	}
-+	/* Writer: end */
-+
-+	while(partial > p) {
-+		brelse(partial->bh);
-+		partial--;
-+	}
-+no_top:
-+	return partial;
-+}
-+
-+/*
-+ * Zero a number of block pointers in either an inode or an indirect block.
-+ * If we restart the transaction we must again get write access to the
-+ * indirect block for further modification.
-+ *
-+ * We release `count' blocks on disk, but (last - first) may be greater
-+ * than `count' because there can be holes in there.
-+ */
-+static void ext3cow_clear_blocks(handle_t *handle, struct inode *inode,
-+		struct buffer_head *bh, ext3cow_fsblk_t block_to_free,
-+		unsigned long count, __le32 *first, __le32 *last)
-+{
-+	__le32 *p;
-+	if (try_to_extend_transaction(handle, inode)) {
-+		if (bh) {
-+			BUFFER_TRACE(bh, "call ext3cow_journal_dirty_metadata");
-+			ext3cow_journal_dirty_metadata(handle, bh);
-+		}
-+		ext3cow_mark_inode_dirty(handle, inode);
-+		ext3cow_journal_test_restart(handle, inode);
-+		if (bh) {
-+			BUFFER_TRACE(bh, "retaking write access");
-+			ext3cow_journal_get_write_access(handle, bh);
-+		}
-+	}
-+
-+	/*
-+	 * Any buffers which are on the journal will be in memory. We find
-+	 * them on the hash table so journal_revoke() will run journal_forget()
-+	 * on them.  We've already detached each block from the file, so
-+	 * bforget() in journal_forget() should be safe.
-+	 *
-+	 * AKPM: turn on bforget in journal_forget()!!!
-+	 */
-+	for (p = first; p < last; p++) {
-+		u32 nr = le32_to_cpu(*p);
-+		if (nr) {
-+			struct buffer_head *bh;
-+
-+			*p = 0;
-+			bh = sb_find_get_block(inode->i_sb, nr);
-+			ext3cow_forget(handle, 0, inode, bh, nr);
-+		}
-+	}
-+
-+	ext3cow_free_blocks(handle, inode, block_to_free, count);
-+}
-+
-+/**
-+ * ext3cow_free_data - free a list of data blocks
-+ * @handle:	handle for this transaction
-+ * @inode:	inode we are dealing with
-+ * @this_bh:	indirect buffer_head which contains *@first and *@last
-+ * @first:	array of block numbers
-+ * @last:	points immediately past the end of array
-+ *
-+ * We are freeing all blocks refered from that array (numbers are stored as
-+ * little-endian 32-bit) and updating @inode->i_blocks appropriately.
-+ *
-+ * We accumulate contiguous runs of blocks to free.  Conveniently, if these
-+ * blocks are contiguous then releasing them at one time will only affect one
-+ * or two bitmap blocks (+ group descriptor(s) and superblock) and we won't
-+ * actually use a lot of journal space.
-+ *
-+ * @this_bh will be %NULL if @first and @last point into the inode's direct
-+ * block pointers.
-+ */
-+static void ext3cow_free_data(handle_t *handle, struct inode *inode,
-+			   struct buffer_head *this_bh,
-+			   __le32 *first, __le32 *last)
-+{
-+	ext3cow_fsblk_t block_to_free = 0;    /* Starting block # of a run */
-+	unsigned long count = 0;	    /* Number of blocks in the run */
-+	__le32 *block_to_free_p = NULL;	    /* Pointer into inode/ind
-+					       corresponding to
-+					       block_to_free */
-+	ext3cow_fsblk_t nr;		    /* Current block # */
-+	__le32 *p;			    /* Pointer into inode/ind
-+					       for current block */
-+	int err;
-+
-+	if (this_bh) {				/* For indirect block */
-+		BUFFER_TRACE(this_bh, "get_write_access");
-+		err = ext3cow_journal_get_write_access(handle, this_bh);
-+		/* Important: if we can't update the indirect pointers
-+		 * to the blocks, we can't free them. */
-+		if (err)
-+			return;
-+	}
-+
-+	for (p = first; p < last; p++) {
-+		nr = le32_to_cpu(*p);
-+		if (nr) {
-+			/* accumulate blocks to free if they're contiguous */
-+			if (count == 0) {
-+				block_to_free = nr;
-+				block_to_free_p = p;
-+				count = 1;
-+			} else if (nr == block_to_free + count) {
-+				count++;
-+			} else {
-+				ext3cow_clear_blocks(handle, inode, this_bh,
-+						  block_to_free,
-+						  count, block_to_free_p, p);
-+				block_to_free = nr;
-+				block_to_free_p = p;
-+				count = 1;
-+			}
-+		}
-+	}
-+
-+	if (count > 0)
-+		ext3cow_clear_blocks(handle, inode, this_bh, block_to_free,
-+				  count, block_to_free_p, p);
-+
-+	if (this_bh) {
-+		BUFFER_TRACE(this_bh, "call ext3cow_journal_dirty_metadata");
-+		ext3cow_journal_dirty_metadata(handle, this_bh);
-+	}
-+}
-+
-+/**
-+ *	ext3cow_free_branches - free an array of branches
-+ *	@handle: JBD handle for this transaction
-+ *	@inode:	inode we are dealing with
-+ *	@parent_bh: the buffer_head which contains *@first and *@last
-+ *	@first:	array of block numbers
-+ *	@last:	pointer immediately past the end of array
-+ *	@depth:	depth of the branches to free
-+ *
-+ *	We are freeing all blocks refered from these branches (numbers are
-+ *	stored as little-endian 32-bit) and updating @inode->i_blocks
-+ *	appropriately.
-+ */
-+static void ext3cow_free_branches(handle_t *handle, struct inode *inode,
-+			       struct buffer_head *parent_bh,
-+			       __le32 *first, __le32 *last, int depth)
-+{
-+	ext3cow_fsblk_t nr;
-+	__le32 *p;
-+
-+	if (is_handle_aborted(handle))
-+		return;
-+
-+	if (depth--) {
-+		struct buffer_head *bh;
-+		int addr_per_block = EXT3COW_ADDR_PER_BLOCK(inode->i_sb);
-+    u32 *bitmap_word = NULL, *first_block = NULL;
-+    unsigned int count = 0, cur = 0, bcount = 0;
-+    int i = 0;
-+		p = last;
-+		while (--p >= first) {
-+			nr = le32_to_cpu(*p);
-+			if (!nr)
-+				continue;		/* A hole */
-+
-+			/* Go read the buffer for the next level down */
-+			bh = sb_bread(inode->i_sb, nr);
-+
-+			/*
-+			 * A read failure? Report error and clear slot
-+			 * (should be rare).
-+			 */
-+			if (!bh) {
-+				ext3cow_error(inode->i_sb, "ext3cow_free_branches",
-+					   "Read failure, inode=%lu, block="E3FSBLK,
-+					   inode->i_ino, nr);
-+				continue;
-+			}
-+      /* Only free the branches that have been newly allocated - znjp */
-+      /* Also, set the bits back to 0 in the bitmap -znjp */
-+      cur = 0;
-+      count = 0;
-+      bitmap_word = (u32*)bh->b_data + addr_per_block;
-+      
-+      for(bcount = 0; bcount < EXT3COW_COWBITMAPS_PER_IBLOCK(inode->i_sb);
-+          bcount++){
-+        for(i = 0; i < EXT3COW_COWBITMAP_SIZE; i++, cur++){
-+          if(cur >= addr_per_block)
-+            goto free;
-+          if(le32_to_cpu(*bitmap_word) & (1UL << i)){
-+            if(count == 0){
-+              first_block = (u32*)bh->b_data + cur;
-+              count = 1;
-+            }else if((u32*)first_block + count == (u32*)bh->b_data + cur){
-+              count++;
-+            }else{
-+              BUFFER_TRACE(bh, "free child branches");
-+              ext3cow_free_branches(handle, inode, bh, (u32*)first_block,
-+                                    (u32*)first_block + count, depth);
-+              first_block = (u32*)bh->b_data + cur;
-+              count = 1;
-+            }
-+            /* Set the bit in the bitmap back to 0 */
-+            *bitmap_word ^= (1UL << i);
-+          }
-+        }
-+        (u32*)bitmap_word++;
-+      }   
-+    free:
-+      if(count){
-+        BUFFER_TRACE(bh, "free child branches");
-+        ext3cow_free_branches(handle, inode, bh, (u32*)first_block,
-+                              (u32*)first_block + count, depth);
-+      }
-+
-+			/*
-+			 * We've probably journalled the indirect block several
-+			 * times during the truncate.  But it's no longer
-+			 * needed and we now drop it from the transaction via
-+			 * journal_revoke().
-+			 *
-+			 * That's easy if it's exclusively part of this
-+			 * transaction.  But if it's part of the committing
-+			 * transaction then journal_forget() will simply
-+			 * brelse() it.  That means that if the underlying
-+			 * block is reallocated in ext3cow_get_block(),
-+			 * unmap_underlying_metadata() will find this block
-+			 * and will try to get rid of it.  damn, damn.
-+			 *
-+			 * If this block has already been committed to the
-+			 * journal, a revoke record will be written.  And
-+			 * revoke records must be emitted *before* clearing
-+			 * this block's bit in the bitmaps.
-+			 */
-+			ext3cow_forget(handle, 1, inode, bh, bh->b_blocknr);
-+
-+			/*
-+			 * Everything below this this pointer has been
-+			 * released.  Now let this top-of-subtree go.
-+			 *
-+			 * We want the freeing of this indirect block to be
-+			 * atomic in the journal with the updating of the
-+			 * bitmap block which owns it.  So make some room in
-+			 * the journal.
-+			 *
-+			 * We zero the parent pointer *after* freeing its
-+			 * pointee in the bitmaps, so if extend_transaction()
-+			 * for some reason fails to put the bitmap changes and
-+			 * the release into the same transaction, recovery
-+			 * will merely complain about releasing a free block,
-+			 * rather than leaking blocks.
-+			 */
-+			if (is_handle_aborted(handle))
-+				return;
-+			if (try_to_extend_transaction(handle, inode)) {
-+				ext3cow_mark_inode_dirty(handle, inode);
-+				ext3cow_journal_test_restart(handle, inode);
-+			}
-+
-+			ext3cow_free_blocks(handle, inode, nr, 1);
-+
-+			if (parent_bh) {
-+				/*
-+				 * The block which we have just freed is
-+				 * pointed to by an indirect block: journal it
-+				 */
-+				BUFFER_TRACE(parent_bh, "get_write_access");
-+				if (!ext3cow_journal_get_write_access(handle,
-+								   parent_bh)){
-+					*p = 0;
-+					BUFFER_TRACE(parent_bh,
-+					"call ext3cow_journal_dirty_metadata");
-+					ext3cow_journal_dirty_metadata(handle,
-+								    parent_bh);
-+				}
-+			}
-+		}
-+	} else {
-+		/* We have reached the bottom of the tree. */
-+		BUFFER_TRACE(parent_bh, "free data blocks");
-+		ext3cow_free_data(handle, inode, parent_bh, first, last);
-+	}
-+}
-+
-+/*
-+ * ext3cow_truncate()
-+ *
-+ * We block out ext3cow_get_block() block instantiations across the entire
-+ * transaction, and VFS/VM ensures that ext3cow_truncate() cannot run
-+ * simultaneously on behalf of the same inode.
-+ *
-+ * As we work through the truncate and commmit bits of it to the journal there
-+ * is one core, guiding principle: the file's tree must always be consistent on
-+ * disk.  We must be able to restart the truncate after a crash.
-+ *
-+ * The file's tree may be transiently inconsistent in memory (although it
-+ * probably isn't), but whenever we close off and commit a journal transaction,
-+ * the contents of (the filesystem + the journal) must be consistent and
-+ * restartable.  It's pretty simple, really: bottom up, right to left (although
-+ * left-to-right works OK too).
-+ *
-+ * Note that at recovery time, journal replay occurs *before* the restart of
-+ * truncate against the orphan inode list.
-+ *
-+ * The committed inode has the new, desired i_size (which is the same as
-+ * i_disksize in this case).  After a crash, ext3cow_orphan_cleanup() will see
-+ * that this inode's truncate did not complete and it will again call
-+ * ext3cow_truncate() to have another go.  So there will be instantiated blocks
-+ * to the right of the truncation point in a crashed ext3cow filesystem.  But
-+ * that's fine - as long as they are linked from the inode, the post-crash
-+ * ext3cow_truncate() run will find them and release them.
-+ */
-+void ext3cow_truncate(struct inode *inode)
-+{
-+	handle_t *handle;
-+	struct ext3cow_inode_info *ei = EXT3COW_I(inode);
-+	__le32 *i_data = ei->i_data;
-+	int addr_per_block = EXT3COW_ADDR_PER_BLOCK(inode->i_sb);
-+	struct address_space *mapping = inode->i_mapping;
-+	int offsets[4];
-+	Indirect chain[4];
-+	Indirect *partial;
-+	__le32 nr = 0;
-+	int n;
-+	long last_block;
-+	unsigned blocksize = inode->i_sb->s_blocksize;
-+	struct page *page;
-+
-+
-+	if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
-+	    S_ISLNK(inode->i_mode)))
-+		return;
-+	if (ext3cow_inode_is_fast_symlink(inode))
-+		return;
-+	if (IS_APPEND(inode) || IS_IMMUTABLE(inode) || 
-+      EXT3COW_IS_UNCHANGEABLE(inode)) /* znjp */
-+		return;
-+
-+  /* If the inode needs to be dup'd, then there are no blocks
-+   * to truncate; they all are part of the previous version.
-+   * - znjp */
-+  if(EXT3COW_S_EPOCHNUMBER(inode->i_sb) > EXT3COW_I_EPOCHNUMBER(inode)){
-+    ext3cow_dup_inode(NULL, inode);
-+    return;
-+  }
-+
-+	/*
-+	 * We have to lock the EOF page here, because lock_page() nests
-+	 * outside journal_start().
-+	 */
-+	if ((inode->i_size & (blocksize - 1)) == 0) {
-+		/* Block boundary? Nothing to do */
-+		page = NULL;
-+	} else {
-+		page = grab_cache_page(mapping,
-+				inode->i_size >> PAGE_CACHE_SHIFT);
-+		if (!page)
-+			return;
-+	}
-+
-+	handle = start_transaction(inode);
-+	if (IS_ERR(handle)) {
-+		if (page) {
-+			clear_highpage(page);
-+			flush_dcache_page(page);
-+			unlock_page(page);
-+			page_cache_release(page);
-+		}
-+		return;		/* AKPM: return what? */
-+	}
-+
-+	last_block = (inode->i_size + blocksize-1)
-+					>> EXT3COW_BLOCK_SIZE_BITS(inode->i_sb);
-+
-+	if (page)
-+		ext3cow_block_truncate_page(handle, page, mapping, inode->i_size);
-+
-+	n = ext3cow_block_to_path(inode, last_block, offsets, NULL);
-+	if (n == 0)
-+		goto out_stop;	/* error */
-+
-+	/*
-+	 * OK.  This truncate is going to happen.  We add the inode to the
-+	 * orphan list, so that if this truncate spans multiple transactions,
-+	 * and we crash, we will resume the truncate when the filesystem
-+	 * recovers.  It also marks the inode dirty, to catch the new size.
-+	 *
-+	 * Implication: the file must always be in a sane, consistent
-+	 * truncatable state while each transaction commits.
-+	 */
-+	if (ext3cow_orphan_add(handle, inode))
-+		goto out_stop;
-+
-+	/*
-+	 * The orphan list entry will now protect us from any crash which
-+	 * occurs before the truncate completes, so it is now safe to propagate
-+	 * the new, shorter inode size (held for now in i_size) into the
-+	 * on-disk inode. We do this via i_disksize, which is the value which
-+	 * ext3cow *really* writes onto the disk inode.
-+	 */
-+	ei->i_disksize = inode->i_size;
-+
-+	/*
-+	 * From here we block out all ext3cow_get_block() callers who want to
-+	 * modify the block allocation tree.
-+	 */
-+	mutex_lock(&ei->truncate_mutex);
-+
-+	if (n == 1) {		/* direct blocks */
-+    unsigned int count = 0;
-+    unsigned long block_to_free = 0;
-+    unsigned long b = 0; 
-+
-+    /* We only want to remove blocks that were allocated in this
-+     * epoch, i.e., have 1 bit in the bitmap. -znjp */
-+    /* If we're going to truncate a block, we should its
-+     * corresponding bit in the bitmap back to 0, meaning,
-+     * it needs to be allocated - znjp */ 
-+    for(b = offsets[0]; b < EXT3COW_NDIR_BLOCKS; b++){
-+      if(EXT3COW_I(inode)->i_cow_bitmap & (1UL << b)){
-+        if(count == 0){
-+          block_to_free = b;
-+          count = 1;
-+        }else if(b == block_to_free + count){
-+          count++;
-+        }else{
-+          ext3cow_free_data(handle, inode, NULL, i_data + (int)block_to_free,
-+                            i_data + (int)(block_to_free + count));
-+          block_to_free = b;
-+          count = 1;
-+        }
-+        /* Turn off the bit in the bitmap */
-+        EXT3COW_I(inode)->i_cow_bitmap ^= (1UL << b);
-+      }
-+    }
-+    if(count > 0)
-+      ext3cow_free_data(handle, inode, NULL, i_data+(int)block_to_free,
-+                        i_data + (int)(block_to_free + count));
-+		goto do_indirects;
-+	}
-+
-+	partial = ext3cow_find_shared(inode, n, offsets, chain, &nr);
-+	/* Kill the top of shared branch (not detached) */
-+	if (nr) {
-+		if (partial == chain) {
-+			/* Shared branch grows from the inode */
-+			ext3cow_free_branches(handle, inode, NULL,
-+					   &nr, &nr+1, (chain+n-1) - partial);
-+			*partial->p = 0;
-+			/*
-+			 * We mark the inode dirty prior to restart,
-+			 * and prior to stop.  No need for it here.
-+			 */
-+		} else {
-+			/* Shared branch grows from an indirect block */
-+			BUFFER_TRACE(partial->bh, "get_write_access");
-+			ext3cow_free_branches(handle, inode, partial->bh,
-+					partial->p,
-+					partial->p+1, (chain+n-1) - partial);
-+		}
-+	}
-+	/* Clear the ends of indirect blocks on the shared branch */
-+	while (partial > chain) {
-+		ext3cow_free_branches(handle, inode, partial->bh, partial->p + 1,
-+				   (__le32*)partial->bh->b_data+addr_per_block,
-+				   (chain+n-1) - partial);
-+		BUFFER_TRACE(partial->bh, "call brelse");
-+		brelse (partial->bh);
-+		partial--;
-+	}
-+do_indirects:
-+	/* Kill the remaining (whole) subtrees */
-+  /* Unless we don't have to.  If the indirect block has a 0 bit
-+   * then all of the children do too, so we can skip the branch - znjp
-+   */
-+	switch (offsets[0]) {
-+	default:
-+   if(EXT3COW_I(inode)->i_cow_bitmap & (1UL << EXT3COW_IND_BLOCK)){
-+     nr = i_data[EXT3COW_IND_BLOCK];
-+     if (nr) {
-+       ext3cow_free_branches(handle, inode, NULL, &nr, &nr+1, 1);
-+       i_data[EXT3COW_IND_BLOCK] = 0;
-+     }
-+     /* And set bitmap back to 0 */
-+     EXT3COW_I(inode)->i_cow_bitmap ^= (1UL << EXT3COW_IND_BLOCK);
-+   }
-+	case EXT3COW_IND_BLOCK:
-+   if(EXT3COW_I(inode)->i_cow_bitmap & (1UL << EXT3COW_DIND_BLOCK)){
-+     nr = i_data[EXT3COW_DIND_BLOCK];
-+     if (nr) {
-+       ext3cow_free_branches(handle, inode, NULL, &nr, &nr+1, 2);
-+       i_data[EXT3COW_DIND_BLOCK] = 0;
-+     }
-+     EXT3COW_I(inode)->i_cow_bitmap ^= (1UL << EXT3COW_DIND_BLOCK);
-+   }
-+	case EXT3COW_DIND_BLOCK:
-+   if(EXT3COW_I(inode)->i_cow_bitmap & (1UL << EXT3COW_TIND_BLOCK)){
-+     nr = i_data[EXT3COW_TIND_BLOCK];
-+     if (nr) {
-+       ext3cow_free_branches(handle, inode, NULL, &nr, &nr+1, 3);
-+       i_data[EXT3COW_TIND_BLOCK] = 0;
-+     }
-+     EXT3COW_I(inode)->i_cow_bitmap ^= (1UL << EXT3COW_TIND_BLOCK);
-+   }
-+	case EXT3COW_TIND_BLOCK:
-+		;
-+	}
-+
-+	ext3cow_discard_reservation(inode);
-+
-+	mutex_unlock(&ei->truncate_mutex);
-+	inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC;
-+	ext3cow_mark_inode_dirty(handle, inode);
-+
-+	/*
-+	 * In a multi-transaction truncate, we only make the final transaction
-+	 * synchronous
-+	 */
-+	if (IS_SYNC(inode))
-+		handle->h_sync = 1;
-+out_stop:
-+	/*
-+	 * If this was a simple ftruncate(), and the file will remain alive
-+	 * then we need to clear up the orphan record which we created above.
-+	 * However, if this was a real unlink then we were called by
-+	 * ext3cow_delete_inode(), and we allow that function to clean up the
-+	 * orphan info for us.
-+	 */
-+	if (inode->i_nlink)
-+		ext3cow_orphan_del(handle, inode);
-+
-+	ext3cow_journal_stop(handle);
-+}
-+
-+static ext3cow_fsblk_t ext3cow_get_inode_block(struct super_block *sb,
-+		unsigned long ino, struct ext3cow_iloc *iloc)
-+{
-+	unsigned long desc, group_desc, block_group;
-+	unsigned long offset;
-+	ext3cow_fsblk_t block;
-+	struct buffer_head *bh;
-+	struct ext3cow_group_desc * gdp;
-+
-+	if (!ext3cow_valid_inum(sb, ino)) {
-+		/*
-+		 * This error is already checked for in namei.c unless we are
-+		 * looking at an NFS filehandle, in which case no error
-+		 * report is needed
-+		 */
-+		return 0;
-+	}
-+
-+	block_group = (ino - 1) / EXT3COW_INODES_PER_GROUP(sb);
-+	if (block_group >= EXT3COW_SB(sb)->s_groups_count) {
-+		ext3cow_error(sb,"ext3cow_get_inode_block","group >= groups count");
-+		return 0;
-+	}
-+	smp_rmb();
-+	group_desc = block_group >> EXT3COW_DESC_PER_BLOCK_BITS(sb);
-+	desc = block_group & (EXT3COW_DESC_PER_BLOCK(sb) - 1);
-+	bh = EXT3COW_SB(sb)->s_group_desc[group_desc];
-+	if (!bh) {
-+		ext3cow_error (sb, "ext3cow_get_inode_block",
-+			    "Descriptor not loaded");
-+		return 0;
-+	}
-+
-+	gdp = (struct ext3cow_group_desc *)bh->b_data;
-+	/*
-+	 * Figure out the offset within the block group inode table
-+	 */
-+	offset = ((ino - 1) % EXT3COW_INODES_PER_GROUP(sb)) *
-+		EXT3COW_INODE_SIZE(sb);
-+	block = le32_to_cpu(gdp[desc].bg_inode_table) +
-+		(offset >> EXT3COW_BLOCK_SIZE_BITS(sb));
-+
-+	iloc->block_group = block_group;
-+	iloc->offset = offset & (EXT3COW_BLOCK_SIZE(sb) - 1);
-+	return block;
-+}
-+
-+/*
-+ * ext3cow_get_inode_loc returns with an extra refcount against the inode's
-+ * underlying buffer_head on success. If 'in_mem' is true, we have all
-+ * data in memory that is needed to recreate the on-disk version of this
-+ * inode.
-+ */
-+static int __ext3cow_get_inode_loc(struct inode *inode,
-+				struct ext3cow_iloc *iloc, int in_mem)
-+{
-+	ext3cow_fsblk_t block;
-+	struct buffer_head *bh;
-+
-+	block = ext3cow_get_inode_block(inode->i_sb, inode->i_ino, iloc);
-+	if (!block)
-+		return -EIO;
-+
-+	bh = sb_getblk(inode->i_sb, block);
-+	if (!bh) {
-+		ext3cow_error (inode->i_sb, "ext3cow_get_inode_loc",
-+				"unable to read inode block - "
-+				"inode=%lu, block="E3FSBLK,
-+				 inode->i_ino, block);
-+		return -EIO;
-+	}
-+	if (!buffer_uptodate(bh)) {
-+		lock_buffer(bh);
-+		if (buffer_uptodate(bh)) {
-+			/* someone brought it uptodate while we waited */
-+			unlock_buffer(bh);
-+			goto has_buffer;
-+		}
-+
-+		/*
-+		 * If we have all information of the inode in memory and this
-+		 * is the only valid inode in the block, we need not read the
-+		 * block.
-+		 */
-+		if (in_mem) {
-+			struct buffer_head *bitmap_bh;
-+			struct ext3cow_group_desc *desc;
-+			int inodes_per_buffer;
-+			int inode_offset, i;
-+			int block_group;
-+			int start;
-+
-+			block_group = (inode->i_ino - 1) /
-+					EXT3COW_INODES_PER_GROUP(inode->i_sb);
-+			inodes_per_buffer = bh->b_size /
-+				EXT3COW_INODE_SIZE(inode->i_sb);
-+			inode_offset = ((inode->i_ino - 1) %
-+					EXT3COW_INODES_PER_GROUP(inode->i_sb));
-+			start = inode_offset & ~(inodes_per_buffer - 1);
-+
-+			/* Is the inode bitmap in cache? */
-+			desc = ext3cow_get_group_desc(inode->i_sb,
-+						block_group, NULL);
-+			if (!desc)
-+				goto make_io;
-+
-+			bitmap_bh = sb_getblk(inode->i_sb,
-+					le32_to_cpu(desc->bg_inode_bitmap));
-+			if (!bitmap_bh)
-+				goto make_io;
-+
-+			/*
-+			 * If the inode bitmap isn't in cache then the
-+			 * optimisation may end up performing two reads instead
-+			 * of one, so skip it.
-+			 */
-+			if (!buffer_uptodate(bitmap_bh)) {
-+				brelse(bitmap_bh);
-+				goto make_io;
-+			}
-+			for (i = start; i < start + inodes_per_buffer; i++) {
-+				if (i == inode_offset)
-+					continue;
-+				if (ext3cow_test_bit(i, bitmap_bh->b_data))
-+					break;
-+			}
-+			brelse(bitmap_bh);
-+			if (i == start + inodes_per_buffer) {
-+				/* all other inodes are free, so skip I/O */
-+				memset(bh->b_data, 0, bh->b_size);
-+				set_buffer_uptodate(bh);
-+				unlock_buffer(bh);
-+				goto has_buffer;
-+			}
-+		}
-+
-+make_io:
-+		/*
-+		 * There are other valid inodes in the buffer, this inode
-+		 * has in-inode xattrs, or we don't have this inode in memory.
-+		 * Read the block from disk.
-+		 */
-+		get_bh(bh);
-+		bh->b_end_io = end_buffer_read_sync;
-+		submit_bh(READ_META, bh);
-+		wait_on_buffer(bh);
-+		if (!buffer_uptodate(bh)) {
-+			ext3cow_error(inode->i_sb, "ext3cow_get_inode_loc",
-+					"unable to read inode block - "
-+					"inode=%lu, block="E3FSBLK,
-+					inode->i_ino, block);
-+			brelse(bh);
-+			return -EIO;
-+		}
-+	}
-+has_buffer:
-+	iloc->bh = bh;
-+	return 0;
-+}
-+
-+int ext3cow_get_inode_loc(struct inode *inode, struct ext3cow_iloc *iloc)
-+{
-+	/* We have all inode data except xattrs in memory here. */
-+	return __ext3cow_get_inode_loc(inode, iloc,
-+		!(EXT3COW_I(inode)->i_state & EXT3COW_STATE_XATTR));
-+}
-+
-+void ext3cow_set_inode_flags(struct inode *inode)
-+{
-+	unsigned int flags = EXT3COW_I(inode)->i_flags;
-+
-+	inode->i_flags &= ~(S_SYNC|S_APPEND|S_IMMUTABLE|S_NOATIME|S_DIRSYNC);
-+	if (flags & EXT3COW_SYNC_FL)
-+		inode->i_flags |= S_SYNC;
-+	if (flags & EXT3COW_APPEND_FL)
-+		inode->i_flags |= S_APPEND;
-+	if (flags & EXT3COW_IMMUTABLE_FL)
-+		inode->i_flags |= S_IMMUTABLE;
-+	if (flags & EXT3COW_NOATIME_FL)
-+		inode->i_flags |= S_NOATIME;
-+	if (flags & EXT3COW_DIRSYNC_FL)
-+		inode->i_flags |= S_DIRSYNC;
-+}
-+
-+void ext3cow_read_inode(struct inode * inode)
-+{
-+	struct ext3cow_iloc iloc;
-+	struct ext3cow_inode *raw_inode;
-+	struct ext3cow_inode_info *ei = EXT3COW_I(inode);
-+	struct buffer_head *bh;
-+	int block;
-+
-+#ifdef CONFIG_EXT3COW_FS_POSIX_ACL
-+	ei->i_acl = EXT3COW_ACL_NOT_CACHED;
-+	ei->i_default_acl = EXT3COW_ACL_NOT_CACHED;
-+#endif
-+	ei->i_block_alloc_info = NULL;
-+
-+	if (__ext3cow_get_inode_loc(inode, &iloc, 0))
-+		goto bad_inode;
-+	bh = iloc.bh;
-+	raw_inode = ext3cow_raw_inode(&iloc);
-+	inode->i_mode = le16_to_cpu(raw_inode->i_mode);
-+	inode->i_uid = (uid_t)le16_to_cpu(raw_inode->i_uid_low);
-+	inode->i_gid = (gid_t)le16_to_cpu(raw_inode->i_gid_low);
-+	if(!(test_opt (inode->i_sb, NO_UID32))) {
-+		inode->i_uid |= le16_to_cpu(raw_inode->i_uid_high) << 16;
-+		inode->i_gid |= le16_to_cpu(raw_inode->i_gid_high) << 16;
-+	}
-+	inode->i_nlink = le16_to_cpu(raw_inode->i_links_count);
-+	inode->i_size = le32_to_cpu(raw_inode->i_size);
-+	inode->i_atime.tv_sec = le32_to_cpu(raw_inode->i_atime);
-+	inode->i_ctime.tv_sec = le32_to_cpu(raw_inode->i_ctime);
-+	inode->i_mtime.tv_sec = le32_to_cpu(raw_inode->i_mtime);
-+	inode->i_atime.tv_nsec = inode->i_ctime.tv_nsec = inode->i_mtime.tv_nsec = 0;
-+
-+	ei->i_state = 0;
-+	ei->i_dir_start_lookup = 0;
-+	ei->i_dtime = le32_to_cpu(raw_inode->i_dtime);
-+	/* We now have enough fields to check if the inode was active or not.
-+	 * This is needed because nfsd might try to access dead inodes
-+	 * the test is that same one that e2fsck uses
-+	 * NeilBrown 1999oct15
-+	 */
-+	if (inode->i_nlink == 0) {
-+		if (inode->i_mode == 0 ||
-+		    !(EXT3COW_SB(inode->i_sb)->s_mount_state & EXT3COW_ORPHAN_FS)) {
-+			/* this inode is deleted */
-+			brelse (bh);
-+			goto bad_inode;
-+		}
-+		/* The only unlinked inodes we let through here have
-+		 * valid i_mode and are being read by the orphan
-+		 * recovery code: that's fine, we're about to complete
-+		 * the process of deleting those. */
-+	}
-+	inode->i_blocks = le32_to_cpu(raw_inode->i_blocks);
-+	ei->i_flags = le32_to_cpu(raw_inode->i_flags);
-+  /* For versioning -znjp */
-+  ei->i_cow_bitmap   = le32_to_cpu(raw_inode->i_cowbitmap);
-+  ei->i_epoch_number = le32_to_cpu(raw_inode->i_epch_number);
-+  ei->i_next_inode   = le32_to_cpu(raw_inode->i_nxt_inode);
-+  
-+#ifdef EXT3COW_FRAGMENTS
-+  /* Taken out for versioning -znjp */
-+	//ei->i_faddr = le32_to_cpu(raw_inode->i_faddr);
-+	//ei->i_frag_no = raw_inode->i_frag;
-+	//ei->i_frag_size = raw_inode->i_fsize;
-+#endif
-+	ei->i_file_acl = le32_to_cpu(raw_inode->i_file_acl);
-+	if (!S_ISREG(inode->i_mode)) {
-+		ei->i_dir_acl = le32_to_cpu(raw_inode->i_dir_acl);
-+	} else {
-+		inode->i_size |=
-+			((__u64)le32_to_cpu(raw_inode->i_size_high)) << 32;
-+	}
-+	ei->i_disksize = inode->i_size;
-+	inode->i_generation = le32_to_cpu(raw_inode->i_generation);
-+	ei->i_block_group = iloc.block_group;
-+	/*
-+	 * NOTE! The in-memory inode i_data array is in little-endian order
-+	 * even on big-endian machines: we do NOT byteswap the block numbers!
-+	 */
-+	for (block = 0; block < EXT3COW_N_BLOCKS; block++)
-+		ei->i_data[block] = raw_inode->i_block[block];
-+	INIT_LIST_HEAD(&ei->i_orphan);
-+
-+	if (inode->i_ino >= EXT3COW_FIRST_INO(inode->i_sb) + 1 &&
-+	    EXT3COW_INODE_SIZE(inode->i_sb) > EXT3COW_GOOD_OLD_INODE_SIZE) {
-+		/*
-+		 * When mke2fs creates big inodes it does not zero out
-+		 * the unused bytes above EXT3COW_GOOD_OLD_INODE_SIZE,
-+		 * so ignore those first few inodes.
-+		 */
-+		ei->i_extra_isize = le16_to_cpu(raw_inode->i_extra_isize);
-+		if (EXT3COW_GOOD_OLD_INODE_SIZE + ei->i_extra_isize >
-+		    EXT3COW_INODE_SIZE(inode->i_sb))
-+			goto bad_inode;
-+		if (ei->i_extra_isize == 0) {
-+			/* The extra space is currently unused. Use it. */
-+			ei->i_extra_isize = sizeof(struct ext3cow_inode) -
-+					    EXT3COW_GOOD_OLD_INODE_SIZE;
-+		} else {
-+			__le32 *magic = (void *)raw_inode +
-+					EXT3COW_GOOD_OLD_INODE_SIZE +
-+					ei->i_extra_isize;
-+			if (*magic == cpu_to_le32(EXT3COW_XATTR_MAGIC))
-+				 ei->i_state |= EXT3COW_STATE_XATTR;
-+		}
-+	} else
-+		ei->i_extra_isize = 0;
-+
-+	if (S_ISREG(inode->i_mode)) {
-+		inode->i_op = &ext3cow_file_inode_operations;
-+		inode->i_fop = &ext3cow_file_operations;
-+		ext3cow_set_aops(inode);
-+	} else if (S_ISDIR(inode->i_mode)) {
-+		inode->i_op = &ext3cow_dir_inode_operations;
-+		inode->i_fop = &ext3cow_dir_operations;
-+	} else if (S_ISLNK(inode->i_mode)) {
-+		if (ext3cow_inode_is_fast_symlink(inode))
-+			inode->i_op = &ext3cow_fast_symlink_inode_operations;
-+		else {
-+			inode->i_op = &ext3cow_symlink_inode_operations;
-+			ext3cow_set_aops(inode);
-+		}
-+	} else {
-+		inode->i_op = &ext3cow_special_inode_operations;
-+		if (raw_inode->i_block[0])
-+			init_special_inode(inode, inode->i_mode,
-+			   old_decode_dev(le32_to_cpu(raw_inode->i_block[0])));
-+		else
-+			init_special_inode(inode, inode->i_mode,
-+			   new_decode_dev(le32_to_cpu(raw_inode->i_block[1])));
-+	}
-+	brelse (iloc.bh);
-+	ext3cow_set_inode_flags(inode);
-+	return;
-+
-+bad_inode:
-+	make_bad_inode(inode);
-+	return;
-+}
-+
-+/*
-+ * Post the struct inode info into an on-disk inode location in the
-+ * buffer-cache.  This gobbles the caller's reference to the
-+ * buffer_head in the inode location struct.
-+ *
-+ * The caller must have write access to iloc->bh.
-+ */
-+static int ext3cow_do_update_inode(handle_t *handle,
-+				struct inode *inode,
-+				struct ext3cow_iloc *iloc)
-+{
-+	struct ext3cow_inode *raw_inode = ext3cow_raw_inode(iloc);
-+	struct ext3cow_inode_info *ei = EXT3COW_I(inode);
-+	struct buffer_head *bh = iloc->bh;
-+	int err = 0, rc, block;
-+
-+	/* For fields not not tracking in the in-memory inode,
-+	 * initialise them to zero for new inodes. */
-+	if (ei->i_state & EXT3COW_STATE_NEW)
-+		memset(raw_inode, 0, EXT3COW_SB(inode->i_sb)->s_inode_size);
-+
-+	raw_inode->i_mode = cpu_to_le16(inode->i_mode);
-+
-+
-+	if(!(test_opt(inode->i_sb, NO_UID32))) {
-+		raw_inode->i_uid_low = cpu_to_le16(low_16_bits(inode->i_uid));
-+		raw_inode->i_gid_low = cpu_to_le16(low_16_bits(inode->i_gid));
-+    
-+    /* Fix up interoperability with old kernels. Otherwise, old inodes get
-+     * re-used with the upper 16 bits of the uid/gid intact
-+     */
-+    
-+		if(!ei->i_dtime) {
-+			raw_inode->i_uid_high =
-+				cpu_to_le16(high_16_bits(inode->i_uid));
-+			raw_inode->i_gid_high =
-+				cpu_to_le16(high_16_bits(inode->i_gid));
-+		} else {
-+			raw_inode->i_uid_high = 0;
-+			raw_inode->i_gid_high = 0;
-+		}
-+    
-+	} else {
-+		raw_inode->i_uid_low =
-+			cpu_to_le16(fs_high2lowuid(inode->i_uid));
-+		raw_inode->i_gid_low =
-+			cpu_to_le16(fs_high2lowgid(inode->i_gid));
-+		raw_inode->i_uid_high = 0;
-+		raw_inode->i_gid_high = 0;
-+	}
-+ 
-+	raw_inode->i_links_count = cpu_to_le16(inode->i_nlink);
-+	raw_inode->i_size = cpu_to_le32(ei->i_disksize);
-+	raw_inode->i_atime = cpu_to_le32(inode->i_atime.tv_sec);
-+	raw_inode->i_ctime = cpu_to_le32(inode->i_ctime.tv_sec);
-+	raw_inode->i_mtime = cpu_to_le32(inode->i_mtime.tv_sec);
-+	raw_inode->i_blocks = cpu_to_le32(inode->i_blocks);
-+	raw_inode->i_dtime = cpu_to_le32(ei->i_dtime);
-+	raw_inode->i_flags = cpu_to_le32(ei->i_flags);
-+  /* For versioning -znjp */
-+  raw_inode->i_cowbitmap   = cpu_to_le16(EXT3COW_I(inode)->i_cow_bitmap);
-+  raw_inode->i_epch_number = cpu_to_le32(EXT3COW_I(inode)->i_epoch_number);
-+  raw_inode->i_nxt_inode   = cpu_to_le32(EXT3COW_I(inode)->i_next_inode);
-+
-+#ifdef EXT3COW_FRAGMENTS
-+  /* Taken out for versioning -znjp */
-+	//raw_inode->i_faddr = cpu_to_le32(ei->i_faddr);
-+	//raw_inode->i_frag = ei->i_frag_no;
-+	//raw_inode->i_fsize = ei->i_frag_size;
-+#endif
-+	raw_inode->i_file_acl = cpu_to_le32(ei->i_file_acl);
-+	if (!S_ISREG(inode->i_mode)) {
-+		raw_inode->i_dir_acl = cpu_to_le32(ei->i_dir_acl);
-+	} else {
-+		raw_inode->i_size_high =
-+			cpu_to_le32(ei->i_disksize >> 32);
-+		if (ei->i_disksize > 0x7fffffffULL) {
-+			struct super_block *sb = inode->i_sb;
-+			if (!EXT3COW_HAS_RO_COMPAT_FEATURE(sb,
-+					EXT3COW_FEATURE_RO_COMPAT_LARGE_FILE) ||
-+			    EXT3COW_SB(sb)->s_es->s_rev_level ==
-+					cpu_to_le32(EXT3COW_GOOD_OLD_REV)) {
-+			       /* If this is the first large file
-+				* created, add a flag to the superblock.
-+				*/
-+				err = ext3cow_journal_get_write_access(handle,
-+						EXT3COW_SB(sb)->s_sbh);
-+				if (err)
-+					goto out_brelse;
-+				ext3cow_update_dynamic_rev(sb);
-+				EXT3COW_SET_RO_COMPAT_FEATURE(sb,
-+					EXT3COW_FEATURE_RO_COMPAT_LARGE_FILE);
-+				sb->s_dirt = 1;
-+				handle->h_sync = 1;
-+				err = ext3cow_journal_dirty_metadata(handle,
-+						EXT3COW_SB(sb)->s_sbh);
-+			}
-+		}
-+	}
-+	raw_inode->i_generation = cpu_to_le32(inode->i_generation);
-+	if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) {
-+		if (old_valid_dev(inode->i_rdev)) {
-+			raw_inode->i_block[0] =
-+				cpu_to_le32(old_encode_dev(inode->i_rdev));
-+			raw_inode->i_block[1] = 0;
-+		} else {
-+			raw_inode->i_block[0] = 0;
-+			raw_inode->i_block[1] =
-+				cpu_to_le32(new_encode_dev(inode->i_rdev));
-+			raw_inode->i_block[2] = 0;
-+		}
-+	} else for (block = 0; block < EXT3COW_N_BLOCKS; block++)
-+		raw_inode->i_block[block] = ei->i_data[block];
-+
-+	if (ei->i_extra_isize)
-+		raw_inode->i_extra_isize = cpu_to_le16(ei->i_extra_isize);
-+
-+	BUFFER_TRACE(bh, "call ext3cow_journal_dirty_metadata");
-+	rc = ext3cow_journal_dirty_metadata(handle, bh);
-+	if (!err)
-+		err = rc;
-+	ei->i_state &= ~EXT3COW_STATE_NEW;
-+
-+out_brelse:
-+	brelse (bh);
-+	ext3cow_std_error(inode->i_sb, err);
-+	return err;
-+}
-+
-+/*
-+ * ext3cow_write_inode()
-+ *
-+ * We are called from a few places:
-+ *
-+ * - Within generic_file_write() for O_SYNC files.
-+ *   Here, there will be no transaction running. We wait for any running
-+ *   trasnaction to commit.
-+ *
-+ * - Within sys_sync(), kupdate and such.
-+ *   We wait on commit, if tol to.
-+ *
-+ * - Within prune_icache() (PF_MEMALLOC == true)
-+ *   Here we simply return.  We can't afford to block kswapd on the
-+ *   journal commit.
-+ *
-+ * In all cases it is actually safe for us to return without doing anything,
-+ * because the inode has been copied into a raw inode buffer in
-+ * ext3cow_mark_inode_dirty().  This is a correctness thing for O_SYNC and for
-+ * knfsd.
-+ *
-+ * Note that we are absolutely dependent upon all inode dirtiers doing the
-+ * right thing: they *must* call mark_inode_dirty() after dirtying info in
-+ * which we are interested.
-+ *
-+ * It would be a bug for them to not do this.  The code:
-+ *
-+ *	mark_inode_dirty(inode)
-+ *	stuff();
-+ *	inode->i_size = expr;
-+ *
-+ * is in error because a kswapd-driven write_inode() could occur while
-+ * `stuff()' is running, and the new i_size will be lost.  Plus the inode
-+ * will no longer be on the superblock's dirty inode list.
-+ */
-+int ext3cow_write_inode(struct inode *inode, int wait)
-+{
-+	if (current->flags & PF_MEMALLOC)
-+		return 0;
-+
-+	if (ext3cow_journal_current_handle()) {
-+		jbd_debug(0, "called recursively, non-PF_MEMALLOC!\n");
-+		dump_stack();
-+		return -EIO;
-+	}
-+
-+	if (!wait)
-+		return 0;
-+
-+	return ext3cow_force_commit(inode->i_sb);
-+}
-+
-+/*
-+ * ext3cow_setattr()
-+ *
-+ * Called from notify_change.
-+ *
-+ * We want to trap VFS attempts to truncate the file as soon as
-+ * possible.  In particular, we want to make sure that when the VFS
-+ * shrinks i_size, we put the inode on the orphan list and modify
-+ * i_disksize immediately, so that during the subsequent flushing of
-+ * dirty pages and freeing of disk blocks, we can guarantee that any
-+ * commit will leave the blocks being flushed in an unused state on
-+ * disk.  (On recovery, the inode will get truncated and the blocks will
-+ * be freed, so we have a strong guarantee that no future commit will
-+ * leave these blocks visible to the user.)
-+ *
-+ * Called with inode->sem down.
-+ */
-+int ext3cow_setattr(struct dentry *dentry, struct iattr *attr)
-+{
-+	struct inode *inode = dentry->d_inode;
-+	int error, rc = 0;
-+	const unsigned int ia_valid = attr->ia_valid;
-+
-+	error = inode_change_ok(inode, attr);
-+	if (error)
-+		return error;
-+
-+  /* For versioning -znjp */
-+  if(is_unchangeable(inode, dentry)){
-+    error = -EROFS;
-+    goto err_out;
-+  }
-+  
-+  if(EXT3COW_S_EPOCHNUMBER(inode->i_sb) > EXT3COW_I_EPOCHNUMBER(inode)){
-+    error = ext3cow_dup_inode(dentry->d_parent->d_inode, inode);
-+    if(error)
-+      goto err_out;
-+  }
-+  
-+	if ((ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid) ||
-+		(ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid)) {
-+		handle_t *handle;
-+
-+		/* (user+group)*(old+new) structure, inode write (sb,
-+		 * inode block, ? - but truncate inode update has it) */
-+		handle = ext3cow_journal_start(inode, 2*(EXT3COW_QUOTA_INIT_BLOCKS(inode->i_sb)+
-+					EXT3COW_QUOTA_DEL_BLOCKS(inode->i_sb))+3);
-+		if (IS_ERR(handle)) {
-+			error = PTR_ERR(handle);
-+			goto err_out;
-+		}
-+		error = DQUOT_TRANSFER(inode, attr) ? -EDQUOT : 0;
-+		if (error) {
-+			ext3cow_journal_stop(handle);
-+			return error;
-+		}
-+		/* Update corresponding info in inode so that everything is in
-+		 * one transaction */
-+		if (attr->ia_valid & ATTR_UID)
-+			inode->i_uid = attr->ia_uid;
-+		if (attr->ia_valid & ATTR_GID)
-+			inode->i_gid = attr->ia_gid;
-+		error = ext3cow_mark_inode_dirty(handle, inode);
-+		ext3cow_journal_stop(handle);
-+	}
-+
-+	if (S_ISREG(inode->i_mode) &&
-+	    attr->ia_valid & ATTR_SIZE && attr->ia_size < inode->i_size) {
-+		handle_t *handle;
-+
-+		handle = ext3cow_journal_start(inode, 3);
-+		if (IS_ERR(handle)) {
-+			error = PTR_ERR(handle);
-+			goto err_out;
-+		}
-+
-+		error = ext3cow_orphan_add(handle, inode);
-+		EXT3COW_I(inode)->i_disksize = attr->ia_size;
-+		rc = ext3cow_mark_inode_dirty(handle, inode);
-+		if (!error)
-+			error = rc;
-+		ext3cow_journal_stop(handle);
-+	}
-+
-+	rc = inode_setattr(inode, attr);
-+
-+	/* If inode_setattr's call to ext3cow_truncate failed to get a
-+	 * transaction handle at all, we need to clean up the in-core
-+	 * orphan list manually. */
-+	if (inode->i_nlink)
-+		ext3cow_orphan_del(NULL, inode);
-+
-+	if (!rc && (ia_valid & ATTR_MODE))
-+		rc = ext3cow_acl_chmod(inode);
-+
-+err_out:
-+	ext3cow_std_error(inode->i_sb, error);
-+	if (!error)
-+		error = rc;
-+	return error;
-+}
-+
-+
-+/*
-+ * How many blocks doth make a writepage()?
-+ *
-+ * With N blocks per page, it may be:
-+ * N data blocks
-+ * 2 indirect block
-+ * 2 dindirect
-+ * 1 tindirect
-+ * N+5 bitmap blocks (from the above)
-+ * N+5 group descriptor summary blocks
-+ * 1 inode block
-+ * 1 superblock.
-+ * 2 * EXT3COW_SINGLEDATA_TRANS_BLOCKS for the quote files
-+ *
-+ * 3 * (N + 5) + 2 + 2 * EXT3COW_SINGLEDATA_TRANS_BLOCKS
-+ *
-+ * With ordered or writeback data it's the same, less the N data blocks.
-+ *
-+ * If the inode's direct blocks can hold an integral number of pages then a
-+ * page cannot straddle two indirect blocks, and we can only touch one indirect
-+ * and dindirect block, and the "5" above becomes "3".
-+ *
-+ * This still overestimates under most circumstances.  If we were to pass the
-+ * start and end offsets in here as well we could do block_to_path() on each
-+ * block and work out the exact number of indirects which are touched.  Pah.
-+ */
-+
-+static int ext3cow_writepage_trans_blocks(struct inode *inode)
-+{
-+	int bpp = ext3cow_journal_blocks_per_page(inode);
-+	int indirects = (EXT3COW_NDIR_BLOCKS % bpp) ? 5 : 3;
-+	int ret;
-+
-+	if (ext3cow_should_journal_data(inode))
-+		ret = 3 * (bpp + indirects) + 2;
-+	else
-+		ret = 2 * (bpp + indirects) + 2;
-+
-+#ifdef CONFIG_QUOTA
-+	/* We know that structure was already allocated during DQUOT_INIT so
-+	 * we will be updating only the data blocks + inodes */
-+	ret += 2*EXT3COW_QUOTA_TRANS_BLOCKS(inode->i_sb);
-+#endif
-+
-+	return ret;
-+}
-+
-+/*
-+ * The caller must have previously called ext3cow_reserve_inode_write().
-+ * Give this, we know that the caller already has write access to iloc->bh.
-+ */
-+int ext3cow_mark_iloc_dirty(handle_t *handle,
-+		struct inode *inode, struct ext3cow_iloc *iloc)
-+{
-+	int err = 0;
-+
-+	/* the do_update_inode consumes one bh->b_count */
-+	get_bh(iloc->bh);
-+
-+	/* ext3cow_do_update_inode() does journal_dirty_metadata */
-+	err = ext3cow_do_update_inode(handle, inode, iloc);
-+	put_bh(iloc->bh);
-+	return err;
-+}
-+
-+/*
-+ * On success, We end up with an outstanding reference count against
-+ * iloc->bh.  This _must_ be cleaned up later.
-+ */
-+
-+int
-+ext3cow_reserve_inode_write(handle_t *handle, struct inode *inode,
-+			 struct ext3cow_iloc *iloc)
-+{
-+	int err = 0;
-+	if (handle) {
-+		err = ext3cow_get_inode_loc(inode, iloc);
-+		if (!err) {
-+			BUFFER_TRACE(iloc->bh, "get_write_access");
-+			err = ext3cow_journal_get_write_access(handle, iloc->bh);
-+			if (err) {
-+				brelse(iloc->bh);
-+				iloc->bh = NULL;
-+			}
-+		}
-+	}
-+	ext3cow_std_error(inode->i_sb, err);
-+	return err;
-+}
-+
-+/*
-+ * What we do here is to mark the in-core inode as clean with respect to inode
-+ * dirtiness (it may still be data-dirty).
-+ * This means that the in-core inode may be reaped by prune_icache
-+ * without having to perform any I/O.  This is a very good thing,
-+ * because *any* task may call prune_icache - even ones which
-+ * have a transaction open against a different journal.
-+ *
-+ * Is this cheating?  Not really.  Sure, we haven't written the
-+ * inode out, but prune_icache isn't a user-visible syncing function.
-+ * Whenever the user wants stuff synced (sys_sync, sys_msync, sys_fsync)
-+ * we start and wait on commits.
-+ *
-+ * Is this efficient/effective?  Well, we're being nice to the system
-+ * by cleaning up our inodes proactively so they can be reaped
-+ * without I/O.  But we are potentially leaving up to five seconds'
-+ * worth of inodes floating about which prune_icache wants us to
-+ * write out.  One way to fix that would be to get prune_icache()
-+ * to do a write_super() to free up some memory.  It has the desired
-+ * effect.
-+ */
-+int ext3cow_mark_inode_dirty(handle_t *handle, struct inode *inode)
-+{
-+	struct ext3cow_iloc iloc;
-+	int err;
-+
-+  if(EXT3COW_IS_FAKEINODE(inode))
-+    return 0;
-+
-+	might_sleep();
-+	err = ext3cow_reserve_inode_write(handle, inode, &iloc);
-+	if (!err)
-+		err = ext3cow_mark_iloc_dirty(handle, inode, &iloc);
-+	return err;
-+}
-+
-+/*
-+ * ext3cow_dirty_inode() is called from __mark_inode_dirty()
-+ *
-+ * We're really interested in the case where a file is being extended.
-+ * i_size has been changed by generic_commit_write() and we thus need
-+ * to include the updated inode in the current transaction.
-+ *
-+ * Also, DQUOT_ALLOC_SPACE() will always dirty the inode when blocks
-+ * are allocated to the file.
-+ *
-+ * If the inode is marked synchronous, we don't honour that here - doing
-+ * so would cause a commit on atime updates, which we don't bother doing.
-+ * We handle synchronous inodes at the highest possible level.
-+ */
-+void ext3cow_dirty_inode(struct inode *inode)
-+{
-+	handle_t *current_handle = ext3cow_journal_current_handle();
-+	handle_t *handle;
-+
-+	handle = ext3cow_journal_start(inode, 2);
-+	if (IS_ERR(handle))
-+		goto out;
-+	if (current_handle &&
-+		current_handle->h_transaction != handle->h_transaction) {
-+		/* This task has a transaction open against a different fs */
-+		printk(KERN_EMERG "%s: transactions do not match!\n",
-+		       __FUNCTION__);
-+	} else {
-+		jbd_debug(5, "marking dirty.  outer handle=%p\n",
-+				current_handle);
-+		ext3cow_mark_inode_dirty(handle, inode);
-+	}
-+	ext3cow_journal_stop(handle);
-+out:
-+	return;
-+}
-+
-+#if 0
-+/*
-+ * Bind an inode's backing buffer_head into this transaction, to prevent
-+ * it from being flushed to disk early.  Unlike
-+ * ext3cow_reserve_inode_write, this leaves behind no bh reference and
-+ * returns no iloc structure, so the caller needs to repeat the iloc
-+ * lookup to mark the inode dirty later.
-+ */
-+static int ext3cow_pin_inode(handle_t *handle, struct inode *inode)
-+{
-+	struct ext3cow_iloc iloc;
-+
-+	int err = 0;
-+	if (handle) {
-+		err = ext3cow_get_inode_loc(inode, &iloc);
-+		if (!err) {
-+			BUFFER_TRACE(iloc.bh, "get_write_access");
-+			err = journal_get_write_access(handle, iloc.bh);
-+			if (!err)
-+				err = ext3cow_journal_dirty_metadata(handle,
-+								  iloc.bh);
-+			brelse(iloc.bh);
-+		}
-+	}
-+	ext3cow_std_error(inode->i_sb, err);
-+	return err;
-+}
-+#endif
-+
-+int ext3cow_change_inode_journal_flag(struct inode *inode, int val)
-+{
-+	journal_t *journal;
-+	handle_t *handle;
-+	int err;
-+
-+	/*
-+	 * We have to be very careful here: changing a data block's
-+	 * journaling status dynamically is dangerous.  If we write a
-+	 * data block to the journal, change the status and then delete
-+	 * that block, we risk forgetting to revoke the old log record
-+	 * from the journal and so a subsequent replay can corrupt data.
-+	 * So, first we make sure that the journal is empty and that
-+	 * nobody is changing anything.
-+	 */
-+
-+	journal = EXT3COW_JOURNAL(inode);
-+	if (is_journal_aborted(journal) || IS_RDONLY(inode))
-+		return -EROFS;
-+
-+	journal_lock_updates(journal);
-+	journal_flush(journal);
-+
-+	/*
-+	 * OK, there are no updates running now, and all cached data is
-+	 * synced to disk.  We are now in a completely consistent state
-+	 * which doesn't have anything in the journal, and we know that
-+	 * no filesystem updates are running, so it is safe to modify
-+	 * the inode's in-core data-journaling state flag now.
-+	 */
-+
-+	if (val)
-+		EXT3COW_I(inode)->i_flags |= EXT3COW_JOURNAL_DATA_FL;
-+	else
-+		EXT3COW_I(inode)->i_flags &= ~EXT3COW_JOURNAL_DATA_FL;
-+	ext3cow_set_aops(inode);
-+
-+	journal_unlock_updates(journal);
-+
-+	/* Finally we can mark the inode as dirty. */
-+
-+	handle = ext3cow_journal_start(inode, 1);
-+	if (IS_ERR(handle))
-+		return PTR_ERR(handle);
-+
-+	err = ext3cow_mark_inode_dirty(handle, inode);
-+	handle->h_sync = 1;
-+	ext3cow_journal_stop(handle);
-+	ext3cow_std_error(inode->i_sb, err);
-+
-+	return err;
-+}
-diff -ruN linux-2.6.20.3/fs/ext3cow/ioctl.c linux-2.6.20.3-ext3cow/fs/ext3cow/ioctl.c
---- linux-2.6.20.3/fs/ext3cow/ioctl.c	1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.20.3-ext3cow/fs/ext3cow/ioctl.c	2008-03-09 11:14:48.000000000 -0400
-@@ -0,0 +1,312 @@
-+/*
-+ * linux/fs/ext3cow/ioctl.c
-+ *
-+ * Copyright (C) 1993, 1994, 1995
-+ * Remy Card (card@masi.ibp.fr)
-+ * Laboratoire MASI - Institut Blaise Pascal
-+ * Universite Pierre et Marie Curie (Paris VI)
-+ */
-+
-+#include <linux/fs.h>
-+#include <linux/jbd.h>
-+#include <linux/capability.h>
-+#include <linux/ext3cow_fs.h>
-+#include <linux/ext3cow_jbd.h>
-+#include <linux/time.h>
-+#include <linux/compat.h>
-+#include <linux/smp_lock.h>
-+#include <asm/uaccess.h>
-+
-+int ext3cow_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
-+		unsigned long arg)
-+{
-+	struct ext3cow_inode_info *ei = EXT3COW_I(inode);
-+	unsigned int flags;
-+	unsigned short rsv_window_size;
-+
-+	ext3cow_debug ("cmd = %u, arg = %lu\n", cmd, arg);
-+
-+	switch (cmd) {
-+    /* Some IOCTLs for version */
-+   case EXT3COW_IOC_TAKESNAPSHOT:
-+    return (unsigned int)ext3cow_take_snapshot(inode->i_sb);
-+   case EXT3COW_IOC_GETEPOCH:
-+    return (unsigned int)EXT3COW_S_EPOCHNUMBER(inode->i_sb);
-+	case EXT3COW_IOC_GETFLAGS:
-+		flags = ei->i_flags & EXT3COW_FL_USER_VISIBLE;
-+		return put_user(flags, (int __user *) arg);
-+	case EXT3COW_IOC_SETFLAGS: {
-+		handle_t *handle = NULL;
-+		int err;
-+		struct ext3cow_iloc iloc;
-+		unsigned int oldflags;
-+		unsigned int jflag;
-+
-+		if (IS_RDONLY(inode))
-+			return -EROFS;
-+
-+		if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
-+			return -EACCES;
-+
-+		if (get_user(flags, (int __user *) arg))
-+			return -EFAULT;
-+
-+		if (!S_ISDIR(inode->i_mode))
-+			flags &= ~EXT3COW_DIRSYNC_FL;
-+
-+		mutex_lock(&inode->i_mutex);
-+		oldflags = ei->i_flags;
-+
-+		/* The JOURNAL_DATA flag is modifiable only by root */
-+		jflag = flags & EXT3COW_JOURNAL_DATA_FL;
-+
-+		/*
-+		 * The IMMUTABLE and APPEND_ONLY flags can only be changed by
-+		 * the relevant capability.
-+		 *
-+		 * This test looks nicer. Thanks to Pauline Middelink
-+		 */
-+		if ((flags ^ oldflags) & (EXT3COW_APPEND_FL | EXT3COW_IMMUTABLE_FL)) {
-+			if (!capable(CAP_LINUX_IMMUTABLE)) {
-+				mutex_unlock(&inode->i_mutex);
-+				return -EPERM;
-+			}
-+		}
-+
-+		/*
-+		 * The JOURNAL_DATA flag can only be changed by
-+		 * the relevant capability.
-+		 */
-+		if ((jflag ^ oldflags) & (EXT3COW_JOURNAL_DATA_FL)) {
-+			if (!capable(CAP_SYS_RESOURCE)) {
-+				mutex_unlock(&inode->i_mutex);
-+				return -EPERM;
-+			}
-+		}
-+
-+
-+		handle = ext3cow_journal_start(inode, 1);
-+		if (IS_ERR(handle)) {
-+			mutex_unlock(&inode->i_mutex);
-+			return PTR_ERR(handle);
-+		}
-+		if (IS_SYNC(inode))
-+			handle->h_sync = 1;
-+		err = ext3cow_reserve_inode_write(handle, inode, &iloc);
-+		if (err)
-+			goto flags_err;
-+
-+		flags = flags & EXT3COW_FL_USER_MODIFIABLE;
-+		flags |= oldflags & ~EXT3COW_FL_USER_MODIFIABLE;
-+		ei->i_flags = flags;
-+
-+		ext3cow_set_inode_flags(inode);
-+		inode->i_ctime = CURRENT_TIME_SEC;
-+
-+		err = ext3cow_mark_iloc_dirty(handle, inode, &iloc);
-+flags_err:
-+		ext3cow_journal_stop(handle);
-+		if (err) {
-+			mutex_unlock(&inode->i_mutex);
-+			return err;
-+		}
-+
-+		if ((jflag ^ oldflags) & (EXT3COW_JOURNAL_DATA_FL))
-+			err = ext3cow_change_inode_journal_flag(inode, jflag);
-+		mutex_unlock(&inode->i_mutex);
-+		return err;
-+	}
-+	case EXT3COW_IOC_GETVERSION:
-+	case EXT3COW_IOC_GETVERSION_OLD:
-+		return put_user(inode->i_generation, (int __user *) arg);
-+	case EXT3COW_IOC_SETVERSION:
-+	case EXT3COW_IOC_SETVERSION_OLD: {
-+		handle_t *handle;
-+		struct ext3cow_iloc iloc;
-+		__u32 generation;
-+		int err;
-+
-+		if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
-+			return -EPERM;
-+		if (IS_RDONLY(inode))
-+			return -EROFS;
-+		if (get_user(generation, (int __user *) arg))
-+			return -EFAULT;
-+
-+		handle = ext3cow_journal_start(inode, 1);
-+		if (IS_ERR(handle))
-+			return PTR_ERR(handle);
-+		err = ext3cow_reserve_inode_write(handle, inode, &iloc);
-+		if (err == 0) {
-+			inode->i_ctime = CURRENT_TIME_SEC;
-+			inode->i_generation = generation;
-+			err = ext3cow_mark_iloc_dirty(handle, inode, &iloc);
-+		}
-+		ext3cow_journal_stop(handle);
-+		return err;
-+	}
-+#ifdef CONFIG_JBD_DEBUG
-+	case EXT3COW_IOC_WAIT_FOR_READONLY:
-+		/*
-+		 * This is racy - by the time we're woken up and running,
-+		 * the superblock could be released.  And the module could
-+		 * have been unloaded.  So sue me.
-+		 *
-+		 * Returns 1 if it slept, else zero.
-+		 */
-+		{
-+			struct super_block *sb = inode->i_sb;
-+			DECLARE_WAITQUEUE(wait, current);
-+			int ret = 0;
-+
-+			set_current_state(TASK_INTERRUPTIBLE);
-+			add_wait_queue(&EXT3COW_SB(sb)->ro_wait_queue, &wait);
-+			if (timer_pending(&EXT3COW_SB(sb)->turn_ro_timer)) {
-+				schedule();
-+				ret = 1;
-+			}
-+			remove_wait_queue(&EXT3COW_SB(sb)->ro_wait_queue, &wait);
-+			return ret;
-+		}
-+#endif
-+	case EXT3COW_IOC_GETRSVSZ:
-+		if (test_opt(inode->i_sb, RESERVATION)
-+			&& S_ISREG(inode->i_mode)
-+			&& ei->i_block_alloc_info) {
-+			rsv_window_size = ei->i_block_alloc_info->rsv_window_node.rsv_goal_size;
-+			return put_user(rsv_window_size, (int __user *)arg);
-+		}
-+		return -ENOTTY;
-+	case EXT3COW_IOC_SETRSVSZ: {
-+
-+		if (!test_opt(inode->i_sb, RESERVATION) ||!S_ISREG(inode->i_mode))
-+			return -ENOTTY;
-+
-+		if (IS_RDONLY(inode))
-+			return -EROFS;
-+
-+		if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
-+			return -EACCES;
-+
-+		if (get_user(rsv_window_size, (int __user *)arg))
-+			return -EFAULT;
-+
-+		if (rsv_window_size > EXT3COW_MAX_RESERVE_BLOCKS)
-+			rsv_window_size = EXT3COW_MAX_RESERVE_BLOCKS;
-+
-+		/*
-+		 * need to allocate reservation structure for this inode
-+		 * before set the window size
-+		 */
-+		mutex_lock(&ei->truncate_mutex);
-+		if (!ei->i_block_alloc_info)
-+			ext3cow_init_block_alloc_info(inode);
-+
-+		if (ei->i_block_alloc_info){
-+			struct ext3cow_reserve_window_node *rsv = &ei->i_block_alloc_info->rsv_window_node;
-+			rsv->rsv_goal_size = rsv_window_size;
-+		}
-+		mutex_unlock(&ei->truncate_mutex);
-+		return 0;
-+	}
-+	case EXT3COW_IOC_GROUP_EXTEND: {
-+		ext3cow_fsblk_t n_blocks_count;
-+		struct super_block *sb = inode->i_sb;
-+		int err;
-+
-+		if (!capable(CAP_SYS_RESOURCE))
-+			return -EPERM;
-+
-+		if (IS_RDONLY(inode))
-+			return -EROFS;
-+
-+		if (get_user(n_blocks_count, (__u32 __user *)arg))
-+			return -EFAULT;
-+
-+		err = ext3cow_group_extend(sb, EXT3COW_SB(sb)->s_es, n_blocks_count);
-+		journal_lock_updates(EXT3COW_SB(sb)->s_journal);
-+		journal_flush(EXT3COW_SB(sb)->s_journal);
-+		journal_unlock_updates(EXT3COW_SB(sb)->s_journal);
-+
-+		return err;
-+	}
-+	case EXT3COW_IOC_GROUP_ADD: {
-+		struct ext3cow_new_group_data input;
-+		struct super_block *sb = inode->i_sb;
-+		int err;
-+
-+		if (!capable(CAP_SYS_RESOURCE))
-+			return -EPERM;
-+
-+		if (IS_RDONLY(inode))
-+			return -EROFS;
-+
-+		if (copy_from_user(&input, (struct ext3cow_new_group_input __user *)arg,
-+				sizeof(input)))
-+			return -EFAULT;
-+
-+		err = ext3cow_group_add(sb, &input);
-+		journal_lock_updates(EXT3COW_SB(sb)->s_journal);
-+		journal_flush(EXT3COW_SB(sb)->s_journal);
-+		journal_unlock_updates(EXT3COW_SB(sb)->s_journal);
-+
-+		return err;
-+	}
-+
-+
-+	default:
-+		return -ENOTTY;
-+	}
-+}
-+
-+#ifdef CONFIG_COMPAT
-+long ext3cow_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-+{
-+	struct inode *inode = file->f_path.dentry->d_inode;
-+	int ret;
-+
-+	/* These are just misnamed, they actually get/put from/to user an int */
-+	switch (cmd) {
-+	case EXT3COW_IOC32_GETFLAGS:
-+		cmd = EXT3COW_IOC_GETFLAGS;
-+		break;
-+	case EXT3COW_IOC32_SETFLAGS:
-+		cmd = EXT3COW_IOC_SETFLAGS;
-+		break;
-+	case EXT3COW_IOC32_GETVERSION:
-+		cmd = EXT3COW_IOC_GETVERSION;
-+		break;
-+	case EXT3COW_IOC32_SETVERSION:
-+		cmd = EXT3COW_IOC_SETVERSION;
-+		break;
-+	case EXT3COW_IOC32_GROUP_EXTEND:
-+		cmd = EXT3COW_IOC_GROUP_EXTEND;
-+		break;
-+	case EXT3COW_IOC32_GETVERSION_OLD:
-+		cmd = EXT3COW_IOC_GETVERSION_OLD;
-+		break;
-+	case EXT3COW_IOC32_SETVERSION_OLD:
-+		cmd = EXT3COW_IOC_SETVERSION_OLD;
-+		break;
-+#ifdef CONFIG_JBD_DEBUG
-+	case EXT3COW_IOC32_WAIT_FOR_READONLY:
-+		cmd = EXT3COW_IOC_WAIT_FOR_READONLY;
-+		break;
-+#endif
-+	case EXT3COW_IOC32_GETRSVSZ:
-+		cmd = EXT3COW_IOC_GETRSVSZ;
-+		break;
-+	case EXT3COW_IOC32_SETRSVSZ:
-+		cmd = EXT3COW_IOC_SETRSVSZ;
-+		break;
-+	case EXT3COW_IOC_GROUP_ADD:
-+		break;
-+	default:
-+		return -ENOIOCTLCMD;
-+	}
-+	lock_kernel();
-+	ret = ext3cow_ioctl(inode, file, cmd, (unsigned long) compat_ptr(arg));
-+	unlock_kernel();
-+	return ret;
-+}
-+#endif
-diff -ruN linux-2.6.20.3/fs/ext3cow/Makefile linux-2.6.20.3-ext3cow/fs/ext3cow/Makefile
---- linux-2.6.20.3/fs/ext3cow/Makefile	1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.20.3-ext3cow/fs/ext3cow/Makefile	2008-03-09 11:14:49.000000000 -0400
-@@ -0,0 +1,12 @@
-+#
-+# Makefile for the linux ext3cow-filesystem routines.
-+#
-+
-+obj-$(CONFIG_EXT3COW_FS) += ext3cow.o
-+
-+ext3cow-y	:= balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \
-+	   ioctl.o namei.o super.o symlink.o hash.o resize.o ext3cow_jbd.o
-+
-+ext3cow-$(CONFIG_EXT3COW_FS_XATTR)	 += xattr.o xattr_user.o xattr_trusted.o
-+ext3cow-$(CONFIG_EXT3COW_FS_POSIX_ACL) += acl.o
-+ext3cow-$(CONFIG_EXT3COW_FS_SECURITY)	 += xattr_security.o
-diff -ruN linux-2.6.20.3/fs/ext3cow/namei.c linux-2.6.20.3-ext3cow/fs/ext3cow/namei.c
---- linux-2.6.20.3/fs/ext3cow/namei.c	1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.20.3-ext3cow/fs/ext3cow/namei.c	2008-03-09 11:14:48.000000000 -0400
-@@ -0,0 +1,2979 @@
-+/*
-+ *  linux/fs/ext3cow/namei.c
-+ *
-+ * Copyright (C) 1992, 1993, 1994, 1995
-+ * Remy Card (card@masi.ibp.fr)
-+ * Laboratoire MASI - Institut Blaise Pascal
-+ * Universite Pierre et Marie Curie (Paris VI)
-+ *
-+ *  from
-+ *
-+ *  linux/fs/minix/namei.c
-+ *
-+ *  Copyright (C) 1991, 1992  Linus Torvalds
-+ *
-+ *  Big-endian to little-endian byte-swapping/bitmaps by
-+ *        David S. Miller (davem@caip.rutgers.edu), 1995
-+ *  Directory entry file type support and forward compatibility hooks
-+ *	for B-tree directories by Theodore Ts'o (tytso@mit.edu), 1998
-+ *  Hash Tree Directory indexing (c)
-+ *	Daniel Phillips, 2001
-+ *  Hash Tree Directory indexing porting
-+ *	Christopher Li, 2002
-+ *  Hash Tree Directory indexing cleanup
-+ *	Theodore Ts'o, 2002
-+ */
-+
-+#include <linux/fs.h>
-+#include <linux/pagemap.h>
-+#include <linux/jbd.h>
-+#include <linux/time.h>
-+#include <linux/ext3cow_fs.h>
-+#include <linux/ext3cow_jbd.h>
-+#include <linux/fcntl.h>
-+#include <linux/stat.h>
-+#include <linux/string.h>
-+#include <linux/quotaops.h>
-+#include <linux/buffer_head.h>
-+#include <linux/bio.h>
-+#include <linux/smp_lock.h>
-+
-+#include "namei.h"
-+#include "xattr.h"
-+#include "acl.h"
-+
-+/*
-+ * define how far ahead to read directories while searching them.
-+ */
-+#define NAMEI_RA_CHUNKS  2
-+#define NAMEI_RA_BLOCKS  4
-+#define NAMEI_RA_SIZE        (NAMEI_RA_CHUNKS * NAMEI_RA_BLOCKS)
-+#define NAMEI_RA_INDEX(c,b)  (((c) * NAMEI_RA_BLOCKS) + (b))
-+
-+/* is the inode marked unchangeable or does the name
-+   contain an epoch less than the current system epoch -znjp */
-+int is_unchangeable(struct inode *inode, struct dentry *dentry){
-+  
-+  char *at = NULL;
-+
-+  if (inode && (EXT3COW_IS_UNCHANGEABLE(inode) || IS_IMMUTABLE(inode)))
-+    return 1;
-+  if(dentry)
-+    at = strrchr(dentry->d_name.name, EXT3COW_FLUX_TOKEN);
-+  if(at && (simple_strtol(&at[1], (char **)NULL, 10) > 0))
-+    return 1;
-+
-+  return 0;
-+}
-+
-+static struct buffer_head *ext3cow_append(handle_t *handle,
-+					struct inode *inode,
-+					u32 *block, int *err)
-+{
-+	struct buffer_head *bh;
-+
-+	*block = inode->i_size >> inode->i_sb->s_blocksize_bits;
-+
-+	if ((bh = ext3cow_bread(handle, inode, *block, 1, err))) {
-+		inode->i_size += inode->i_sb->s_blocksize;
-+		EXT3COW_I(inode)->i_disksize = inode->i_size;
-+		ext3cow_journal_get_write_access(handle,bh);
-+	}
-+	return bh;
-+}
-+
-+#ifndef assert
-+#define assert(test) J_ASSERT(test)
-+#endif
-+
-+#ifndef swap
-+#define swap(x, y) do { typeof(x) z = x; x = y; y = z; } while (0)
-+#endif
-+
-+#ifdef DX_DEBUG
-+#define dxtrace(command) command
-+#else
-+#define dxtrace(command)
-+#endif
-+
-+struct fake_dirent
-+{
-+	__le32 inode;
-+	__le16 rec_len;
-+	u8 name_len;
-+	u8 file_type;
-+};
-+
-+struct dx_countlimit
-+{
-+	__le16 limit;
-+	__le16 count;
-+};
-+
-+struct dx_entry
-+{
-+	__le32 hash;
-+	__le32 block;
-+};
-+
-+/*
-+ * dx_root_info is laid out so that if it should somehow get overlaid by a
-+ * dirent the two low bits of the hash version will be zero.  Therefore, the
-+ * hash version mod 4 should never be 0.  Sincerely, the paranoia department.
-+ */
-+
-+struct dx_root
-+{
-+	struct fake_dirent dot;
-+	char dot_name[4];
-+	struct fake_dirent dotdot;
-+	char dotdot_name[4];
-+	struct dx_root_info
-+	{
-+		__le32 reserved_zero;
-+		u8 hash_version;
-+		u8 info_length; /* 8 */
-+		u8 indirect_levels;
-+		u8 unused_flags;
-+	}
-+	info;
-+	struct dx_entry	entries[0];
-+};
-+
-+struct dx_node
-+{
-+	struct fake_dirent fake;
-+	struct dx_entry	entries[0];
-+};
-+
-+
-+struct dx_frame
-+{
-+	struct buffer_head *bh;
-+	struct dx_entry *entries;
-+	struct dx_entry *at;
-+};
-+
-+struct dx_map_entry
-+{
-+	u32 hash;
-+	u32 offs;
-+};
-+
-+#ifdef CONFIG_EXT3COW_INDEX
-+static inline unsigned dx_get_block (struct dx_entry *entry);
-+static void dx_set_block (struct dx_entry *entry, unsigned value);
-+static inline unsigned dx_get_hash (struct dx_entry *entry);
-+static void dx_set_hash (struct dx_entry *entry, unsigned value);
-+static unsigned dx_get_count (struct dx_entry *entries);
-+static unsigned dx_get_limit (struct dx_entry *entries);
-+static void dx_set_count (struct dx_entry *entries, unsigned value);
-+static void dx_set_limit (struct dx_entry *entries, unsigned value);
-+static unsigned dx_root_limit (struct inode *dir, unsigned infosize);
-+static unsigned dx_node_limit (struct inode *dir);
-+static struct dx_frame *dx_probe(struct dentry *dentry,
-+				 struct inode *dir,
-+				 struct dx_hash_info *hinfo,
-+				 struct dx_frame *frame,
-+				 int *err);
-+static void dx_release (struct dx_frame *frames);
-+static int dx_make_map (struct ext3cow_dir_entry_2 *de, int size,
-+			struct dx_hash_info *hinfo, struct dx_map_entry map[]);
-+static void dx_sort_map(struct dx_map_entry *map, unsigned count);
-+static struct ext3cow_dir_entry_2 *dx_move_dirents (char *from, char *to,
-+		struct dx_map_entry *offsets, int count);
-+static struct ext3cow_dir_entry_2* dx_pack_dirents (char *base, int size);
-+static void dx_insert_block (struct dx_frame *frame, u32 hash, u32 block);
-+static int ext3cow_htree_next_block(struct inode *dir, __u32 hash,
-+				 struct dx_frame *frame,
-+				 struct dx_frame *frames,
-+				 __u32 *start_hash);
-+static struct buffer_head * ext3cow_dx_find_entry(struct dentry *dentry,
-+		       struct ext3cow_dir_entry_2 **res_dir, int *err);
-+static int ext3cow_dx_add_entry(handle_t *handle, struct dentry *dentry,
-+			     struct inode *inode);
-+
-+/*
-+ * Future: use high four bits of block for coalesce-on-delete flags
-+ * Mask them off for now.
-+ */
-+
-+static inline unsigned dx_get_block (struct dx_entry *entry)
-+{
-+	return le32_to_cpu(entry->block) & 0x00ffffff;
-+}
-+
-+static inline void dx_set_block (struct dx_entry *entry, unsigned value)
-+{
-+	entry->block = cpu_to_le32(value);
-+}
-+
-+static inline unsigned dx_get_hash (struct dx_entry *entry)
-+{
-+	return le32_to_cpu(entry->hash);
-+}
-+
-+static inline void dx_set_hash (struct dx_entry *entry, unsigned value)
-+{
-+	entry->hash = cpu_to_le32(value);
-+}
-+
-+static inline unsigned dx_get_count (struct dx_entry *entries)
-+{
-+	return le16_to_cpu(((struct dx_countlimit *) entries)->count);
-+}
-+
-+static inline unsigned dx_get_limit (struct dx_entry *entries)
-+{
-+	return le16_to_cpu(((struct dx_countlimit *) entries)->limit);
-+}
-+
-+static inline void dx_set_count (struct dx_entry *entries, unsigned value)
-+{
-+	((struct dx_countlimit *) entries)->count = cpu_to_le16(value);
-+}
-+
-+static inline void dx_set_limit (struct dx_entry *entries, unsigned value)
-+{
-+	((struct dx_countlimit *) entries)->limit = cpu_to_le16(value);
-+}
-+
-+static inline unsigned dx_root_limit (struct inode *dir, unsigned infosize)
-+{
-+	unsigned entry_space = dir->i_sb->s_blocksize - EXT3COW_DIR_REC_LEN(1) -
-+		EXT3COW_DIR_REC_LEN(2) - infosize;
-+	return 0? 20: entry_space / sizeof(struct dx_entry);
-+}
-+
-+static inline unsigned dx_node_limit (struct inode *dir)
-+{
-+	unsigned entry_space = dir->i_sb->s_blocksize - EXT3COW_DIR_REC_LEN(0);
-+	return 0? 22: entry_space / sizeof(struct dx_entry);
-+}
-+
-+/*
-+ * Debug
-+ */
-+#ifdef DX_DEBUG
-+static void dx_show_index (char * label, struct dx_entry *entries)
-+{
-+        int i, n = dx_get_count (entries);
-+        printk("%s index ", label);
-+        for (i = 0; i < n; i++)
-+        {
-+                printk("%x->%u ", i? dx_get_hash(entries + i): 0, dx_get_block(entries + i));
-+        }
-+        printk("\n");
-+}
-+
-+struct stats
-+{
-+	unsigned names;
-+	unsigned space;
-+	unsigned bcount;
-+};
-+
-+static struct stats dx_show_leaf(struct dx_hash_info *hinfo, struct ext3cow_dir_entry_2 *de,
-+				 int size, int show_names)
-+{
-+	unsigned names = 0, space = 0;
-+	char *base = (char *) de;
-+	struct dx_hash_info h = *hinfo;
-+
-+	printk("names: ");
-+	while ((char *) de < base + size)
-+	{
-+		if (de->inode)
-+		{
-+			if (show_names)
-+			{
-+				int len = de->name_len;
-+				char *name = de->name;
-+				while (len--) printk("%c", *name++);
-+				ext3cowfs_dirhash(de->name, de->name_len, &h);
-+				printk(":%x.%u ", h.hash,
-+				       ((char *) de - base));
-+			}
-+			space += EXT3COW_DIR_REC_LEN(de->name_len);
-+			names++;
-+		}
-+		de = (struct ext3cow_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len));
-+	}
-+	printk("(%i)\n", names);
-+	return (struct stats) { names, space, 1 };
-+}
-+
-+struct stats dx_show_entries(struct dx_hash_info *hinfo, struct inode *dir,
-+			     struct dx_entry *entries, int levels)
-+{
-+	unsigned blocksize = dir->i_sb->s_blocksize;
-+	unsigned count = dx_get_count (entries), names = 0, space = 0, i;
-+	unsigned bcount = 0;
-+	struct buffer_head *bh;
-+	int err;
-+	printk("%i indexed blocks...\n", count);
-+	for (i = 0; i < count; i++, entries++)
-+	{
-+		u32 block = dx_get_block(entries), hash = i? dx_get_hash(entries): 0;
-+		u32 range = i < count - 1? (dx_get_hash(entries + 1) - hash): ~hash;
-+		struct stats stats;
-+		printk("%s%3u:%03u hash %8x/%8x ",levels?"":"   ", i, block, hash, range);
-+		if (!(bh = ext3cow_bread (NULL,dir, block, 0,&err))) continue;
-+		stats = levels?
-+		   dx_show_entries(hinfo, dir, ((struct dx_node *) bh->b_data)->entries, levels - 1):
-+		   dx_show_leaf(hinfo, (struct ext3cow_dir_entry_2 *) bh->b_data, blocksize, 0);
-+		names += stats.names;
-+		space += stats.space;
-+		bcount += stats.bcount;
-+		brelse (bh);
-+	}
-+	if (bcount)
-+		printk("%snames %u, fullness %u (%u%%)\n", levels?"":"   ",
-+			names, space/bcount,(space/bcount)*100/blocksize);
-+	return (struct stats) { names, space, bcount};
-+}
-+#endif /* DX_DEBUG */
-+
-+/*
-+ * Probe for a directory leaf block to search.
-+ *
-+ * dx_probe can return ERR_BAD_DX_DIR, which means there was a format
-+ * error in the directory index, and the caller should fall back to
-+ * searching the directory normally.  The callers of dx_probe **MUST**
-+ * check for this error code, and make sure it never gets reflected
-+ * back to userspace.
-+ */
-+static struct dx_frame *
-+dx_probe(struct dentry *dentry, struct inode *dir,
-+	 struct dx_hash_info *hinfo, struct dx_frame *frame_in, int *err)
-+{
-+	unsigned count, indirect;
-+	struct dx_entry *at, *entries, *p, *q, *m;
-+	struct dx_root *root;
-+	struct buffer_head *bh;
-+	struct dx_frame *frame = frame_in;
-+	u32 hash;
-+
-+	frame->bh = NULL;
-+	if (dentry)
-+		dir = dentry->d_parent->d_inode;
-+	if (!(bh = ext3cow_bread (NULL,dir, 0, 0, err)))
-+		goto fail;
-+	root = (struct dx_root *) bh->b_data;
-+	if (root->info.hash_version != DX_HASH_TEA &&
-+	    root->info.hash_version != DX_HASH_HALF_MD4 &&
-+	    root->info.hash_version != DX_HASH_LEGACY) {
-+		ext3cow_warning(dir->i_sb, __FUNCTION__,
-+			     "Unrecognised inode hash code %d",
-+			     root->info.hash_version);
-+		brelse(bh);
-+		*err = ERR_BAD_DX_DIR;
-+		goto fail;
-+	}
-+	hinfo->hash_version = root->info.hash_version;
-+	hinfo->seed = EXT3COW_SB(dir->i_sb)->s_hash_seed;
-+	if (dentry)
-+		ext3cowfs_dirhash(dentry->d_name.name, dentry->d_name.len, hinfo);
-+	hash = hinfo->hash;
-+
-+	if (root->info.unused_flags & 1) {
-+		ext3cow_warning(dir->i_sb, __FUNCTION__,
-+			     "Unimplemented inode hash flags: %#06x",
-+			     root->info.unused_flags);
-+		brelse(bh);
-+		*err = ERR_BAD_DX_DIR;
-+		goto fail;
-+	}
-+
-+	if ((indirect = root->info.indirect_levels) > 1) {
-+		ext3cow_warning(dir->i_sb, __FUNCTION__,
-+			     "Unimplemented inode hash depth: %#06x",
-+			     root->info.indirect_levels);
-+		brelse(bh);
-+		*err = ERR_BAD_DX_DIR;
-+		goto fail;
-+	}
-+
-+	entries = (struct dx_entry *) (((char *)&root->info) +
-+				       root->info.info_length);
-+	assert(dx_get_limit(entries) == dx_root_limit(dir,
-+						      root->info.info_length));
-+	dxtrace (printk("Look up %x", hash));
-+	while (1)
-+	{
-+		count = dx_get_count(entries);
-+		assert (count && count <= dx_get_limit(entries));
-+		p = entries + 1;
-+		q = entries + count - 1;
-+		while (p <= q)
-+		{
-+			m = p + (q - p)/2;
-+			dxtrace(printk("."));
-+			if (dx_get_hash(m) > hash)
-+				q = m - 1;
-+			else
-+				p = m + 1;
-+		}
-+
-+		if (0) // linear search cross check
-+		{
-+			unsigned n = count - 1;
-+			at = entries;
-+			while (n--)
-+			{
-+				dxtrace(printk(","));
-+				if (dx_get_hash(++at) > hash)
-+				{
-+					at--;
-+					break;
-+				}
-+			}
-+			assert (at == p - 1);
-+		}
-+
-+		at = p - 1;
-+		dxtrace(printk(" %x->%u\n", at == entries? 0: dx_get_hash(at), dx_get_block(at)));
-+		frame->bh = bh;
-+		frame->entries = entries;
-+		frame->at = at;
-+		if (!indirect--) return frame;
-+		if (!(bh = ext3cow_bread (NULL,dir, dx_get_block(at), 0, err)))
-+			goto fail2;
-+		at = entries = ((struct dx_node *) bh->b_data)->entries;
-+		assert (dx_get_limit(entries) == dx_node_limit (dir));
-+		frame++;
-+	}
-+fail2:
-+	while (frame >= frame_in) {
-+		brelse(frame->bh);
-+		frame--;
-+	}
-+fail:
-+	return NULL;
-+}
-+
-+static void dx_release (struct dx_frame *frames)
-+{
-+	if (frames[0].bh == NULL)
-+		return;
-+
-+	if (((struct dx_root *) frames[0].bh->b_data)->info.indirect_levels)
-+		brelse(frames[1].bh);
-+	brelse(frames[0].bh);
-+}
-+
-+/*
-+ * This function increments the frame pointer to search the next leaf
-+ * block, and reads in the necessary intervening nodes if the search
-+ * should be necessary.  Whether or not the search is necessary is
-+ * controlled by the hash parameter.  If the hash value is even, then
-+ * the search is only continued if the next block starts with that
-+ * hash value.  This is used if we are searching for a specific file.
-+ *
-+ * If the hash value is HASH_NB_ALWAYS, then always go to the next block.
-+ *
-+ * This function returns 1 if the caller should continue to search,
-+ * or 0 if it should not.  If there is an error reading one of the
-+ * index blocks, it will a negative error code.
-+ *
-+ * If start_hash is non-null, it will be filled in with the starting
-+ * hash of the next page.
-+ */
-+static int ext3cow_htree_next_block(struct inode *dir, __u32 hash,
-+				 struct dx_frame *frame,
-+				 struct dx_frame *frames,
-+				 __u32 *start_hash)
-+{
-+	struct dx_frame *p;
-+	struct buffer_head *bh;
-+	int err, num_frames = 0;
-+	__u32 bhash;
-+
-+	p = frame;
-+	/*
-+	 * Find the next leaf page by incrementing the frame pointer.
-+	 * If we run out of entries in the interior node, loop around and
-+	 * increment pointer in the parent node.  When we break out of
-+	 * this loop, num_frames indicates the number of interior
-+	 * nodes need to be read.
-+	 */
-+	while (1) {
-+		if (++(p->at) < p->entries + dx_get_count(p->entries))
-+			break;
-+		if (p == frames)
-+			return 0;
-+		num_frames++;
-+		p--;
-+	}
-+
-+	/*
-+	 * If the hash is 1, then continue only if the next page has a
-+	 * continuation hash of any value.  This is used for readdir
-+	 * handling.  Otherwise, check to see if the hash matches the
-+	 * desired contiuation hash.  If it doesn't, return since
-+	 * there's no point to read in the successive index pages.
-+	 */
-+	bhash = dx_get_hash(p->at);
-+	if (start_hash)
-+		*start_hash = bhash;
-+	if ((hash & 1) == 0) {
-+		if ((bhash & ~1) != hash)
-+			return 0;
-+	}
-+	/*
-+	 * If the hash is HASH_NB_ALWAYS, we always go to the next
-+	 * block so no check is necessary
-+	 */
-+	while (num_frames--) {
-+		if (!(bh = ext3cow_bread(NULL, dir, dx_get_block(p->at),
-+				      0, &err)))
-+			return err; /* Failure */
-+		p++;
-+		brelse (p->bh);
-+		p->bh = bh;
-+		p->at = p->entries = ((struct dx_node *) bh->b_data)->entries;
-+	}
-+	return 1;
-+}
-+
-+
-+/*
-+ * p is at least 6 bytes before the end of page
-+ */
-+static inline struct ext3cow_dir_entry_2 *ext3cow_next_entry(struct ext3cow_dir_entry_2 *p)
-+{
-+	return (struct ext3cow_dir_entry_2 *)((char*)p + le16_to_cpu(p->rec_len));
-+}
-+
-+/*
-+ * This function fills a red-black tree with information from a
-+ * directory block.  It returns the number directory entries loaded
-+ * into the tree.  If there is an error it is returned in err.
-+ */
-+static int htree_dirblock_to_tree(struct file *dir_file,
-+				  struct inode *dir, int block,
-+				  struct dx_hash_info *hinfo,
-+				  __u32 start_hash, __u32 start_minor_hash)
-+{
-+	struct buffer_head *bh;
-+	struct ext3cow_dir_entry_2 *de, *top;
-+	int err, count = 0;
-+
-+	dxtrace(printk("In htree dirblock_to_tree: block %d\n", block));
-+	if (!(bh = ext3cow_bread (NULL, dir, block, 0, &err)))
-+		return err;
-+
-+	de = (struct ext3cow_dir_entry_2 *) bh->b_data;
-+	top = (struct ext3cow_dir_entry_2 *) ((char *) de +
-+					   dir->i_sb->s_blocksize -
-+					   EXT3COW_DIR_REC_LEN(0));
-+	for (; de < top; de = ext3cow_next_entry(de)) {
-+		if (!ext3cow_check_dir_entry("htree_dirblock_to_tree", dir, de, bh,
-+					(block<<EXT3COW_BLOCK_SIZE_BITS(dir->i_sb))
-+						+((char *)de - bh->b_data))) {
-+			/* On error, skip the f_pos to the next block. */
-+			dir_file->f_pos = (dir_file->f_pos |
-+					(dir->i_sb->s_blocksize - 1)) + 1;
-+			brelse (bh);
-+			return count;
-+		}
-+		ext3cowfs_dirhash(de->name, de->name_len, hinfo);
-+		if ((hinfo->hash < start_hash) ||
-+		    ((hinfo->hash == start_hash) &&
-+		     (hinfo->minor_hash < start_minor_hash)))
-+			continue;
-+		if (de->inode == 0)
-+			continue;
-+		if ((err = ext3cow_htree_store_dirent(dir_file,
-+				   hinfo->hash, hinfo->minor_hash, de)) != 0) {
-+			brelse(bh);
-+			return err;
-+		}
-+		count++;
-+	}
-+	brelse(bh);
-+	return count;
-+}
-+
-+
-+/*
-+ * This function fills a red-black tree with information from a
-+ * directory.  We start scanning the directory in hash order, starting
-+ * at start_hash and start_minor_hash.
-+ *
-+ * This function returns the number of entries inserted into the tree,
-+ * or a negative error code.
-+ */
-+int ext3cow_htree_fill_tree(struct file *dir_file, __u32 start_hash,
-+			 __u32 start_minor_hash, __u32 *next_hash)
-+{
-+	struct dx_hash_info hinfo;
-+	struct ext3cow_dir_entry_2 *de;
-+	struct dx_frame frames[2], *frame;
-+	struct inode *dir;
-+	int block, err;
-+	int count = 0;
-+	int ret;
-+	__u32 hashval;
-+
-+	dxtrace(printk("In htree_fill_tree, start hash: %x:%x\n", start_hash,
-+		       start_minor_hash));
-+	dir = dir_file->f_path.dentry->d_inode;
-+	if (!(EXT3COW_I(dir)->i_flags & EXT3COW_INDEX_FL)) {
-+		hinfo.hash_version = EXT3COW_SB(dir->i_sb)->s_def_hash_version;
-+		hinfo.seed = EXT3COW_SB(dir->i_sb)->s_hash_seed;
-+		count = htree_dirblock_to_tree(dir_file, dir, 0, &hinfo,
-+					       start_hash, start_minor_hash);
-+		*next_hash = ~0;
-+		return count;
-+	}
-+	hinfo.hash = start_hash;
-+	hinfo.minor_hash = 0;
-+	frame = dx_probe(NULL, dir_file->f_path.dentry->d_inode, &hinfo, frames, &err);
-+	if (!frame)
-+		return err;
-+
-+	/* Add '.' and '..' from the htree header */
-+	if (!start_hash && !start_minor_hash) {
-+		de = (struct ext3cow_dir_entry_2 *) frames[0].bh->b_data;
-+		if ((err = ext3cow_htree_store_dirent(dir_file, 0, 0, de)) != 0)
-+			goto errout;
-+		count++;
-+	}
-+	if (start_hash < 2 || (start_hash ==2 && start_minor_hash==0)) {
-+		de = (struct ext3cow_dir_entry_2 *) frames[0].bh->b_data;
-+		de = ext3cow_next_entry(de);
-+		if ((err = ext3cow_htree_store_dirent(dir_file, 2, 0, de)) != 0)
-+			goto errout;
-+		count++;
-+	}
-+
-+	while (1) {
-+		block = dx_get_block(frame->at);
-+		ret = htree_dirblock_to_tree(dir_file, dir, block, &hinfo,
-+					     start_hash, start_minor_hash);
-+		if (ret < 0) {
-+			err = ret;
-+			goto errout;
-+		}
-+		count += ret;
-+		hashval = ~0;
-+		ret = ext3cow_htree_next_block(dir, HASH_NB_ALWAYS,
-+					    frame, frames, &hashval);
-+		*next_hash = hashval;
-+		if (ret < 0) {
-+			err = ret;
-+			goto errout;
-+		}
-+		/*
-+		 * Stop if:  (a) there are no more entries, or
-+		 * (b) we have inserted at least one entry and the
-+		 * next hash value is not a continuation
-+		 */
-+		if ((ret == 0) ||
-+		    (count && ((hashval & 1) == 0)))
-+			break;
-+	}
-+	dx_release(frames);
-+	dxtrace(printk("Fill tree: returned %d entries, next hash: %x\n",
-+		       count, *next_hash));
-+	return count;
-+errout:
-+	dx_release(frames);
-+	return (err);
-+}
-+
-+
-+/*
-+ * Directory block splitting, compacting
-+ */
-+
-+static int dx_make_map (struct ext3cow_dir_entry_2 *de, int size,
-+			struct dx_hash_info *hinfo, struct dx_map_entry *map_tail)
-+{
-+	int count = 0;
-+	char *base = (char *) de;
-+	struct dx_hash_info h = *hinfo;
-+
-+	while ((char *) de < base + size)
-+	{
-+		if (de->name_len && de->inode) {
-+			ext3cowfs_dirhash(de->name, de->name_len, &h);
-+			map_tail--;
-+			map_tail->hash = h.hash;
-+			map_tail->offs = (u32) ((char *) de - base);
-+			count++;
-+			cond_resched();
-+		}
-+		/* XXX: do we need to check rec_len == 0 case? -Chris */
-+		de = (struct ext3cow_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len));
-+	}
-+	return count;
-+}
-+
-+static void dx_sort_map (struct dx_map_entry *map, unsigned count)
-+{
-+        struct dx_map_entry *p, *q, *top = map + count - 1;
-+        int more;
-+        /* Combsort until bubble sort doesn't suck */
-+        while (count > 2)
-+	{
-+                count = count*10/13;
-+                if (count - 9 < 2) /* 9, 10 -> 11 */
-+                        count = 11;
-+                for (p = top, q = p - count; q >= map; p--, q--)
-+                        if (p->hash < q->hash)
-+                                swap(*p, *q);
-+        }
-+        /* Garden variety bubble sort */
-+        do {
-+                more = 0;
-+                q = top;
-+                while (q-- > map)
-+		{
-+                        if (q[1].hash >= q[0].hash)
-+				continue;
-+                        swap(*(q+1), *q);
-+                        more = 1;
-+		}
-+	} while(more);
-+}
-+
-+static void dx_insert_block(struct dx_frame *frame, u32 hash, u32 block)
-+{
-+	struct dx_entry *entries = frame->entries;
-+	struct dx_entry *old = frame->at, *new = old + 1;
-+	int count = dx_get_count(entries);
-+
-+	assert(count < dx_get_limit(entries));
-+	assert(old < entries + count);
-+	memmove(new + 1, new, (char *)(entries + count) - (char *)(new));
-+	dx_set_hash(new, hash);
-+	dx_set_block(new, block);
-+	dx_set_count(entries, count + 1);
-+}
-+#endif
-+
-+
-+static void ext3cow_update_dx_flag(struct inode *inode)
-+{
-+	if (!EXT3COW_HAS_COMPAT_FEATURE(inode->i_sb,
-+				     EXT3COW_FEATURE_COMPAT_DIR_INDEX))
-+		EXT3COW_I(inode)->i_flags &= ~EXT3COW_INDEX_FL;
-+}
-+
-+/*
-+ * NOTE! unlike strncmp, ext3cow_match returns 1 for success, 0 for failure.
-+ *
-+ * `len <= EXT3COW_NAME_LEN' is guaranteed by caller.
-+ * `de != NULL' is guaranteed by caller.
-+ */
-+static inline int ext3cow_match (int len, const char * const name,
-+			      struct ext3cow_dir_entry_2 * de)
-+{
-+	if (len != de->name_len)
-+		return 0;
-+	if (!de->inode)
-+		return 0;
-+	return !memcmp(name, de->name, len);
-+}
-+
-+/*
-+ * Returns 0 if not found, -1 on failure, and 1 on success
-+ */
-+/* For versioning - this is the function used when looking for
-+ * names.  We now handle names which include the flux token,
-+ * strip it off and continue looking -znjp */
-+static inline int search_dirblock(struct buffer_head * bh,
-+				  struct inode *dir,
-+				  struct dentry *dentry,
-+				  unsigned long offset,
-+				  struct ext3cow_dir_entry_2 ** res_dir)
-+{
-+	struct ext3cow_dir_entry_2 * de;
-+	char * dlimit, * flux = NULL;
-+	int de_len;
-+	char name[EXT3COW_NAME_LEN];
-+	int namelen = dentry->d_name.len;
-+  unsigned int epoch_number = EXT3COW_I_EPOCHNUMBER(dir);
-+
-+  /* Get the name for the dentry */
-+  memcpy(name, dentry->d_name.name, namelen);
-+  name[namelen] = '\0';
-+
-+  /* Check to see if the flux token is in the name */
-+  flux = strrchr(dentry->d_name.name, EXT3COW_FLUX_TOKEN);
-+  if(NULL != flux){
-+    /* If we're here, the name we want is in the past. */
-+    int new_namelen = strlen(dentry->d_name.name) - strlen(flux);
-+    /* Get the epoch number */
-+    epoch_number = simple_strtol(&flux[1], (char **)NULL, 10) - 1;
-+    /* If there's a valid epoch number or if we're version listing
-+     * we need the name seperately, otherwise the FLUX_TOKEN exists
-+     * in the file name */
-+    if(epoch_number + 1 == 0 && (strlen(flux) > 1)){ 
-+      /* EXT3COW_FLUX_TOKEN exists in the file name */
-+      epoch_number = EXT3COW_S_EPOCHNUMBER(dir->i_sb);
-+    }else{
-+      /* Grab the correct name and length */
-+      memcpy(name, dentry->d_name.name, new_namelen);
-+      name[new_namelen] = '\0';
-+      namelen = strlen(name);
-+    }
-+  }
-+
-+
-+	de = (struct ext3cow_dir_entry_2 *) bh->b_data;
-+	dlimit = bh->b_data + dir->i_sb->s_blocksize;
-+	while ((char *) de < dlimit) {
-+		/* this code is executed quadratically often */
-+		/* do minimal checking `by hand' */
-+
-+    /* Can't just return first entry of something;
-+     * may exist twice if died and same name appears again. - znjp
-+     */
-+		if ((char *) de + namelen <= dlimit &&
-+		    ext3cow_match (namelen, name, de) && 
-+        EXT3COW_IS_DIRENT_SCOPED(de, epoch_number)) {
-+			/* found a match - just to be sure, do a full check */
-+			if (!ext3cow_check_dir_entry("ext3cow_find_entry",
-+						  dir, de, bh, offset))
-+				return -1;
-+			*res_dir = de;
-+			return 1;
-+		}
-+		/* prevent looping on a bad block */
-+		de_len = le16_to_cpu(de->rec_len);
-+		if (de_len <= 0)
-+			return -1;
-+		offset += de_len;
-+		de = (struct ext3cow_dir_entry_2 *) ((char *) de + de_len);
-+	}
-+	return 0;
-+}
-+
-+
-+/*
-+ *	ext3cow_find_entry()
-+ *
-+ * finds an entry in the specified directory with the wanted name. It
-+ * returns the cache buffer in which the entry was found, and the entry
-+ * itself (as a parameter - res_dir). It does NOT read the inode of the
-+ * entry - you'll have to do that yourself if you want to.
-+ *
-+ * The returned buffer_head has ->b_count elevated.  The caller is expected
-+ * to brelse() it when appropriate.
-+ */
-+static struct buffer_head * ext3cow_find_entry (struct dentry *dentry,
-+					struct ext3cow_dir_entry_2 ** res_dir)
-+{
-+	struct super_block * sb;
-+	struct buffer_head * bh_use[NAMEI_RA_SIZE];
-+	struct buffer_head * bh, *ret = NULL;
-+	unsigned long start, block, b;
-+	int ra_max = 0;		/* Number of bh's in the readahead
-+				   buffer, bh_use[] */
-+	int ra_ptr = 0;		/* Current index into readahead
-+				   buffer */
-+	int num = 0;
-+	int nblocks, i, err;
-+	struct inode *dir = dentry->d_parent->d_inode;
-+	int namelen;
-+	const u8 *name;
-+	unsigned blocksize;
-+
-+	*res_dir = NULL;
-+	sb = dir->i_sb;
-+	blocksize = sb->s_blocksize;
-+	namelen = dentry->d_name.len;
-+	name = dentry->d_name.name;
-+	if (namelen > EXT3COW_NAME_LEN)
-+		return NULL;
-+#ifdef CONFIG_EXT3COW_INDEX
-+	if (is_dx(dir)) {
-+		bh = ext3cow_dx_find_entry(dentry, res_dir, &err);
-+		/*
-+		 * On success, or if the error was file not found,
-+		 * return.  Otherwise, fall back to doing a search the
-+		 * old fashioned way.
-+		 */
-+		if (bh || (err != ERR_BAD_DX_DIR))
-+			return bh;
-+		dxtrace(printk("ext3cow_find_entry: dx failed, falling back\n"));
-+	}
-+#endif
-+	nblocks = dir->i_size >> EXT3COW_BLOCK_SIZE_BITS(sb);
-+	start = EXT3COW_I(dir)->i_dir_start_lookup;
-+	if (start >= nblocks)
-+		start = 0;
-+	block = start;
-+restart:
-+	do {
-+		/*
-+		 * We deal with the read-ahead logic here.
-+		 */
-+		if (ra_ptr >= ra_max) {
-+			/* Refill the readahead buffer */
-+			ra_ptr = 0;
-+			b = block;
-+			for (ra_max = 0; ra_max < NAMEI_RA_SIZE; ra_max++) {
-+				/*
-+				 * Terminate if we reach the end of the
-+				 * directory and must wrap, or if our
-+				 * search has finished at this block.
-+				 */
-+				if (b >= nblocks || (num && block == start)) {
-+					bh_use[ra_max] = NULL;
-+					break;
-+				}
-+				num++;
-+				bh = ext3cow_getblk(NULL, dir, b++, 0, &err);
-+				bh_use[ra_max] = bh;
-+				if (bh)
-+					ll_rw_block(READ_META, 1, &bh);
-+			}
-+		}
-+		if ((bh = bh_use[ra_ptr++]) == NULL)
-+			goto next;
-+		wait_on_buffer(bh);
-+		if (!buffer_uptodate(bh)) {
-+			/* read error, skip block & hope for the best */
-+			ext3cow_error(sb, __FUNCTION__, "reading directory #%lu "
-+				   "offset %lu", dir->i_ino, block);
-+			brelse(bh);
-+			goto next;
-+		}
-+		i = search_dirblock(bh, dir, dentry,
-+			    block << EXT3COW_BLOCK_SIZE_BITS(sb), res_dir);
-+		if (i == 1) {
-+			EXT3COW_I(dir)->i_dir_start_lookup = block;
-+			ret = bh;
-+			goto cleanup_and_exit;
-+		} else {
-+			brelse(bh);
-+			if (i < 0)
-+				goto cleanup_and_exit;
-+		}
-+	next:
-+		if (++block >= nblocks)
-+			block = 0;
-+	} while (block != start);
-+
-+	/*
-+	 * If the directory has grown while we were searching, then
-+	 * search the last part of the directory before giving up.
-+	 */
-+	block = nblocks;
-+	nblocks = dir->i_size >> EXT3COW_BLOCK_SIZE_BITS(sb);
-+	if (block < nblocks) {
-+		start = 0;
-+		goto restart;
-+	}
-+
-+cleanup_and_exit:
-+	/* Clean up the read-ahead blocks */
-+	for (; ra_ptr < ra_max; ra_ptr++)
-+		brelse (bh_use[ra_ptr]);
-+	return ret;
-+}
-+
-+#ifdef CONFIG_EXT3COW_INDEX
-+static struct buffer_head * ext3cow_dx_find_entry(struct dentry *dentry,
-+		       struct ext3cow_dir_entry_2 **res_dir, int *err)
-+{
-+	struct super_block * sb;
-+	struct dx_hash_info	hinfo;
-+	u32 hash;
-+	struct dx_frame frames[2], *frame;
-+	struct ext3cow_dir_entry_2 *de, *top;
-+	struct buffer_head *bh;
-+	unsigned long block;
-+	int retval;
-+	int namelen = dentry->d_name.len;
-+	const u8 *name = dentry->d_name.name;
-+	struct inode *dir = dentry->d_parent->d_inode;
-+
-+	sb = dir->i_sb;
-+	/* NFS may look up ".." - look at dx_root directory block */
-+	if (namelen > 2 || name[0] != '.'||(name[1] != '.' && name[1] != '\0')){
-+		if (!(frame = dx_probe(dentry, NULL, &hinfo, frames, err)))
-+			return NULL;
-+	} else {
-+		frame = frames;
-+		frame->bh = NULL;			/* for dx_release() */
-+		frame->at = (struct dx_entry *)frames;	/* hack for zero entry*/
-+		dx_set_block(frame->at, 0);		/* dx_root block is 0 */
-+	}
-+	hash = hinfo.hash;
-+	do {
-+		block = dx_get_block(frame->at);
-+		if (!(bh = ext3cow_bread (NULL,dir, block, 0, err)))
-+			goto errout;
-+		de = (struct ext3cow_dir_entry_2 *) bh->b_data;
-+		top = (struct ext3cow_dir_entry_2 *) ((char *) de + sb->s_blocksize -
-+				       EXT3COW_DIR_REC_LEN(0));
-+		for (; de < top; de = ext3cow_next_entry(de))
-+		if (ext3cow_match (namelen, name, de)) {
-+			if (!ext3cow_check_dir_entry("ext3cow_find_entry",
-+						  dir, de, bh,
-+				  (block<<EXT3COW_BLOCK_SIZE_BITS(sb))
-+					  +((char *)de - bh->b_data))) {
-+				brelse (bh);
-+				goto errout;
-+			}
-+			*res_dir = de;
-+			dx_release (frames);
-+			return bh;
-+		}
-+		brelse (bh);
-+		/* Check to see if we should continue to search */
-+		retval = ext3cow_htree_next_block(dir, hash, frame,
-+					       frames, NULL);
-+		if (retval < 0) {
-+			ext3cow_warning(sb, __FUNCTION__,
-+			     "error reading index page in directory #%lu",
-+			     dir->i_ino);
-+			*err = retval;
-+			goto errout;
-+		}
-+	} while (retval == 1);
-+
-+	*err = -ENOENT;
-+errout:
-+	dxtrace(printk("%s not found\n", name));
-+	dx_release (frames);
-+	return NULL;
-+}
-+#endif
-+
-+/* ext3cow_lookup: One the key functions of this versioning file sytem,
-+ * allowing people to return to the past.
-+ *
-+ * Two policies for inode chains:
-+ * 1) If it's the head of the list, it's the most current inode
-+ *    and always changable.  The inode number is static.
-+ * 2) If it's any inode in the chain that's not the head,
-+ *    than it's an inode in the past and unchangeable.  The inode
-+ *    number may change.
-+ */
-+static struct dentry *ext3cow_lookup(struct inode * dir, struct dentry *dentry,
-+                                     struct nameidata *nd)
-+{
-+	struct inode * inode = NULL;
-+	struct ext3cow_dir_entry_2 * de = NULL;
-+	struct buffer_head * bh = NULL;
-+  unsigned int epoch_number = 0;
-+  char * flux = NULL;
-+  
-+	if (dentry->d_name.len > EXT3COW_NAME_LEN)
-+		return ERR_PTR(-ENAMETOOLONG);
-+
-+  /* Find the epoch number to scope with -znjp 
-+   * if the parent is unchangeable, so is the inode 
-+   */
-+  if(EXT3COW_IS_UNCHANGEABLE(dir))     
-+    epoch_number = EXT3COW_I_EPOCHNUMBER(dir);
-+  else
-+    epoch_number = EXT3COW_S_EPOCHNUMBER(dir->i_sb);
-+
-+	bh = ext3cow_find_entry(dentry, &de);
-+	if (bh) {
-+		unsigned long ino = le32_to_cpu(de->inode);
-+		brelse (bh);
-+		if (!ext3cow_valid_inum(dir->i_sb, ino)) {
-+			ext3cow_error(dir->i_sb, "ext3cow_lookup",
-+				   "bad inode number: %lu", ino);
-+			inode = NULL;
-+		} else
-+			inode = iget(dir->i_sb, ino);
-+
-+		if (!inode)
-+			return ERR_PTR(-EACCES);
-+
-+    /* Is this a version listing ? */
-+    if ((char)dentry->d_name.name[dentry->d_name.len - 1] == 
-+        EXT3COW_FLUX_TOKEN) {
-+      /* prevent going round in circles */
-+      if (dentry->d_parent && 
-+          dentry->d_parent->d_name.name[dentry->d_parent->d_name.len - 1] ==
-+          EXT3COW_FLUX_TOKEN) {
-+        return NULL;
-+      }
-+      /* we fake a directory using the directory inode instead of
-+       * the file one and subsequently force a call to ext3cow_readdir */
-+      iput(inode);
-+      inode = ext3cow_fake_inode(dir, EXT3COW_S_EPOCHNUMBER(dir->i_sb));
-+      EXT3COW_I(inode)->i_next_inode = EXT3COW_I(dir)->i_next_inode;
-+      d_splice_alias(inode, dentry);
-+      
-+      return NULL;
-+    }
-+
-+    /* Is the user time-shifting to the past? */
-+    flux = strrchr(dentry->d_name.name, EXT3COW_FLUX_TOKEN);
-+    if(NULL != flux){
-+
-+      if(strnicmp(&flux[1], "onehour", 8) == 0){
-+        epoch_number = get_seconds() - ONEHOUR;
-+        printk(KERN_INFO "ONEHOUR!\n");
-+      }else if(strnicmp(&flux[1], "yesterday", 10) == 0 ||
-+               strnicmp(&flux[1], "oneday", 7) == 0){
-+        epoch_number = get_seconds() - YESTERDAY;
-+      }else if(strnicmp(&flux[1], "oneweek", 8) == 0){
-+        epoch_number = get_seconds() - ONEWEEK;
-+      }else if(strnicmp(&flux[1], "onemonth", 9) == 0){
-+        epoch_number = get_seconds() - ONEMONTH;
-+      }else if(strnicmp(&flux[1], "oneyear", 8) == 0){
-+        epoch_number = get_seconds() - ONEYEAR;
-+      }else
-+        epoch_number = simple_strtol(&flux[1], (char **)NULL, 10) - 1;
-+
-+      /* No future epochs */
-+      if(epoch_number + 1 > EXT3COW_S_EPOCHNUMBER(dir->i_sb))                
-+        return ERR_PTR(-ENOENT); 
-+
-+      /* Move to present 
-+      if(epoch_number + 1 == 0)
-+        epoch_number = EXT3COW_S_EPOCHNUMBER(dir->i_sb);       
-+      */
-+    }
-+     
-+    /* Find correct inode in chain */
-+    while(EXT3COW_I_EPOCHNUMBER(inode) > epoch_number){
-+
-+      printk(KERN_INFO "Looking for %u with epoch %u\n", epoch_number, 
-+             EXT3COW_I_EPOCHNUMBER(inode));
-+
-+      ino = EXT3COW_I(inode)->i_next_inode;
-+      if(ino == 0){
-+        ext3cow_warning(dir->i_sb, "ext3cow_lookup",
-+                        "Next inode is 0 in lookup.");
-+        iput(inode);
-+        return ERR_PTR(-ENOENT);
-+      }
-+      iput(inode); /* for correct usage count (i_count) */
-+      inode = iget(dir->i_sb, ino);
-+      
-+      if (!inode){
-+        ext3cow_warning(dir->i_sb, "ext3cow_lookup",
-+                        "Could not access inode number %lu",
-+                        ino);
-+        return ERR_PTR(-EACCES);
-+      }
-+    }
-+
-+    /* If we're in the past, fake the inode for scoping and "unchangability" */
-+    if(flux || (epoch_number != EXT3COW_S_EPOCHNUMBER(dir->i_sb))){
-+      printk(KERN_INFO "Faking %s\n", dentry->d_name.name);
-+      inode = ext3cow_fake_inode(inode, epoch_number);
-+    }
-+
-+    if (!inode)
-+      return ERR_PTR(-EACCES);
-+	}
-+	return d_splice_alias(inode, dentry);
-+}
-+
-+
-+struct dentry *ext3cow_get_parent(struct dentry *child)
-+{
-+	unsigned long ino;
-+	struct dentry *parent;
-+	struct inode *inode;
-+	struct dentry dotdot;
-+	struct ext3cow_dir_entry_2 * de;
-+	struct buffer_head *bh;
-+
-+	dotdot.d_name.name = "..";
-+	dotdot.d_name.len = 2;
-+	dotdot.d_parent = child; /* confusing, isn't it! */
-+
-+	bh = ext3cow_find_entry(&dotdot, &de);
-+	inode = NULL;
-+	if (!bh)
-+		return ERR_PTR(-ENOENT);
-+	ino = le32_to_cpu(de->inode);
-+	brelse(bh);
-+
-+	if (!ext3cow_valid_inum(child->d_inode->i_sb, ino)) {
-+		ext3cow_error(child->d_inode->i_sb, "ext3cow_get_parent",
-+			   "bad inode number: %lu", ino);
-+		inode = NULL;
-+	} else
-+		inode = iget(child->d_inode->i_sb, ino);
-+
-+	if (!inode)
-+		return ERR_PTR(-EACCES);
-+
-+	parent = d_alloc_anon(inode);
-+	if (!parent) {
-+		iput(inode);
-+		parent = ERR_PTR(-ENOMEM);
-+	}
-+	return parent;
-+}
-+
-+#define S_SHIFT 12
-+static unsigned char ext3cow_type_by_mode[S_IFMT >> S_SHIFT] = {
-+	[S_IFREG >> S_SHIFT]	= EXT3COW_FT_REG_FILE,
-+	[S_IFDIR >> S_SHIFT]	= EXT3COW_FT_DIR,
-+	[S_IFCHR >> S_SHIFT]	= EXT3COW_FT_CHRDEV,
-+	[S_IFBLK >> S_SHIFT]	= EXT3COW_FT_BLKDEV,
-+	[S_IFIFO >> S_SHIFT]	= EXT3COW_FT_FIFO,
-+	[S_IFSOCK >> S_SHIFT]	= EXT3COW_FT_SOCK,
-+	[S_IFLNK >> S_SHIFT]	= EXT3COW_FT_SYMLINK,
-+};
-+
-+static inline void ext3cow_set_de_type(struct super_block *sb,
-+				struct ext3cow_dir_entry_2 *de,
-+				umode_t mode) {
-+	if (EXT3COW_HAS_INCOMPAT_FEATURE(sb, EXT3COW_FEATURE_INCOMPAT_FILETYPE))
-+		de->file_type = ext3cow_type_by_mode[(mode & S_IFMT)>>S_SHIFT];
-+}
-+
-+#ifdef CONFIG_EXT3COW_INDEX
-+static struct ext3cow_dir_entry_2 *
-+dx_move_dirents(char *from, char *to, struct dx_map_entry *map, int count)
-+{
-+	unsigned rec_len = 0;
-+
-+	while (count--) {
-+		struct ext3cow_dir_entry_2 *de = (struct ext3cow_dir_entry_2 *) (from + map->offs);
-+		rec_len = EXT3COW_DIR_REC_LEN(de->name_len);
-+		memcpy (to, de, rec_len);
-+		((struct ext3cow_dir_entry_2 *) to)->rec_len =
-+				cpu_to_le16(rec_len);
-+		de->inode = 0;
-+		map++;
-+		to += rec_len;
-+	}
-+	return (struct ext3cow_dir_entry_2 *) (to - rec_len);
-+}
-+
-+static struct ext3cow_dir_entry_2* dx_pack_dirents(char *base, int size)
-+{
-+	struct ext3cow_dir_entry_2 *next, *to, *prev, *de = (struct ext3cow_dir_entry_2 *) base;
-+	unsigned rec_len = 0;
-+
-+	prev = to = de;
-+	while ((char*)de < base + size) {
-+		next = (struct ext3cow_dir_entry_2 *) ((char *) de +
-+						    le16_to_cpu(de->rec_len));
-+		if (de->inode && de->name_len) {
-+			rec_len = EXT3COW_DIR_REC_LEN(de->name_len);
-+			if (de > to)
-+				memmove(to, de, rec_len);
-+			to->rec_len = cpu_to_le16(rec_len);
-+			prev = to;
-+			to = (struct ext3cow_dir_entry_2 *) (((char *) to) + rec_len);
-+		}
-+		de = next;
-+	}
-+	return prev;
-+}
-+
-+static struct ext3cow_dir_entry_2 *do_split(handle_t *handle, struct inode *dir,
-+			struct buffer_head **bh,struct dx_frame *frame,
-+			struct dx_hash_info *hinfo, int *error)
-+{
-+	unsigned blocksize = dir->i_sb->s_blocksize;
-+	unsigned count, continued;
-+	struct buffer_head *bh2;
-+	u32 newblock;
-+	u32 hash2;
-+	struct dx_map_entry *map;
-+	char *data1 = (*bh)->b_data, *data2;
-+	unsigned split;
-+	struct ext3cow_dir_entry_2 *de = NULL, *de2;
-+	int	err;
-+
-+	bh2 = ext3cow_append (handle, dir, &newblock, error);
-+	if (!(bh2)) {
-+		brelse(*bh);
-+		*bh = NULL;
-+		goto errout;
-+	}
-+
-+	BUFFER_TRACE(*bh, "get_write_access");
-+	err = ext3cow_journal_get_write_access(handle, *bh);
-+	if (err) {
-+	journal_error:
-+		brelse(*bh);
-+		brelse(bh2);
-+		*bh = NULL;
-+		ext3cow_std_error(dir->i_sb, err);
-+		goto errout;
-+	}
-+	BUFFER_TRACE(frame->bh, "get_write_access");
-+	err = ext3cow_journal_get_write_access(handle, frame->bh);
-+	if (err)
-+		goto journal_error;
-+
-+	data2 = bh2->b_data;
-+
-+	/* create map in the end of data2 block */
-+	map = (struct dx_map_entry *) (data2 + blocksize);
-+	count = dx_make_map ((struct ext3cow_dir_entry_2 *) data1,
-+			     blocksize, hinfo, map);
-+	map -= count;
-+	split = count/2; // need to adjust to actual middle
-+	dx_sort_map (map, count);
-+	hash2 = map[split].hash;
-+	continued = hash2 == map[split - 1].hash;
-+	dxtrace(printk("Split block %i at %x, %i/%i\n",
-+		dx_get_block(frame->at), hash2, split, count-split));
-+
-+	/* Fancy dance to stay within two buffers */
-+	de2 = dx_move_dirents(data1, data2, map + split, count - split);
-+	de = dx_pack_dirents(data1,blocksize);
-+	de->rec_len = cpu_to_le16(data1 + blocksize - (char *) de);
-+	de2->rec_len = cpu_to_le16(data2 + blocksize - (char *) de2);
-+	dxtrace(dx_show_leaf (hinfo, (struct ext3cow_dir_entry_2 *) data1, blocksize, 1));
-+	dxtrace(dx_show_leaf (hinfo, (struct ext3cow_dir_entry_2 *) data2, blocksize, 1));
-+
-+	/* Which block gets the new entry? */
-+	if (hinfo->hash >= hash2)
-+	{
-+		swap(*bh, bh2);
-+		de = de2;
-+	}
-+	dx_insert_block (frame, hash2 + continued, newblock);
-+	err = ext3cow_journal_dirty_metadata (handle, bh2);
-+	if (err)
-+		goto journal_error;
-+	err = ext3cow_journal_dirty_metadata (handle, frame->bh);
-+	if (err)
-+		goto journal_error;
-+	brelse (bh2);
-+	dxtrace(dx_show_index ("frame", frame->entries));
-+errout:
-+	return de;
-+}
-+#endif
-+
-+
-+/*
-+ * Add a new entry into a directory (leaf) block.  If de is non-NULL,
-+ * it points to a directory entry which is guaranteed to be large
-+ * enough for new directory entry.  If de is NULL, then
-+ * add_dirent_to_buf will attempt search the directory block for
-+ * space.  It will return -ENOSPC if no space is available, and -EIO
-+ * and -EEXIST if directory entry already exists.
-+ *
-+ * NOTE!  bh is NOT released in the case where ENOSPC is returned.  In
-+ * all other cases bh is released.
-+ */
-+static int add_dirent_to_buf(handle_t *handle, struct dentry *dentry,
-+			     struct inode *inode, struct ext3cow_dir_entry_2 *de,
-+			     struct buffer_head * bh)
-+{
-+	struct inode	*dir = dentry->d_parent->d_inode;
-+	const char	*name = dentry->d_name.name;
-+	int		namelen = dentry->d_name.len;
-+	unsigned long	offset = 0;
-+	unsigned short	reclen;
-+	int		nlen, rlen, err;
-+	char		*top;
-+
-+	reclen = EXT3COW_DIR_REC_LEN(namelen);
-+	if (!de) {
-+		de = (struct ext3cow_dir_entry_2 *)bh->b_data;
-+		top = bh->b_data + dir->i_sb->s_blocksize - reclen;
-+		while ((char *) de <= top) {
-+			if (!ext3cow_check_dir_entry("ext3cow_add_entry", dir, de,
-+						  bh, offset)) {
-+				brelse (bh);
-+        ext3cow_reclaim_dup_inode(dentry->d_parent->d_parent->d_inode, dir);
-+				return -EIO;
-+			}
-+      /* If name exists and it's still alive, no add. But if it's a new
-+       * name in this scope, ok to add. -znjp */
-+			if (ext3cow_match (namelen, name, de) && EXT3COW_IS_DIRENT_ALIVE(de)) {
-+				brelse (bh);
-+				return -EEXIST;
-+			}
-+			nlen = EXT3COW_DIR_REC_LEN(de->name_len);
-+			rlen = le16_to_cpu(de->rec_len);
-+			if ((de->inode? rlen - nlen: rlen) >= reclen)
-+				break;
-+			de = (struct ext3cow_dir_entry_2 *)((char *)de + rlen);
-+			offset += rlen;
-+		}
-+		if ((char *) de > top)
-+			return -ENOSPC;
-+	}
-+	BUFFER_TRACE(bh, "get_write_access");
-+	err = ext3cow_journal_get_write_access(handle, bh);
-+	if (err) {
-+		ext3cow_std_error(dir->i_sb, err);
-+		brelse(bh);
-+		return err;
-+	}
-+
-+	/* By now the buffer is marked for journaling */
-+	nlen = EXT3COW_DIR_REC_LEN(de->name_len);
-+	rlen = le16_to_cpu(de->rec_len);
-+	if (de->inode) {
-+		struct ext3cow_dir_entry_2 *de1 = (struct ext3cow_dir_entry_2 *)((char *)de + nlen);
-+		de1->rec_len = cpu_to_le16(rlen - nlen);
-+		de->rec_len = cpu_to_le16(nlen);
-+		de = de1;
-+	}
-+	de->file_type = EXT3COW_FT_UNKNOWN;
-+	if (inode) {
-+		de->inode = cpu_to_le32(inode->i_ino);
-+		ext3cow_set_de_type(dir->i_sb, de, inode->i_mode);
-+	} else
-+		de->inode = 0;
-+  /* For versioning -znjp */
-+  de->birth_epoch = cpu_to_le32(EXT3COW_S_EPOCHNUMBER(dir->i_sb));
-+  de->death_epoch = cpu_to_le32(EXT3COW_DIRENT_ALIVE);
-+	de->name_len = namelen;
-+	memcpy (de->name, name, namelen);
-+	/*
-+	 * XXX shouldn't update any times until successful
-+	 * completion of syscall, but too many callers depend
-+	 * on this.
-+	 *
-+	 * XXX similarly, too many callers depend on
-+	 * ext3cow_new_inode() setting the times, but error
-+	 * recovery deletes the inode, so the worst that can
-+	 * happen is that the times are slightly out of date
-+	 * and/or different from the directory change time.
-+	 */
-+	dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC;
-+	ext3cow_update_dx_flag(dir);
-+	dir->i_version++;
-+	ext3cow_mark_inode_dirty(handle, dir);
-+	BUFFER_TRACE(bh, "call ext3cow_journal_dirty_metadata");
-+	err = ext3cow_journal_dirty_metadata(handle, bh);
-+	if (err)
-+		ext3cow_std_error(dir->i_sb, err);
-+	brelse(bh);
-+	return 0;
-+}
-+
-+#ifdef CONFIG_EXT3COW_INDEX
-+/*
-+ * This converts a one block unindexed directory to a 3 block indexed
-+ * directory, and adds the dentry to the indexed directory.
-+ */
-+static int make_indexed_dir(handle_t *handle, struct dentry *dentry,
-+			    struct inode *inode, struct buffer_head *bh)
-+{
-+	struct inode	*dir = dentry->d_parent->d_inode;
-+	const char	*name = dentry->d_name.name;
-+	int		namelen = dentry->d_name.len;
-+	struct buffer_head *bh2;
-+	struct dx_root	*root;
-+	struct dx_frame	frames[2], *frame;
-+	struct dx_entry *entries;
-+	struct ext3cow_dir_entry_2	*de, *de2;
-+	char		*data1, *top;
-+	unsigned	len;
-+	int		retval;
-+	unsigned	blocksize;
-+	struct dx_hash_info hinfo;
-+	u32		block;
-+	struct fake_dirent *fde;
-+
-+	blocksize =  dir->i_sb->s_blocksize;
-+	dxtrace(printk("Creating index\n"));
-+	retval = ext3cow_journal_get_write_access(handle, bh);
-+	if (retval) {
-+		ext3cow_std_error(dir->i_sb, retval);
-+		brelse(bh);
-+		return retval;
-+	}
-+	root = (struct dx_root *) bh->b_data;
-+
-+	bh2 = ext3cow_append (handle, dir, &block, &retval);
-+	if (!(bh2)) {
-+		brelse(bh);
-+		return retval;
-+	}
-+	EXT3COW_I(dir)->i_flags |= EXT3COW_INDEX_FL;
-+	data1 = bh2->b_data;
-+
-+	/* The 0th block becomes the root, move the dirents out */
-+	fde = &root->dotdot;
-+	de = (struct ext3cow_dir_entry_2 *)((char *)fde + le16_to_cpu(fde->rec_len));
-+	len = ((char *) root) + blocksize - (char *) de;
-+	memcpy (data1, de, len);
-+	de = (struct ext3cow_dir_entry_2 *) data1;
-+	top = data1 + len;
-+	while ((char *)(de2=(void*)de+le16_to_cpu(de->rec_len)) < top)
-+		de = de2;
-+	de->rec_len = cpu_to_le16(data1 + blocksize - (char *) de);
-+	/* Initialize the root; the dot dirents already exist */
-+	de = (struct ext3cow_dir_entry_2 *) (&root->dotdot);
-+	de->rec_len = cpu_to_le16(blocksize - EXT3COW_DIR_REC_LEN(2));
-+	memset (&root->info, 0, sizeof(root->info));
-+	root->info.info_length = sizeof(root->info);
-+	root->info.hash_version = EXT3COW_SB(dir->i_sb)->s_def_hash_version;
-+	entries = root->entries;
-+	dx_set_block (entries, 1);
-+	dx_set_count (entries, 1);
-+	dx_set_limit (entries, dx_root_limit(dir, sizeof(root->info)));
-+
-+	/* Initialize as for dx_probe */
-+	hinfo.hash_version = root->info.hash_version;
-+	hinfo.seed = EXT3COW_SB(dir->i_sb)->s_hash_seed;
-+	ext3cowfs_dirhash(name, namelen, &hinfo);
-+	frame = frames;
-+	frame->entries = entries;
-+	frame->at = entries;
-+	frame->bh = bh;
-+	bh = bh2;
-+	de = do_split(handle,dir, &bh, frame, &hinfo, &retval);
-+	dx_release (frames);
-+	if (!(de))
-+		return retval;
-+
-+	return add_dirent_to_buf(handle, dentry, inode, de, bh);
-+}
-+#endif
-+
-+/*
-+ *	ext3cow_add_entry()
-+ *
-+ * adds a file entry to the specified directory, using the same
-+ * semantics as ext3cow_find_entry(). It returns NULL if it failed.
-+ *
-+ * NOTE!! The inode part of 'de' is left at 0 - which means you
-+ * may not sleep between calling this and putting something into
-+ * the entry, as someone else might have used it while you slept.
-+ */
-+static int ext3cow_add_entry (handle_t *handle, struct dentry *dentry,
-+	struct inode *inode)
-+{
-+	struct inode *dir = dentry->d_parent->d_inode;
-+	unsigned long offset;
-+	struct buffer_head * bh;
-+	struct ext3cow_dir_entry_2 *de;
-+	struct super_block * sb;
-+	int	retval;
-+#ifdef CONFIG_EXT3COW_INDEX
-+	int	dx_fallback=0;
-+#endif
-+	unsigned blocksize;
-+	u32 block, blocks;
-+
-+	sb = dir->i_sb;
-+	blocksize = sb->s_blocksize;
-+	if (!dentry->d_name.len)
-+		return -EINVAL;
-+  /* No additions in the past -znjp */
-+  if(is_unchangeable(dir, dentry))
-+    return -EROFS;
-+
-+  if(EXT3COW_S_EPOCHNUMBER(sb) > EXT3COW_I_EPOCHNUMBER(dir)){   
-+    if(ext3cow_dup_inode(dentry->d_parent->d_parent->d_inode, dir))
-+      return -1;
-+  }
-+
-+#ifdef CONFIG_EXT3COW_INDEX
-+	if (is_dx(dir)) {
-+		retval = ext3cow_dx_add_entry(handle, dentry, inode);
-+		if (!retval || (retval != ERR_BAD_DX_DIR)){
-+      ext3cow_reclaim_dup_inode(dentry->d_parent->d_parent->d_inode, dir);
-+			return retval;
-+    }
-+		EXT3COW_I(dir)->i_flags &= ~EXT3COW_INDEX_FL;
-+		dx_fallback++;
-+		ext3cow_mark_inode_dirty(handle, dir);
-+	}
-+#endif
-+	blocks = dir->i_size >> sb->s_blocksize_bits;
-+	for (block = 0, offset = 0; block < blocks; block++) {
-+		bh = ext3cow_bread(handle, dir, block, 0, &retval);
-+		if(!bh){
-+      ext3cow_reclaim_dup_inode(dentry->d_parent->d_parent->d_inode, dir);
-+			return retval;
-+    }
-+		retval = add_dirent_to_buf(handle, dentry, inode, NULL, bh);
-+		if (retval != -ENOSPC)
-+			return retval;
-+
-+#ifdef CONFIG_EXT3COW_INDEX
-+		if (blocks == 1 && !dx_fallback &&
-+		    EXT3COW_HAS_COMPAT_FEATURE(sb, EXT3COW_FEATURE_COMPAT_DIR_INDEX))
-+			return make_indexed_dir(handle, dentry, inode, bh);
-+#endif
-+		brelse(bh);
-+	}
-+
-+	bh = ext3cow_append(handle, dir, &block, &retval);
-+	if (!bh){
-+    ext3cow_reclaim_dup_inode(dentry->d_parent->d_parent->d_inode, dir);
-+		return retval;
-+  }
-+	de = (struct ext3cow_dir_entry_2 *) bh->b_data;
-+	de->inode = 0;
-+	de->rec_len = cpu_to_le16(blocksize);
-+	return add_dirent_to_buf(handle, dentry, inode, de, bh);
-+}
-+
-+#ifdef CONFIG_EXT3COW_INDEX
-+/*
-+ * Returns 0 for success, or a negative error value
-+ */
-+static int ext3cow_dx_add_entry(handle_t *handle, struct dentry *dentry,
-+			     struct inode *inode)
-+{
-+	struct dx_frame frames[2], *frame;
-+	struct dx_entry *entries, *at;
-+	struct dx_hash_info hinfo;
-+	struct buffer_head * bh;
-+	struct inode *dir = dentry->d_parent->d_inode;
-+	struct super_block * sb = dir->i_sb;
-+	struct ext3cow_dir_entry_2 *de;
-+	int err;
-+
-+	frame = dx_probe(dentry, NULL, &hinfo, frames, &err);
-+	if (!frame)
-+		return err;
-+	entries = frame->entries;
-+	at = frame->at;
-+
-+	if (!(bh = ext3cow_bread(handle,dir, dx_get_block(frame->at), 0, &err)))
-+		goto cleanup;
-+
-+	BUFFER_TRACE(bh, "get_write_access");
-+	err = ext3cow_journal_get_write_access(handle, bh);
-+	if (err)
-+		goto journal_error;
-+
-+	err = add_dirent_to_buf(handle, dentry, inode, NULL, bh);
-+	if (err != -ENOSPC) {
-+		bh = NULL;
-+		goto cleanup;
-+	}
-+
-+	/* Block full, should compress but for now just split */
-+	dxtrace(printk("using %u of %u node entries\n",
-+		       dx_get_count(entries), dx_get_limit(entries)));
-+	/* Need to split index? */
-+	if (dx_get_count(entries) == dx_get_limit(entries)) {
-+		u32 newblock;
-+		unsigned icount = dx_get_count(entries);
-+		int levels = frame - frames;
-+		struct dx_entry *entries2;
-+		struct dx_node *node2;
-+		struct buffer_head *bh2;
-+
-+		if (levels && (dx_get_count(frames->entries) ==
-+			       dx_get_limit(frames->entries))) {
-+			ext3cow_warning(sb, __FUNCTION__,
-+				     "Directory index full!");
-+			err = -ENOSPC;
-+			goto cleanup;
-+		}
-+		bh2 = ext3cow_append (handle, dir, &newblock, &err);
-+		if (!(bh2))
-+			goto cleanup;
-+		node2 = (struct dx_node *)(bh2->b_data);
-+		entries2 = node2->entries;
-+		node2->fake.rec_len = cpu_to_le16(sb->s_blocksize);
-+		node2->fake.inode = 0;
-+		BUFFER_TRACE(frame->bh, "get_write_access");
-+		err = ext3cow_journal_get_write_access(handle, frame->bh);
-+		if (err)
-+			goto journal_error;
-+		if (levels) {
-+			unsigned icount1 = icount/2, icount2 = icount - icount1;
-+			unsigned hash2 = dx_get_hash(entries + icount1);
-+			dxtrace(printk("Split index %i/%i\n", icount1, icount2));
-+
-+			BUFFER_TRACE(frame->bh, "get_write_access"); /* index root */
-+			err = ext3cow_journal_get_write_access(handle,
-+							     frames[0].bh);
-+			if (err)
-+				goto journal_error;
-+
-+			memcpy ((char *) entries2, (char *) (entries + icount1),
-+				icount2 * sizeof(struct dx_entry));
-+			dx_set_count (entries, icount1);
-+			dx_set_count (entries2, icount2);
-+			dx_set_limit (entries2, dx_node_limit(dir));
-+
-+			/* Which index block gets the new entry? */
-+			if (at - entries >= icount1) {
-+				frame->at = at = at - entries - icount1 + entries2;
-+				frame->entries = entries = entries2;
-+				swap(frame->bh, bh2);
-+			}
-+			dx_insert_block (frames + 0, hash2, newblock);
-+			dxtrace(dx_show_index ("node", frames[1].entries));
-+			dxtrace(dx_show_index ("node",
-+			       ((struct dx_node *) bh2->b_data)->entries));
-+			err = ext3cow_journal_dirty_metadata(handle, bh2);
-+			if (err)
-+				goto journal_error;
-+			brelse (bh2);
-+		} else {
-+			dxtrace(printk("Creating second level index...\n"));
-+			memcpy((char *) entries2, (char *) entries,
-+			       icount * sizeof(struct dx_entry));
-+			dx_set_limit(entries2, dx_node_limit(dir));
-+
-+			/* Set up root */
-+			dx_set_count(entries, 1);
-+			dx_set_block(entries + 0, newblock);
-+			((struct dx_root *) frames[0].bh->b_data)->info.indirect_levels = 1;
-+
-+			/* Add new access path frame */
-+			frame = frames + 1;
-+			frame->at = at = at - entries + entries2;
-+			frame->entries = entries = entries2;
-+			frame->bh = bh2;
-+			err = ext3cow_journal_get_write_access(handle,
-+							     frame->bh);
-+			if (err)
-+				goto journal_error;
-+		}
-+		ext3cow_journal_dirty_metadata(handle, frames[0].bh);
-+	}
-+	de = do_split(handle, dir, &bh, frame, &hinfo, &err);
-+	if (!de)
-+		goto cleanup;
-+	err = add_dirent_to_buf(handle, dentry, inode, de, bh);
-+	bh = NULL;
-+	goto cleanup;
-+
-+journal_error:
-+	ext3cow_std_error(dir->i_sb, err);
-+cleanup:
-+	if (bh)
-+		brelse(bh);
-+	dx_release(frames);
-+	return err;
-+}
-+#endif
-+
-+/*
-+ * ext3cow_delete_entry deletes a directory entry by merging it with the
-+ * previous entry
-+ */
-+static int ext3cow_delete_entry (handle_t *handle,
-+                                 struct inode * dir,
-+                                 struct ext3cow_dir_entry_2 * de_del,
-+                                 struct buffer_head * bh,
-+                                 struct dentry *dentry)
-+{
-+	struct ext3cow_dir_entry_2 * de, * pde;
-+	int i;
-+
-+	i = 0;
-+	pde = NULL;
-+	de = (struct ext3cow_dir_entry_2 *) bh->b_data;
-+	while (i < bh->b_size) {
-+		if (!ext3cow_check_dir_entry("ext3cow_delete_entry", dir, de, bh, i))
-+			return -EIO;
-+		if (de == de_del)  {
-+      /* Can't delete an already dead entry - znjp */
-+      if(!EXT3COW_IS_DIRENT_ALIVE(de))
-+        return 0;
-+      
-+      if(EXT3COW_S_EPOCHNUMBER(dir->i_sb) > EXT3COW_I_EPOCHNUMBER(dir)){
-+        if(ext3cow_dup_inode(dentry->d_parent->d_parent->d_inode, dir))
-+          return -1;
-+      }
-+
-+			BUFFER_TRACE(bh, "get_write_access");
-+			ext3cow_journal_get_write_access(handle, bh);
-+      /* There used to be code here to adjust the rec_len
-+       * but since names really never go away, the code was deleted 
-+			if (pde)
-+				pde->rec_len =
-+					cpu_to_le16(le16_to_cpu(pde->rec_len) +
-+						    le16_to_cpu(de->rec_len));
-+			else
-+				de->inode = 0;
-+      */
-+      /* Mark it dead - znjp */
-+      de->death_epoch = cpu_to_le32(EXT3COW_I_EPOCHNUMBER(dir));
-+			dir->i_version++;
-+			BUFFER_TRACE(bh, "call ext3cow_journal_dirty_metadata");
-+			ext3cow_journal_dirty_metadata(handle, bh);
-+			return 0;
-+		}
-+		i += le16_to_cpu(de->rec_len);
-+		pde = de;
-+		de = (struct ext3cow_dir_entry_2 *)
-+			((char *) de + le16_to_cpu(de->rec_len));
-+	}
-+	return -ENOENT;
-+}
-+
-+/*
-+ * ext3cow_mark_inode_dirty is somewhat expensive, so unlike ext2 we
-+ * do not perform it in these functions.  We perform it at the call site,
-+ * if it is needed.
-+ */
-+static inline void ext3cow_inc_count(handle_t *handle, struct inode *inode)
-+{
-+	inc_nlink(inode);
-+}
-+
-+static inline void ext3cow_dec_count(handle_t *handle, struct inode *inode)
-+{
-+	drop_nlink(inode);
-+}
-+
-+static int ext3cow_add_nondir(handle_t *handle,
-+		struct dentry *dentry, struct inode *inode)
-+{
-+	int err = ext3cow_add_entry(handle, dentry, inode);
-+	if (!err) {
-+		ext3cow_mark_inode_dirty(handle, inode);
-+		d_instantiate(dentry, inode);
-+		return 0;
-+	}
-+	ext3cow_dec_count(handle, inode);
-+	iput(inode);
-+	return err;
-+}
-+
-+/*
-+ * By the time this is called, we already have created
-+ * the directory cache entry for the new file, but it
-+ * is so far negative - it has no inode.
-+ *
-+ * If the create succeeds, we fill in the inode information
-+ * with d_instantiate().
-+ */
-+static int ext3cow_create (struct inode * dir, struct dentry * dentry, int mode,
-+		struct nameidata *nd)
-+{
-+	handle_t *handle;
-+	struct inode * inode;
-+	int err, retries = 0;
-+
-+  /* Can't create in the past -znjp */
-+  if(is_unchangeable(dir, dentry))
-+    return -EROFS;
-+
-+retry:
-+	handle = ext3cow_journal_start(dir, EXT3COW_DATA_TRANS_BLOCKS(dir->i_sb) +
-+					EXT3COW_INDEX_EXTRA_TRANS_BLOCKS + 3 +
-+					2*EXT3COW_QUOTA_INIT_BLOCKS(dir->i_sb));
-+	if (IS_ERR(handle))
-+		return PTR_ERR(handle);
-+
-+	if (IS_DIRSYNC(dir))
-+		handle->h_sync = 1;
-+
-+	inode = ext3cow_new_inode (handle, dir, mode);
-+	err = PTR_ERR(inode);
-+	if (!IS_ERR(inode)) {
-+		inode->i_op = &ext3cow_file_inode_operations;
-+		inode->i_fop = &ext3cow_file_operations;
-+		ext3cow_set_aops(inode);
-+		err = ext3cow_add_nondir(handle, dentry, inode);
-+	}
-+	ext3cow_journal_stop(handle);
-+	if (err == -ENOSPC && ext3cow_should_retry_alloc(dir->i_sb, &retries))
-+		goto retry;
-+	return err;
-+}
-+
-+static int ext3cow_mknod (struct inode * dir, struct dentry *dentry,
-+			int mode, dev_t rdev)
-+{
-+	handle_t *handle;
-+	struct inode *inode;
-+	int err, retries = 0;
-+
-+	if (!new_valid_dev(rdev))
-+		return -EINVAL;
-+
-+retry:
-+	handle = ext3cow_journal_start(dir, EXT3COW_DATA_TRANS_BLOCKS(dir->i_sb) +
-+					EXT3COW_INDEX_EXTRA_TRANS_BLOCKS + 3 +
-+					2*EXT3COW_QUOTA_INIT_BLOCKS(dir->i_sb));
-+	if (IS_ERR(handle))
-+		return PTR_ERR(handle);
-+
-+	if (IS_DIRSYNC(dir))
-+		handle->h_sync = 1;
-+
-+	inode = ext3cow_new_inode (handle, dir, mode);
-+	err = PTR_ERR(inode);
-+	if (!IS_ERR(inode)) {
-+		init_special_inode(inode, inode->i_mode, rdev);
-+#ifdef CONFIG_EXT3COW_FS_XATTR
-+		inode->i_op = &ext3cow_special_inode_operations;
-+#endif
-+		err = ext3cow_add_nondir(handle, dentry, inode);
-+	}
-+	ext3cow_journal_stop(handle);
-+	if (err == -ENOSPC && ext3cow_should_retry_alloc(dir->i_sb, &retries))
-+		goto retry;
-+	return err;
-+}
-+
-+static int ext3cow_mkdir(struct inode * dir, struct dentry * dentry, int mode)
-+{
-+	handle_t *handle;
-+	struct inode * inode;
-+	struct buffer_head * dir_block;
-+	struct ext3cow_dir_entry_2 * de;
-+	int err, retries = 0;
-+
-+	if (dir->i_nlink >= EXT3COW_LINK_MAX)
-+		return -EMLINK;
-+  /* No mkdirs in the past -znjp */
-+  if(is_unchangeable(dir, dentry))
-+    return -EROFS;
-+
-+
-+retry:
-+	handle = ext3cow_journal_start(dir, EXT3COW_DATA_TRANS_BLOCKS(dir->i_sb) +
-+					EXT3COW_INDEX_EXTRA_TRANS_BLOCKS + 3 +
-+					2*EXT3COW_QUOTA_INIT_BLOCKS(dir->i_sb));
-+	if (IS_ERR(handle))
-+		return PTR_ERR(handle);
-+
-+	if (IS_DIRSYNC(dir))
-+		handle->h_sync = 1;
-+
-+	inode = ext3cow_new_inode (handle, dir, S_IFDIR | mode);
-+	err = PTR_ERR(inode);
-+	if (IS_ERR(inode))
-+		goto out_stop;
-+
-+	inode->i_op = &ext3cow_dir_inode_operations;
-+	inode->i_fop = &ext3cow_dir_operations;
-+	inode->i_size = EXT3COW_I(inode)->i_disksize = inode->i_sb->s_blocksize;
-+	dir_block = ext3cow_bread (handle, inode, 0, 1, &err);
-+	if (!dir_block) {
-+		drop_nlink(inode); /* is this nlink == 0? */
-+		ext3cow_mark_inode_dirty(handle, inode);
-+		iput (inode);
-+		goto out_stop;
-+	}
-+	BUFFER_TRACE(dir_block, "get_write_access");
-+	ext3cow_journal_get_write_access(handle, dir_block);
-+	de = (struct ext3cow_dir_entry_2 *) dir_block->b_data;
-+	de->inode = cpu_to_le32(inode->i_ino);
-+	de->name_len = 1;
-+	de->rec_len = cpu_to_le16(EXT3COW_DIR_REC_LEN(de->name_len));
-+  /* For versioning -znjp */
-+  de->birth_epoch = cpu_to_le32(EXT3COW_S_EPOCHNUMBER(dir->i_sb));
-+  de->death_epoch = cpu_to_le32(EXT3COW_DIRENT_ALIVE);
-+	strcpy (de->name, ".");
-+	ext3cow_set_de_type(dir->i_sb, de, S_IFDIR);
-+	de = (struct ext3cow_dir_entry_2 *)
-+			((char *) de + le16_to_cpu(de->rec_len));
-+	de->inode = cpu_to_le32(dir->i_ino);
-+	de->rec_len = cpu_to_le16(inode->i_sb->s_blocksize-EXT3COW_DIR_REC_LEN(1));
-+	de->name_len = 2;
-+	strcpy (de->name, "..");
-+	ext3cow_set_de_type(dir->i_sb, de, S_IFDIR);
-+	inode->i_nlink = 2;
-+  /* For versioning -znjp */
-+  de->birth_epoch = cpu_to_le32(EXT3COW_I_EPOCHNUMBER(dir)); 
-+  de->death_epoch = cpu_to_le32(EXT3COW_DIRENT_ALIVE);
-+	BUFFER_TRACE(dir_block, "call ext3cow_journal_dirty_metadata");
-+	ext3cow_journal_dirty_metadata(handle, dir_block);
-+	brelse (dir_block);
-+	ext3cow_mark_inode_dirty(handle, inode);
-+	err = ext3cow_add_entry (handle, dentry, inode);
-+	if (err) {
-+		inode->i_nlink = 0;
-+		ext3cow_mark_inode_dirty(handle, inode);
-+		iput (inode);
-+		goto out_stop;
-+	}
-+	inc_nlink(dir);
-+	ext3cow_update_dx_flag(dir);
-+	ext3cow_mark_inode_dirty(handle, dir);
-+	d_instantiate(dentry, inode);
-+out_stop:
-+	ext3cow_journal_stop(handle);
-+	if (err == -ENOSPC && ext3cow_should_retry_alloc(dir->i_sb, &retries))
-+		goto retry;
-+	return err;
-+}
-+
-+/*
-+ * routine to check that the specified directory is empty (for rmdir)
-+ */
-+static int empty_dir (struct inode * inode)
-+{
-+	unsigned long offset;
-+	struct buffer_head * bh;
-+	struct ext3cow_dir_entry_2 * de, * de1;
-+	struct super_block * sb;
-+	int err = 0;
-+
-+	sb = inode->i_sb;
-+	if (inode->i_size < EXT3COW_DIR_REC_LEN(1) + EXT3COW_DIR_REC_LEN(2) ||
-+	    !(bh = ext3cow_bread (NULL, inode, 0, 0, &err))) {
-+		if (err)
-+			ext3cow_error(inode->i_sb, __FUNCTION__,
-+				   "error %d reading directory #%lu offset 0",
-+				   err, inode->i_ino);
-+		else
-+			ext3cow_warning(inode->i_sb, __FUNCTION__,
-+				     "bad directory (dir #%lu) - no data block",
-+				     inode->i_ino);
-+		return 1;
-+	}
-+	de = (struct ext3cow_dir_entry_2 *) bh->b_data;
-+	de1 = (struct ext3cow_dir_entry_2 *)
-+			((char *) de + le16_to_cpu(de->rec_len));
-+	if (le32_to_cpu(de->inode) != inode->i_ino ||
-+			!le32_to_cpu(de1->inode) ||
-+			strcmp (".", de->name) ||
-+			strcmp ("..", de1->name)) {
-+		ext3cow_warning (inode->i_sb, "empty_dir",
-+			      "bad directory (dir #%lu) - no `.' or `..'",
-+			      inode->i_ino);
-+		brelse (bh);
-+		return 1;
-+	}
-+	offset = le16_to_cpu(de->rec_len) + le16_to_cpu(de1->rec_len);
-+	de = (struct ext3cow_dir_entry_2 *)
-+			((char *) de1 + le16_to_cpu(de1->rec_len));
-+	while (offset < inode->i_size ) {
-+		if (!bh ||
-+			(void *) de >= (void *) (bh->b_data+sb->s_blocksize)) {
-+			err = 0;
-+			brelse (bh);
-+			bh = ext3cow_bread (NULL, inode,
-+				offset >> EXT3COW_BLOCK_SIZE_BITS(sb), 0, &err);
-+			if (!bh) {
-+				if (err)
-+					ext3cow_error(sb, __FUNCTION__,
-+						   "error %d reading directory"
-+						   " #%lu offset %lu",
-+						   err, inode->i_ino, offset);
-+				offset += sb->s_blocksize;
-+				continue;
-+			}
-+			de = (struct ext3cow_dir_entry_2 *) bh->b_data;
-+		}
-+		if (!ext3cow_check_dir_entry("empty_dir", inode, de, bh, offset)) {
-+			de = (struct ext3cow_dir_entry_2 *)(bh->b_data +
-+							 sb->s_blocksize);
-+			offset = (offset | (sb->s_blocksize - 1)) + 1;
-+			continue;
-+		}
-+    /* Can remove a dir only if all dirents are out of scope -znjp */
-+		if (le32_to_cpu(de->inode) &&
-+        EXT3COW_IS_DIRENT_SCOPED(de, EXT3COW_I_EPOCHNUMBER(inode))) {
-+			brelse (bh);
-+			return 0;
-+		}
-+		offset += le16_to_cpu(de->rec_len);
-+		de = (struct ext3cow_dir_entry_2 *)
-+				((char *) de + le16_to_cpu(de->rec_len));
-+	}
-+	brelse (bh);
-+	return 1;
-+}
-+
-+/* ext3cow_orphan_add() links an unlinked or truncated inode into a list of
-+ * such inodes, starting at the superblock, in case we crash before the
-+ * file is closed/deleted, or in case the inode truncate spans multiple
-+ * transactions and the last transaction is not recovered after a crash.
-+ *
-+ * At filesystem recovery time, we walk this list deleting unlinked
-+ * inodes and truncating linked inodes in ext3cow_orphan_cleanup().
-+ */
-+int ext3cow_orphan_add(handle_t *handle, struct inode *inode)
-+{
-+	struct super_block *sb = inode->i_sb;
-+	struct ext3cow_iloc iloc;
-+	int err = 0, rc;
-+
-+	lock_super(sb);
-+	if (!list_empty(&EXT3COW_I(inode)->i_orphan))
-+		goto out_unlock;
-+
-+	/* Orphan handling is only valid for files with data blocks
-+	 * being truncated, or files being unlinked. */
-+
-+	/* @@@ FIXME: Observation from aviro:
-+	 * I think I can trigger J_ASSERT in ext3cow_orphan_add().  We block
-+	 * here (on lock_super()), so race with ext3cow_link() which might bump
-+	 * ->i_nlink. For, say it, character device. Not a regular file,
-+	 * not a directory, not a symlink and ->i_nlink > 0.
-+	 */
-+	J_ASSERT ((S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
-+		S_ISLNK(inode->i_mode)) || inode->i_nlink == 0);
-+
-+	BUFFER_TRACE(EXT3COW_SB(sb)->s_sbh, "get_write_access");
-+	err = ext3cow_journal_get_write_access(handle, EXT3COW_SB(sb)->s_sbh);
-+	if (err)
-+		goto out_unlock;
-+
-+	err = ext3cow_reserve_inode_write(handle, inode, &iloc);
-+	if (err)
-+		goto out_unlock;
-+
-+	/* Insert this inode at the head of the on-disk orphan list... */
-+	NEXT_ORPHAN(inode) = le32_to_cpu(EXT3COW_SB(sb)->s_es->s_last_orphan);
-+	EXT3COW_SB(sb)->s_es->s_last_orphan = cpu_to_le32(inode->i_ino);
-+	err = ext3cow_journal_dirty_metadata(handle, EXT3COW_SB(sb)->s_sbh);
-+	rc = ext3cow_mark_iloc_dirty(handle, inode, &iloc);
-+	if (!err)
-+		err = rc;
-+
-+	/* Only add to the head of the in-memory list if all the
-+	 * previous operations succeeded.  If the orphan_add is going to
-+	 * fail (possibly taking the journal offline), we can't risk
-+	 * leaving the inode on the orphan list: stray orphan-list
-+	 * entries can cause panics at unmount time.
-+	 *
-+	 * This is safe: on error we're going to ignore the orphan list
-+	 * anyway on the next recovery. */
-+	if (!err)
-+		list_add(&EXT3COW_I(inode)->i_orphan, &EXT3COW_SB(sb)->s_orphan);
-+
-+	jbd_debug(4, "superblock will point to %lu\n", inode->i_ino);
-+	jbd_debug(4, "orphan inode %lu will point to %d\n",
-+			inode->i_ino, NEXT_ORPHAN(inode));
-+out_unlock:
-+	unlock_super(sb);
-+	ext3cow_std_error(inode->i_sb, err);
-+	return err;
-+}
-+
-+/*
-+ * ext3cow_orphan_del() removes an unlinked or truncated inode from the list
-+ * of such inodes stored on disk, because it is finally being cleaned up.
-+ */
-+int ext3cow_orphan_del(handle_t *handle, struct inode *inode)
-+{
-+	struct list_head *prev;
-+	struct ext3cow_inode_info *ei = EXT3COW_I(inode);
-+	struct ext3cow_sb_info *sbi;
-+	unsigned long ino_next;
-+	struct ext3cow_iloc iloc;
-+	int err = 0;
-+
-+	lock_super(inode->i_sb);
-+	if (list_empty(&ei->i_orphan)) {
-+		unlock_super(inode->i_sb);
-+		return 0;
-+	}
-+
-+	ino_next = NEXT_ORPHAN(inode);
-+	prev = ei->i_orphan.prev;
-+	sbi = EXT3COW_SB(inode->i_sb);
-+
-+	jbd_debug(4, "remove inode %lu from orphan list\n", inode->i_ino);
-+
-+	list_del_init(&ei->i_orphan);
-+
-+	/* If we're on an error path, we may not have a valid
-+	 * transaction handle with which to update the orphan list on
-+	 * disk, but we still need to remove the inode from the linked
-+	 * list in memory. */
-+	if (!handle)
-+		goto out;
-+
-+	err = ext3cow_reserve_inode_write(handle, inode, &iloc);
-+	if (err)
-+		goto out_err;
-+
-+	if (prev == &sbi->s_orphan) {
-+		jbd_debug(4, "superblock will point to %lu\n", ino_next);
-+		BUFFER_TRACE(sbi->s_sbh, "get_write_access");
-+		err = ext3cow_journal_get_write_access(handle, sbi->s_sbh);
-+		if (err)
-+			goto out_brelse;
-+		sbi->s_es->s_last_orphan = cpu_to_le32(ino_next);
-+		err = ext3cow_journal_dirty_metadata(handle, sbi->s_sbh);
-+	} else {
-+		struct ext3cow_iloc iloc2;
-+		struct inode *i_prev =
-+			&list_entry(prev, struct ext3cow_inode_info, i_orphan)->vfs_inode;
-+
-+		jbd_debug(4, "orphan inode %lu will point to %lu\n",
-+			  i_prev->i_ino, ino_next);
-+		err = ext3cow_reserve_inode_write(handle, i_prev, &iloc2);
-+		if (err)
-+			goto out_brelse;
-+		NEXT_ORPHAN(i_prev) = ino_next;
-+		err = ext3cow_mark_iloc_dirty(handle, i_prev, &iloc2);
-+	}
-+	if (err)
-+		goto out_brelse;
-+	NEXT_ORPHAN(inode) = 0;
-+	err = ext3cow_mark_iloc_dirty(handle, inode, &iloc);
-+
-+out_err:
-+	ext3cow_std_error(inode->i_sb, err);
-+out:
-+	unlock_super(inode->i_sb);
-+	return err;
-+
-+out_brelse:
-+	brelse(iloc.bh);
-+	goto out_err;
-+}
-+
-+static int ext3cow_rmdir (struct inode * dir, struct dentry *dentry)
-+{
-+	int retval;
-+	struct inode * inode;
-+	struct buffer_head * bh;
-+	struct ext3cow_dir_entry_2 * de;
-+	handle_t *handle;
-+
-+	/* Initialize quotas before so that eventual writes go in
-+	 * separate transaction */
-+	DQUOT_INIT(dentry->d_inode);
-+	handle = ext3cow_journal_start(dir, EXT3COW_DELETE_TRANS_BLOCKS(dir->i_sb));
-+	if (IS_ERR(handle))
-+		return PTR_ERR(handle);
-+
-+	retval = -ENOENT;
-+	bh = ext3cow_find_entry (dentry, &de);
-+	if (!bh)
-+		goto end_rmdir;
-+
-+	if (IS_DIRSYNC(dir))
-+		handle->h_sync = 1;
-+
-+	inode = dentry->d_inode;
-+
-+  /* Can't rmdir in the past -znjp */
-+  retval = -EROFS;
-+  if(is_unchangeable(inode, dentry))
-+    goto end_rmdir;
-+
-+	retval = -EIO;
-+	if (le32_to_cpu(de->inode) != inode->i_ino)
-+		goto end_rmdir;
-+
-+	retval = -ENOTEMPTY;
-+	if (!empty_dir (inode))
-+		goto end_rmdir;
-+
-+	retval = ext3cow_delete_entry(handle, dir, de, bh, dentry);
-+	if (retval)
-+		goto end_rmdir;
-+	if (inode->i_nlink != 2)
-+		ext3cow_warning (inode->i_sb, "ext3cow_rmdir",
-+			      "empty directory has nlink!=2 (%d)",
-+			      inode->i_nlink);
-+	inode->i_version++;
-+
-+  /* We only delete things that were created in the same epoch -znjp */
-+  if(de->birth_epoch == de->death_epoch){
-+    clear_nlink(inode);
-+    /* There's no need to set i_disksize: the fact that i_nlink is
-+     * zero will ensure that the right thing happens during any
-+     * recovery. */
-+    inode->i_size = 0;
-+    ext3cow_orphan_add(handle, inode);
-+    drop_nlink(dir);
-+  }
-+  EXT3COW_I(inode)->i_flags |= EXT3COW_UNCHANGEABLE_FL;
-+  inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC;
-+  ext3cow_mark_inode_dirty(handle, inode);
-+  ext3cow_update_dx_flag(dir);
-+	ext3cow_mark_inode_dirty(handle, dir);
-+
-+end_rmdir:
-+	ext3cow_journal_stop(handle);
-+	brelse (bh);
-+	return retval;
-+}
-+
-+static int ext3cow_unlink(struct inode * dir, struct dentry *dentry)
-+{
-+	int retval;
-+	struct inode * inode;
-+	struct buffer_head * bh;
-+	struct ext3cow_dir_entry_2 * de;
-+	handle_t *handle;
-+
-+	/* Initialize quotas before so that eventual writes go
-+	 * in separate transaction */
-+	DQUOT_INIT(dentry->d_inode);
-+	handle = ext3cow_journal_start(dir, EXT3COW_DELETE_TRANS_BLOCKS(dir->i_sb));
-+	if (IS_ERR(handle))
-+		return PTR_ERR(handle);
-+
-+	if (IS_DIRSYNC(dir))
-+		handle->h_sync = 1;
-+
-+	retval = -ENOENT;
-+	bh = ext3cow_find_entry (dentry, &de);
-+	if (!bh)
-+		goto end_unlink;
-+
-+	inode = dentry->d_inode;
-+
-+  /* Can't unlink in the past -znjp */
-+  retval = -EROFS;
-+  if(is_unchangeable(inode, dentry))
-+    goto end_unlink;  
-+  
-+	retval = -EIO;
-+	if (le32_to_cpu(de->inode) != inode->i_ino)
-+		goto end_unlink;
-+
-+	if (!inode->i_nlink) {
-+		ext3cow_warning (inode->i_sb, "ext3cow_unlink",
-+			      "Deleting nonexistent file (%lu), %d",
-+			      inode->i_ino, inode->i_nlink);
-+		inode->i_nlink = 1;
-+	}
-+	retval = ext3cow_delete_entry(handle, dir, de, bh, dentry);
-+	if (retval)
-+		goto end_unlink;
-+	dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC;
-+	ext3cow_update_dx_flag(dir);
-+	ext3cow_mark_inode_dirty(handle, dir);
-+
-+  /* If the file should be deleted here, don't actually delete it
-+   * but mark it unchangeable, i.e. it's now in the past. -znjp */
-+
-+  /* If file was created in this epoch, then we actually unlink it,
-+   * if not, then it belongs to the past, so mark it unchangeable -znjp */
-+  if(de->birth_epoch == de->death_epoch){
-+  	drop_nlink(inode);
-+    if (!inode->i_nlink){
-+      ext3cow_orphan_add(handle, inode);
-+    }
-+  }else{
-+    if(!(inode->i_nlink - 1))
-+      EXT3COW_I(inode)->i_flags |= EXT3COW_UNCHANGEABLE_FL; 
-+  }
-+	inode->i_ctime = dir->i_ctime;
-+	ext3cow_mark_inode_dirty(handle, inode);
-+	retval = 0;
-+
-+end_unlink:
-+	ext3cow_journal_stop(handle);
-+	brelse (bh);
-+	return retval;
-+}
-+
-+static int ext3cow_symlink (struct inode * dir,
-+		struct dentry *dentry, const char * symname)
-+{
-+	handle_t *handle;
-+	struct inode * inode;
-+	int l, err, retries = 0;
-+
-+	l = strlen(symname)+1;
-+	if (l > dir->i_sb->s_blocksize)
-+		return -ENAMETOOLONG;
-+
-+retry:
-+	handle = ext3cow_journal_start(dir, EXT3COW_DATA_TRANS_BLOCKS(dir->i_sb) +
-+					EXT3COW_INDEX_EXTRA_TRANS_BLOCKS + 5 +
-+					2*EXT3COW_QUOTA_INIT_BLOCKS(dir->i_sb));
-+	if (IS_ERR(handle))
-+		return PTR_ERR(handle);
-+
-+	if (IS_DIRSYNC(dir))
-+		handle->h_sync = 1;
-+
-+	inode = ext3cow_new_inode (handle, dir, S_IFLNK|S_IRWXUGO);
-+	err = PTR_ERR(inode);
-+	if (IS_ERR(inode))
-+		goto out_stop;
-+
-+	if (l > sizeof (EXT3COW_I(inode)->i_data)) {
-+		inode->i_op = &ext3cow_symlink_inode_operations;
-+		ext3cow_set_aops(inode);
-+		/*
-+		 * page_symlink() calls into ext3cow_prepare/commit_write.
-+		 * We have a transaction open.  All is sweetness.  It also sets
-+		 * i_size in generic_commit_write().
-+		 */
-+		err = __page_symlink(inode, symname, l,
-+				mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS);
-+		if (err) {
-+			ext3cow_dec_count(handle, inode);
-+			ext3cow_mark_inode_dirty(handle, inode);
-+			iput (inode);
-+			goto out_stop;
-+		}
-+	} else {
-+		inode->i_op = &ext3cow_fast_symlink_inode_operations;
-+		memcpy((char*)&EXT3COW_I(inode)->i_data,symname,l);
-+		inode->i_size = l-1;
-+	}
-+	EXT3COW_I(inode)->i_disksize = inode->i_size;
-+	err = ext3cow_add_nondir(handle, dentry, inode);
-+out_stop:
-+	ext3cow_journal_stop(handle);
-+	if (err == -ENOSPC && ext3cow_should_retry_alloc(dir->i_sb, &retries))
-+		goto retry;
-+	return err;
-+}
-+
-+static int ext3cow_link (struct dentry * old_dentry,
-+		struct inode * dir, struct dentry *dentry)
-+{
-+	handle_t *handle;
-+	struct inode *inode = old_dentry->d_inode;
-+	int err, retries = 0;
-+
-+	if (inode->i_nlink >= EXT3COW_LINK_MAX)
-+		return -EMLINK;
-+
-+retry:
-+	handle = ext3cow_journal_start(dir, EXT3COW_DATA_TRANS_BLOCKS(dir->i_sb) +
-+					EXT3COW_INDEX_EXTRA_TRANS_BLOCKS);
-+	if (IS_ERR(handle))
-+		return PTR_ERR(handle);
-+
-+	if (IS_DIRSYNC(dir))
-+		handle->h_sync = 1;
-+
-+	inode->i_ctime = CURRENT_TIME_SEC;
-+	ext3cow_inc_count(handle, inode);
-+	atomic_inc(&inode->i_count);
-+
-+	err = ext3cow_add_nondir(handle, dentry, inode);
-+	ext3cow_journal_stop(handle);
-+	if (err == -ENOSPC && ext3cow_should_retry_alloc(dir->i_sb, &retries))
-+		goto retry;
-+	return err;
-+}
-+
-+#define PARENT_INO(buffer) \
-+	((struct ext3cow_dir_entry_2 *) ((char *) buffer + \
-+	le16_to_cpu(((struct ext3cow_dir_entry_2 *) buffer)->rec_len)))->inode
-+
-+/*
-+ * Anybody can rename anything with this: the permission checks are left to the
-+ * higher-level routines.
-+ */
-+static int ext3cow_rename (struct inode * old_dir, struct dentry *old_dentry,
-+			   struct inode * new_dir,struct dentry *new_dentry)
-+{
-+	handle_t *handle;
-+	struct inode * old_inode, * new_inode;
-+	struct buffer_head * old_bh, * new_bh, * dir_bh;
-+	struct ext3cow_dir_entry_2 * old_de, * new_de;
-+	int retval;
-+
-+	old_bh = new_bh = dir_bh = NULL;
-+
-+	/* Initialize quotas before so that eventual writes go
-+	 * in separate transaction */
-+	if (new_dentry->d_inode)
-+		DQUOT_INIT(new_dentry->d_inode);
-+	handle = ext3cow_journal_start(old_dir, 2 *
-+                                 EXT3COW_DATA_TRANS_BLOCKS(old_dir->i_sb) +
-+                                 EXT3COW_INDEX_EXTRA_TRANS_BLOCKS + 2);
-+	if (IS_ERR(handle))
-+		return PTR_ERR(handle);
-+
-+	if (IS_DIRSYNC(old_dir) || IS_DIRSYNC(new_dir))
-+		handle->h_sync = 1;
-+
-+	old_bh = ext3cow_find_entry (old_dentry, &old_de);
-+	/*
-+	 *  Check for inode number is _not_ due to possible IO errors.
-+	 *  We might rmdir the source, keep it as pwd of some process
-+	 *  and merrily kill the link to whatever was created under the
-+	 *  same name. Goodbye sticky bit ;-<
-+	 */
-+	old_inode = old_dentry->d_inode;
-+	retval = -ENOENT;
-+	if (!old_bh || le32_to_cpu(old_de->inode) != old_inode->i_ino)
-+		goto end_rename;
-+
-+	new_inode = new_dentry->d_inode;
-+	new_bh = ext3cow_find_entry (new_dentry, &new_de);
-+	if (new_bh) {
-+		if (!new_inode) {
-+			brelse (new_bh);
-+			new_bh = NULL;
-+		}
-+	}
-+
-+  /* can't move something into the past -znjp */
-+  retval = -EROFS;
-+  if(is_unchangeable(new_inode, new_dentry)) 
-+    goto end_rename;
-+  /* can't some move from the past -znjp */
-+  if(is_unchangeable(old_inode, old_dentry))
-+    goto end_rename;
-+
-+	if (S_ISDIR(old_inode->i_mode)) {
-+		if (new_inode) {
-+			retval = -ENOTEMPTY;
-+			if (!empty_dir (new_inode))
-+				goto end_rename;
-+		}
-+		retval = -EIO;
-+		dir_bh = ext3cow_bread (handle, old_inode, 0, 0, &retval);
-+		if (!dir_bh)
-+			goto end_rename;
-+		if (le32_to_cpu(PARENT_INO(dir_bh->b_data)) != old_dir->i_ino)
-+			goto end_rename;
-+		retval = -EMLINK;
-+		if (!new_inode && new_dir!=old_dir &&
-+				new_dir->i_nlink >= EXT3COW_LINK_MAX)
-+			goto end_rename;
-+	}
-+	if (!new_bh) {
-+		retval = ext3cow_add_entry (handle, new_dentry, old_inode);
-+		if (retval)
-+			goto end_rename;
-+	} else {
-+		BUFFER_TRACE(new_bh, "get write access");
-+		ext3cow_journal_get_write_access(handle, new_bh);
-+		new_de->inode = cpu_to_le32(old_inode->i_ino);
-+		if (EXT3COW_HAS_INCOMPAT_FEATURE(new_dir->i_sb,
-+					      EXT3COW_FEATURE_INCOMPAT_FILETYPE))
-+			new_de->file_type = old_de->file_type;
-+		new_dir->i_version++;
-+		BUFFER_TRACE(new_bh, "call ext3cow_journal_dirty_metadata");
-+		ext3cow_journal_dirty_metadata(handle, new_bh);
-+		brelse(new_bh);
-+		new_bh = NULL;
-+	}
-+
-+	/*
-+	 * Like most other Unix systems, set the ctime for inodes on a
-+	 * rename.
-+	 */
-+	old_inode->i_ctime = CURRENT_TIME_SEC;
-+	ext3cow_mark_inode_dirty(handle, old_inode);
-+
-+	/*
-+	 * ok, that's it
-+	 */
-+	if (le32_to_cpu(old_de->inode) != old_inode->i_ino ||
-+	    old_de->name_len != old_dentry->d_name.len ||
-+	    strncmp(old_de->name, old_dentry->d_name.name, old_de->name_len) ||
-+	    (retval = ext3cow_delete_entry(handle, old_dir,
-+                                     old_de, old_bh, new_dentry)) == -ENOENT) {
-+		/* old_de could have moved from under us during htree split, so
-+		 * make sure that we are deleting the right entry.  We might
-+		 * also be pointing to a stale entry in the unused part of
-+		 * old_bh so just checking inum and the name isn't enough. */
-+		struct buffer_head *old_bh2;
-+		struct ext3cow_dir_entry_2 *old_de2;
-+
-+		old_bh2 = ext3cow_find_entry(old_dentry, &old_de2);
-+		if (old_bh2) {
-+			retval = ext3cow_delete_entry(handle, old_dir,
-+                                    old_de2, old_bh2, new_dentry);
-+			brelse(old_bh2);
-+		}
-+	}
-+	if (retval) {
-+		ext3cow_warning(old_dir->i_sb, "ext3cow_rename",
-+				"Deleting old file (%lu), %d, error=%d",
-+				old_dir->i_ino, old_dir->i_nlink, retval);
-+	}
-+
-+	if (new_inode) {
-+		new_inode->i_ctime = CURRENT_TIME_SEC;
-+	}
-+  if(!is_unchangeable(old_inode, old_dentry))
-+    old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME_SEC;
-+	ext3cow_update_dx_flag(old_dir);
-+	if (dir_bh) {
-+		BUFFER_TRACE(dir_bh, "get_write_access");
-+		ext3cow_journal_get_write_access(handle, dir_bh);
-+		PARENT_INO(dir_bh->b_data) = cpu_to_le32(new_dir->i_ino);
-+		BUFFER_TRACE(dir_bh, "call ext3cow_journal_dirty_metadata");
-+		ext3cow_journal_dirty_metadata(handle, dir_bh);
-+		if (!new_inode) {
-+			inc_nlink(new_dir);
-+			ext3cow_update_dx_flag(new_dir);
-+			ext3cow_mark_inode_dirty(handle, new_dir);
-+		}
-+	}
-+	ext3cow_mark_inode_dirty(handle, old_dir);
-+	if (new_inode) {
-+		ext3cow_mark_inode_dirty(handle, new_inode);
-+		if (!new_inode->i_nlink)
-+			ext3cow_orphan_add(handle, new_inode);
-+	}
-+	retval = 0;
-+
-+end_rename:
-+	brelse (dir_bh);
-+	brelse (old_bh);
-+	brelse (new_bh);
-+	ext3cow_journal_stop(handle);
-+	return retval;
-+}
-+
-+/* ext3cow_fake_inode: This function creates a VFS-only inode
-+ * used for properly scoping views into the past file system - znjp
-+ */
-+struct inode *ext3cow_fake_inode(struct inode *inode,
-+                                 unsigned int epoch_number)
-+{
-+  struct inode * fake_inode = NULL;
-+  struct ext3cow_inode_info * ini = NULL;
-+  struct ext3cow_inode_info * fake_ini = NULL;
-+  static unsigned int last_ino = UINT_MAX;
-+  int err = 0;
-+  int block = -1;
-+
-+  if(NULL == inode){
-+    printk(KERN_ERR "Trying to duplicate a NULL inode.\n");
-+    return NULL;
-+  }
-+
-+  if(EXT3COW_IS_FAKEINODE(inode)){
-+    printk(KERN_ERR "Trying to fake a fake inode.\n");
-+    return inode;
-+  }
-+
-+  printk(KERN_INFO "** faking inode %lu\n", inode->i_ino);
-+
-+  ini = EXT3COW_I(inode);
-+  
-+  /* Create a new VFS-only inode */
-+  fake_inode = new_inode(inode->i_sb);   
-+  err = PTR_ERR(fake_inode);
-+  if(!IS_ERR(fake_inode)){
-+
-+    fake_ini = EXT3COW_I(fake_inode);
-+
-+    printk(KERN_INFO "** got inode %lu setting with %u\n", fake_inode->i_ino,
-+           last_ino);
-+
-+    /* When inode is a directory, we can fake the inode number */
-+    //if(S_ISDIR(inode->i_mode))
-+    fake_inode->i_ino  = --last_ino;
-+
-+    fake_inode->i_mode = inode->i_mode;
-+    fake_inode->i_uid  = inode->i_uid;
-+    fake_inode->i_gid  = inode->i_gid;
-+
-+    atomic_set(&fake_inode->i_count, 1);
-+
-+    fake_inode->i_nlink         = inode->i_nlink;
-+    fake_inode->i_size          = inode->i_size;
-+    fake_inode->i_atime.tv_sec  = inode->i_atime.tv_sec;
-+    fake_inode->i_ctime.tv_sec  = inode->i_ctime.tv_sec;
-+    fake_inode->i_mtime.tv_sec  = inode->i_mtime.tv_sec;
-+    fake_inode->i_atime.tv_nsec = inode->i_atime.tv_nsec;
-+    fake_inode->i_ctime.tv_nsec = inode->i_ctime.tv_nsec;
-+    fake_inode->i_mtime.tv_nsec = inode->i_mtime.tv_nsec;
-+
-+    fake_ini->i_state = ini->i_state;
-+    fake_ini->i_dir_start_lookup = ini->i_dir_start_lookup;
-+    fake_ini->i_dtime = ini->i_dtime;
-+
-+    fake_inode->i_blocks  = inode->i_blocks;
-+    fake_ini->i_flags     = ini->i_flags;
-+#ifdef EXT3COW_FRAGMENTS
-+    /* Taken out for versioning -znjp */
-+    //fake_ini->i_faddr     = ini->i_faddr;
-+    //fake_ini->i_frag_no   = ini->i_frag_no;
-+    //fake_ini->i_frag_size = ini->i_frag_size;
-+#endif
-+    fake_ini->i_file_acl = ini->i_file_acl;
-+    if (!S_ISREG(fake_inode->i_mode)) {
-+      fake_ini->i_dir_acl = ini->i_dir_acl;
-+    } 
-+    fake_ini->i_disksize = inode->i_size;
-+    fake_inode->i_generation = inode->i_generation;
-+    //TODO: This could be wrong.
-+    //fake_ini->i_block_group = ini->i_block_group; //iloc.block_group;
-+
-+    for (block = 0; block < EXT3COW_N_BLOCKS; block++)
-+      fake_ini->i_data[block] = ini->i_data[block];
-+
-+    fake_ini->i_extra_isize = ini->i_extra_isize;
-+
-+    /* set copy-on-write bitmap to 0 */
-+    fake_ini->i_cow_bitmap = 0x0000;
-+    
-+    /* Mark fake inode unchangeable, etc. */
-+    fake_ini->i_flags |= EXT3COW_UNCHANGEABLE_FL;
-+    fake_ini->i_flags |= EXT3COW_UNVERSIONABLE_FL;
-+    fake_ini->i_flags |= EXT3COW_FAKEINODE_FL;
-+    fake_ini->i_flags |= EXT3COW_IMMUTABLE_FL;
-+
-+    /* Make sure we get the right operations */
-+    if (S_ISREG(fake_inode->i_mode)) {
-+      fake_inode->i_op = &ext3cow_file_inode_operations;
-+      fake_inode->i_fop = &ext3cow_file_operations;
-+      ext3cow_set_aops(fake_inode);
-+    } else if (S_ISDIR(fake_inode->i_mode)) {
-+      fake_inode->i_op = &ext3cow_dir_inode_operations;
-+      fake_inode->i_fop = &ext3cow_dir_operations;
-+    } else if (S_ISLNK(fake_inode->i_mode)) {
-+      //if (ext3cow_inode_is_fast_symlink(cow_inode))
-+      if((S_ISLNK(fake_inode->i_mode) && fake_inode->i_blocks - 
-+          (EXT3COW_I(fake_inode)->i_file_acl ? 
-+           (fake_inode->i_sb->s_blocksize >> 9) : 0)))
-+        fake_inode->i_op = &ext3cow_fast_symlink_inode_operations;
-+      else {
-+        fake_inode->i_op = &ext3cow_symlink_inode_operations;
-+        ext3cow_set_aops(fake_inode);
-+      }
-+    } else {
-+      fake_inode->i_op = &ext3cow_special_inode_operations;
-+    }
-+
-+    fake_ini->i_epoch_number = epoch_number;
-+    fake_ini->i_next_inode = 0;
-+    
-+    iput(inode); /* dec i_count */
-+
-+    return fake_inode;
-+  }else
-+    ext3cow_warning(inode->i_sb, "ext3cow_fake_inode",
-+                    "Could not create fake inode.");
-+   
-+ 	return NULL;
-+}
-+
-+/* 
-+ * ext3cow_dup_inode: This function creates a new inode, 
-+ * copies all the metadata from the passed in inode,  
-+ * and adds it to the version chain, creating a new version.  
-+ * The head of the chain never changes; it is always the most current version.
-+ * Similar in nature to ext3cow_creat and ext3cow_read_inode. -znjp
-+ */
-+int ext3cow_dup_inode(struct inode *dir, struct inode *inode){
-+
-+  struct inode *cow_inode = NULL;
-+  struct inode *parent = NULL;
-+  struct ext3cow_inode_info *ini = NULL;
-+  struct ext3cow_inode_info *cow_ini = NULL;
-+  handle_t *handle = NULL;
-+  int err = 0;
-+  int block = -1;
-+  unsigned int epoch_number_temp = 0;
-+  int retries = 0;
-+
-+  printk(KERN_INFO "** duping inode %lu\n", inode->i_ino);
-+
-+  if(EXT3COW_IS_UNVERSIONABLE(inode))
-+    return 0;
-+
-+  if(NULL == inode){
-+    printk(KERN_ERR "Trying to duplicate a NULL inode.\n");
-+    return -1;
-+  }
-+
-+	if (inode->i_nlink == 0) {
-+		if (inode->i_mode == 0 ||
-+		    !(EXT3COW_SB(inode->i_sb)->s_mount_state & EXT3COW_ORPHAN_FS)) {
-+			/* this inode is deleted */
-+      return -1;
-+		}
-+		/* The only unlinked inodes we let through here have
-+		 * valid i_mode and are being read by the orphan
-+		 * recovery code: that's fine, we're about to complete
-+		 * the process of deleting those. */
-+	}
-+
-+  ini = EXT3COW_I(inode);
-+
-+  /* This is for truncate, which can't pass in a parent */
-+  if(NULL == dir)
-+    parent = inode;
-+  else
-+    parent = dir;
-+
-+ retry:
-+	handle = ext3cow_journal_start(parent, EXT3COW_DATA_TRANS_BLOCKS(dir->i_sb) +
-+					EXT3COW_INDEX_EXTRA_TRANS_BLOCKS + 3 +
-+					2*EXT3COW_QUOTA_INIT_BLOCKS(dir->i_sb));
-+	if (IS_ERR(handle))
-+		return PTR_ERR(handle);
-+
-+	if (IS_DIRSYNC(parent))
-+		handle->h_sync = 1;
-+
-+	cow_inode = ext3cow_new_inode (handle, parent, inode->i_mode);
-+	err = PTR_ERR(cow_inode);
-+	if (!IS_ERR(cow_inode)) {
-+
-+    printk(KERN_INFO "  ** Allocated new inode %lu\n", cow_inode->i_ino);
-+
-+    cow_ini = EXT3COW_I(cow_inode);
-+    
-+    cow_inode->i_mode = inode->i_mode;
-+    cow_inode->i_uid  = inode->i_uid;
-+    cow_inode->i_gid  = inode->i_gid;
-+
-+    cow_inode->i_nlink         = inode->i_nlink;
-+    cow_inode->i_size          = inode->i_size;
-+    cow_inode->i_atime.tv_sec  = inode->i_atime.tv_sec;
-+    cow_inode->i_ctime.tv_sec  = inode->i_ctime.tv_sec;
-+    cow_inode->i_mtime.tv_sec  = inode->i_mtime.tv_sec;
-+    cow_inode->i_atime.tv_nsec = inode->i_atime.tv_nsec;
-+    cow_inode->i_ctime.tv_nsec = inode->i_ctime.tv_nsec;
-+    cow_inode->i_mtime.tv_nsec = inode->i_mtime.tv_nsec;
-+
-+    cow_ini->i_state = ini->i_state;
-+    cow_ini->i_dir_start_lookup = ini->i_dir_start_lookup;
-+    cow_ini->i_dtime = ini->i_dtime;
-+
-+    cow_inode->i_blocks  = inode->i_blocks;
-+    cow_ini->i_flags     = ini->i_flags;
-+#ifdef EXT3COW_FRAGMENTS
-+    /* Taken out for versioning -znjp */
-+    //cow_ini->i_faddr     = ini->i_faddr;
-+    //cow_ini->i_frag_no   = ini->i_frag_no;
-+    //cow_ini->i_frag_size = ini->i_frag_size;
-+#endif
-+    cow_ini->i_file_acl = ini->i_file_acl;
-+    if (!S_ISREG(cow_inode->i_mode)) {
-+      cow_ini->i_dir_acl = ini->i_dir_acl;
-+    } 
-+    cow_ini->i_disksize = inode->i_size;
-+    cow_inode->i_generation = inode->i_generation;
-+    //TODO: This could be wrong.
-+    cow_ini->i_block_group = ini->i_block_group; //iloc.block_group;
-+
-+    for (block = 0; block < EXT3COW_N_BLOCKS; block++)
-+      cow_ini->i_data[block] = ini->i_data[block];
-+
-+    //TODO: This could be wrong
-+    //cow_ini->i_orphan = NULL; //INIT_LIST_HEAD(&ei->i_orphan);
-+   
-+    cow_ini->i_extra_isize = ini->i_extra_isize;
-+
-+    /* Make sure we get the right operations */
-+    if (S_ISREG(cow_inode->i_mode)) {
-+      cow_inode->i_op = &ext3cow_file_inode_operations;
-+      cow_inode->i_fop = &ext3cow_file_operations;
-+      ext3cow_set_aops(cow_inode);
-+    } else if (S_ISDIR(cow_inode->i_mode)) {
-+      cow_inode->i_op = &ext3cow_dir_inode_operations;
-+      cow_inode->i_fop = &ext3cow_dir_operations;
-+    } else if (S_ISLNK(cow_inode->i_mode)) {
-+      //if (ext3cow_inode_is_fast_symlink(cow_inode))
-+      if((S_ISLNK(cow_inode->i_mode) && cow_inode->i_blocks - 
-+          (EXT3COW_I(cow_inode)->i_file_acl ? 
-+           (cow_inode->i_sb->s_blocksize >> 9) : 0)))
-+        cow_inode->i_op = &ext3cow_fast_symlink_inode_operations;
-+      else {
-+        cow_inode->i_op = &ext3cow_symlink_inode_operations;
-+        ext3cow_set_aops(cow_inode);
-+      }
-+    } else {
-+      cow_inode->i_op = &ext3cow_special_inode_operations;
-+      /*
-+      if (raw_inode->i_block[0])
-+        init_special_inode(inode, inode->i_mode,
-+                           old_decode_dev(le32_to_cpu(raw_inode->i_block[0])));
-+      else
-+        init_special_inode(inode, inode->i_mode,
-+                           new_decode_dev(le32_to_cpu(raw_inode->i_block[1])));
-+      */
-+    }
-+    
-+    /* Dup in the direct cow bitmap */
-+    cow_ini->i_cow_bitmap = ini->i_cow_bitmap;
-+    ini->i_cow_bitmap     = 0x0000;
-+    /* Mark new inode unchangeable */
-+    cow_ini->i_flags |= EXT3COW_UNCHANGEABLE_FL;
-+    /* Switch epoch numbers */
-+    epoch_number_temp = ini->i_epoch_number;
-+    ini->i_epoch_number = cow_ini->i_epoch_number;
-+    cow_ini->i_epoch_number = epoch_number_temp;
-+    /* Chain Inodes together */
-+    cow_ini->i_next_inode = ini->i_next_inode;
-+    ini->i_next_inode = cow_inode->i_ino;
-+
-+    ext3cow_mark_inode_dirty(handle, cow_inode);
-+    ext3cow_mark_inode_dirty(handle, inode);
-+    
-+    iput(cow_inode); /* dec i_count */
-+
-+    err = 0;
-+	}
-+	ext3cow_journal_stop(handle);
-+	if (err == -ENOSPC && ext3cow_should_retry_alloc(dir->i_sb, &retries))
-+		goto retry;
-+	return err;
-+
-+}
-+
-+/* ext3cow_reclaim_dup_inode: rolls back a recently dup'd inode
-+ * on error, including epoch number and bitmaps.  Should not
-+ * be used for removing versions.  */
-+int ext3cow_reclaim_dup_inode(struct inode *dir, struct inode *inode)
-+{
-+  handle_t *handle = NULL;
-+  int err = 0;
-+  struct inode *old_inode = NULL;
-+  struct inode *parent = dir;
-+
-+  if(!parent)
-+    parent = inode;
-+
-+  if(is_bad_inode(inode))
-+    return -1;
-+  
-+  handle = ext3cow_journal_start(parent, 
-+                                 EXT3COW_DELETE_TRANS_BLOCKS(parent->i_sb));
-+  if(IS_ERR(handle))
-+    return PTR_ERR(handle);
-+
-+  if(IS_DIRSYNC(parent))
-+    handle->h_sync = 1;
-+
-+  old_inode = iget(parent->i_sb, EXT3COW_I_NEXT_INODE(inode));
-+  err = PTR_ERR(old_inode);
-+  if (!IS_ERR(old_inode)){
-+
-+    EXT3COW_I(inode)->i_epoch_number = EXT3COW_I_EPOCHNUMBER(old_inode);
-+    EXT3COW_I(inode)->i_cow_bitmap   = EXT3COW_I(old_inode)->i_cow_bitmap;
-+    EXT3COW_I(inode)->i_next_inode   = EXT3COW_I(old_inode)->i_next_inode;
-+    old_inode->i_nlink = 0;
-+
-+    iput(old_inode);
-+    ext3cow_mark_inode_dirty(handle, inode);
-+  }else
-+    ext3cow_error(inode->i_sb, "ext3cow_reclaim_dup_inode", 
-+                  "Couldn't remove dup'd inode.");
-+  
-+  ext3cow_journal_stop(handle);
-+  
-+  return 0;
-+}
-+
-+/*
-+ * directories can handle most operations...
-+ */
-+struct inode_operations ext3cow_dir_inode_operations = {
-+	.create		= ext3cow_create,
-+	.lookup		= ext3cow_lookup,
-+	.link		= ext3cow_link,
-+	.unlink		= ext3cow_unlink,
-+	.symlink	= ext3cow_symlink,
-+	.mkdir		= ext3cow_mkdir,
-+	.rmdir		= ext3cow_rmdir,
-+	.mknod		= ext3cow_mknod,
-+	.rename		= ext3cow_rename,
-+	.setattr	= ext3cow_setattr,
-+#ifdef CONFIG_EXT3COW_FS_XATTR
-+	.setxattr	= generic_setxattr,
-+	.getxattr	= generic_getxattr,
-+	.listxattr	= ext3cow_listxattr,
-+	.removexattr	= generic_removexattr,
-+#endif
-+	.permission	= ext3cow_permission,
-+};
-+
-+struct inode_operations ext3cow_special_inode_operations = {
-+	.setattr	= ext3cow_setattr,
-+#ifdef CONFIG_EXT3COW_FS_XATTR
-+	.setxattr	= generic_setxattr,
-+	.getxattr	= generic_getxattr,
-+	.listxattr	= ext3cow_listxattr,
-+	.removexattr	= generic_removexattr,
-+#endif
-+	.permission	= ext3cow_permission,
-+};
-diff -ruN linux-2.6.20.3/fs/ext3cow/namei.h linux-2.6.20.3-ext3cow/fs/ext3cow/namei.h
---- linux-2.6.20.3/fs/ext3cow/namei.h	1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.20.3-ext3cow/fs/ext3cow/namei.h	2008-03-09 11:14:48.000000000 -0400
-@@ -0,0 +1,8 @@
-+/*  linux/fs/ext3cow/namei.h
-+ *
-+ * Copyright (C) 2005 Simtec Electronics
-+ *	Ben Dooks <ben@simtec.co.uk>
-+ *
-+*/
-+
-+extern struct dentry *ext3cow_get_parent(struct dentry *child);
-diff -ruN linux-2.6.20.3/fs/ext3cow/resize.c linux-2.6.20.3-ext3cow/fs/ext3cow/resize.c
---- linux-2.6.20.3/fs/ext3cow/resize.c	1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.20.3-ext3cow/fs/ext3cow/resize.c	2008-03-09 11:14:48.000000000 -0400
-@@ -0,0 +1,1042 @@
-+/*
-+ *  linux/fs/ext3cow/resize.c
-+ *
-+ * Support for resizing an ext3cow filesystem while it is mounted.
-+ *
-+ * Copyright (C) 2001, 2002 Andreas Dilger <adilger@clusterfs.com>
-+ *
-+ * This could probably be made into a module, because it is not often in use.
-+ */
-+
-+
-+#define EXT3COWFS_DEBUG
-+
-+#include <linux/sched.h>
-+#include <linux/smp_lock.h>
-+#include <linux/ext3cow_jbd.h>
-+
-+#include <linux/errno.h>
-+#include <linux/slab.h>
-+
-+
-+#define outside(b, first, last)	((b) < (first) || (b) >= (last))
-+#define inside(b, first, last)	((b) >= (first) && (b) < (last))
-+
-+static int verify_group_input(struct super_block *sb,
-+			      struct ext3cow_new_group_data *input)
-+{
-+	struct ext3cow_sb_info *sbi = EXT3COW_SB(sb);
-+	struct ext3cow_super_block *es = sbi->s_es;
-+	ext3cow_fsblk_t start = le32_to_cpu(es->s_blocks_count);
-+	ext3cow_fsblk_t end = start + input->blocks_count;
-+	unsigned group = input->group;
-+	ext3cow_fsblk_t itend = input->inode_table + sbi->s_itb_per_group;
-+	unsigned overhead = ext3cow_bg_has_super(sb, group) ?
-+		(1 + ext3cow_bg_num_gdb(sb, group) +
-+		 le16_to_cpu(es->s_reserved_gdt_blocks)) : 0;
-+	ext3cow_fsblk_t metaend = start + overhead;
-+	struct buffer_head *bh = NULL;
-+	ext3cow_grpblk_t free_blocks_count;
-+	int err = -EINVAL;
-+
-+	input->free_blocks_count = free_blocks_count =
-+		input->blocks_count - 2 - overhead - sbi->s_itb_per_group;
-+
-+	if (test_opt(sb, DEBUG))
-+		printk(KERN_DEBUG "EXT3COW-fs: adding %s group %u: %u blocks "
-+		       "(%d free, %u reserved)\n",
-+		       ext3cow_bg_has_super(sb, input->group) ? "normal" :
-+		       "no-super", input->group, input->blocks_count,
-+		       free_blocks_count, input->reserved_blocks);
-+
-+	if (group != sbi->s_groups_count)
-+		ext3cow_warning(sb, __FUNCTION__,
-+			     "Cannot add at group %u (only %lu groups)",
-+			     input->group, sbi->s_groups_count);
-+	else if ((start - le32_to_cpu(es->s_first_data_block)) %
-+		 EXT3COW_BLOCKS_PER_GROUP(sb))
-+		ext3cow_warning(sb, __FUNCTION__, "Last group not full");
-+	else if (input->reserved_blocks > input->blocks_count / 5)
-+		ext3cow_warning(sb, __FUNCTION__, "Reserved blocks too high (%u)",
-+			     input->reserved_blocks);
-+	else if (free_blocks_count < 0)
-+		ext3cow_warning(sb, __FUNCTION__, "Bad blocks count %u",
-+			     input->blocks_count);
-+	else if (!(bh = sb_bread(sb, end - 1)))
-+		ext3cow_warning(sb, __FUNCTION__,
-+			     "Cannot read last block ("E3FSBLK")",
-+			     end - 1);
-+	else if (outside(input->block_bitmap, start, end))
-+		ext3cow_warning(sb, __FUNCTION__,
-+			     "Block bitmap not in group (block %u)",
-+			     input->block_bitmap);
-+	else if (outside(input->inode_bitmap, start, end))
-+		ext3cow_warning(sb, __FUNCTION__,
-+			     "Inode bitmap not in group (block %u)",
-+			     input->inode_bitmap);
-+	else if (outside(input->inode_table, start, end) ||
-+	         outside(itend - 1, start, end))
-+		ext3cow_warning(sb, __FUNCTION__,
-+			     "Inode table not in group (blocks %u-"E3FSBLK")",
-+			     input->inode_table, itend - 1);
-+	else if (input->inode_bitmap == input->block_bitmap)
-+		ext3cow_warning(sb, __FUNCTION__,
-+			     "Block bitmap same as inode bitmap (%u)",
-+			     input->block_bitmap);
-+	else if (inside(input->block_bitmap, input->inode_table, itend))
-+		ext3cow_warning(sb, __FUNCTION__,
-+			     "Block bitmap (%u) in inode table (%u-"E3FSBLK")",
-+			     input->block_bitmap, input->inode_table, itend-1);
-+	else if (inside(input->inode_bitmap, input->inode_table, itend))
-+		ext3cow_warning(sb, __FUNCTION__,
-+			     "Inode bitmap (%u) in inode table (%u-"E3FSBLK")",
-+			     input->inode_bitmap, input->inode_table, itend-1);
-+	else if (inside(input->block_bitmap, start, metaend))
-+		ext3cow_warning(sb, __FUNCTION__,
-+			     "Block bitmap (%u) in GDT table"
-+			     " ("E3FSBLK"-"E3FSBLK")",
-+			     input->block_bitmap, start, metaend - 1);
-+	else if (inside(input->inode_bitmap, start, metaend))
-+		ext3cow_warning(sb, __FUNCTION__,
-+			     "Inode bitmap (%u) in GDT table"
-+			     " ("E3FSBLK"-"E3FSBLK")",
-+			     input->inode_bitmap, start, metaend - 1);
-+	else if (inside(input->inode_table, start, metaend) ||
-+	         inside(itend - 1, start, metaend))
-+		ext3cow_warning(sb, __FUNCTION__,
-+			     "Inode table (%u-"E3FSBLK") overlaps"
-+			     "GDT table ("E3FSBLK"-"E3FSBLK")",
-+			     input->inode_table, itend - 1, start, metaend - 1);
-+	else
-+		err = 0;
-+	brelse(bh);
-+
-+	return err;
-+}
-+
-+static struct buffer_head *bclean(handle_t *handle, struct super_block *sb,
-+				  ext3cow_fsblk_t blk)
-+{
-+	struct buffer_head *bh;
-+	int err;
-+
-+	bh = sb_getblk(sb, blk);
-+	if (!bh)
-+		return ERR_PTR(-EIO);
-+	if ((err = ext3cow_journal_get_write_access(handle, bh))) {
-+		brelse(bh);
-+		bh = ERR_PTR(err);
-+	} else {
-+		lock_buffer(bh);
-+		memset(bh->b_data, 0, sb->s_blocksize);
-+		set_buffer_uptodate(bh);
-+		unlock_buffer(bh);
-+	}
-+
-+	return bh;
-+}
-+
-+/*
-+ * To avoid calling the atomic setbit hundreds or thousands of times, we only
-+ * need to use it within a single byte (to ensure we get endianness right).
-+ * We can use memset for the rest of the bitmap as there are no other users.
-+ */
-+static void mark_bitmap_end(int start_bit, int end_bit, char *bitmap)
-+{
-+	int i;
-+
-+	if (start_bit >= end_bit)
-+		return;
-+
-+	ext3cow_debug("mark end bits +%d through +%d used\n", start_bit, end_bit);
-+	for (i = start_bit; i < ((start_bit + 7) & ~7UL); i++)
-+		ext3cow_set_bit(i, bitmap);
-+	if (i < end_bit)
-+		memset(bitmap + (i >> 3), 0xff, (end_bit - i) >> 3);
-+}
-+
-+/*
-+ * Set up the block and inode bitmaps, and the inode table for the new group.
-+ * This doesn't need to be part of the main transaction, since we are only
-+ * changing blocks outside the actual filesystem.  We still do journaling to
-+ * ensure the recovery is correct in case of a failure just after resize.
-+ * If any part of this fails, we simply abort the resize.
-+ */
-+static int setup_new_group_blocks(struct super_block *sb,
-+				  struct ext3cow_new_group_data *input)
-+{
-+	struct ext3cow_sb_info *sbi = EXT3COW_SB(sb);
-+	ext3cow_fsblk_t start = ext3cow_group_first_block_no(sb, input->group);
-+	int reserved_gdb = ext3cow_bg_has_super(sb, input->group) ?
-+		le16_to_cpu(sbi->s_es->s_reserved_gdt_blocks) : 0;
-+	unsigned long gdblocks = ext3cow_bg_num_gdb(sb, input->group);
-+	struct buffer_head *bh;
-+	handle_t *handle;
-+	ext3cow_fsblk_t block;
-+	ext3cow_grpblk_t bit;
-+	int i;
-+	int err = 0, err2;
-+
-+	handle = ext3cow_journal_start_sb(sb, reserved_gdb + gdblocks +
-+				       2 + sbi->s_itb_per_group);
-+	if (IS_ERR(handle))
-+		return PTR_ERR(handle);
-+
-+	lock_super(sb);
-+	if (input->group != sbi->s_groups_count) {
-+		err = -EBUSY;
-+		goto exit_journal;
-+	}
-+
-+	if (IS_ERR(bh = bclean(handle, sb, input->block_bitmap))) {
-+		err = PTR_ERR(bh);
-+		goto exit_journal;
-+	}
-+
-+	if (ext3cow_bg_has_super(sb, input->group)) {
-+		ext3cow_debug("mark backup superblock %#04lx (+0)\n", start);
-+		ext3cow_set_bit(0, bh->b_data);
-+	}
-+
-+	/* Copy all of the GDT blocks into the backup in this group */
-+	for (i = 0, bit = 1, block = start + 1;
-+	     i < gdblocks; i++, block++, bit++) {
-+		struct buffer_head *gdb;
-+
-+		ext3cow_debug("update backup group %#04lx (+%d)\n", block, bit);
-+
-+		gdb = sb_getblk(sb, block);
-+		if (!gdb) {
-+			err = -EIO;
-+			goto exit_bh;
-+		}
-+		if ((err = ext3cow_journal_get_write_access(handle, gdb))) {
-+			brelse(gdb);
-+			goto exit_bh;
-+		}
-+		lock_buffer(bh);
-+		memcpy(gdb->b_data, sbi->s_group_desc[i]->b_data, bh->b_size);
-+		set_buffer_uptodate(gdb);
-+		unlock_buffer(bh);
-+		ext3cow_journal_dirty_metadata(handle, gdb);
-+		ext3cow_set_bit(bit, bh->b_data);
-+		brelse(gdb);
-+	}
-+
-+	/* Zero out all of the reserved backup group descriptor table blocks */
-+	for (i = 0, bit = gdblocks + 1, block = start + bit;
-+	     i < reserved_gdb; i++, block++, bit++) {
-+		struct buffer_head *gdb;
-+
-+		ext3cow_debug("clear reserved block %#04lx (+%d)\n", block, bit);
-+
-+		if (IS_ERR(gdb = bclean(handle, sb, block))) {
-+			err = PTR_ERR(bh);
-+			goto exit_bh;
-+		}
-+		ext3cow_journal_dirty_metadata(handle, gdb);
-+		ext3cow_set_bit(bit, bh->b_data);
-+		brelse(gdb);
-+	}
-+	ext3cow_debug("mark block bitmap %#04x (+%ld)\n", input->block_bitmap,
-+		   input->block_bitmap - start);
-+	ext3cow_set_bit(input->block_bitmap - start, bh->b_data);
-+	ext3cow_debug("mark inode bitmap %#04x (+%ld)\n", input->inode_bitmap,
-+		   input->inode_bitmap - start);
-+	ext3cow_set_bit(input->inode_bitmap - start, bh->b_data);
-+
-+	/* Zero out all of the inode table blocks */
-+	for (i = 0, block = input->inode_table, bit = block - start;
-+	     i < sbi->s_itb_per_group; i++, bit++, block++) {
-+		struct buffer_head *it;
-+
-+		ext3cow_debug("clear inode block %#04lx (+%d)\n", block, bit);
-+		if (IS_ERR(it = bclean(handle, sb, block))) {
-+			err = PTR_ERR(it);
-+			goto exit_bh;
-+		}
-+		ext3cow_journal_dirty_metadata(handle, it);
-+		brelse(it);
-+		ext3cow_set_bit(bit, bh->b_data);
-+	}
-+	mark_bitmap_end(input->blocks_count, EXT3COW_BLOCKS_PER_GROUP(sb),
-+			bh->b_data);
-+	ext3cow_journal_dirty_metadata(handle, bh);
-+	brelse(bh);
-+
-+	/* Mark unused entries in inode bitmap used */
-+	ext3cow_debug("clear inode bitmap %#04x (+%ld)\n",
-+		   input->inode_bitmap, input->inode_bitmap - start);
-+	if (IS_ERR(bh = bclean(handle, sb, input->inode_bitmap))) {
-+		err = PTR_ERR(bh);
-+		goto exit_journal;
-+	}
-+
-+	mark_bitmap_end(EXT3COW_INODES_PER_GROUP(sb), EXT3COW_BLOCKS_PER_GROUP(sb),
-+			bh->b_data);
-+	ext3cow_journal_dirty_metadata(handle, bh);
-+exit_bh:
-+	brelse(bh);
-+
-+exit_journal:
-+	unlock_super(sb);
-+	if ((err2 = ext3cow_journal_stop(handle)) && !err)
-+		err = err2;
-+
-+	return err;
-+}
-+
-+/*
-+ * Iterate through the groups which hold BACKUP superblock/GDT copies in an
-+ * ext3cow filesystem.  The counters should be initialized to 1, 5, and 7 before
-+ * calling this for the first time.  In a sparse filesystem it will be the
-+ * sequence of powers of 3, 5, and 7: 1, 3, 5, 7, 9, 25, 27, 49, 81, ...
-+ * For a non-sparse filesystem it will be every group: 1, 2, 3, 4, ...
-+ */
-+static unsigned ext3cow_list_backups(struct super_block *sb, unsigned *three,
-+				  unsigned *five, unsigned *seven)
-+{
-+	unsigned *min = three;
-+	int mult = 3;
-+	unsigned ret;
-+
-+	if (!EXT3COW_HAS_RO_COMPAT_FEATURE(sb,
-+					EXT3COW_FEATURE_RO_COMPAT_SPARSE_SUPER)) {
-+		ret = *min;
-+		*min += 1;
-+		return ret;
-+	}
-+
-+	if (*five < *min) {
-+		min = five;
-+		mult = 5;
-+	}
-+	if (*seven < *min) {
-+		min = seven;
-+		mult = 7;
-+	}
-+
-+	ret = *min;
-+	*min *= mult;
-+
-+	return ret;
-+}
-+
-+/*
-+ * Check that all of the backup GDT blocks are held in the primary GDT block.
-+ * It is assumed that they are stored in group order.  Returns the number of
-+ * groups in current filesystem that have BACKUPS, or -ve error code.
-+ */
-+static int verify_reserved_gdb(struct super_block *sb,
-+			       struct buffer_head *primary)
-+{
-+	const ext3cow_fsblk_t blk = primary->b_blocknr;
-+	const unsigned long end = EXT3COW_SB(sb)->s_groups_count;
-+	unsigned three = 1;
-+	unsigned five = 5;
-+	unsigned seven = 7;
-+	unsigned grp;
-+	__le32 *p = (__le32 *)primary->b_data;
-+	int gdbackups = 0;
-+
-+	while ((grp = ext3cow_list_backups(sb, &three, &five, &seven)) < end) {
-+		if (le32_to_cpu(*p++) != grp * EXT3COW_BLOCKS_PER_GROUP(sb) + blk){
-+			ext3cow_warning(sb, __FUNCTION__,
-+				     "reserved GDT "E3FSBLK
-+				     " missing grp %d ("E3FSBLK")",
-+				     blk, grp,
-+				     grp * EXT3COW_BLOCKS_PER_GROUP(sb) + blk);
-+			return -EINVAL;
-+		}
-+		if (++gdbackups > EXT3COW_ADDR_PER_BLOCK(sb))
-+			return -EFBIG;
-+	}
-+
-+	return gdbackups;
-+}
-+
-+/*
-+ * Called when we need to bring a reserved group descriptor table block into
-+ * use from the resize inode.  The primary copy of the new GDT block currently
-+ * is an indirect block (under the double indirect block in the resize inode).
-+ * The new backup GDT blocks will be stored as leaf blocks in this indirect
-+ * block, in group order.  Even though we know all the block numbers we need,
-+ * we check to ensure that the resize inode has actually reserved these blocks.
-+ *
-+ * Don't need to update the block bitmaps because the blocks are still in use.
-+ *
-+ * We get all of the error cases out of the way, so that we are sure to not
-+ * fail once we start modifying the data on disk, because JBD has no rollback.
-+ */
-+static int add_new_gdb(handle_t *handle, struct inode *inode,
-+		       struct ext3cow_new_group_data *input,
-+		       struct buffer_head **primary)
-+{
-+	struct super_block *sb = inode->i_sb;
-+	struct ext3cow_super_block *es = EXT3COW_SB(sb)->s_es;
-+	unsigned long gdb_num = input->group / EXT3COW_DESC_PER_BLOCK(sb);
-+	ext3cow_fsblk_t gdblock = EXT3COW_SB(sb)->s_sbh->b_blocknr + 1 + gdb_num;
-+	struct buffer_head **o_group_desc, **n_group_desc;
-+	struct buffer_head *dind;
-+	int gdbackups;
-+	struct ext3cow_iloc iloc;
-+	__le32 *data;
-+	int err;
-+
-+	if (test_opt(sb, DEBUG))
-+		printk(KERN_DEBUG
-+		       "EXT3COW-fs: ext3cow_add_new_gdb: adding group block %lu\n",
-+		       gdb_num);
-+
-+	/*
-+	 * If we are not using the primary superblock/GDT copy don't resize,
-+	 * because the user tools have no way of handling this.  Probably a
-+	 * bad time to do it anyways.
-+	 */
-+	if (EXT3COW_SB(sb)->s_sbh->b_blocknr !=
-+	    le32_to_cpu(EXT3COW_SB(sb)->s_es->s_first_data_block)) {
-+		ext3cow_warning(sb, __FUNCTION__,
-+			"won't resize using backup superblock at %llu",
-+			(unsigned long long)EXT3COW_SB(sb)->s_sbh->b_blocknr);
-+		return -EPERM;
-+	}
-+
-+	*primary = sb_bread(sb, gdblock);
-+	if (!*primary)
-+		return -EIO;
-+
-+	if ((gdbackups = verify_reserved_gdb(sb, *primary)) < 0) {
-+		err = gdbackups;
-+		goto exit_bh;
-+	}
-+
-+	data = EXT3COW_I(inode)->i_data + EXT3COW_DIND_BLOCK;
-+	dind = sb_bread(sb, le32_to_cpu(*data));
-+	if (!dind) {
-+		err = -EIO;
-+		goto exit_bh;
-+	}
-+
-+	data = (__le32 *)dind->b_data;
-+	if (le32_to_cpu(data[gdb_num % EXT3COW_ADDR_PER_BLOCK(sb)]) != gdblock) {
-+		ext3cow_warning(sb, __FUNCTION__,
-+			     "new group %u GDT block "E3FSBLK" not reserved",
-+			     input->group, gdblock);
-+		err = -EINVAL;
-+		goto exit_dind;
-+	}
-+
-+	if ((err = ext3cow_journal_get_write_access(handle, EXT3COW_SB(sb)->s_sbh)))
-+		goto exit_dind;
-+
-+	if ((err = ext3cow_journal_get_write_access(handle, *primary)))
-+		goto exit_sbh;
-+
-+	if ((err = ext3cow_journal_get_write_access(handle, dind)))
-+		goto exit_primary;
-+
-+	/* ext3cow_reserve_inode_write() gets a reference on the iloc */
-+	if ((err = ext3cow_reserve_inode_write(handle, inode, &iloc)))
-+		goto exit_dindj;
-+
-+	n_group_desc = kmalloc((gdb_num + 1) * sizeof(struct buffer_head *),
-+			GFP_KERNEL);
-+	if (!n_group_desc) {
-+		err = -ENOMEM;
-+		ext3cow_warning (sb, __FUNCTION__,
-+			      "not enough memory for %lu groups", gdb_num + 1);
-+		goto exit_inode;
-+	}
-+
-+	/*
-+	 * Finally, we have all of the possible failures behind us...
-+	 *
-+	 * Remove new GDT block from inode double-indirect block and clear out
-+	 * the new GDT block for use (which also "frees" the backup GDT blocks
-+	 * from the reserved inode).  We don't need to change the bitmaps for
-+	 * these blocks, because they are marked as in-use from being in the
-+	 * reserved inode, and will become GDT blocks (primary and backup).
-+	 */
-+	data[gdb_num % EXT3COW_ADDR_PER_BLOCK(sb)] = 0;
-+	ext3cow_journal_dirty_metadata(handle, dind);
-+	brelse(dind);
-+	inode->i_blocks -= (gdbackups + 1) * sb->s_blocksize >> 9;
-+	ext3cow_mark_iloc_dirty(handle, inode, &iloc);
-+	memset((*primary)->b_data, 0, sb->s_blocksize);
-+	ext3cow_journal_dirty_metadata(handle, *primary);
-+
-+	o_group_desc = EXT3COW_SB(sb)->s_group_desc;
-+	memcpy(n_group_desc, o_group_desc,
-+	       EXT3COW_SB(sb)->s_gdb_count * sizeof(struct buffer_head *));
-+	n_group_desc[gdb_num] = *primary;
-+	EXT3COW_SB(sb)->s_group_desc = n_group_desc;
-+	EXT3COW_SB(sb)->s_gdb_count++;
-+	kfree(o_group_desc);
-+
-+	es->s_reserved_gdt_blocks =
-+		cpu_to_le16(le16_to_cpu(es->s_reserved_gdt_blocks) - 1);
-+	ext3cow_journal_dirty_metadata(handle, EXT3COW_SB(sb)->s_sbh);
-+
-+	return 0;
-+
-+exit_inode:
-+	//ext3cow_journal_release_buffer(handle, iloc.bh);
-+	brelse(iloc.bh);
-+exit_dindj:
-+	//ext3cow_journal_release_buffer(handle, dind);
-+exit_primary:
-+	//ext3cow_journal_release_buffer(handle, *primary);
-+exit_sbh:
-+	//ext3cow_journal_release_buffer(handle, *primary);
-+exit_dind:
-+	brelse(dind);
-+exit_bh:
-+	brelse(*primary);
-+
-+	ext3cow_debug("leaving with error %d\n", err);
-+	return err;
-+}
-+
-+/*
-+ * Called when we are adding a new group which has a backup copy of each of
-+ * the GDT blocks (i.e. sparse group) and there are reserved GDT blocks.
-+ * We need to add these reserved backup GDT blocks to the resize inode, so
-+ * that they are kept for future resizing and not allocated to files.
-+ *
-+ * Each reserved backup GDT block will go into a different indirect block.
-+ * The indirect blocks are actually the primary reserved GDT blocks,
-+ * so we know in advance what their block numbers are.  We only get the
-+ * double-indirect block to verify it is pointing to the primary reserved
-+ * GDT blocks so we don't overwrite a data block by accident.  The reserved
-+ * backup GDT blocks are stored in their reserved primary GDT block.
-+ */
-+static int reserve_backup_gdb(handle_t *handle, struct inode *inode,
-+			      struct ext3cow_new_group_data *input)
-+{
-+	struct super_block *sb = inode->i_sb;
-+	int reserved_gdb =le16_to_cpu(EXT3COW_SB(sb)->s_es->s_reserved_gdt_blocks);
-+	struct buffer_head **primary;
-+	struct buffer_head *dind;
-+	struct ext3cow_iloc iloc;
-+	ext3cow_fsblk_t blk;
-+	__le32 *data, *end;
-+	int gdbackups = 0;
-+	int res, i;
-+	int err;
-+
-+	primary = kmalloc(reserved_gdb * sizeof(*primary), GFP_KERNEL);
-+	if (!primary)
-+		return -ENOMEM;
-+
-+	data = EXT3COW_I(inode)->i_data + EXT3COW_DIND_BLOCK;
-+	dind = sb_bread(sb, le32_to_cpu(*data));
-+	if (!dind) {
-+		err = -EIO;
-+		goto exit_free;
-+	}
-+
-+	blk = EXT3COW_SB(sb)->s_sbh->b_blocknr + 1 + EXT3COW_SB(sb)->s_gdb_count;
-+	data = (__le32 *)dind->b_data + EXT3COW_SB(sb)->s_gdb_count;
-+	end = (__le32 *)dind->b_data + EXT3COW_ADDR_PER_BLOCK(sb);
-+
-+	/* Get each reserved primary GDT block and verify it holds backups */
-+	for (res = 0; res < reserved_gdb; res++, blk++) {
-+		if (le32_to_cpu(*data) != blk) {
-+			ext3cow_warning(sb, __FUNCTION__,
-+				     "reserved block "E3FSBLK
-+				     " not at offset %ld",
-+				     blk,
-+				     (long)(data - (__le32 *)dind->b_data));
-+			err = -EINVAL;
-+			goto exit_bh;
-+		}
-+		primary[res] = sb_bread(sb, blk);
-+		if (!primary[res]) {
-+			err = -EIO;
-+			goto exit_bh;
-+		}
-+		if ((gdbackups = verify_reserved_gdb(sb, primary[res])) < 0) {
-+			brelse(primary[res]);
-+			err = gdbackups;
-+			goto exit_bh;
-+		}
-+		if (++data >= end)
-+			data = (__le32 *)dind->b_data;
-+	}
-+
-+	for (i = 0; i < reserved_gdb; i++) {
-+		if ((err = ext3cow_journal_get_write_access(handle, primary[i]))) {
-+			/*
-+			int j;
-+			for (j = 0; j < i; j++)
-+				ext3cow_journal_release_buffer(handle, primary[j]);
-+			 */
-+			goto exit_bh;
-+		}
-+	}
-+
-+	if ((err = ext3cow_reserve_inode_write(handle, inode, &iloc)))
-+		goto exit_bh;
-+
-+	/*
-+	 * Finally we can add each of the reserved backup GDT blocks from
-+	 * the new group to its reserved primary GDT block.
-+	 */
-+	blk = input->group * EXT3COW_BLOCKS_PER_GROUP(sb);
-+	for (i = 0; i < reserved_gdb; i++) {
-+		int err2;
-+		data = (__le32 *)primary[i]->b_data;
-+		/* printk("reserving backup %lu[%u] = %lu\n",
-+		       primary[i]->b_blocknr, gdbackups,
-+		       blk + primary[i]->b_blocknr); */
-+		data[gdbackups] = cpu_to_le32(blk + primary[i]->b_blocknr);
-+		err2 = ext3cow_journal_dirty_metadata(handle, primary[i]);
-+		if (!err)
-+			err = err2;
-+	}
-+	inode->i_blocks += reserved_gdb * sb->s_blocksize >> 9;
-+	ext3cow_mark_iloc_dirty(handle, inode, &iloc);
-+
-+exit_bh:
-+	while (--res >= 0)
-+		brelse(primary[res]);
-+	brelse(dind);
-+
-+exit_free:
-+	kfree(primary);
-+
-+	return err;
-+}
-+
-+/*
-+ * Update the backup copies of the ext3cow metadata.  These don't need to be part
-+ * of the main resize transaction, because e2fsck will re-write them if there
-+ * is a problem (basically only OOM will cause a problem).  However, we
-+ * _should_ update the backups if possible, in case the primary gets trashed
-+ * for some reason and we need to run e2fsck from a backup superblock.  The
-+ * important part is that the new block and inode counts are in the backup
-+ * superblocks, and the location of the new group metadata in the GDT backups.
-+ *
-+ * We do not need lock_super() for this, because these blocks are not
-+ * otherwise touched by the filesystem code when it is mounted.  We don't
-+ * need to worry about last changing from sbi->s_groups_count, because the
-+ * worst that can happen is that we do not copy the full number of backups
-+ * at this time.  The resize which changed s_groups_count will backup again.
-+ */
-+static void update_backups(struct super_block *sb,
-+			   int blk_off, char *data, int size)
-+{
-+	struct ext3cow_sb_info *sbi = EXT3COW_SB(sb);
-+	const unsigned long last = sbi->s_groups_count;
-+	const int bpg = EXT3COW_BLOCKS_PER_GROUP(sb);
-+	unsigned three = 1;
-+	unsigned five = 5;
-+	unsigned seven = 7;
-+	unsigned group;
-+	int rest = sb->s_blocksize - size;
-+	handle_t *handle;
-+	int err = 0, err2;
-+
-+	handle = ext3cow_journal_start_sb(sb, EXT3COW_MAX_TRANS_DATA);
-+	if (IS_ERR(handle)) {
-+		group = 1;
-+		err = PTR_ERR(handle);
-+		goto exit_err;
-+	}
-+
-+	while ((group = ext3cow_list_backups(sb, &three, &five, &seven)) < last) {
-+		struct buffer_head *bh;
-+
-+		/* Out of journal space, and can't get more - abort - so sad */
-+		if (handle->h_buffer_credits == 0 &&
-+		    ext3cow_journal_extend(handle, EXT3COW_MAX_TRANS_DATA) &&
-+		    (err = ext3cow_journal_restart(handle, EXT3COW_MAX_TRANS_DATA)))
-+			break;
-+
-+		bh = sb_getblk(sb, group * bpg + blk_off);
-+		if (!bh) {
-+			err = -EIO;
-+			break;
-+		}
-+		ext3cow_debug("update metadata backup %#04lx\n",
-+			  (unsigned long)bh->b_blocknr);
-+		if ((err = ext3cow_journal_get_write_access(handle, bh)))
-+			break;
-+		lock_buffer(bh);
-+		memcpy(bh->b_data, data, size);
-+		if (rest)
-+			memset(bh->b_data + size, 0, rest);
-+		set_buffer_uptodate(bh);
-+		unlock_buffer(bh);
-+		ext3cow_journal_dirty_metadata(handle, bh);
-+		brelse(bh);
-+	}
-+	if ((err2 = ext3cow_journal_stop(handle)) && !err)
-+		err = err2;
-+
-+	/*
-+	 * Ugh! Need to have e2fsck write the backup copies.  It is too
-+	 * late to revert the resize, we shouldn't fail just because of
-+	 * the backup copies (they are only needed in case of corruption).
-+	 *
-+	 * However, if we got here we have a journal problem too, so we
-+	 * can't really start a transaction to mark the superblock.
-+	 * Chicken out and just set the flag on the hope it will be written
-+	 * to disk, and if not - we will simply wait until next fsck.
-+	 */
-+exit_err:
-+	if (err) {
-+		ext3cow_warning(sb, __FUNCTION__,
-+			     "can't update backup for group %d (err %d), "
-+			     "forcing fsck on next reboot", group, err);
-+		sbi->s_mount_state &= ~EXT3COW_VALID_FS;
-+		sbi->s_es->s_state &= cpu_to_le16(~EXT3COW_VALID_FS);
-+		mark_buffer_dirty(sbi->s_sbh);
-+	}
-+}
-+
-+/* Add group descriptor data to an existing or new group descriptor block.
-+ * Ensure we handle all possible error conditions _before_ we start modifying
-+ * the filesystem, because we cannot abort the transaction and not have it
-+ * write the data to disk.
-+ *
-+ * If we are on a GDT block boundary, we need to get the reserved GDT block.
-+ * Otherwise, we may need to add backup GDT blocks for a sparse group.
-+ *
-+ * We only need to hold the superblock lock while we are actually adding
-+ * in the new group's counts to the superblock.  Prior to that we have
-+ * not really "added" the group at all.  We re-check that we are still
-+ * adding in the last group in case things have changed since verifying.
-+ */
-+int ext3cow_group_add(struct super_block *sb, struct ext3cow_new_group_data *input)
-+{
-+	struct ext3cow_sb_info *sbi = EXT3COW_SB(sb);
-+	struct ext3cow_super_block *es = sbi->s_es;
-+	int reserved_gdb = ext3cow_bg_has_super(sb, input->group) ?
-+		le16_to_cpu(es->s_reserved_gdt_blocks) : 0;
-+	struct buffer_head *primary = NULL;
-+	struct ext3cow_group_desc *gdp;
-+	struct inode *inode = NULL;
-+	handle_t *handle;
-+	int gdb_off, gdb_num;
-+	int err, err2;
-+
-+	gdb_num = input->group / EXT3COW_DESC_PER_BLOCK(sb);
-+	gdb_off = input->group % EXT3COW_DESC_PER_BLOCK(sb);
-+
-+	if (gdb_off == 0 && !EXT3COW_HAS_RO_COMPAT_FEATURE(sb,
-+					EXT3COW_FEATURE_RO_COMPAT_SPARSE_SUPER)) {
-+		ext3cow_warning(sb, __FUNCTION__,
-+			     "Can't resize non-sparse filesystem further");
-+		return -EPERM;
-+	}
-+
-+	if (le32_to_cpu(es->s_blocks_count) + input->blocks_count <
-+	    le32_to_cpu(es->s_blocks_count)) {
-+		ext3cow_warning(sb, __FUNCTION__, "blocks_count overflow\n");
-+		return -EINVAL;
-+	}
-+
-+	if (le32_to_cpu(es->s_inodes_count) + EXT3COW_INODES_PER_GROUP(sb) <
-+	    le32_to_cpu(es->s_inodes_count)) {
-+		ext3cow_warning(sb, __FUNCTION__, "inodes_count overflow\n");
-+		return -EINVAL;
-+	}
-+
-+	if (reserved_gdb || gdb_off == 0) {
-+		if (!EXT3COW_HAS_COMPAT_FEATURE(sb,
-+					     EXT3COW_FEATURE_COMPAT_RESIZE_INODE)){
-+			ext3cow_warning(sb, __FUNCTION__,
-+				     "No reserved GDT blocks, can't resize");
-+			return -EPERM;
-+		}
-+		inode = iget(sb, EXT3COW_RESIZE_INO);
-+		if (!inode || is_bad_inode(inode)) {
-+			ext3cow_warning(sb, __FUNCTION__,
-+				     "Error opening resize inode");
-+			iput(inode);
-+			return -ENOENT;
-+		}
-+	}
-+
-+	if ((err = verify_group_input(sb, input)))
-+		goto exit_put;
-+
-+	if ((err = setup_new_group_blocks(sb, input)))
-+		goto exit_put;
-+
-+	/*
-+	 * We will always be modifying at least the superblock and a GDT
-+	 * block.  If we are adding a group past the last current GDT block,
-+	 * we will also modify the inode and the dindirect block.  If we
-+	 * are adding a group with superblock/GDT backups  we will also
-+	 * modify each of the reserved GDT dindirect blocks.
-+	 */
-+	handle = ext3cow_journal_start_sb(sb,
-+				       ext3cow_bg_has_super(sb, input->group) ?
-+				       3 + reserved_gdb : 4);
-+	if (IS_ERR(handle)) {
-+		err = PTR_ERR(handle);
-+		goto exit_put;
-+	}
-+
-+	lock_super(sb);
-+	if (input->group != sbi->s_groups_count) {
-+		ext3cow_warning(sb, __FUNCTION__,
-+			     "multiple resizers run on filesystem!");
-+		err = -EBUSY;
-+		goto exit_journal;
-+	}
-+
-+	if ((err = ext3cow_journal_get_write_access(handle, sbi->s_sbh)))
-+		goto exit_journal;
-+
-+	/*
-+	 * We will only either add reserved group blocks to a backup group
-+	 * or remove reserved blocks for the first group in a new group block.
-+	 * Doing both would be mean more complex code, and sane people don't
-+	 * use non-sparse filesystems anymore.  This is already checked above.
-+	 */
-+	if (gdb_off) {
-+		primary = sbi->s_group_desc[gdb_num];
-+		if ((err = ext3cow_journal_get_write_access(handle, primary)))
-+			goto exit_journal;
-+
-+		if (reserved_gdb && ext3cow_bg_num_gdb(sb, input->group) &&
-+		    (err = reserve_backup_gdb(handle, inode, input)))
-+			goto exit_journal;
-+	} else if ((err = add_new_gdb(handle, inode, input, &primary)))
-+		goto exit_journal;
-+
-+	/*
-+	 * OK, now we've set up the new group.  Time to make it active.
-+	 *
-+	 * Current kernels don't lock all allocations via lock_super(),
-+	 * so we have to be safe wrt. concurrent accesses the group
-+	 * data.  So we need to be careful to set all of the relevant
-+	 * group descriptor data etc. *before* we enable the group.
-+	 *
-+	 * The key field here is sbi->s_groups_count: as long as
-+	 * that retains its old value, nobody is going to access the new
-+	 * group.
-+	 *
-+	 * So first we update all the descriptor metadata for the new
-+	 * group; then we update the total disk blocks count; then we
-+	 * update the groups count to enable the group; then finally we
-+	 * update the free space counts so that the system can start
-+	 * using the new disk blocks.
-+	 */
-+
-+	/* Update group descriptor block for new group */
-+	gdp = (struct ext3cow_group_desc *)primary->b_data + gdb_off;
-+
-+	gdp->bg_block_bitmap = cpu_to_le32(input->block_bitmap);
-+	gdp->bg_inode_bitmap = cpu_to_le32(input->inode_bitmap);
-+	gdp->bg_inode_table = cpu_to_le32(input->inode_table);
-+	gdp->bg_free_blocks_count = cpu_to_le16(input->free_blocks_count);
-+	gdp->bg_free_inodes_count = cpu_to_le16(EXT3COW_INODES_PER_GROUP(sb));
-+
-+	/*
-+	 * Make the new blocks and inodes valid next.  We do this before
-+	 * increasing the group count so that once the group is enabled,
-+	 * all of its blocks and inodes are already valid.
-+	 *
-+	 * We always allocate group-by-group, then block-by-block or
-+	 * inode-by-inode within a group, so enabling these
-+	 * blocks/inodes before the group is live won't actually let us
-+	 * allocate the new space yet.
-+	 */
-+	es->s_blocks_count = cpu_to_le32(le32_to_cpu(es->s_blocks_count) +
-+		input->blocks_count);
-+	es->s_inodes_count = cpu_to_le32(le32_to_cpu(es->s_inodes_count) +
-+		EXT3COW_INODES_PER_GROUP(sb));
-+
-+	/*
-+	 * We need to protect s_groups_count against other CPUs seeing
-+	 * inconsistent state in the superblock.
-+	 *
-+	 * The precise rules we use are:
-+	 *
-+	 * * Writers of s_groups_count *must* hold lock_super
-+	 * AND
-+	 * * Writers must perform a smp_wmb() after updating all dependent
-+	 *   data and before modifying the groups count
-+	 *
-+	 * * Readers must hold lock_super() over the access
-+	 * OR
-+	 * * Readers must perform an smp_rmb() after reading the groups count
-+	 *   and before reading any dependent data.
-+	 *
-+	 * NB. These rules can be relaxed when checking the group count
-+	 * while freeing data, as we can only allocate from a block
-+	 * group after serialising against the group count, and we can
-+	 * only then free after serialising in turn against that
-+	 * allocation.
-+	 */
-+	smp_wmb();
-+
-+	/* Update the global fs size fields */
-+	sbi->s_groups_count++;
-+
-+	ext3cow_journal_dirty_metadata(handle, primary);
-+
-+	/* Update the reserved block counts only once the new group is
-+	 * active. */
-+	es->s_r_blocks_count = cpu_to_le32(le32_to_cpu(es->s_r_blocks_count) +
-+		input->reserved_blocks);
-+
-+	/* Update the free space counts */
-+	percpu_counter_mod(&sbi->s_freeblocks_counter,
-+			   input->free_blocks_count);
-+	percpu_counter_mod(&sbi->s_freeinodes_counter,
-+			   EXT3COW_INODES_PER_GROUP(sb));
-+
-+	ext3cow_journal_dirty_metadata(handle, sbi->s_sbh);
-+	sb->s_dirt = 1;
-+
-+exit_journal:
-+	unlock_super(sb);
-+	if ((err2 = ext3cow_journal_stop(handle)) && !err)
-+		err = err2;
-+	if (!err) {
-+		update_backups(sb, sbi->s_sbh->b_blocknr, (char *)es,
-+			       sizeof(struct ext3cow_super_block));
-+		update_backups(sb, primary->b_blocknr, primary->b_data,
-+			       primary->b_size);
-+	}
-+exit_put:
-+	iput(inode);
-+	return err;
-+} /* ext3cow_group_add */
-+
-+/* Extend the filesystem to the new number of blocks specified.  This entry
-+ * point is only used to extend the current filesystem to the end of the last
-+ * existing group.  It can be accessed via ioctl, or by "remount,resize=<size>"
-+ * for emergencies (because it has no dependencies on reserved blocks).
-+ *
-+ * If we _really_ wanted, we could use default values to call ext3cow_group_add()
-+ * allow the "remount" trick to work for arbitrary resizing, assuming enough
-+ * GDT blocks are reserved to grow to the desired size.
-+ */
-+int ext3cow_group_extend(struct super_block *sb, struct ext3cow_super_block *es,
-+		      ext3cow_fsblk_t n_blocks_count)
-+{
-+	ext3cow_fsblk_t o_blocks_count;
-+	unsigned long o_groups_count;
-+	ext3cow_grpblk_t last;
-+	ext3cow_grpblk_t add;
-+	struct buffer_head * bh;
-+	handle_t *handle;
-+	int err;
-+	unsigned long freed_blocks;
-+
-+	/* We don't need to worry about locking wrt other resizers just
-+	 * yet: we're going to revalidate es->s_blocks_count after
-+	 * taking lock_super() below. */
-+	o_blocks_count = le32_to_cpu(es->s_blocks_count);
-+	o_groups_count = EXT3COW_SB(sb)->s_groups_count;
-+
-+	if (test_opt(sb, DEBUG))
-+		printk(KERN_DEBUG "EXT3COW-fs: extending last group from "E3FSBLK" uto "E3FSBLK" blocks\n",
-+		       o_blocks_count, n_blocks_count);
-+
-+	if (n_blocks_count == 0 || n_blocks_count == o_blocks_count)
-+		return 0;
-+
-+	if (n_blocks_count > (sector_t)(~0ULL) >> (sb->s_blocksize_bits - 9)) {
-+		printk(KERN_ERR "EXT3COW-fs: filesystem on %s:"
-+			" too large to resize to %lu blocks safely\n",
-+			sb->s_id, n_blocks_count);
-+		if (sizeof(sector_t) < 8)
-+			ext3cow_warning(sb, __FUNCTION__,
-+			"CONFIG_LBD not enabled\n");
-+		return -EINVAL;
-+	}
-+
-+	if (n_blocks_count < o_blocks_count) {
-+		ext3cow_warning(sb, __FUNCTION__,
-+			     "can't shrink FS - resize aborted");
-+		return -EBUSY;
-+	}
-+
-+	/* Handle the remaining blocks in the last group only. */
-+	last = (o_blocks_count - le32_to_cpu(es->s_first_data_block)) %
-+		EXT3COW_BLOCKS_PER_GROUP(sb);
-+
-+	if (last == 0) {
-+		ext3cow_warning(sb, __FUNCTION__,
-+			     "need to use ext2online to resize further");
-+		return -EPERM;
-+	}
-+
-+	add = EXT3COW_BLOCKS_PER_GROUP(sb) - last;
-+
-+	if (o_blocks_count + add < o_blocks_count) {
-+		ext3cow_warning(sb, __FUNCTION__, "blocks_count overflow");
-+		return -EINVAL;
-+	}
-+
-+	if (o_blocks_count + add > n_blocks_count)
-+		add = n_blocks_count - o_blocks_count;
-+
-+	if (o_blocks_count + add < n_blocks_count)
-+		ext3cow_warning(sb, __FUNCTION__,
-+			     "will only finish group ("E3FSBLK
-+			     " blocks, %u new)",
-+			     o_blocks_count + add, add);
-+
-+	/* See if the device is actually as big as what was requested */
-+	bh = sb_bread(sb, o_blocks_count + add -1);
-+	if (!bh) {
-+		ext3cow_warning(sb, __FUNCTION__,
-+			     "can't read last block, resize aborted");
-+		return -ENOSPC;
-+	}
-+	brelse(bh);
-+
-+	/* We will update the superblock, one block bitmap, and
-+	 * one group descriptor via ext3cow_free_blocks().
-+	 */
-+	handle = ext3cow_journal_start_sb(sb, 3);
-+	if (IS_ERR(handle)) {
-+		err = PTR_ERR(handle);
-+		ext3cow_warning(sb, __FUNCTION__, "error %d on journal start",err);
-+		goto exit_put;
-+	}
-+
-+	lock_super(sb);
-+	if (o_blocks_count != le32_to_cpu(es->s_blocks_count)) {
-+		ext3cow_warning(sb, __FUNCTION__,
-+			     "multiple resizers run on filesystem!");
-+		unlock_super(sb);
-+		err = -EBUSY;
-+		goto exit_put;
-+	}
-+
-+	if ((err = ext3cow_journal_get_write_access(handle,
-+						 EXT3COW_SB(sb)->s_sbh))) {
-+		ext3cow_warning(sb, __FUNCTION__,
-+			     "error %d on journal write access", err);
-+		unlock_super(sb);
-+		ext3cow_journal_stop(handle);
-+		goto exit_put;
-+	}
-+	es->s_blocks_count = cpu_to_le32(o_blocks_count + add);
-+	ext3cow_journal_dirty_metadata(handle, EXT3COW_SB(sb)->s_sbh);
-+	sb->s_dirt = 1;
-+	unlock_super(sb);
-+	ext3cow_debug("freeing blocks %lu through "E3FSBLK"\n", o_blocks_count,
-+		   o_blocks_count + add);
-+	ext3cow_free_blocks_sb(handle, sb, o_blocks_count, add, &freed_blocks);
-+	ext3cow_debug("freed blocks "E3FSBLK" through "E3FSBLK"\n", o_blocks_count,
-+		   o_blocks_count + add);
-+	if ((err = ext3cow_journal_stop(handle)))
-+		goto exit_put;
-+	if (test_opt(sb, DEBUG))
-+		printk(KERN_DEBUG "EXT3COW-fs: extended group to %u blocks\n",
-+		       le32_to_cpu(es->s_blocks_count));
-+	update_backups(sb, EXT3COW_SB(sb)->s_sbh->b_blocknr, (char *)es,
-+		       sizeof(struct ext3cow_super_block));
-+exit_put:
-+	return err;
-+} /* ext3cow_group_extend */
-diff -ruN linux-2.6.20.3/fs/ext3cow/super.c linux-2.6.20.3-ext3cow/fs/ext3cow/super.c
---- linux-2.6.20.3/fs/ext3cow/super.c	1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.20.3-ext3cow/fs/ext3cow/super.c	2008-03-09 11:14:49.000000000 -0400
-@@ -0,0 +1,2808 @@
-+/*
-+ *  linux/fs/ext3cow/super.c
-+ *
-+ * Copyright (C) 1992, 1993, 1994, 1995
-+ * Remy Card (card@masi.ibp.fr)
-+ * Laboratoire MASI - Institut Blaise Pascal
-+ * Universite Pierre et Marie Curie (Paris VI)
-+ *
-+ *  from
-+ *
-+ *  linux/fs/minix/inode.c
-+ *
-+ *  Copyright (C) 1991, 1992  Linus Torvalds
-+ *
-+ *  Big-endian to little-endian byte-swapping/bitmaps by
-+ *        David S. Miller (davem@caip.rutgers.edu), 1995
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/string.h>
-+#include <linux/fs.h>
-+#include <linux/time.h>
-+#include <linux/jbd.h>
-+#include <linux/ext3cow_fs.h>
-+#include <linux/ext3cow_jbd.h>
-+#include <linux/slab.h>
-+#include <linux/init.h>
-+#include <linux/blkdev.h>
-+#include <linux/parser.h>
-+#include <linux/smp_lock.h>
-+#include <linux/buffer_head.h>
-+#include <linux/vfs.h>
-+#include <linux/random.h>
-+#include <linux/mount.h>
-+#include <linux/namei.h>
-+#include <linux/quotaops.h>
-+#include <linux/seq_file.h>
-+
-+#include <asm/uaccess.h>
-+
-+#include "xattr.h"
-+#include "acl.h"
-+#include "namei.h"
-+
-+static int ext3cow_load_journal(struct super_block *, struct ext3cow_super_block *,
-+			     unsigned long journal_devnum);
-+static int ext3cow_create_journal(struct super_block *, struct ext3cow_super_block *,
-+			       unsigned int);
-+static void ext3cow_commit_super (struct super_block * sb,
-+			       struct ext3cow_super_block * es,
-+			       int sync);
-+static void ext3cow_mark_recovery_complete(struct super_block * sb,
-+					struct ext3cow_super_block * es);
-+static void ext3cow_clear_journal_err(struct super_block * sb,
-+				   struct ext3cow_super_block * es);
-+static int ext3cow_sync_fs(struct super_block *sb, int wait);
-+static const char *ext3cow_decode_error(struct super_block * sb, int errno,
-+				     char nbuf[16]);
-+static int ext3cow_remount (struct super_block * sb, int * flags, char * data);
-+static int ext3cow_statfs (struct dentry * dentry, struct kstatfs * buf);
-+static void ext3cow_unlockfs(struct super_block *sb);
-+static void ext3cow_write_super (struct super_block * sb);
-+static void ext3cow_write_super_lockfs(struct super_block *sb);
-+
-+/*
-+ * Wrappers for journal_start/end.
-+ *
-+ * The only special thing we need to do here is to make sure that all
-+ * journal_end calls result in the superblock being marked dirty, so
-+ * that sync() will call the filesystem's write_super callback if
-+ * appropriate.
-+ */
-+handle_t *ext3cow_journal_start_sb(struct super_block *sb, int nblocks)
-+{
-+	journal_t *journal;
-+
-+	if (sb->s_flags & MS_RDONLY)
-+		return ERR_PTR(-EROFS);
-+
-+	/* Special case here: if the journal has aborted behind our
-+	 * backs (eg. EIO in the commit thread), then we still need to
-+	 * take the FS itself readonly cleanly. */
-+	journal = EXT3COW_SB(sb)->s_journal;
-+	if (is_journal_aborted(journal)) {
-+		ext3cow_abort(sb, __FUNCTION__,
-+			   "Detected aborted journal");
-+		return ERR_PTR(-EROFS);
-+	}
-+
-+	return journal_start(journal, nblocks);
-+}
-+
-+/*
-+ * The only special thing we need to do here is to make sure that all
-+ * journal_stop calls result in the superblock being marked dirty, so
-+ * that sync() will call the filesystem's write_super callback if
-+ * appropriate.
-+ */
-+int __ext3cow_journal_stop(const char *where, handle_t *handle)
-+{
-+	struct super_block *sb;
-+	int err;
-+	int rc;
-+
-+	sb = handle->h_transaction->t_journal->j_private;
-+	err = handle->h_err;
-+	rc = journal_stop(handle);
-+
-+	if (!err)
-+		err = rc;
-+	if (err)
-+		__ext3cow_std_error(sb, where, err);
-+	return err;
-+}
-+
-+void ext3cow_journal_abort_handle(const char *caller, const char *err_fn,
-+		struct buffer_head *bh, handle_t *handle, int err)
-+{
-+	char nbuf[16];
-+	const char *errstr = ext3cow_decode_error(NULL, err, nbuf);
-+
-+	if (bh)
-+		BUFFER_TRACE(bh, "abort");
-+
-+	if (!handle->h_err)
-+		handle->h_err = err;
-+
-+	if (is_handle_aborted(handle))
-+		return;
-+
-+	printk(KERN_ERR "%s: aborting transaction: %s in %s\n",
-+	       caller, errstr, err_fn);
-+
-+	journal_abort_handle(handle);
-+}
-+
-+/* Deal with the reporting of failure conditions on a filesystem such as
-+ * inconsistencies detected or read IO failures.
-+ *
-+ * On ext2, we can store the error state of the filesystem in the
-+ * superblock.  That is not possible on ext3cow, because we may have other
-+ * write ordering constraints on the superblock which prevent us from
-+ * writing it out straight away; and given that the journal is about to
-+ * be aborted, we can't rely on the current, or future, transactions to
-+ * write out the superblock safely.
-+ *
-+ * We'll just use the journal_abort() error code to record an error in
-+ * the journal instead.  On recovery, the journal will compain about
-+ * that error until we've noted it down and cleared it.
-+ */
-+
-+static void ext3cow_handle_error(struct super_block *sb)
-+{
-+	struct ext3cow_super_block *es = EXT3COW_SB(sb)->s_es;
-+
-+	EXT3COW_SB(sb)->s_mount_state |= EXT3COW_ERROR_FS;
-+	es->s_state |= cpu_to_le16(EXT3COW_ERROR_FS);
-+
-+	if (sb->s_flags & MS_RDONLY)
-+		return;
-+
-+	if (!test_opt (sb, ERRORS_CONT)) {
-+		journal_t *journal = EXT3COW_SB(sb)->s_journal;
-+
-+		EXT3COW_SB(sb)->s_mount_opt |= EXT3COW_MOUNT_ABORT;
-+		if (journal)
-+			journal_abort(journal, -EIO);
-+	}
-+	if (test_opt (sb, ERRORS_RO)) {
-+		printk (KERN_CRIT "Remounting filesystem read-only\n");
-+		sb->s_flags |= MS_RDONLY;
-+	}
-+	ext3cow_commit_super(sb, es, 1);
-+	if (test_opt(sb, ERRORS_PANIC))
-+		panic("EXT3COW-fs (device %s): panic forced after error\n",
-+			sb->s_id);
-+}
-+
-+void ext3cow_error (struct super_block * sb, const char * function,
-+		 const char * fmt, ...)
-+{
-+	va_list args;
-+
-+	va_start(args, fmt);
-+	printk(KERN_CRIT "EXT3COW-fs error (device %s): %s: ",sb->s_id, function);
-+	vprintk(fmt, args);
-+	printk("\n");
-+	va_end(args);
-+
-+	ext3cow_handle_error(sb);
-+}
-+
-+static const char *ext3cow_decode_error(struct super_block * sb, int errno,
-+				     char nbuf[16])
-+{
-+	char *errstr = NULL;
-+
-+	switch (errno) {
-+	case -EIO:
-+		errstr = "IO failure";
-+		break;
-+	case -ENOMEM:
-+		errstr = "Out of memory";
-+		break;
-+	case -EROFS:
-+		if (!sb || EXT3COW_SB(sb)->s_journal->j_flags & JFS_ABORT)
-+			errstr = "Journal has aborted";
-+		else
-+			errstr = "Readonly filesystem";
-+		break;
-+	default:
-+		/* If the caller passed in an extra buffer for unknown
-+		 * errors, textualise them now.  Else we just return
-+		 * NULL. */
-+		if (nbuf) {
-+			/* Check for truncated error codes... */
-+			if (snprintf(nbuf, 16, "error %d", -errno) >= 0)
-+				errstr = nbuf;
-+		}
-+		break;
-+	}
-+
-+	return errstr;
-+}
-+
-+/* __ext3cow_std_error decodes expected errors from journaling functions
-+ * automatically and invokes the appropriate error response.  */
-+
-+void __ext3cow_std_error (struct super_block * sb, const char * function,
-+		       int errno)
-+{
-+	char nbuf[16];
-+	const char *errstr;
-+
-+	/* Special case: if the error is EROFS, and we're not already
-+	 * inside a transaction, then there's really no point in logging
-+	 * an error. */
-+	if (errno == -EROFS && journal_current_handle() == NULL &&
-+	    (sb->s_flags & MS_RDONLY))
-+		return;
-+
-+	errstr = ext3cow_decode_error(sb, errno, nbuf);
-+	printk (KERN_CRIT "EXT3COW-fs error (device %s) in %s: %s\n",
-+		sb->s_id, function, errstr);
-+
-+	ext3cow_handle_error(sb);
-+}
-+
-+/*
-+ * ext3cow_abort is a much stronger failure handler than ext3cow_error.  The
-+ * abort function may be used to deal with unrecoverable failures such
-+ * as journal IO errors or ENOMEM at a critical moment in log management.
-+ *
-+ * We unconditionally force the filesystem into an ABORT|READONLY state,
-+ * unless the error response on the fs has been set to panic in which
-+ * case we take the easy way out and panic immediately.
-+ */
-+
-+void ext3cow_abort (struct super_block * sb, const char * function,
-+		 const char * fmt, ...)
-+{
-+	va_list args;
-+
-+	printk (KERN_CRIT "ext3cow_abort called.\n");
-+
-+	va_start(args, fmt);
-+	printk(KERN_CRIT "EXT3COW-fs error (device %s): %s: ",sb->s_id, function);
-+	vprintk(fmt, args);
-+	printk("\n");
-+	va_end(args);
-+
-+	if (test_opt(sb, ERRORS_PANIC))
-+		panic("EXT3COW-fs panic from previous error\n");
-+
-+	if (sb->s_flags & MS_RDONLY)
-+		return;
-+
-+	printk(KERN_CRIT "Remounting filesystem read-only\n");
-+	EXT3COW_SB(sb)->s_mount_state |= EXT3COW_ERROR_FS;
-+	sb->s_flags |= MS_RDONLY;
-+	EXT3COW_SB(sb)->s_mount_opt |= EXT3COW_MOUNT_ABORT;
-+	journal_abort(EXT3COW_SB(sb)->s_journal, -EIO);
-+}
-+
-+void ext3cow_warning (struct super_block * sb, const char * function,
-+		   const char * fmt, ...)
-+{
-+	va_list args;
-+
-+	va_start(args, fmt);
-+	printk(KERN_WARNING "EXT3COW-fs warning (device %s): %s: ",
-+	       sb->s_id, function);
-+	vprintk(fmt, args);
-+	printk("\n");
-+	va_end(args);
-+}
-+
-+void ext3cow_update_dynamic_rev(struct super_block *sb)
-+{
-+	struct ext3cow_super_block *es = EXT3COW_SB(sb)->s_es;
-+
-+	if (le32_to_cpu(es->s_rev_level) > EXT3COW_GOOD_OLD_REV)
-+		return;
-+
-+	ext3cow_warning(sb, __FUNCTION__,
-+		     "updating to rev %d because of new feature flag, "
-+		     "running e2fsck is recommended",
-+		     EXT3COW_DYNAMIC_REV);
-+
-+	es->s_first_ino = cpu_to_le32(EXT3COW_GOOD_OLD_FIRST_INO);
-+	es->s_inode_size = cpu_to_le16(EXT3COW_GOOD_OLD_INODE_SIZE);
-+	es->s_rev_level = cpu_to_le32(EXT3COW_DYNAMIC_REV);
-+	/* leave es->s_feature_*compat flags alone */
-+	/* es->s_uuid will be set by e2fsck if empty */
-+
-+	/*
-+	 * The rest of the superblock fields should be zero, and if not it
-+	 * means they are likely already in use, so leave them alone.  We
-+	 * can leave it up to e2fsck to clean up any inconsistencies there.
-+	 */
-+}
-+
-+/*
-+ * Open the external journal device
-+ */
-+static struct block_device *ext3cow_blkdev_get(dev_t dev)
-+{
-+	struct block_device *bdev;
-+	char b[BDEVNAME_SIZE];
-+
-+	bdev = open_by_devnum(dev, FMODE_READ|FMODE_WRITE);
-+	if (IS_ERR(bdev))
-+		goto fail;
-+	return bdev;
-+
-+fail:
-+	printk(KERN_ERR "EXT3COW: failed to open journal device %s: %ld\n",
-+			__bdevname(dev, b), PTR_ERR(bdev));
-+	return NULL;
-+}
-+
-+/*
-+ * Release the journal device
-+ */
-+static int ext3cow_blkdev_put(struct block_device *bdev)
-+{
-+	bd_release(bdev);
-+	return blkdev_put(bdev);
-+}
-+
-+static int ext3cow_blkdev_remove(struct ext3cow_sb_info *sbi)
-+{
-+	struct block_device *bdev;
-+	int ret = -ENODEV;
-+
-+	bdev = sbi->journal_bdev;
-+	if (bdev) {
-+		ret = ext3cow_blkdev_put(bdev);
-+		sbi->journal_bdev = NULL;
-+	}
-+	return ret;
-+}
-+
-+static inline struct inode *orphan_list_entry(struct list_head *l)
-+{
-+	return &list_entry(l, struct ext3cow_inode_info, i_orphan)->vfs_inode;
-+}
-+
-+static void dump_orphan_list(struct super_block *sb, struct ext3cow_sb_info *sbi)
-+{
-+	struct list_head *l;
-+
-+	printk(KERN_ERR "sb orphan head is %d\n",
-+	       le32_to_cpu(sbi->s_es->s_last_orphan));
-+
-+	printk(KERN_ERR "sb_info orphan list:\n");
-+	list_for_each(l, &sbi->s_orphan) {
-+		struct inode *inode = orphan_list_entry(l);
-+		printk(KERN_ERR "  "
-+		       "inode %s:%lu at %p: mode %o, nlink %d, next %d\n",
-+		       inode->i_sb->s_id, inode->i_ino, inode,
-+		       inode->i_mode, inode->i_nlink,
-+		       NEXT_ORPHAN(inode));
-+	}
-+}
-+
-+static void ext3cow_put_super (struct super_block * sb)
-+{
-+	struct ext3cow_sb_info *sbi = EXT3COW_SB(sb);
-+	struct ext3cow_super_block *es = sbi->s_es;
-+	int i;
-+
-+	ext3cow_xattr_put_super(sb);
-+	journal_destroy(sbi->s_journal);
-+	if (!(sb->s_flags & MS_RDONLY)) {
-+		EXT3COW_CLEAR_INCOMPAT_FEATURE(sb, EXT3COW_FEATURE_INCOMPAT_RECOVER);
-+		es->s_state = cpu_to_le16(sbi->s_mount_state);
-+		BUFFER_TRACE(sbi->s_sbh, "marking dirty");
-+		mark_buffer_dirty(sbi->s_sbh);
-+		ext3cow_commit_super(sb, es, 1);
-+	}
-+
-+	for (i = 0; i < sbi->s_gdb_count; i++)
-+		brelse(sbi->s_group_desc[i]);
-+	kfree(sbi->s_group_desc);
-+	percpu_counter_destroy(&sbi->s_freeblocks_counter);
-+	percpu_counter_destroy(&sbi->s_freeinodes_counter);
-+	percpu_counter_destroy(&sbi->s_dirs_counter);
-+	brelse(sbi->s_sbh);
-+#ifdef CONFIG_QUOTA
-+	for (i = 0; i < MAXQUOTAS; i++)
-+		kfree(sbi->s_qf_names[i]);
-+#endif
-+
-+	/* Debugging code just in case the in-memory inode orphan list
-+	 * isn't empty.  The on-disk one can be non-empty if we've
-+	 * detected an error and taken the fs readonly, but the
-+	 * in-memory list had better be clean by this point. */
-+	if (!list_empty(&sbi->s_orphan))
-+		dump_orphan_list(sb, sbi);
-+	J_ASSERT(list_empty(&sbi->s_orphan));
-+
-+	invalidate_bdev(sb->s_bdev, 0);
-+	if (sbi->journal_bdev && sbi->journal_bdev != sb->s_bdev) {
-+		/*
-+		 * Invalidate the journal device's buffers.  We don't want them
-+		 * floating about in memory - the physical journal device may
-+		 * hotswapped, and it breaks the `ro-after' testing code.
-+		 */
-+		sync_blockdev(sbi->journal_bdev);
-+		invalidate_bdev(sbi->journal_bdev, 0);
-+		ext3cow_blkdev_remove(sbi);
-+	}
-+	sb->s_fs_info = NULL;
-+	kfree(sbi);
-+	return;
-+}
-+
-+static struct kmem_cache *ext3cow_inode_cachep;
-+
-+/*
-+ * Called inside transaction, so use GFP_NOFS
-+ */
-+static struct inode *ext3cow_alloc_inode(struct super_block *sb)
-+{
-+	struct ext3cow_inode_info *ei;
-+
-+	ei = kmem_cache_alloc(ext3cow_inode_cachep, GFP_NOFS);
-+	if (!ei)
-+		return NULL;
-+#ifdef CONFIG_EXT3COW_FS_POSIX_ACL
-+	ei->i_acl = EXT3COW_ACL_NOT_CACHED;
-+	ei->i_default_acl = EXT3COW_ACL_NOT_CACHED;
-+#endif
-+	ei->i_block_alloc_info = NULL;
-+	ei->vfs_inode.i_version = 1;
-+	return &ei->vfs_inode;
-+}
-+
-+static void ext3cow_destroy_inode(struct inode *inode)
-+{
-+	kmem_cache_free(ext3cow_inode_cachep, EXT3COW_I(inode));
-+}
-+
-+static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags)
-+{
-+	struct ext3cow_inode_info *ei = (struct ext3cow_inode_info *) foo;
-+
-+	if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
-+	    SLAB_CTOR_CONSTRUCTOR) {
-+		INIT_LIST_HEAD(&ei->i_orphan);
-+#ifdef CONFIG_EXT3COW_FS_XATTR
-+		init_rwsem(&ei->xattr_sem);
-+#endif
-+		mutex_init(&ei->truncate_mutex);
-+		inode_init_once(&ei->vfs_inode);
-+	}
-+}
-+
-+static int init_inodecache(void)
-+{
-+	ext3cow_inode_cachep = kmem_cache_create("ext3cow_inode_cache",
-+					     sizeof(struct ext3cow_inode_info),
-+					     0, (SLAB_RECLAIM_ACCOUNT|
-+						SLAB_MEM_SPREAD),
-+					     init_once, NULL);
-+	if (ext3cow_inode_cachep == NULL)
-+		return -ENOMEM;
-+	return 0;
-+}
-+
-+static void destroy_inodecache(void)
-+{
-+	kmem_cache_destroy(ext3cow_inode_cachep);
-+}
-+
-+static void ext3cow_clear_inode(struct inode *inode)
-+{
-+	struct ext3cow_block_alloc_info *rsv = EXT3COW_I(inode)->i_block_alloc_info;
-+#ifdef CONFIG_EXT3COW_FS_POSIX_ACL
-+	if (EXT3COW_I(inode)->i_acl &&
-+			EXT3COW_I(inode)->i_acl != EXT3COW_ACL_NOT_CACHED) {
-+		posix_acl_release(EXT3COW_I(inode)->i_acl);
-+		EXT3COW_I(inode)->i_acl = EXT3COW_ACL_NOT_CACHED;
-+	}
-+	if (EXT3COW_I(inode)->i_default_acl &&
-+			EXT3COW_I(inode)->i_default_acl != EXT3COW_ACL_NOT_CACHED) {
-+		posix_acl_release(EXT3COW_I(inode)->i_default_acl);
-+		EXT3COW_I(inode)->i_default_acl = EXT3COW_ACL_NOT_CACHED;
-+	}
-+#endif
-+	ext3cow_discard_reservation(inode);
-+	EXT3COW_I(inode)->i_block_alloc_info = NULL;
-+	if (unlikely(rsv))
-+		kfree(rsv);
-+}
-+
-+static inline void ext3cow_show_quota_options(struct seq_file *seq, struct super_block *sb)
-+{
-+#if defined(CONFIG_QUOTA)
-+	struct ext3cow_sb_info *sbi = EXT3COW_SB(sb);
-+
-+	if (sbi->s_jquota_fmt)
-+		seq_printf(seq, ",jqfmt=%s",
-+		(sbi->s_jquota_fmt == QFMT_VFS_OLD) ? "vfsold": "vfsv0");
-+
-+	if (sbi->s_qf_names[USRQUOTA])
-+		seq_printf(seq, ",usrjquota=%s", sbi->s_qf_names[USRQUOTA]);
-+
-+	if (sbi->s_qf_names[GRPQUOTA])
-+		seq_printf(seq, ",grpjquota=%s", sbi->s_qf_names[GRPQUOTA]);
-+
-+	if (sbi->s_mount_opt & EXT3COW_MOUNT_USRQUOTA)
-+		seq_puts(seq, ",usrquota");
-+
-+	if (sbi->s_mount_opt & EXT3COW_MOUNT_GRPQUOTA)
-+		seq_puts(seq, ",grpquota");
-+#endif
-+}
-+
-+static int ext3cow_show_options(struct seq_file *seq, struct vfsmount *vfs)
-+{
-+	struct super_block *sb = vfs->mnt_sb;
-+
-+	if (test_opt(sb, DATA_FLAGS) == EXT3COW_MOUNT_JOURNAL_DATA)
-+		seq_puts(seq, ",data=journal");
-+	else if (test_opt(sb, DATA_FLAGS) == EXT3COW_MOUNT_ORDERED_DATA)
-+		seq_puts(seq, ",data=ordered");
-+	else if (test_opt(sb, DATA_FLAGS) == EXT3COW_MOUNT_WRITEBACK_DATA)
-+		seq_puts(seq, ",data=writeback");
-+
-+	ext3cow_show_quota_options(seq, sb);
-+
-+	return 0;
-+}
-+
-+
-+static struct dentry *ext3cow_get_dentry(struct super_block *sb, void *vobjp)
-+{
-+	__u32 *objp = vobjp;
-+	unsigned long ino = objp[0];
-+	__u32 generation = objp[1];
-+	struct inode *inode;
-+	struct dentry *result;
-+
-+	if (ino < EXT3COW_FIRST_INO(sb) && ino != EXT3COW_ROOT_INO)
-+		return ERR_PTR(-ESTALE);
-+	if (ino > le32_to_cpu(EXT3COW_SB(sb)->s_es->s_inodes_count))
-+		return ERR_PTR(-ESTALE);
-+
-+	/* iget isn't really right if the inode is currently unallocated!!
-+	 *
-+	 * ext3cow_read_inode will return a bad_inode if the inode had been
-+	 * deleted, so we should be safe.
-+	 *
-+	 * Currently we don't know the generation for parent directory, so
-+	 * a generation of 0 means "accept any"
-+	 */
-+	inode = iget(sb, ino);
-+	if (inode == NULL)
-+		return ERR_PTR(-ENOMEM);
-+	if (is_bad_inode(inode) ||
-+	    (generation && inode->i_generation != generation)) {
-+		iput(inode);
-+		return ERR_PTR(-ESTALE);
-+	}
-+	/* now to find a dentry.
-+	 * If possible, get a well-connected one
-+	 */
-+	result = d_alloc_anon(inode);
-+	if (!result) {
-+		iput(inode);
-+		return ERR_PTR(-ENOMEM);
-+	}
-+	return result;
-+}
-+
-+#ifdef CONFIG_QUOTA
-+#define QTYPE2NAME(t) ((t)==USRQUOTA?"user":"group")
-+#define QTYPE2MOPT(on, t) ((t)==USRQUOTA?((on)##USRJQUOTA):((on)##GRPJQUOTA))
-+
-+static int ext3cow_dquot_initialize(struct inode *inode, int type);
-+static int ext3cow_dquot_drop(struct inode *inode);
-+static int ext3cow_write_dquot(struct dquot *dquot);
-+static int ext3cow_acquire_dquot(struct dquot *dquot);
-+static int ext3cow_release_dquot(struct dquot *dquot);
-+static int ext3cow_mark_dquot_dirty(struct dquot *dquot);
-+static int ext3cow_write_info(struct super_block *sb, int type);
-+static int ext3cow_quota_on(struct super_block *sb, int type, int format_id, char *path);
-+static int ext3cow_quota_on_mount(struct super_block *sb, int type);
-+static ssize_t ext3cow_quota_read(struct super_block *sb, int type, char *data,
-+			       size_t len, loff_t off);
-+static ssize_t ext3cow_quota_write(struct super_block *sb, int type,
-+				const char *data, size_t len, loff_t off);
-+
-+static struct dquot_operations ext3cow_quota_operations = {
-+	.initialize	= ext3cow_dquot_initialize,
-+	.drop		= ext3cow_dquot_drop,
-+	.alloc_space	= dquot_alloc_space,
-+	.alloc_inode	= dquot_alloc_inode,
-+	.free_space	= dquot_free_space,
-+	.free_inode	= dquot_free_inode,
-+	.transfer	= dquot_transfer,
-+	.write_dquot	= ext3cow_write_dquot,
-+	.acquire_dquot	= ext3cow_acquire_dquot,
-+	.release_dquot	= ext3cow_release_dquot,
-+	.mark_dirty	= ext3cow_mark_dquot_dirty,
-+	.write_info	= ext3cow_write_info
-+};
-+
-+static struct quotactl_ops ext3cow_qctl_operations = {
-+	.quota_on	= ext3cow_quota_on,
-+	.quota_off	= vfs_quota_off,
-+	.quota_sync	= vfs_quota_sync,
-+	.get_info	= vfs_get_dqinfo,
-+	.set_info	= vfs_set_dqinfo,
-+	.get_dqblk	= vfs_get_dqblk,
-+	.set_dqblk	= vfs_set_dqblk
-+};
-+#endif
-+
-+static struct super_operations ext3cow_sops = {
-+	.alloc_inode	= ext3cow_alloc_inode,
-+	.destroy_inode	= ext3cow_destroy_inode,
-+	.read_inode	= ext3cow_read_inode,
-+	.write_inode	= ext3cow_write_inode,
-+	.dirty_inode	= ext3cow_dirty_inode,
-+	.delete_inode	= ext3cow_delete_inode,
-+	.put_super	= ext3cow_put_super,
-+	.write_super	= ext3cow_write_super,
-+	.sync_fs	= ext3cow_sync_fs,
-+	.write_super_lockfs = ext3cow_write_super_lockfs,
-+	.unlockfs	= ext3cow_unlockfs,
-+	.statfs		= ext3cow_statfs,
-+	.remount_fs	= ext3cow_remount,
-+	.clear_inode	= ext3cow_clear_inode,
-+	.show_options	= ext3cow_show_options,
-+#ifdef CONFIG_QUOTA
-+	.quota_read	= ext3cow_quota_read,
-+	.quota_write	= ext3cow_quota_write,
-+#endif
-+};
-+
-+static struct export_operations ext3cow_export_ops = {
-+	.get_parent = ext3cow_get_parent,
-+	.get_dentry = ext3cow_get_dentry,
-+};
-+
-+enum {
-+	Opt_bsd_df, Opt_minix_df, Opt_grpid, Opt_nogrpid,
-+	Opt_resgid, Opt_resuid, Opt_sb, Opt_err_cont, Opt_err_panic, Opt_err_ro,
-+	Opt_nouid32, Opt_nocheck, Opt_debug, Opt_oldalloc, Opt_orlov,
-+	Opt_user_xattr, Opt_nouser_xattr, Opt_acl, Opt_noacl,
-+	Opt_reservation, Opt_noreservation, Opt_noload, Opt_nobh, Opt_bh,
-+	Opt_commit, Opt_journal_update, Opt_journal_inum, Opt_journal_dev,
-+	Opt_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback,
-+	Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota,
-+	Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_quota, Opt_noquota,
-+	Opt_ignore, Opt_barrier, Opt_err, Opt_resize, Opt_usrquota,
-+	Opt_grpquota
-+};
-+
-+static match_table_t tokens = {
-+	{Opt_bsd_df, "bsddf"},
-+	{Opt_minix_df, "minixdf"},
-+	{Opt_grpid, "grpid"},
-+	{Opt_grpid, "bsdgroups"},
-+	{Opt_nogrpid, "nogrpid"},
-+	{Opt_nogrpid, "sysvgroups"},
-+	{Opt_resgid, "resgid=%u"},
-+	{Opt_resuid, "resuid=%u"},
-+	{Opt_sb, "sb=%u"},
-+	{Opt_err_cont, "errors=continue"},
-+	{Opt_err_panic, "errors=panic"},
-+	{Opt_err_ro, "errors=remount-ro"},
-+	{Opt_nouid32, "nouid32"},
-+	{Opt_nocheck, "nocheck"},
-+	{Opt_nocheck, "check=none"},
-+	{Opt_debug, "debug"},
-+	{Opt_oldalloc, "oldalloc"},
-+	{Opt_orlov, "orlov"},
-+	{Opt_user_xattr, "user_xattr"},
-+	{Opt_nouser_xattr, "nouser_xattr"},
-+	{Opt_acl, "acl"},
-+	{Opt_noacl, "noacl"},
-+	{Opt_reservation, "reservation"},
-+	{Opt_noreservation, "noreservation"},
-+	{Opt_noload, "noload"},
-+	{Opt_nobh, "nobh"},
-+	{Opt_bh, "bh"},
-+	{Opt_commit, "commit=%u"},
-+	{Opt_journal_update, "journal=update"},
-+	{Opt_journal_inum, "journal=%u"},
-+	{Opt_journal_dev, "journal_dev=%u"},
-+	{Opt_abort, "abort"},
-+	{Opt_data_journal, "data=journal"},
-+	{Opt_data_ordered, "data=ordered"},
-+	{Opt_data_writeback, "data=writeback"},
-+	{Opt_offusrjquota, "usrjquota="},
-+	{Opt_usrjquota, "usrjquota=%s"},
-+	{Opt_offgrpjquota, "grpjquota="},
-+	{Opt_grpjquota, "grpjquota=%s"},
-+	{Opt_jqfmt_vfsold, "jqfmt=vfsold"},
-+	{Opt_jqfmt_vfsv0, "jqfmt=vfsv0"},
-+	{Opt_grpquota, "grpquota"},
-+	{Opt_noquota, "noquota"},
-+	{Opt_quota, "quota"},
-+	{Opt_usrquota, "usrquota"},
-+	{Opt_barrier, "barrier=%u"},
-+	{Opt_err, NULL},
-+	{Opt_resize, "resize"},
-+};
-+
-+static ext3cow_fsblk_t get_sb_block(void **data)
-+{
-+	ext3cow_fsblk_t	sb_block;
-+	char		*options = (char *) *data;
-+
-+	if (!options || strncmp(options, "sb=", 3) != 0)
-+		return 1;	/* Default location */
-+	options += 3;
-+	/*todo: use simple_strtoll with >32bit ext3cow */
-+	sb_block = simple_strtoul(options, &options, 0);
-+	if (*options && *options != ',') {
-+		printk("EXT3COW-fs: Invalid sb specification: %s\n",
-+		       (char *) *data);
-+		return 1;
-+	}
-+	if (*options == ',')
-+		options++;
-+	*data = (void *) options;
-+	return sb_block;
-+}
-+
-+static int parse_options (char *options, struct super_block *sb,
-+			  unsigned int *inum, unsigned long *journal_devnum,
-+			  ext3cow_fsblk_t *n_blocks_count, int is_remount)
-+{
-+	struct ext3cow_sb_info *sbi = EXT3COW_SB(sb);
-+	char * p;
-+	substring_t args[MAX_OPT_ARGS];
-+	int data_opt = 0;
-+	int option;
-+#ifdef CONFIG_QUOTA
-+	int qtype;
-+	char *qname;
-+#endif
-+
-+	if (!options)
-+		return 1;
-+
-+	while ((p = strsep (&options, ",")) != NULL) {
-+		int token;
-+		if (!*p)
-+			continue;
-+
-+		token = match_token(p, tokens, args);
-+		switch (token) {
-+		case Opt_bsd_df:
-+			clear_opt (sbi->s_mount_opt, MINIX_DF);
-+			break;
-+		case Opt_minix_df:
-+			set_opt (sbi->s_mount_opt, MINIX_DF);
-+			break;
-+		case Opt_grpid:
-+			set_opt (sbi->s_mount_opt, GRPID);
-+			break;
-+		case Opt_nogrpid:
-+			clear_opt (sbi->s_mount_opt, GRPID);
-+			break;
-+		case Opt_resuid:
-+			if (match_int(&args[0], &option))
-+				return 0;
-+			sbi->s_resuid = option;
-+			break;
-+		case Opt_resgid:
-+			if (match_int(&args[0], &option))
-+				return 0;
-+			sbi->s_resgid = option;
-+			break;
-+		case Opt_sb:
-+			/* handled by get_sb_block() instead of here */
-+			/* *sb_block = match_int(&args[0]); */
-+			break;
-+		case Opt_err_panic:
-+			clear_opt (sbi->s_mount_opt, ERRORS_CONT);
-+			clear_opt (sbi->s_mount_opt, ERRORS_RO);
-+			set_opt (sbi->s_mount_opt, ERRORS_PANIC);
-+			break;
-+		case Opt_err_ro:
-+			clear_opt (sbi->s_mount_opt, ERRORS_CONT);
-+			clear_opt (sbi->s_mount_opt, ERRORS_PANIC);
-+			set_opt (sbi->s_mount_opt, ERRORS_RO);
-+			break;
-+		case Opt_err_cont:
-+			clear_opt (sbi->s_mount_opt, ERRORS_RO);
-+			clear_opt (sbi->s_mount_opt, ERRORS_PANIC);
-+			set_opt (sbi->s_mount_opt, ERRORS_CONT);
-+			break;
-+		case Opt_nouid32:
-+			set_opt (sbi->s_mount_opt, NO_UID32);
-+			break;
-+		case Opt_nocheck:
-+			clear_opt (sbi->s_mount_opt, CHECK);
-+			break;
-+		case Opt_debug:
-+			set_opt (sbi->s_mount_opt, DEBUG);
-+			break;
-+		case Opt_oldalloc:
-+			set_opt (sbi->s_mount_opt, OLDALLOC);
-+			break;
-+		case Opt_orlov:
-+			clear_opt (sbi->s_mount_opt, OLDALLOC);
-+			break;
-+#ifdef CONFIG_EXT3COW_FS_XATTR
-+		case Opt_user_xattr:
-+			set_opt (sbi->s_mount_opt, XATTR_USER);
-+			break;
-+		case Opt_nouser_xattr:
-+			clear_opt (sbi->s_mount_opt, XATTR_USER);
-+			break;
-+#else
-+		case Opt_user_xattr:
-+		case Opt_nouser_xattr:
-+			printk("EXT3COW (no)user_xattr options not supported\n");
-+			break;
-+#endif
-+#ifdef CONFIG_EXT3COW_FS_POSIX_ACL
-+		case Opt_acl:
-+			set_opt(sbi->s_mount_opt, POSIX_ACL);
-+			break;
-+		case Opt_noacl:
-+			clear_opt(sbi->s_mount_opt, POSIX_ACL);
-+			break;
-+#else
-+		case Opt_acl:
-+		case Opt_noacl:
-+			printk("EXT3COW (no)acl options not supported\n");
-+			break;
-+#endif
-+		case Opt_reservation:
-+			set_opt(sbi->s_mount_opt, RESERVATION);
-+			break;
-+		case Opt_noreservation:
-+			clear_opt(sbi->s_mount_opt, RESERVATION);
-+			break;
-+		case Opt_journal_update:
-+			/* @@@ FIXME */
-+			/* Eventually we will want to be able to create
-+			   a journal file here.  For now, only allow the
-+			   user to specify an existing inode to be the
-+			   journal file. */
-+			if (is_remount) {
-+				printk(KERN_ERR "EXT3COW-fs: cannot specify "
-+				       "journal on remount\n");
-+				return 0;
-+			}
-+			set_opt (sbi->s_mount_opt, UPDATE_JOURNAL);
-+			break;
-+		case Opt_journal_inum:
-+			if (is_remount) {
-+				printk(KERN_ERR "EXT3COW-fs: cannot specify "
-+				       "journal on remount\n");
-+				return 0;
-+			}
-+			if (match_int(&args[0], &option))
-+				return 0;
-+			*inum = option;
-+			break;
-+		case Opt_journal_dev:
-+			if (is_remount) {
-+				printk(KERN_ERR "EXT3COW-fs: cannot specify "
-+				       "journal on remount\n");
-+				return 0;
-+			}
-+			if (match_int(&args[0], &option))
-+				return 0;
-+			*journal_devnum = option;
-+			break;
-+		case Opt_noload:
-+			set_opt (sbi->s_mount_opt, NOLOAD);
-+			break;
-+		case Opt_commit:
-+			if (match_int(&args[0], &option))
-+				return 0;
-+			if (option < 0)
-+				return 0;
-+			if (option == 0)
-+				option = JBD_DEFAULT_MAX_COMMIT_AGE;
-+			sbi->s_commit_interval = HZ * option;
-+			break;
-+		case Opt_data_journal:
-+			data_opt = EXT3COW_MOUNT_JOURNAL_DATA;
-+			goto datacheck;
-+		case Opt_data_ordered:
-+			data_opt = EXT3COW_MOUNT_ORDERED_DATA;
-+			goto datacheck;
-+		case Opt_data_writeback:
-+			data_opt = EXT3COW_MOUNT_WRITEBACK_DATA;
-+		datacheck:
-+			if (is_remount) {
-+				if ((sbi->s_mount_opt & EXT3COW_MOUNT_DATA_FLAGS)
-+						!= data_opt) {
-+					printk(KERN_ERR
-+						"EXT3COW-fs: cannot change data "
-+						"mode on remount\n");
-+					return 0;
-+				}
-+			} else {
-+				sbi->s_mount_opt &= ~EXT3COW_MOUNT_DATA_FLAGS;
-+				sbi->s_mount_opt |= data_opt;
-+			}
-+			break;
-+#ifdef CONFIG_QUOTA
-+		case Opt_usrjquota:
-+			qtype = USRQUOTA;
-+			goto set_qf_name;
-+		case Opt_grpjquota:
-+			qtype = GRPQUOTA;
-+set_qf_name:
-+			if (sb_any_quota_enabled(sb)) {
-+				printk(KERN_ERR
-+					"EXT3COW-fs: Cannot change journalled "
-+					"quota options when quota turned on.\n");
-+				return 0;
-+			}
-+			qname = match_strdup(&args[0]);
-+			if (!qname) {
-+				printk(KERN_ERR
-+					"EXT3COW-fs: not enough memory for "
-+					"storing quotafile name.\n");
-+				return 0;
-+			}
-+			if (sbi->s_qf_names[qtype] &&
-+			    strcmp(sbi->s_qf_names[qtype], qname)) {
-+				printk(KERN_ERR
-+					"EXT3COW-fs: %s quota file already "
-+					"specified.\n", QTYPE2NAME(qtype));
-+				kfree(qname);
-+				return 0;
-+			}
-+			sbi->s_qf_names[qtype] = qname;
-+			if (strchr(sbi->s_qf_names[qtype], '/')) {
-+				printk(KERN_ERR
-+					"EXT3COW-fs: quotafile must be on "
-+					"filesystem root.\n");
-+				kfree(sbi->s_qf_names[qtype]);
-+				sbi->s_qf_names[qtype] = NULL;
-+				return 0;
-+			}
-+			set_opt(sbi->s_mount_opt, QUOTA);
-+			break;
-+		case Opt_offusrjquota:
-+			qtype = USRQUOTA;
-+			goto clear_qf_name;
-+		case Opt_offgrpjquota:
-+			qtype = GRPQUOTA;
-+clear_qf_name:
-+			if (sb_any_quota_enabled(sb)) {
-+				printk(KERN_ERR "EXT3COW-fs: Cannot change "
-+					"journalled quota options when "
-+					"quota turned on.\n");
-+				return 0;
-+			}
-+			/*
-+			 * The space will be released later when all options
-+			 * are confirmed to be correct
-+			 */
-+			sbi->s_qf_names[qtype] = NULL;
-+			break;
-+		case Opt_jqfmt_vfsold:
-+			sbi->s_jquota_fmt = QFMT_VFS_OLD;
-+			break;
-+		case Opt_jqfmt_vfsv0:
-+			sbi->s_jquota_fmt = QFMT_VFS_V0;
-+			break;
-+		case Opt_quota:
-+		case Opt_usrquota:
-+			set_opt(sbi->s_mount_opt, QUOTA);
-+			set_opt(sbi->s_mount_opt, USRQUOTA);
-+			break;
-+		case Opt_grpquota:
-+			set_opt(sbi->s_mount_opt, QUOTA);
-+			set_opt(sbi->s_mount_opt, GRPQUOTA);
-+			break;
-+		case Opt_noquota:
-+			if (sb_any_quota_enabled(sb)) {
-+				printk(KERN_ERR "EXT3COW-fs: Cannot change quota "
-+					"options when quota turned on.\n");
-+				return 0;
-+			}
-+			clear_opt(sbi->s_mount_opt, QUOTA);
-+			clear_opt(sbi->s_mount_opt, USRQUOTA);
-+			clear_opt(sbi->s_mount_opt, GRPQUOTA);
-+			break;
-+#else
-+		case Opt_quota:
-+		case Opt_usrquota:
-+		case Opt_grpquota:
-+		case Opt_usrjquota:
-+		case Opt_grpjquota:
-+		case Opt_offusrjquota:
-+		case Opt_offgrpjquota:
-+		case Opt_jqfmt_vfsold:
-+		case Opt_jqfmt_vfsv0:
-+			printk(KERN_ERR
-+				"EXT3COW-fs: journalled quota options not "
-+				"supported.\n");
-+			break;
-+		case Opt_noquota:
-+			break;
-+#endif
-+		case Opt_abort:
-+			set_opt(sbi->s_mount_opt, ABORT);
-+			break;
-+		case Opt_barrier:
-+			if (match_int(&args[0], &option))
-+				return 0;
-+			if (option)
-+				set_opt(sbi->s_mount_opt, BARRIER);
-+			else
-+				clear_opt(sbi->s_mount_opt, BARRIER);
-+			break;
-+		case Opt_ignore:
-+			break;
-+		case Opt_resize:
-+			if (!is_remount) {
-+				printk("EXT3COW-fs: resize option only available "
-+					"for remount\n");
-+				return 0;
-+			}
-+			if (match_int(&args[0], &option) != 0)
-+				return 0;
-+			*n_blocks_count = option;
-+			break;
-+		case Opt_nobh:
-+			set_opt(sbi->s_mount_opt, NOBH);
-+			break;
-+		case Opt_bh:
-+			clear_opt(sbi->s_mount_opt, NOBH);
-+			break;
-+		default:
-+			printk (KERN_ERR
-+				"EXT3COW-fs: Unrecognized mount option \"%s\" "
-+				"or missing value\n", p);
-+			return 0;
-+		}
-+	}
-+#ifdef CONFIG_QUOTA
-+	if (sbi->s_qf_names[USRQUOTA] || sbi->s_qf_names[GRPQUOTA]) {
-+		if ((sbi->s_mount_opt & EXT3COW_MOUNT_USRQUOTA) &&
-+		     sbi->s_qf_names[USRQUOTA])
-+			clear_opt(sbi->s_mount_opt, USRQUOTA);
-+
-+		if ((sbi->s_mount_opt & EXT3COW_MOUNT_GRPQUOTA) &&
-+		     sbi->s_qf_names[GRPQUOTA])
-+			clear_opt(sbi->s_mount_opt, GRPQUOTA);
-+
-+		if ((sbi->s_qf_names[USRQUOTA] &&
-+				(sbi->s_mount_opt & EXT3COW_MOUNT_GRPQUOTA)) ||
-+		    (sbi->s_qf_names[GRPQUOTA] &&
-+				(sbi->s_mount_opt & EXT3COW_MOUNT_USRQUOTA))) {
-+			printk(KERN_ERR "EXT3COW-fs: old and new quota "
-+					"format mixing.\n");
-+			return 0;
-+		}
-+
-+		if (!sbi->s_jquota_fmt) {
-+			printk(KERN_ERR "EXT3COW-fs: journalled quota format "
-+					"not specified.\n");
-+			return 0;
-+		}
-+	} else {
-+		if (sbi->s_jquota_fmt) {
-+			printk(KERN_ERR "EXT3COW-fs: journalled quota format "
-+					"specified with no journalling "
-+					"enabled.\n");
-+			return 0;
-+		}
-+	}
-+#endif
-+	return 1;
-+}
-+
-+static int ext3cow_setup_super(struct super_block *sb, struct ext3cow_super_block *es,
-+			    int read_only)
-+{
-+	struct ext3cow_sb_info *sbi = EXT3COW_SB(sb);
-+	int res = 0;
-+
-+	if (le32_to_cpu(es->s_rev_level) > EXT3COW_MAX_SUPP_REV) {
-+		printk (KERN_ERR "EXT3COW-fs warning: revision level too high, "
-+			"forcing read-only mode\n");
-+		res = MS_RDONLY;
-+	}
-+	if (read_only)
-+		return res;
-+	if (!(sbi->s_mount_state & EXT3COW_VALID_FS))
-+		printk (KERN_WARNING "EXT3COW-fs warning: mounting unchecked fs, "
-+			"running e2fsck is recommended\n");
-+	else if ((sbi->s_mount_state & EXT3COW_ERROR_FS))
-+		printk (KERN_WARNING
-+			"EXT3COW-fs warning: mounting fs with errors, "
-+			"running e2fsck is recommended\n");
-+	else if ((__s16) le16_to_cpu(es->s_max_mnt_count) >= 0 &&
-+		 le16_to_cpu(es->s_mnt_count) >=
-+		 (unsigned short) (__s16) le16_to_cpu(es->s_max_mnt_count))
-+		printk (KERN_WARNING
-+			"EXT3COW-fs warning: maximal mount count reached, "
-+			"running e2fsck is recommended\n");
-+	else if (le32_to_cpu(es->s_checkinterval) &&
-+		(le32_to_cpu(es->s_lastcheck) +
-+			le32_to_cpu(es->s_checkinterval) <= get_seconds()))
-+		printk (KERN_WARNING
-+			"EXT3COW-fs warning: checktime reached, "
-+			"running e2fsck is recommended\n");
-+#if 0
-+		/* @@@ We _will_ want to clear the valid bit if we find
-+                   inconsistencies, to force a fsck at reboot.  But for
-+                   a plain journaled filesystem we can keep it set as
-+                   valid forever! :) */
-+	es->s_state = cpu_to_le16(le16_to_cpu(es->s_state) & ~EXT3COW_VALID_FS);
-+#endif
-+	if (!(__s16) le16_to_cpu(es->s_max_mnt_count))
-+		es->s_max_mnt_count = cpu_to_le16(EXT3COW_DFL_MAX_MNT_COUNT);
-+	es->s_mnt_count=cpu_to_le16(le16_to_cpu(es->s_mnt_count) + 1);
-+	es->s_mtime = cpu_to_le32(get_seconds());
-+	ext3cow_update_dynamic_rev(sb);
-+	EXT3COW_SET_INCOMPAT_FEATURE(sb, EXT3COW_FEATURE_INCOMPAT_RECOVER);
-+
-+	ext3cow_commit_super(sb, es, 1);
-+	if (test_opt(sb, DEBUG))
-+		printk(KERN_INFO "[EXT3COW FS bs=%lu, gc=%lu, "
-+				"bpg=%lu, ipg=%lu, mo=%04lx]\n",
-+			sb->s_blocksize,
-+			sbi->s_groups_count,
-+			EXT3COW_BLOCKS_PER_GROUP(sb),
-+			EXT3COW_INODES_PER_GROUP(sb),
-+			sbi->s_mount_opt);
-+
-+	printk(KERN_INFO "EXT3COW FS on %s, ", sb->s_id);
-+	if (EXT3COW_SB(sb)->s_journal->j_inode == NULL) {
-+		char b[BDEVNAME_SIZE];
-+
-+		printk("external journal on %s\n",
-+			bdevname(EXT3COW_SB(sb)->s_journal->j_dev, b));
-+	} else {
-+		printk("internal journal\n");
-+	}
-+	return res;
-+}
-+
-+/* Called at mount-time, super-block is locked */
-+static int ext3cow_check_descriptors (struct super_block * sb)
-+{
-+	struct ext3cow_sb_info *sbi = EXT3COW_SB(sb);
-+	ext3cow_fsblk_t first_block = le32_to_cpu(sbi->s_es->s_first_data_block);
-+	ext3cow_fsblk_t last_block;
-+	struct ext3cow_group_desc * gdp = NULL;
-+	int desc_block = 0;
-+	int i;
-+
-+	ext3cow_debug ("Checking group descriptors");
-+
-+	for (i = 0; i < sbi->s_groups_count; i++)
-+	{
-+		if (i == sbi->s_groups_count - 1)
-+			last_block = le32_to_cpu(sbi->s_es->s_blocks_count) - 1;
-+		else
-+			last_block = first_block +
-+				(EXT3COW_BLOCKS_PER_GROUP(sb) - 1);
-+
-+		if ((i % EXT3COW_DESC_PER_BLOCK(sb)) == 0)
-+			gdp = (struct ext3cow_group_desc *)
-+					sbi->s_group_desc[desc_block++]->b_data;
-+		if (le32_to_cpu(gdp->bg_block_bitmap) < first_block ||
-+		    le32_to_cpu(gdp->bg_block_bitmap) > last_block)
-+		{
-+			ext3cow_error (sb, "ext3cow_check_descriptors",
-+				    "Block bitmap for group %d"
-+				    " not in group (block %lu)!",
-+				    i, (unsigned long)
-+					le32_to_cpu(gdp->bg_block_bitmap));
-+			return 0;
-+		}
-+		if (le32_to_cpu(gdp->bg_inode_bitmap) < first_block ||
-+		    le32_to_cpu(gdp->bg_inode_bitmap) > last_block)
-+		{
-+			ext3cow_error (sb, "ext3cow_check_descriptors",
-+				    "Inode bitmap for group %d"
-+				    " not in group (block %lu)!",
-+				    i, (unsigned long)
-+					le32_to_cpu(gdp->bg_inode_bitmap));
-+			return 0;
-+		}
-+		if (le32_to_cpu(gdp->bg_inode_table) < first_block ||
-+		    le32_to_cpu(gdp->bg_inode_table) + sbi->s_itb_per_group >
-+		    last_block)
-+		{
-+			ext3cow_error (sb, "ext3cow_check_descriptors",
-+				    "Inode table for group %d"
-+				    " not in group (block %lu)!",
-+				    i, (unsigned long)
-+					le32_to_cpu(gdp->bg_inode_table));
-+			return 0;
-+		}
-+		first_block += EXT3COW_BLOCKS_PER_GROUP(sb);
-+		gdp++;
-+	}
-+
-+	sbi->s_es->s_free_blocks_count=cpu_to_le32(ext3cow_count_free_blocks(sb));
-+	sbi->s_es->s_free_inodes_count=cpu_to_le32(ext3cow_count_free_inodes(sb));
-+	return 1;
-+}
-+
-+
-+/* ext3cow_orphan_cleanup() walks a singly-linked list of inodes (starting at
-+ * the superblock) which were deleted from all directories, but held open by
-+ * a process at the time of a crash.  We walk the list and try to delete these
-+ * inodes at recovery time (only with a read-write filesystem).
-+ *
-+ * In order to keep the orphan inode chain consistent during traversal (in
-+ * case of crash during recovery), we link each inode into the superblock
-+ * orphan list_head and handle it the same way as an inode deletion during
-+ * normal operation (which journals the operations for us).
-+ *
-+ * We only do an iget() and an iput() on each inode, which is very safe if we
-+ * accidentally point at an in-use or already deleted inode.  The worst that
-+ * can happen in this case is that we get a "bit already cleared" message from
-+ * ext3cow_free_inode().  The only reason we would point at a wrong inode is if
-+ * e2fsck was run on this filesystem, and it must have already done the orphan
-+ * inode cleanup for us, so we can safely abort without any further action.
-+ */
-+static void ext3cow_orphan_cleanup (struct super_block * sb,
-+				 struct ext3cow_super_block * es)
-+{
-+	unsigned int s_flags = sb->s_flags;
-+	int nr_orphans = 0, nr_truncates = 0;
-+#ifdef CONFIG_QUOTA
-+	int i;
-+#endif
-+	if (!es->s_last_orphan) {
-+		jbd_debug(4, "no orphan inodes to clean up\n");
-+		return;
-+	}
-+
-+	if (bdev_read_only(sb->s_bdev)) {
-+		printk(KERN_ERR "EXT3COW-fs: write access "
-+			"unavailable, skipping orphan cleanup.\n");
-+		return;
-+	}
-+
-+	if (EXT3COW_SB(sb)->s_mount_state & EXT3COW_ERROR_FS) {
-+		if (es->s_last_orphan)
-+			jbd_debug(1, "Errors on filesystem, "
-+				  "clearing orphan list.\n");
-+		es->s_last_orphan = 0;
-+		jbd_debug(1, "Skipping orphan recovery on fs with errors.\n");
-+		return;
-+	}
-+
-+	if (s_flags & MS_RDONLY) {
-+		printk(KERN_INFO "EXT3COW-fs: %s: orphan cleanup on readonly fs\n",
-+		       sb->s_id);
-+		sb->s_flags &= ~MS_RDONLY;
-+	}
-+#ifdef CONFIG_QUOTA
-+	/* Needed for iput() to work correctly and not trash data */
-+	sb->s_flags |= MS_ACTIVE;
-+	/* Turn on quotas so that they are updated correctly */
-+	for (i = 0; i < MAXQUOTAS; i++) {
-+		if (EXT3COW_SB(sb)->s_qf_names[i]) {
-+			int ret = ext3cow_quota_on_mount(sb, i);
-+			if (ret < 0)
-+				printk(KERN_ERR
-+					"EXT3COW-fs: Cannot turn on journalled "
-+					"quota: error %d\n", ret);
-+		}
-+	}
-+#endif
-+
-+	while (es->s_last_orphan) {
-+		struct inode *inode;
-+
-+		if (!(inode =
-+		      ext3cow_orphan_get(sb, le32_to_cpu(es->s_last_orphan)))) {
-+			es->s_last_orphan = 0;
-+			break;
-+		}
-+
-+		list_add(&EXT3COW_I(inode)->i_orphan, &EXT3COW_SB(sb)->s_orphan);
-+		DQUOT_INIT(inode);
-+		if (inode->i_nlink) {
-+			printk(KERN_DEBUG
-+				"%s: truncating inode %lu to %Ld bytes\n",
-+				__FUNCTION__, inode->i_ino, inode->i_size);
-+			jbd_debug(2, "truncating inode %lu to %Ld bytes\n",
-+				  inode->i_ino, inode->i_size);
-+			ext3cow_truncate(inode);
-+			nr_truncates++;
-+		} else {
-+			printk(KERN_DEBUG
-+				"%s: deleting unreferenced inode %lu\n",
-+				__FUNCTION__, inode->i_ino);
-+			jbd_debug(2, "deleting unreferenced inode %lu\n",
-+				  inode->i_ino);
-+			nr_orphans++;
-+		}
-+		iput(inode);  /* The delete magic happens here! */
-+	}
-+
-+#define PLURAL(x) (x), ((x)==1) ? "" : "s"
-+
-+	if (nr_orphans)
-+		printk(KERN_INFO "EXT3COW-fs: %s: %d orphan inode%s deleted\n",
-+		       sb->s_id, PLURAL(nr_orphans));
-+	if (nr_truncates)
-+		printk(KERN_INFO "EXT3COW-fs: %s: %d truncate%s cleaned up\n",
-+		       sb->s_id, PLURAL(nr_truncates));
-+#ifdef CONFIG_QUOTA
-+	/* Turn quotas off */
-+	for (i = 0; i < MAXQUOTAS; i++) {
-+		if (sb_dqopt(sb)->files[i])
-+			vfs_quota_off(sb, i);
-+	}
-+#endif
-+	sb->s_flags = s_flags; /* Restore MS_RDONLY status */
-+}
-+
-+/*
-+ * Maximal file size.  There is a direct, and {,double-,triple-}indirect
-+ * block limit, and also a limit of (2^32 - 1) 512-byte sectors in i_blocks.
-+ * We need to be 1 filesystem block less than the 2^32 sector limit.
-+ */
-+static loff_t ext3cow_max_size(int bits)
-+{
-+	loff_t res = EXT3COW_NDIR_BLOCKS;
-+	/* This constant is calculated to be the largest file size for a
-+	 * dense, 4k-blocksize file such that the total number of
-+	 * sectors in the file, including data and all indirect blocks,
-+	 * does not exceed 2^32. */
-+	const loff_t upper_limit = 0x1ff7fffd000LL;
-+
-+	res += 1LL << (bits-2);
-+	res += 1LL << (2*(bits-2));
-+	res += 1LL << (3*(bits-2));
-+	res <<= bits;
-+	if (res > upper_limit)
-+		res = upper_limit;
-+	return res;
-+}
-+
-+static ext3cow_fsblk_t descriptor_loc(struct super_block *sb,
-+				    ext3cow_fsblk_t logic_sb_block,
-+				    int nr)
-+{
-+	struct ext3cow_sb_info *sbi = EXT3COW_SB(sb);
-+	unsigned long bg, first_meta_bg;
-+	int has_super = 0;
-+
-+	first_meta_bg = le32_to_cpu(sbi->s_es->s_first_meta_bg);
-+
-+	if (!EXT3COW_HAS_INCOMPAT_FEATURE(sb, EXT3COW_FEATURE_INCOMPAT_META_BG) ||
-+	    nr < first_meta_bg)
-+		return (logic_sb_block + nr + 1);
-+	bg = sbi->s_desc_per_block * nr;
-+	if (ext3cow_bg_has_super(sb, bg))
-+		has_super = 1;
-+	return (has_super + ext3cow_group_first_block_no(sb, bg));
-+}
-+
-+
-+static int ext3cow_fill_super (struct super_block *sb, void *data, int silent)
-+{
-+	struct buffer_head * bh;
-+	struct ext3cow_super_block *es = NULL;
-+	struct ext3cow_sb_info *sbi;
-+	ext3cow_fsblk_t block;
-+	ext3cow_fsblk_t sb_block = get_sb_block(&data);
-+	ext3cow_fsblk_t logic_sb_block;
-+	unsigned long offset = 0;
-+	unsigned int journal_inum = 0;
-+	unsigned long journal_devnum = 0;
-+	unsigned long def_mount_opts;
-+	struct inode *root;
-+	int blocksize;
-+	int hblock;
-+	int db_count;
-+	int i;
-+	int needs_recovery;
-+	__le32 features;
-+
-+	sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
-+	if (!sbi)
-+		return -ENOMEM;
-+	sb->s_fs_info = sbi;
-+	sbi->s_mount_opt = 0;
-+	sbi->s_resuid = EXT3COW_DEF_RESUID;
-+	sbi->s_resgid = EXT3COW_DEF_RESGID;
-+
-+	unlock_kernel();
-+
-+	blocksize = sb_min_blocksize(sb, EXT3COW_MIN_BLOCK_SIZE);
-+	if (!blocksize) {
-+		printk(KERN_ERR "EXT3COW-fs: unable to set blocksize\n");
-+		goto out_fail;
-+	}
-+
-+	/*
-+	 * The ext3cow superblock will not be buffer aligned for other than 1kB
-+	 * block sizes.  We need to calculate the offset from buffer start.
-+	 */
-+	if (blocksize != EXT3COW_MIN_BLOCK_SIZE) {
-+		logic_sb_block = (sb_block * EXT3COW_MIN_BLOCK_SIZE) / blocksize;
-+		offset = (sb_block * EXT3COW_MIN_BLOCK_SIZE) % blocksize;
-+	} else {
-+		logic_sb_block = sb_block;
-+	}
-+
-+	if (!(bh = sb_bread(sb, logic_sb_block))) {
-+		printk (KERN_ERR "EXT3COW-fs: unable to read superblock\n");
-+		goto out_fail;
-+	}
-+	/*
-+	 * Note: s_es must be initialized as soon as possible because
-+	 *       some ext3cow macro-instructions depend on its value
-+	 */
-+	es = (struct ext3cow_super_block *) (((char *)bh->b_data) + offset);
-+	sbi->s_es = es;
-+	sb->s_magic = le16_to_cpu(es->s_magic);
-+	if (sb->s_magic != EXT3COW_SUPER_MAGIC)
-+		goto cantfind_ext3cow;
-+
-+	/* Set defaults before we parse the mount options */
-+	def_mount_opts = le32_to_cpu(es->s_default_mount_opts);
-+	if (def_mount_opts & EXT3COW_DEFM_DEBUG)
-+		set_opt(sbi->s_mount_opt, DEBUG);
-+	if (def_mount_opts & EXT3COW_DEFM_BSDGROUPS)
-+		set_opt(sbi->s_mount_opt, GRPID);
-+	if (def_mount_opts & EXT3COW_DEFM_UID16)
-+		set_opt(sbi->s_mount_opt, NO_UID32);
-+#ifdef CONFIG_EXT3COW_FS_XATTR
-+	if (def_mount_opts & EXT3COW_DEFM_XATTR_USER)
-+		set_opt(sbi->s_mount_opt, XATTR_USER);
-+#endif
-+#ifdef CONFIG_EXT3COW_FS_POSIX_ACL
-+	if (def_mount_opts & EXT3COW_DEFM_ACL)
-+		set_opt(sbi->s_mount_opt, POSIX_ACL);
-+#endif
-+	if ((def_mount_opts & EXT3COW_DEFM_JMODE) == EXT3COW_DEFM_JMODE_DATA)
-+		sbi->s_mount_opt |= EXT3COW_MOUNT_JOURNAL_DATA;
-+	else if ((def_mount_opts & EXT3COW_DEFM_JMODE) == EXT3COW_DEFM_JMODE_ORDERED)
-+		sbi->s_mount_opt |= EXT3COW_MOUNT_ORDERED_DATA;
-+	else if ((def_mount_opts & EXT3COW_DEFM_JMODE) == EXT3COW_DEFM_JMODE_WBACK)
-+		sbi->s_mount_opt |= EXT3COW_MOUNT_WRITEBACK_DATA;
-+
-+	if (le16_to_cpu(sbi->s_es->s_errors) == EXT3COW_ERRORS_PANIC)
-+		set_opt(sbi->s_mount_opt, ERRORS_PANIC);
-+	else if (le16_to_cpu(sbi->s_es->s_errors) == EXT3COW_ERRORS_RO)
-+		set_opt(sbi->s_mount_opt, ERRORS_RO);
-+	else
-+		set_opt(sbi->s_mount_opt, ERRORS_CONT);
-+
-+	sbi->s_resuid = le16_to_cpu(es->s_def_resuid);
-+	sbi->s_resgid = le16_to_cpu(es->s_def_resgid);
-+
-+	set_opt(sbi->s_mount_opt, RESERVATION);
-+
-+	if (!parse_options ((char *) data, sb, &journal_inum, &journal_devnum,
-+			    NULL, 0))
-+		goto failed_mount;
-+
-+	sb->s_flags = (sb->s_flags & ~MS_POSIXACL) |
-+		((sbi->s_mount_opt & EXT3COW_MOUNT_POSIX_ACL) ? MS_POSIXACL : 0);
-+
-+	if (le32_to_cpu(es->s_rev_level) == EXT3COW_GOOD_OLD_REV &&
-+	    (EXT3COW_HAS_COMPAT_FEATURE(sb, ~0U) ||
-+	     EXT3COW_HAS_RO_COMPAT_FEATURE(sb, ~0U) ||
-+	     EXT3COW_HAS_INCOMPAT_FEATURE(sb, ~0U)))
-+		printk(KERN_WARNING
-+		       "EXT3COW-fs warning: feature flags set on rev 0 fs, "
-+		       "running e2fsck is recommended\n");
-+	/*
-+	 * Check feature flags regardless of the revision level, since we
-+	 * previously didn't change the revision level when setting the flags,
-+	 * so there is a chance incompat flags are set on a rev 0 filesystem.
-+	 */
-+	features = EXT3COW_HAS_INCOMPAT_FEATURE(sb, ~EXT3COW_FEATURE_INCOMPAT_SUPP);
-+	if (features) {
-+		printk(KERN_ERR "EXT3COW-fs: %s: couldn't mount because of "
-+		       "unsupported optional features (%x).\n",
-+		       sb->s_id, le32_to_cpu(features));
-+		goto failed_mount;
-+	}
-+	features = EXT3COW_HAS_RO_COMPAT_FEATURE(sb, ~EXT3COW_FEATURE_RO_COMPAT_SUPP);
-+	if (!(sb->s_flags & MS_RDONLY) && features) {
-+		printk(KERN_ERR "EXT3COW-fs: %s: couldn't mount RDWR because of "
-+		       "unsupported optional features (%x).\n",
-+		       sb->s_id, le32_to_cpu(features));
-+		goto failed_mount;
-+	}
-+	blocksize = BLOCK_SIZE << le32_to_cpu(es->s_log_block_size);
-+
-+	if (blocksize < EXT3COW_MIN_BLOCK_SIZE ||
-+	    blocksize > EXT3COW_MAX_BLOCK_SIZE) {
-+		printk(KERN_ERR
-+		       "EXT3COW-fs: Unsupported filesystem blocksize %d on %s.\n",
-+		       blocksize, sb->s_id);
-+		goto failed_mount;
-+	}
-+
-+	hblock = bdev_hardsect_size(sb->s_bdev);
-+	if (sb->s_blocksize != blocksize) {
-+		/*
-+		 * Make sure the blocksize for the filesystem is larger
-+		 * than the hardware sectorsize for the machine.
-+		 */
-+		if (blocksize < hblock) {
-+			printk(KERN_ERR "EXT3COW-fs: blocksize %d too small for "
-+			       "device blocksize %d.\n", blocksize, hblock);
-+			goto failed_mount;
-+		}
-+
-+		brelse (bh);
-+		sb_set_blocksize(sb, blocksize);
-+		logic_sb_block = (sb_block * EXT3COW_MIN_BLOCK_SIZE) / blocksize;
-+		offset = (sb_block * EXT3COW_MIN_BLOCK_SIZE) % blocksize;
-+		bh = sb_bread(sb, logic_sb_block);
-+		if (!bh) {
-+			printk(KERN_ERR
-+			       "EXT3COW-fs: Can't read superblock on 2nd try.\n");
-+			goto failed_mount;
-+		}
-+		es = (struct ext3cow_super_block *)(((char *)bh->b_data) + offset);
-+		sbi->s_es = es;
-+		if (es->s_magic != cpu_to_le16(EXT3COW_SUPER_MAGIC)) {
-+			printk (KERN_ERR
-+				"EXT3COW-fs: Magic mismatch, very weird !\n");
-+			goto failed_mount;
-+		}
-+	}
-+
-+	sb->s_maxbytes = ext3cow_max_size(sb->s_blocksize_bits);
-+
-+	if (le32_to_cpu(es->s_rev_level) == EXT3COW_GOOD_OLD_REV) {
-+		sbi->s_inode_size = EXT3COW_GOOD_OLD_INODE_SIZE;
-+		sbi->s_first_ino = EXT3COW_GOOD_OLD_FIRST_INO;
-+	} else {
-+		sbi->s_inode_size = le16_to_cpu(es->s_inode_size);
-+		sbi->s_first_ino = le32_to_cpu(es->s_first_ino);
-+		if ((sbi->s_inode_size < EXT3COW_GOOD_OLD_INODE_SIZE) ||
-+		    (sbi->s_inode_size & (sbi->s_inode_size - 1)) ||
-+		    (sbi->s_inode_size > blocksize)) {
-+			printk (KERN_ERR
-+				"EXT3COW-fs: unsupported inode size: %d\n",
-+				sbi->s_inode_size);
-+			goto failed_mount;
-+		}
-+	}
-+	sbi->s_frag_size = EXT3COW_MIN_FRAG_SIZE <<
-+				   le32_to_cpu(es->s_log_frag_size);
-+	if (blocksize != sbi->s_frag_size) {
-+		printk(KERN_ERR
-+		       "EXT3COW-fs: fragsize %lu != blocksize %u (unsupported)\n",
-+		       sbi->s_frag_size, blocksize);
-+		goto failed_mount;
-+	}
-+	sbi->s_frags_per_block = 1;
-+	sbi->s_blocks_per_group = le32_to_cpu(es->s_blocks_per_group);
-+	sbi->s_frags_per_group = le32_to_cpu(es->s_frags_per_group);
-+	sbi->s_inodes_per_group = le32_to_cpu(es->s_inodes_per_group);
-+	if (EXT3COW_INODE_SIZE(sb) == 0)
-+		goto cantfind_ext3cow;
-+	sbi->s_inodes_per_block = blocksize / EXT3COW_INODE_SIZE(sb);
-+	if (sbi->s_inodes_per_block == 0)
-+		goto cantfind_ext3cow;
-+	sbi->s_itb_per_group = sbi->s_inodes_per_group /
-+					sbi->s_inodes_per_block;
-+	sbi->s_desc_per_block = blocksize / sizeof(struct ext3cow_group_desc);
-+	sbi->s_sbh = bh;
-+	sbi->s_mount_state = le16_to_cpu(es->s_state);
-+	sbi->s_addr_per_block_bits = ilog2(EXT3COW_ADDR_PER_BLOCK(sb));
-+	sbi->s_desc_per_block_bits = ilog2(EXT3COW_DESC_PER_BLOCK(sb));
-+	for (i=0; i < 4; i++)
-+		sbi->s_hash_seed[i] = le32_to_cpu(es->s_hash_seed[i]);
-+	sbi->s_def_hash_version = es->s_def_hash_version;
-+
-+  /* Epoch number for versioning -znjp */
-+  sbi->s_epoch_number = le32_to_cpu(es->s_epoch_number);
-+  printk(KERN_INFO "EXT3COW-fs: System epoch number: %u\n",
-+         sbi->s_epoch_number);
-+
-+	if (sbi->s_blocks_per_group > blocksize * 8) {
-+		printk (KERN_ERR
-+			"EXT3COW-fs: #blocks per group too big: %lu\n",
-+			sbi->s_blocks_per_group);
-+		goto failed_mount;
-+	}
-+	if (sbi->s_frags_per_group > blocksize * 8) {
-+		printk (KERN_ERR
-+			"EXT3COW-fs: #fragments per group too big: %lu\n",
-+			sbi->s_frags_per_group);
-+		goto failed_mount;
-+	}
-+	if (sbi->s_inodes_per_group > blocksize * 8) {
-+		printk (KERN_ERR
-+			"EXT3COW-fs: #inodes per group too big: %lu\n",
-+			sbi->s_inodes_per_group);
-+		goto failed_mount;
-+	}
-+
-+	if (le32_to_cpu(es->s_blocks_count) >
-+		    (sector_t)(~0ULL) >> (sb->s_blocksize_bits - 9)) {
-+		printk(KERN_ERR "EXT3COW-fs: filesystem on %s:"
-+			" too large to mount safely\n", sb->s_id);
-+		if (sizeof(sector_t) < 8)
-+			printk(KERN_WARNING "EXT3COW-fs: CONFIG_LBD not "
-+					"enabled\n");
-+		goto failed_mount;
-+	}
-+
-+	if (EXT3COW_BLOCKS_PER_GROUP(sb) == 0)
-+		goto cantfind_ext3cow;
-+	sbi->s_groups_count = ((le32_to_cpu(es->s_blocks_count) -
-+			       le32_to_cpu(es->s_first_data_block) - 1)
-+				       / EXT3COW_BLOCKS_PER_GROUP(sb)) + 1;
-+	db_count = (sbi->s_groups_count + EXT3COW_DESC_PER_BLOCK(sb) - 1) /
-+		   EXT3COW_DESC_PER_BLOCK(sb);
-+	sbi->s_group_desc = kmalloc(db_count * sizeof (struct buffer_head *),
-+				    GFP_KERNEL);
-+	if (sbi->s_group_desc == NULL) {
-+		printk (KERN_ERR "EXT3COW-fs: not enough memory\n");
-+		goto failed_mount;
-+	}
-+
-+	bgl_lock_init(&sbi->s_blockgroup_lock);
-+
-+	for (i = 0; i < db_count; i++) {
-+		block = descriptor_loc(sb, logic_sb_block, i);
-+		sbi->s_group_desc[i] = sb_bread(sb, block);
-+		if (!sbi->s_group_desc[i]) {
-+			printk (KERN_ERR "EXT3COW-fs: "
-+				"can't read group descriptor %d\n", i);
-+			db_count = i;
-+			goto failed_mount2;
-+		}
-+	}
-+	if (!ext3cow_check_descriptors (sb)) {
-+		printk(KERN_ERR "EXT3COW-fs: group descriptors corrupted!\n");
-+		goto failed_mount2;
-+	}
-+	sbi->s_gdb_count = db_count;
-+	get_random_bytes(&sbi->s_next_generation, sizeof(u32));
-+	spin_lock_init(&sbi->s_next_gen_lock);
-+
-+	percpu_counter_init(&sbi->s_freeblocks_counter,
-+		ext3cow_count_free_blocks(sb));
-+	percpu_counter_init(&sbi->s_freeinodes_counter,
-+		ext3cow_count_free_inodes(sb));
-+	percpu_counter_init(&sbi->s_dirs_counter,
-+		ext3cow_count_dirs(sb));
-+
-+	/* per fileystem reservation list head & lock */
-+	spin_lock_init(&sbi->s_rsv_window_lock);
-+	sbi->s_rsv_window_root = RB_ROOT;
-+	/* Add a single, static dummy reservation to the start of the
-+	 * reservation window list --- it gives us a placeholder for
-+	 * append-at-start-of-list which makes the allocation logic
-+	 * _much_ simpler. */
-+	sbi->s_rsv_window_head.rsv_start = EXT3COW_RESERVE_WINDOW_NOT_ALLOCATED;
-+	sbi->s_rsv_window_head.rsv_end = EXT3COW_RESERVE_WINDOW_NOT_ALLOCATED;
-+	sbi->s_rsv_window_head.rsv_alloc_hit = 0;
-+	sbi->s_rsv_window_head.rsv_goal_size = 0;
-+	ext3cow_rsv_window_add(sb, &sbi->s_rsv_window_head);
-+
-+	/*
-+	 * set up enough so that it can read an inode
-+	 */
-+	sb->s_op = &ext3cow_sops;
-+	sb->s_export_op = &ext3cow_export_ops;
-+	sb->s_xattr = ext3cow_xattr_handlers;
-+#ifdef CONFIG_QUOTA
-+	sb->s_qcop = &ext3cow_qctl_operations;
-+	sb->dq_op = &ext3cow_quota_operations;
-+#endif
-+	INIT_LIST_HEAD(&sbi->s_orphan); /* unlinked but open files */
-+
-+	sb->s_root = NULL;
-+
-+	needs_recovery = (es->s_last_orphan != 0 ||
-+			  EXT3COW_HAS_INCOMPAT_FEATURE(sb,
-+				    EXT3COW_FEATURE_INCOMPAT_RECOVER));
-+
-+	/*
-+	 * The first inode we look at is the journal inode.  Don't try
-+	 * root first: it may be modified in the journal!
-+	 */
-+	if (!test_opt(sb, NOLOAD) &&
-+	    EXT3COW_HAS_COMPAT_FEATURE(sb, EXT3COW_FEATURE_COMPAT_HAS_JOURNAL)) {
-+		if (ext3cow_load_journal(sb, es, journal_devnum))
-+			goto failed_mount3;
-+	} else if (journal_inum) {
-+		if (ext3cow_create_journal(sb, es, journal_inum))
-+			goto failed_mount3;
-+	} else {
-+		if (!silent)
-+			printk (KERN_ERR
-+				"ext3cow: No journal on filesystem on %s\n",
-+				sb->s_id);
-+		goto failed_mount3;
-+	}
-+
-+	/* We have now updated the journal if required, so we can
-+	 * validate the data journaling mode. */
-+	switch (test_opt(sb, DATA_FLAGS)) {
-+	case 0:
-+		/* No mode set, assume a default based on the journal
-+                   capabilities: ORDERED_DATA if the journal can
-+                   cope, else JOURNAL_DATA */
-+		if (journal_check_available_features
-+		    (sbi->s_journal, 0, 0, JFS_FEATURE_INCOMPAT_REVOKE))
-+			set_opt(sbi->s_mount_opt, ORDERED_DATA);
-+		else
-+			set_opt(sbi->s_mount_opt, JOURNAL_DATA);
-+		break;
-+
-+	case EXT3COW_MOUNT_ORDERED_DATA:
-+	case EXT3COW_MOUNT_WRITEBACK_DATA:
-+		if (!journal_check_available_features
-+		    (sbi->s_journal, 0, 0, JFS_FEATURE_INCOMPAT_REVOKE)) {
-+			printk(KERN_ERR "EXT3COW-fs: Journal does not support "
-+			       "requested data journaling mode\n");
-+			goto failed_mount4;
-+		}
-+	default:
-+		break;
-+	}
-+
-+	if (test_opt(sb, NOBH)) {
-+		if (!(test_opt(sb, DATA_FLAGS) == EXT3COW_MOUNT_WRITEBACK_DATA)) {
-+			printk(KERN_WARNING "EXT3COW-fs: Ignoring nobh option - "
-+				"its supported only with writeback mode\n");
-+			clear_opt(sbi->s_mount_opt, NOBH);
-+		}
-+	}
-+	/*
-+	 * The journal_load will have done any necessary log recovery,
-+	 * so we can safely mount the rest of the filesystem now.
-+	 */
-+
-+	root = iget(sb, EXT3COW_ROOT_INO);
-+	sb->s_root = d_alloc_root(root);
-+	if (!sb->s_root) {
-+		printk(KERN_ERR "EXT3COW-fs: get root inode failed\n");
-+		iput(root);
-+		goto failed_mount4;
-+	}
-+	if (!S_ISDIR(root->i_mode) || !root->i_blocks || !root->i_size) {
-+		dput(sb->s_root);
-+		sb->s_root = NULL;
-+		printk(KERN_ERR "EXT3COW-fs: corrupt root inode, run e2fsck\n");
-+		goto failed_mount4;
-+	}
-+
-+	ext3cow_setup_super (sb, es, sb->s_flags & MS_RDONLY);
-+	/*
-+	 * akpm: core read_super() calls in here with the superblock locked.
-+	 * That deadlocks, because orphan cleanup needs to lock the superblock
-+	 * in numerous places.  Here we just pop the lock - it's relatively
-+	 * harmless, because we are now ready to accept write_super() requests,
-+	 * and aviro says that's the only reason for hanging onto the
-+	 * superblock lock.
-+	 */
-+	EXT3COW_SB(sb)->s_mount_state |= EXT3COW_ORPHAN_FS;
-+	ext3cow_orphan_cleanup(sb, es);
-+	EXT3COW_SB(sb)->s_mount_state &= ~EXT3COW_ORPHAN_FS;
-+	if (needs_recovery)
-+		printk (KERN_INFO "EXT3COW-fs: recovery complete.\n");
-+	ext3cow_mark_recovery_complete(sb, es);
-+	printk (KERN_INFO "EXT3COW-fs: mounted filesystem with %s data mode.\n",
-+		test_opt(sb,DATA_FLAGS) == EXT3COW_MOUNT_JOURNAL_DATA ? "journal":
-+		test_opt(sb,DATA_FLAGS) == EXT3COW_MOUNT_ORDERED_DATA ? "ordered":
-+		"writeback");
-+
-+	lock_kernel();
-+	return 0;
-+
-+cantfind_ext3cow:
-+	if (!silent)
-+		printk(KERN_ERR "VFS: Can't find ext3cow filesystem on dev %s.\n",
-+		       sb->s_id);
-+	goto failed_mount;
-+
-+failed_mount4:
-+	journal_destroy(sbi->s_journal);
-+failed_mount3:
-+	percpu_counter_destroy(&sbi->s_freeblocks_counter);
-+	percpu_counter_destroy(&sbi->s_freeinodes_counter);
-+	percpu_counter_destroy(&sbi->s_dirs_counter);
-+failed_mount2:
-+	for (i = 0; i < db_count; i++)
-+		brelse(sbi->s_group_desc[i]);
-+	kfree(sbi->s_group_desc);
-+failed_mount:
-+#ifdef CONFIG_QUOTA
-+	for (i = 0; i < MAXQUOTAS; i++)
-+		kfree(sbi->s_qf_names[i]);
-+#endif
-+	ext3cow_blkdev_remove(sbi);
-+	brelse(bh);
-+out_fail:
-+	sb->s_fs_info = NULL;
-+	kfree(sbi);
-+	lock_kernel();
-+	return -EINVAL;
-+}
-+
-+/*
-+ * Setup any per-fs journal parameters now.  We'll do this both on
-+ * initial mount, once the journal has been initialised but before we've
-+ * done any recovery; and again on any subsequent remount.
-+ */
-+static void ext3cow_init_journal_params(struct super_block *sb, journal_t *journal)
-+{
-+	struct ext3cow_sb_info *sbi = EXT3COW_SB(sb);
-+
-+	if (sbi->s_commit_interval)
-+		journal->j_commit_interval = sbi->s_commit_interval;
-+	/* We could also set up an ext3cow-specific default for the commit
-+	 * interval here, but for now we'll just fall back to the jbd
-+	 * default. */
-+
-+	spin_lock(&journal->j_state_lock);
-+	if (test_opt(sb, BARRIER))
-+		journal->j_flags |= JFS_BARRIER;
-+	else
-+		journal->j_flags &= ~JFS_BARRIER;
-+	spin_unlock(&journal->j_state_lock);
-+}
-+
-+static journal_t *ext3cow_get_journal(struct super_block *sb,
-+				   unsigned int journal_inum)
-+{
-+	struct inode *journal_inode;
-+	journal_t *journal;
-+
-+	/* First, test for the existence of a valid inode on disk.  Bad
-+	 * things happen if we iget() an unused inode, as the subsequent
-+	 * iput() will try to delete it. */
-+
-+	journal_inode = iget(sb, journal_inum);
-+	if (!journal_inode) {
-+		printk(KERN_ERR "EXT3COW-fs: no journal found.\n");
-+		return NULL;
-+	}
-+	if (!journal_inode->i_nlink) {
-+		make_bad_inode(journal_inode);
-+		iput(journal_inode);
-+		printk(KERN_ERR "EXT3COW-fs: journal inode is deleted.\n");
-+		return NULL;
-+	}
-+
-+	jbd_debug(2, "Journal inode found at %p: %Ld bytes\n",
-+		  journal_inode, journal_inode->i_size);
-+	if (is_bad_inode(journal_inode) || !S_ISREG(journal_inode->i_mode)) {
-+		printk(KERN_ERR "EXT3COW-fs: invalid journal inode.\n");
-+		iput(journal_inode);
-+		return NULL;
-+	}
-+
-+	journal = journal_init_inode(journal_inode);
-+	if (!journal) {
-+		printk(KERN_ERR "EXT3COW-fs: Could not load journal inode\n");
-+		iput(journal_inode);
-+		return NULL;
-+	}
-+  /* Make sure the journal never gets versioned -znjp */
-+  EXT3COW_I(journal_inode)->i_flags |= EXT3COW_UNVERSIONABLE_FL;
-+	journal->j_private = sb;
-+	ext3cow_init_journal_params(sb, journal);
-+	return journal;
-+}
-+
-+static journal_t *ext3cow_get_dev_journal(struct super_block *sb,
-+				       dev_t j_dev)
-+{
-+	struct buffer_head * bh;
-+	journal_t *journal;
-+	ext3cow_fsblk_t start;
-+	ext3cow_fsblk_t len;
-+	int hblock, blocksize;
-+	ext3cow_fsblk_t sb_block;
-+	unsigned long offset;
-+	struct ext3cow_super_block * es;
-+	struct block_device *bdev;
-+
-+	bdev = ext3cow_blkdev_get(j_dev);
-+	if (bdev == NULL)
-+		return NULL;
-+
-+	if (bd_claim(bdev, sb)) {
-+		printk(KERN_ERR
-+		        "EXT3COW: failed to claim external journal device.\n");
-+		blkdev_put(bdev);
-+		return NULL;
-+	}
-+
-+	blocksize = sb->s_blocksize;
-+	hblock = bdev_hardsect_size(bdev);
-+	if (blocksize < hblock) {
-+		printk(KERN_ERR
-+			"EXT3COW-fs: blocksize too small for journal device.\n");
-+		goto out_bdev;
-+	}
-+
-+	sb_block = EXT3COW_MIN_BLOCK_SIZE / blocksize;
-+	offset = EXT3COW_MIN_BLOCK_SIZE % blocksize;
-+	set_blocksize(bdev, blocksize);
-+	if (!(bh = __bread(bdev, sb_block, blocksize))) {
-+		printk(KERN_ERR "EXT3COW-fs: couldn't read superblock of "
-+		       "external journal\n");
-+		goto out_bdev;
-+	}
-+
-+	es = (struct ext3cow_super_block *) (((char *)bh->b_data) + offset);
-+	if ((le16_to_cpu(es->s_magic) != EXT3COW_SUPER_MAGIC) ||
-+	    !(le32_to_cpu(es->s_feature_incompat) &
-+	      EXT3COW_FEATURE_INCOMPAT_JOURNAL_DEV)) {
-+		printk(KERN_ERR "EXT3COW-fs: external journal has "
-+					"bad superblock\n");
-+		brelse(bh);
-+		goto out_bdev;
-+	}
-+
-+	if (memcmp(EXT3COW_SB(sb)->s_es->s_journal_uuid, es->s_uuid, 16)) {
-+		printk(KERN_ERR "EXT3COW-fs: journal UUID does not match\n");
-+		brelse(bh);
-+		goto out_bdev;
-+	}
-+
-+	len = le32_to_cpu(es->s_blocks_count);
-+	start = sb_block + 1;
-+	brelse(bh);	/* we're done with the superblock */
-+
-+	journal = journal_init_dev(bdev, sb->s_bdev,
-+					start, len, blocksize);
-+	if (!journal) {
-+		printk(KERN_ERR "EXT3COW-fs: failed to create device journal\n");
-+		goto out_bdev;
-+	}
-+	journal->j_private = sb;
-+	ll_rw_block(READ, 1, &journal->j_sb_buffer);
-+	wait_on_buffer(journal->j_sb_buffer);
-+	if (!buffer_uptodate(journal->j_sb_buffer)) {
-+		printk(KERN_ERR "EXT3COW-fs: I/O error on journal device\n");
-+		goto out_journal;
-+	}
-+	if (be32_to_cpu(journal->j_superblock->s_nr_users) != 1) {
-+		printk(KERN_ERR "EXT3COW-fs: External journal has more than one "
-+					"user (unsupported) - %d\n",
-+			be32_to_cpu(journal->j_superblock->s_nr_users));
-+		goto out_journal;
-+	}
-+	EXT3COW_SB(sb)->journal_bdev = bdev;
-+	ext3cow_init_journal_params(sb, journal);
-+	return journal;
-+out_journal:
-+	journal_destroy(journal);
-+out_bdev:
-+	ext3cow_blkdev_put(bdev);
-+	return NULL;
-+}
-+
-+static int ext3cow_load_journal(struct super_block *sb,
-+			     struct ext3cow_super_block *es,
-+			     unsigned long journal_devnum)
-+{
-+	journal_t *journal;
-+	unsigned int journal_inum = le32_to_cpu(es->s_journal_inum);
-+	dev_t journal_dev;
-+	int err = 0;
-+	int really_read_only;
-+
-+	if (journal_devnum &&
-+	    journal_devnum != le32_to_cpu(es->s_journal_dev)) {
-+		printk(KERN_INFO "EXT3COW-fs: external journal device major/minor "
-+			"numbers have changed\n");
-+		journal_dev = new_decode_dev(journal_devnum);
-+	} else
-+		journal_dev = new_decode_dev(le32_to_cpu(es->s_journal_dev));
-+
-+	really_read_only = bdev_read_only(sb->s_bdev);
-+
-+	/*
-+	 * Are we loading a blank journal or performing recovery after a
-+	 * crash?  For recovery, we need to check in advance whether we
-+	 * can get read-write access to the device.
-+	 */
-+
-+	if (EXT3COW_HAS_INCOMPAT_FEATURE(sb, EXT3COW_FEATURE_INCOMPAT_RECOVER)) {
-+		if (sb->s_flags & MS_RDONLY) {
-+			printk(KERN_INFO "EXT3COW-fs: INFO: recovery "
-+					"required on readonly filesystem.\n");
-+			if (really_read_only) {
-+				printk(KERN_ERR "EXT3COW-fs: write access "
-+					"unavailable, cannot proceed.\n");
-+				return -EROFS;
-+			}
-+			printk (KERN_INFO "EXT3COW-fs: write access will "
-+					"be enabled during recovery.\n");
-+		}
-+	}
-+
-+	if (journal_inum && journal_dev) {
-+		printk(KERN_ERR "EXT3COW-fs: filesystem has both journal "
-+		       "and inode journals!\n");
-+		return -EINVAL;
-+	}
-+
-+	if (journal_inum) {
-+		if (!(journal = ext3cow_get_journal(sb, journal_inum)))
-+			return -EINVAL;
-+	} else {
-+		if (!(journal = ext3cow_get_dev_journal(sb, journal_dev)))
-+			return -EINVAL;
-+	}
-+
-+	if (!really_read_only && test_opt(sb, UPDATE_JOURNAL)) {
-+		err = journal_update_format(journal);
-+		if (err)  {
-+			printk(KERN_ERR "EXT3COW-fs: error updating journal.\n");
-+			journal_destroy(journal);
-+			return err;
-+		}
-+	}
-+
-+	if (!EXT3COW_HAS_INCOMPAT_FEATURE(sb, EXT3COW_FEATURE_INCOMPAT_RECOVER))
-+		err = journal_wipe(journal, !really_read_only);
-+	if (!err)
-+		err = journal_load(journal);
-+
-+	if (err) {
-+		printk(KERN_ERR "EXT3COW-fs: error loading journal.\n");
-+		journal_destroy(journal);
-+		return err;
-+	}
-+
-+	EXT3COW_SB(sb)->s_journal = journal;
-+	ext3cow_clear_journal_err(sb, es);
-+
-+	if (journal_devnum &&
-+	    journal_devnum != le32_to_cpu(es->s_journal_dev)) {
-+		es->s_journal_dev = cpu_to_le32(journal_devnum);
-+		sb->s_dirt = 1;
-+
-+		/* Make sure we flush the recovery flag to disk. */
-+		ext3cow_commit_super(sb, es, 1);
-+	}
-+
-+	return 0;
-+}
-+
-+static int ext3cow_create_journal(struct super_block * sb,
-+			       struct ext3cow_super_block * es,
-+			       unsigned int journal_inum)
-+{
-+	journal_t *journal;
-+
-+	if (sb->s_flags & MS_RDONLY) {
-+		printk(KERN_ERR "EXT3COW-fs: readonly filesystem when trying to "
-+				"create journal.\n");
-+		return -EROFS;
-+	}
-+
-+	if (!(journal = ext3cow_get_journal(sb, journal_inum)))
-+		return -EINVAL;
-+
-+	printk(KERN_INFO "EXT3COW-fs: creating new journal on inode %u\n",
-+	       journal_inum);
-+
-+	if (journal_create(journal)) {
-+		printk(KERN_ERR "EXT3COW-fs: error creating journal.\n");
-+		journal_destroy(journal);
-+		return -EIO;
-+	}
-+
-+	EXT3COW_SB(sb)->s_journal = journal;
-+
-+	ext3cow_update_dynamic_rev(sb);
-+	EXT3COW_SET_INCOMPAT_FEATURE(sb, EXT3COW_FEATURE_INCOMPAT_RECOVER);
-+	EXT3COW_SET_COMPAT_FEATURE(sb, EXT3COW_FEATURE_COMPAT_HAS_JOURNAL);
-+
-+	es->s_journal_inum = cpu_to_le32(journal_inum);
-+	sb->s_dirt = 1;
-+
-+	/* Make sure we flush the recovery flag to disk. */
-+	ext3cow_commit_super(sb, es, 1);
-+
-+	return 0;
-+}
-+
-+static void ext3cow_commit_super (struct super_block * sb,
-+			       struct ext3cow_super_block * es,
-+			       int sync)
-+{
-+	struct buffer_head *sbh = EXT3COW_SB(sb)->s_sbh;
-+
-+	if (!sbh)
-+		return;
-+	es->s_wtime = cpu_to_le32(get_seconds());
-+	es->s_free_blocks_count = cpu_to_le32(ext3cow_count_free_blocks(sb));
-+	es->s_free_inodes_count = cpu_to_le32(ext3cow_count_free_inodes(sb));
-+	BUFFER_TRACE(sbh, "marking dirty");
-+	mark_buffer_dirty(sbh);
-+	if (sync)
-+		sync_dirty_buffer(sbh);
-+}
-+
-+
-+/*
-+ * Have we just finished recovery?  If so, and if we are mounting (or
-+ * remounting) the filesystem readonly, then we will end up with a
-+ * consistent fs on disk.  Record that fact.
-+ */
-+static void ext3cow_mark_recovery_complete(struct super_block * sb,
-+					struct ext3cow_super_block * es)
-+{
-+	journal_t *journal = EXT3COW_SB(sb)->s_journal;
-+
-+	journal_lock_updates(journal);
-+	journal_flush(journal);
-+	if (EXT3COW_HAS_INCOMPAT_FEATURE(sb, EXT3COW_FEATURE_INCOMPAT_RECOVER) &&
-+	    sb->s_flags & MS_RDONLY) {
-+		EXT3COW_CLEAR_INCOMPAT_FEATURE(sb, EXT3COW_FEATURE_INCOMPAT_RECOVER);
-+		sb->s_dirt = 0;
-+		ext3cow_commit_super(sb, es, 1);
-+	}
-+	journal_unlock_updates(journal);
-+}
-+
-+/*
-+ * If we are mounting (or read-write remounting) a filesystem whose journal
-+ * has recorded an error from a previous lifetime, move that error to the
-+ * main filesystem now.
-+ */
-+static void ext3cow_clear_journal_err(struct super_block * sb,
-+				   struct ext3cow_super_block * es)
-+{
-+	journal_t *journal;
-+	int j_errno;
-+	const char *errstr;
-+
-+	journal = EXT3COW_SB(sb)->s_journal;
-+
-+	/*
-+	 * Now check for any error status which may have been recorded in the
-+	 * journal by a prior ext3cow_error() or ext3cow_abort()
-+	 */
-+
-+	j_errno = journal_errno(journal);
-+	if (j_errno) {
-+		char nbuf[16];
-+
-+		errstr = ext3cow_decode_error(sb, j_errno, nbuf);
-+		ext3cow_warning(sb, __FUNCTION__, "Filesystem error recorded "
-+			     "from previous mount: %s", errstr);
-+		ext3cow_warning(sb, __FUNCTION__, "Marking fs in need of "
-+			     "filesystem check.");
-+
-+		EXT3COW_SB(sb)->s_mount_state |= EXT3COW_ERROR_FS;
-+		es->s_state |= cpu_to_le16(EXT3COW_ERROR_FS);
-+		ext3cow_commit_super (sb, es, 1);
-+
-+		journal_clear_err(journal);
-+	}
-+}
-+
-+/*
-+ * Force the running and committing transactions to commit,
-+ * and wait on the commit.
-+ */
-+int ext3cow_force_commit(struct super_block *sb)
-+{
-+	journal_t *journal;
-+	int ret;
-+
-+	if (sb->s_flags & MS_RDONLY)
-+		return 0;
-+
-+	journal = EXT3COW_SB(sb)->s_journal;
-+	sb->s_dirt = 0;
-+	ret = ext3cow_journal_force_commit(journal);
-+	return ret;
-+}
-+
-+/*
-+ * Ext3 always journals updates to the superblock itself, so we don't
-+ * have to propagate any other updates to the superblock on disk at this
-+ * point.  Just start an async writeback to get the buffers on their way
-+ * to the disk.
-+ *
-+ * This implicitly triggers the writebehind on sync().
-+ */
-+
-+static void ext3cow_write_super (struct super_block * sb)
-+{
-+	if (mutex_trylock(&sb->s_lock) != 0)
-+		BUG();
-+	sb->s_dirt = 0;
-+}
-+
-+static int ext3cow_sync_fs(struct super_block *sb, int wait)
-+{
-+	tid_t target;
-+
-+	sb->s_dirt = 0;
-+	if (journal_start_commit(EXT3COW_SB(sb)->s_journal, &target)) {
-+		if (wait)
-+			log_wait_commit(EXT3COW_SB(sb)->s_journal, target);
-+	}
-+	return 0;
-+}
-+
-+/*
-+ * LVM calls this function before a (read-only) snapshot is created.  This
-+ * gives us a chance to flush the journal completely and mark the fs clean.
-+ */
-+static void ext3cow_write_super_lockfs(struct super_block *sb)
-+{
-+	sb->s_dirt = 0;
-+
-+	if (!(sb->s_flags & MS_RDONLY)) {
-+		journal_t *journal = EXT3COW_SB(sb)->s_journal;
-+
-+		/* Now we set up the journal barrier. */
-+		journal_lock_updates(journal);
-+		journal_flush(journal);
-+
-+		/* Journal blocked and flushed, clear needs_recovery flag. */
-+		EXT3COW_CLEAR_INCOMPAT_FEATURE(sb, EXT3COW_FEATURE_INCOMPAT_RECOVER);
-+		ext3cow_commit_super(sb, EXT3COW_SB(sb)->s_es, 1);
-+	}
-+}
-+
-+/*
-+ * Called by LVM after the snapshot is done.  We need to reset the RECOVER
-+ * flag here, even though the filesystem is not technically dirty yet.
-+ */
-+static void ext3cow_unlockfs(struct super_block *sb)
-+{
-+	if (!(sb->s_flags & MS_RDONLY)) {
-+		lock_super(sb);
-+		/* Reser the needs_recovery flag before the fs is unlocked. */
-+		EXT3COW_SET_INCOMPAT_FEATURE(sb, EXT3COW_FEATURE_INCOMPAT_RECOVER);
-+		ext3cow_commit_super(sb, EXT3COW_SB(sb)->s_es, 1);
-+		unlock_super(sb);
-+		journal_unlock_updates(EXT3COW_SB(sb)->s_journal);
-+	}
-+}
-+
-+static int ext3cow_remount (struct super_block * sb, int * flags, char * data)
-+{
-+	struct ext3cow_super_block * es;
-+	struct ext3cow_sb_info *sbi = EXT3COW_SB(sb);
-+	ext3cow_fsblk_t n_blocks_count = 0;
-+	unsigned long old_sb_flags;
-+	struct ext3cow_mount_options old_opts;
-+	int err;
-+#ifdef CONFIG_QUOTA
-+	int i;
-+#endif
-+
-+	/* Store the original options */
-+	old_sb_flags = sb->s_flags;
-+	old_opts.s_mount_opt = sbi->s_mount_opt;
-+	old_opts.s_resuid = sbi->s_resuid;
-+	old_opts.s_resgid = sbi->s_resgid;
-+	old_opts.s_commit_interval = sbi->s_commit_interval;
-+#ifdef CONFIG_QUOTA
-+	old_opts.s_jquota_fmt = sbi->s_jquota_fmt;
-+	for (i = 0; i < MAXQUOTAS; i++)
-+		old_opts.s_qf_names[i] = sbi->s_qf_names[i];
-+#endif
-+
-+	/*
-+	 * Allow the "check" option to be passed as a remount option.
-+	 */
-+	if (!parse_options(data, sb, NULL, NULL, &n_blocks_count, 1)) {
-+		err = -EINVAL;
-+		goto restore_opts;
-+	}
-+
-+	if (sbi->s_mount_opt & EXT3COW_MOUNT_ABORT)
-+		ext3cow_abort(sb, __FUNCTION__, "Abort forced by user");
-+
-+	sb->s_flags = (sb->s_flags & ~MS_POSIXACL) |
-+		((sbi->s_mount_opt & EXT3COW_MOUNT_POSIX_ACL) ? MS_POSIXACL : 0);
-+
-+	es = sbi->s_es;
-+
-+	ext3cow_init_journal_params(sb, sbi->s_journal);
-+
-+	if ((*flags & MS_RDONLY) != (sb->s_flags & MS_RDONLY) ||
-+		n_blocks_count > le32_to_cpu(es->s_blocks_count)) {
-+		if (sbi->s_mount_opt & EXT3COW_MOUNT_ABORT) {
-+			err = -EROFS;
-+			goto restore_opts;
-+		}
-+
-+		if (*flags & MS_RDONLY) {
-+			/*
-+			 * First of all, the unconditional stuff we have to do
-+			 * to disable replay of the journal when we next remount
-+			 */
-+			sb->s_flags |= MS_RDONLY;
-+
-+			/*
-+			 * OK, test if we are remounting a valid rw partition
-+			 * readonly, and if so set the rdonly flag and then
-+			 * mark the partition as valid again.
-+			 */
-+			if (!(es->s_state & cpu_to_le16(EXT3COW_VALID_FS)) &&
-+			    (sbi->s_mount_state & EXT3COW_VALID_FS))
-+				es->s_state = cpu_to_le16(sbi->s_mount_state);
-+
-+			ext3cow_mark_recovery_complete(sb, es);
-+		} else {
-+			__le32 ret;
-+			if ((ret = EXT3COW_HAS_RO_COMPAT_FEATURE(sb,
-+					~EXT3COW_FEATURE_RO_COMPAT_SUPP))) {
-+				printk(KERN_WARNING "EXT3COW-fs: %s: couldn't "
-+				       "remount RDWR because of unsupported "
-+				       "optional features (%x).\n",
-+				       sb->s_id, le32_to_cpu(ret));
-+				err = -EROFS;
-+				goto restore_opts;
-+			}
-+			/*
-+			 * Mounting a RDONLY partition read-write, so reread
-+			 * and store the current valid flag.  (It may have
-+			 * been changed by e2fsck since we originally mounted
-+			 * the partition.)
-+			 */
-+			ext3cow_clear_journal_err(sb, es);
-+			sbi->s_mount_state = le16_to_cpu(es->s_state);
-+			if ((err = ext3cow_group_extend(sb, es, n_blocks_count)))
-+				goto restore_opts;
-+			if (!ext3cow_setup_super (sb, es, 0))
-+				sb->s_flags &= ~MS_RDONLY;
-+		}
-+	}
-+#ifdef CONFIG_QUOTA
-+	/* Release old quota file names */
-+	for (i = 0; i < MAXQUOTAS; i++)
-+		if (old_opts.s_qf_names[i] &&
-+		    old_opts.s_qf_names[i] != sbi->s_qf_names[i])
-+			kfree(old_opts.s_qf_names[i]);
-+#endif
-+	return 0;
-+restore_opts:
-+	sb->s_flags = old_sb_flags;
-+	sbi->s_mount_opt = old_opts.s_mount_opt;
-+	sbi->s_resuid = old_opts.s_resuid;
-+	sbi->s_resgid = old_opts.s_resgid;
-+	sbi->s_commit_interval = old_opts.s_commit_interval;
-+#ifdef CONFIG_QUOTA
-+	sbi->s_jquota_fmt = old_opts.s_jquota_fmt;
-+	for (i = 0; i < MAXQUOTAS; i++) {
-+		if (sbi->s_qf_names[i] &&
-+		    old_opts.s_qf_names[i] != sbi->s_qf_names[i])
-+			kfree(sbi->s_qf_names[i]);
-+		sbi->s_qf_names[i] = old_opts.s_qf_names[i];
-+	}
-+#endif
-+	return err;
-+}
-+
-+static int ext3cow_statfs (struct dentry * dentry, struct kstatfs * buf)
-+{
-+	struct super_block *sb = dentry->d_sb;
-+	struct ext3cow_sb_info *sbi = EXT3COW_SB(sb);
-+	struct ext3cow_super_block *es = sbi->s_es;
-+	ext3cow_fsblk_t overhead;
-+	int i;
-+	u64 fsid;
-+
-+	if (test_opt (sb, MINIX_DF))
-+		overhead = 0;
-+	else {
-+		unsigned long ngroups;
-+		ngroups = EXT3COW_SB(sb)->s_groups_count;
-+		smp_rmb();
-+
-+		/*
-+		 * Compute the overhead (FS structures)
-+		 */
-+
-+		/*
-+		 * All of the blocks before first_data_block are
-+		 * overhead
-+		 */
-+		overhead = le32_to_cpu(es->s_first_data_block);
-+
-+		/*
-+		 * Add the overhead attributed to the superblock and
-+		 * block group descriptors.  If the sparse superblocks
-+		 * feature is turned on, then not all groups have this.
-+		 */
-+		for (i = 0; i < ngroups; i++) {
-+			overhead += ext3cow_bg_has_super(sb, i) +
-+				ext3cow_bg_num_gdb(sb, i);
-+			cond_resched();
-+		}
-+
-+		/*
-+		 * Every block group has an inode bitmap, a block
-+		 * bitmap, and an inode table.
-+		 */
-+		overhead += (ngroups * (2 + EXT3COW_SB(sb)->s_itb_per_group));
-+	}
-+
-+	buf->f_type = EXT3COW_SUPER_MAGIC;
-+	buf->f_bsize = sb->s_blocksize;
-+	buf->f_blocks = le32_to_cpu(es->s_blocks_count) - overhead;
-+	buf->f_bfree = percpu_counter_sum(&sbi->s_freeblocks_counter);
-+	buf->f_bavail = buf->f_bfree - le32_to_cpu(es->s_r_blocks_count);
-+	if (buf->f_bfree < le32_to_cpu(es->s_r_blocks_count))
-+		buf->f_bavail = 0;
-+	buf->f_files = le32_to_cpu(es->s_inodes_count);
-+	buf->f_ffree = percpu_counter_sum(&sbi->s_freeinodes_counter);
-+	buf->f_namelen = EXT3COW_NAME_LEN;
-+	fsid = le64_to_cpup((void *)es->s_uuid) ^
-+	       le64_to_cpup((void *)es->s_uuid + sizeof(u64));
-+	buf->f_fsid.val[0] = fsid & 0xFFFFFFFFUL;
-+	buf->f_fsid.val[1] = (fsid >> 32) & 0xFFFFFFFFUL;
-+	return 0;
-+}
-+
-+/* Helper function for writing quotas on sync - we need to start transaction before quota file
-+ * is locked for write. Otherwise the are possible deadlocks:
-+ * Process 1                         Process 2
-+ * ext3cow_create()                     quota_sync()
-+ *   journal_start()                   write_dquot()
-+ *   DQUOT_INIT()                        down(dqio_mutex)
-+ *     down(dqio_mutex)                    journal_start()
-+ *
-+ */
-+
-+#ifdef CONFIG_QUOTA
-+
-+static inline struct inode *dquot_to_inode(struct dquot *dquot)
-+{
-+	return sb_dqopt(dquot->dq_sb)->files[dquot->dq_type];
-+}
-+
-+static int ext3cow_dquot_initialize(struct inode *inode, int type)
-+{
-+	handle_t *handle;
-+	int ret, err;
-+
-+	/* We may create quota structure so we need to reserve enough blocks */
-+	handle = ext3cow_journal_start(inode, 2*EXT3COW_QUOTA_INIT_BLOCKS(inode->i_sb));
-+	if (IS_ERR(handle))
-+		return PTR_ERR(handle);
-+	ret = dquot_initialize(inode, type);
-+	err = ext3cow_journal_stop(handle);
-+	if (!ret)
-+		ret = err;
-+	return ret;
-+}
-+
-+static int ext3cow_dquot_drop(struct inode *inode)
-+{
-+	handle_t *handle;
-+	int ret, err;
-+
-+	/* We may delete quota structure so we need to reserve enough blocks */
-+	handle = ext3cow_journal_start(inode, 2*EXT3COW_QUOTA_DEL_BLOCKS(inode->i_sb));
-+	if (IS_ERR(handle))
-+		return PTR_ERR(handle);
-+	ret = dquot_drop(inode);
-+	err = ext3cow_journal_stop(handle);
-+	if (!ret)
-+		ret = err;
-+	return ret;
-+}
-+
-+static int ext3cow_write_dquot(struct dquot *dquot)
-+{
-+	int ret, err;
-+	handle_t *handle;
-+	struct inode *inode;
-+
-+	inode = dquot_to_inode(dquot);
-+	handle = ext3cow_journal_start(inode,
-+					EXT3COW_QUOTA_TRANS_BLOCKS(dquot->dq_sb));
-+	if (IS_ERR(handle))
-+		return PTR_ERR(handle);
-+	ret = dquot_commit(dquot);
-+	err = ext3cow_journal_stop(handle);
-+	if (!ret)
-+		ret = err;
-+	return ret;
-+}
-+
-+static int ext3cow_acquire_dquot(struct dquot *dquot)
-+{
-+	int ret, err;
-+	handle_t *handle;
-+
-+	handle = ext3cow_journal_start(dquot_to_inode(dquot),
-+					EXT3COW_QUOTA_INIT_BLOCKS(dquot->dq_sb));
-+	if (IS_ERR(handle))
-+		return PTR_ERR(handle);
-+	ret = dquot_acquire(dquot);
-+	err = ext3cow_journal_stop(handle);
-+	if (!ret)
-+		ret = err;
-+	return ret;
-+}
-+
-+static int ext3cow_release_dquot(struct dquot *dquot)
-+{
-+	int ret, err;
-+	handle_t *handle;
-+
-+	handle = ext3cow_journal_start(dquot_to_inode(dquot),
-+					EXT3COW_QUOTA_DEL_BLOCKS(dquot->dq_sb));
-+	if (IS_ERR(handle))
-+		return PTR_ERR(handle);
-+	ret = dquot_release(dquot);
-+	err = ext3cow_journal_stop(handle);
-+	if (!ret)
-+		ret = err;
-+	return ret;
-+}
-+
-+static int ext3cow_mark_dquot_dirty(struct dquot *dquot)
-+{
-+	/* Are we journalling quotas? */
-+	if (EXT3COW_SB(dquot->dq_sb)->s_qf_names[USRQUOTA] ||
-+	    EXT3COW_SB(dquot->dq_sb)->s_qf_names[GRPQUOTA]) {
-+		dquot_mark_dquot_dirty(dquot);
-+		return ext3cow_write_dquot(dquot);
-+	} else {
-+		return dquot_mark_dquot_dirty(dquot);
-+	}
-+}
-+
-+static int ext3cow_write_info(struct super_block *sb, int type)
-+{
-+	int ret, err;
-+	handle_t *handle;
-+
-+	/* Data block + inode block */
-+	handle = ext3cow_journal_start(sb->s_root->d_inode, 2);
-+	if (IS_ERR(handle))
-+		return PTR_ERR(handle);
-+	ret = dquot_commit_info(sb, type);
-+	err = ext3cow_journal_stop(handle);
-+	if (!ret)
-+		ret = err;
-+	return ret;
-+}
-+
-+/*
-+ * Turn on quotas during mount time - we need to find
-+ * the quota file and such...
-+ */
-+static int ext3cow_quota_on_mount(struct super_block *sb, int type)
-+{
-+	return vfs_quota_on_mount(sb, EXT3COW_SB(sb)->s_qf_names[type],
-+			EXT3COW_SB(sb)->s_jquota_fmt, type);
-+}
-+
-+/*
-+ * Standard function to be called on quota_on
-+ */
-+static int ext3cow_quota_on(struct super_block *sb, int type, int format_id,
-+			 char *path)
-+{
-+	int err;
-+	struct nameidata nd;
-+
-+	if (!test_opt(sb, QUOTA))
-+		return -EINVAL;
-+	/* Not journalling quota? */
-+	if (!EXT3COW_SB(sb)->s_qf_names[USRQUOTA] &&
-+	    !EXT3COW_SB(sb)->s_qf_names[GRPQUOTA])
-+		return vfs_quota_on(sb, type, format_id, path);
-+	err = path_lookup(path, LOOKUP_FOLLOW, &nd);
-+	if (err)
-+		return err;
-+	/* Quotafile not on the same filesystem? */
-+	if (nd.mnt->mnt_sb != sb) {
-+		path_release(&nd);
-+		return -EXDEV;
-+	}
-+	/* Quotafile not of fs root? */
-+	if (nd.dentry->d_parent->d_inode != sb->s_root->d_inode)
-+		printk(KERN_WARNING
-+			"EXT3COW-fs: Quota file not on filesystem root. "
-+			"Journalled quota will not work.\n");
-+	path_release(&nd);
-+	return vfs_quota_on(sb, type, format_id, path);
-+}
-+
-+/* Read data from quotafile - avoid pagecache and such because we cannot afford
-+ * acquiring the locks... As quota files are never truncated and quota code
-+ * itself serializes the operations (and noone else should touch the files)
-+ * we don't have to be afraid of races */
-+static ssize_t ext3cow_quota_read(struct super_block *sb, int type, char *data,
-+			       size_t len, loff_t off)
-+{
-+	struct inode *inode = sb_dqopt(sb)->files[type];
-+	sector_t blk = off >> EXT3COW_BLOCK_SIZE_BITS(sb);
-+	int err = 0;
-+	int offset = off & (sb->s_blocksize - 1);
-+	int tocopy;
-+	size_t toread;
-+	struct buffer_head *bh;
-+	loff_t i_size = i_size_read(inode);
-+
-+	if (off > i_size)
-+		return 0;
-+	if (off+len > i_size)
-+		len = i_size-off;
-+	toread = len;
-+	while (toread > 0) {
-+		tocopy = sb->s_blocksize - offset < toread ?
-+				sb->s_blocksize - offset : toread;
-+		bh = ext3cow_bread(NULL, inode, blk, 0, &err);
-+		if (err)
-+			return err;
-+		if (!bh)	/* A hole? */
-+			memset(data, 0, tocopy);
-+		else
-+			memcpy(data, bh->b_data+offset, tocopy);
-+		brelse(bh);
-+		offset = 0;
-+		toread -= tocopy;
-+		data += tocopy;
-+		blk++;
-+	}
-+	return len;
-+}
-+
-+/* Write to quotafile (we know the transaction is already started and has
-+ * enough credits) */
-+static ssize_t ext3cow_quota_write(struct super_block *sb, int type,
-+				const char *data, size_t len, loff_t off)
-+{
-+	struct inode *inode = sb_dqopt(sb)->files[type];
-+	sector_t blk = off >> EXT3COW_BLOCK_SIZE_BITS(sb);
-+	int err = 0;
-+	int offset = off & (sb->s_blocksize - 1);
-+	int tocopy;
-+	int journal_quota = EXT3COW_SB(sb)->s_qf_names[type] != NULL;
-+	size_t towrite = len;
-+	struct buffer_head *bh;
-+	handle_t *handle = journal_current_handle();
-+
-+	mutex_lock_nested(&inode->i_mutex, I_MUTEX_QUOTA);
-+	while (towrite > 0) {
-+		tocopy = sb->s_blocksize - offset < towrite ?
-+				sb->s_blocksize - offset : towrite;
-+		bh = ext3cow_bread(handle, inode, blk, 1, &err);
-+		if (!bh)
-+			goto out;
-+		if (journal_quota) {
-+			err = ext3cow_journal_get_write_access(handle, bh);
-+			if (err) {
-+				brelse(bh);
-+				goto out;
-+			}
-+		}
-+		lock_buffer(bh);
-+		memcpy(bh->b_data+offset, data, tocopy);
-+		flush_dcache_page(bh->b_page);
-+		unlock_buffer(bh);
-+		if (journal_quota)
-+			err = ext3cow_journal_dirty_metadata(handle, bh);
-+		else {
-+			/* Always do at least ordered writes for quotas */
-+			err = ext3cow_journal_dirty_data(handle, bh);
-+			mark_buffer_dirty(bh);
-+		}
-+		brelse(bh);
-+		if (err)
-+			goto out;
-+		offset = 0;
-+		towrite -= tocopy;
-+		data += tocopy;
-+		blk++;
-+	}
-+out:
-+	if (len == towrite)
-+		return err;
-+	if (inode->i_size < off+len-towrite) {
-+		i_size_write(inode, off+len-towrite);
-+		EXT3COW_I(inode)->i_disksize = inode->i_size;
-+	}
-+	inode->i_version++;
-+	inode->i_mtime = inode->i_ctime = CURRENT_TIME;
-+	ext3cow_mark_inode_dirty(handle, inode);
-+	mutex_unlock(&inode->i_mutex);
-+	return len - towrite;
-+}
-+
-+#endif
-+
-+static int ext3cow_get_sb(struct file_system_type *fs_type,
-+	int flags, const char *dev_name, void *data, struct vfsmount *mnt)
-+{
-+	return get_sb_bdev(fs_type, flags, dev_name, data, ext3cow_fill_super, mnt);
-+}
-+
-+/* Code to update the epoch counter in the super block -znjp */
-+unsigned int ext3cow_take_snapshot(struct super_block *sb){
-+
-+  struct ext3cow_sb_info *sbi = NULL;
-+  struct ext3cow_super_block *es = NULL;
-+  tid_t target;
-+
-+  if(NULL == sb){
-+    printk("EXT3COW-fs: superblock is NULL when taking snapshot.\n");
-+    return -1;
-+  }
-+
-+  sbi = EXT3COW_SB(sb);
-+  es = sbi->s_es;
-+
-+  /* Sync the dirty blocks */
-+  if (journal_start_commit(EXT3COW_SB(sb)->s_journal, &target)) {
-+    log_wait_commit(EXT3COW_SB(sb)->s_journal, target);
-+	}
-+  
-+
-+  sbi->s_epoch_number = cpu_to_le32(get_seconds());
-+  es->s_epoch_number = sbi->s_epoch_number;
-+  sb->s_dirt = 1;
-+
-+  BUFFER_TRACE(EXT3COW_SB(sb)->s_sbh, "marking dirty");
-+  mark_buffer_dirty(sbi->s_sbh);
-+  ext3cow_commit_super (sb, es, 1);
-+
-+  return (unsigned int)sbi->s_epoch_number;
-+}
-+
-+static struct file_system_type ext3cow_fs_type = {
-+	.owner		= THIS_MODULE,
-+	.name		= "ext3cow",
-+	.get_sb		= ext3cow_get_sb,
-+	.kill_sb	= kill_block_super,
-+	.fs_flags	= FS_REQUIRES_DEV,
-+};
-+
-+static int __init init_ext3cow_fs(void)
-+{
-+	int err = init_ext3cow_xattr();
-+	if (err)
-+		return err;
-+	err = init_inodecache();
-+	if (err)
-+		goto out1;
-+        err = register_filesystem(&ext3cow_fs_type);
-+	if (err)
-+		goto out;
-+	return 0;
-+out:
-+	destroy_inodecache();
-+out1:
-+	exit_ext3cow_xattr();
-+	return err;
-+}
-+
-+static void __exit exit_ext3cow_fs(void)
-+{
-+	unregister_filesystem(&ext3cow_fs_type);
-+	destroy_inodecache();
-+	exit_ext3cow_xattr();
-+}
-+
-+MODULE_AUTHOR("Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others");
-+MODULE_DESCRIPTION("Second Extended Filesystem with journaling extensions");
-+MODULE_LICENSE("GPL");
-+module_init(init_ext3cow_fs)
-+module_exit(exit_ext3cow_fs)
-diff -ruN linux-2.6.20.3/fs/ext3cow/symlink.c linux-2.6.20.3-ext3cow/fs/ext3cow/symlink.c
---- linux-2.6.20.3/fs/ext3cow/symlink.c	1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.20.3-ext3cow/fs/ext3cow/symlink.c	2008-03-09 11:14:48.000000000 -0400
-@@ -0,0 +1,54 @@
-+/*
-+ *  linux/fs/ext3cow/symlink.c
-+ *
-+ * Only fast symlinks left here - the rest is done by generic code. AV, 1999
-+ *
-+ * Copyright (C) 1992, 1993, 1994, 1995
-+ * Remy Card (card@masi.ibp.fr)
-+ * Laboratoire MASI - Institut Blaise Pascal
-+ * Universite Pierre et Marie Curie (Paris VI)
-+ *
-+ *  from
-+ *
-+ *  linux/fs/minix/symlink.c
-+ *
-+ *  Copyright (C) 1991, 1992  Linus Torvalds
-+ *
-+ *  ext3cow symlink handling code
-+ */
-+
-+#include <linux/fs.h>
-+#include <linux/jbd.h>
-+#include <linux/ext3cow_fs.h>
-+#include <linux/namei.h>
-+#include "xattr.h"
-+
-+static void * ext3cow_follow_link(struct dentry *dentry, struct nameidata *nd)
-+{
-+	struct ext3cow_inode_info *ei = EXT3COW_I(dentry->d_inode);
-+	nd_set_link(nd, (char*)ei->i_data);
-+	return NULL;
-+}
-+
-+struct inode_operations ext3cow_symlink_inode_operations = {
-+	.readlink	= generic_readlink,
-+	.follow_link	= page_follow_link_light,
-+	.put_link	= page_put_link,
-+#ifdef CONFIG_EXT3COW_FS_XATTR
-+	.setxattr	= generic_setxattr,
-+	.getxattr	= generic_getxattr,
-+	.listxattr	= ext3cow_listxattr,
-+	.removexattr	= generic_removexattr,
-+#endif
-+};
-+
-+struct inode_operations ext3cow_fast_symlink_inode_operations = {
-+	.readlink	= generic_readlink,
-+	.follow_link	= ext3cow_follow_link,
-+#ifdef CONFIG_EXT3COW_FS_XATTR
-+	.setxattr	= generic_setxattr,
-+	.getxattr	= generic_getxattr,
-+	.listxattr	= ext3cow_listxattr,
-+	.removexattr	= generic_removexattr,
-+#endif
-+};
-diff -ruN linux-2.6.20.3/fs/ext3cow/xattr.c linux-2.6.20.3-ext3cow/fs/ext3cow/xattr.c
---- linux-2.6.20.3/fs/ext3cow/xattr.c	1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.20.3-ext3cow/fs/ext3cow/xattr.c	2008-03-09 11:14:49.000000000 -0400
-@@ -0,0 +1,1314 @@
-+/*
-+ * linux/fs/ext3cow/xattr.c
-+ *
-+ * Copyright (C) 2001-2003 Andreas Gruenbacher, <agruen@suse.de>
-+ *
-+ * Fix by Harrison Xing <harrison@mountainviewdata.com>.
-+ * Ext3 code with a lot of help from Eric Jarman <ejarman@acm.org>.
-+ * Extended attributes for symlinks and special files added per
-+ *  suggestion of Luka Renko <luka.renko@hermes.si>.
-+ * xattr consolidation Copyright (c) 2004 James Morris <jmorris@redhat.com>,
-+ *  Red Hat Inc.
-+ * ea-in-inode support by Alex Tomas <alex@clusterfs.com> aka bzzz
-+ *  and Andreas Gruenbacher <agruen@suse.de>.
-+ */
-+
-+/*
-+ * Extended attributes are stored directly in inodes (on file systems with
-+ * inodes bigger than 128 bytes) and on additional disk blocks. The i_file_acl
-+ * field contains the block number if an inode uses an additional block. All
-+ * attributes must fit in the inode and one additional block. Blocks that
-+ * contain the identical set of attributes may be shared among several inodes.
-+ * Identical blocks are detected by keeping a cache of blocks that have
-+ * recently been accessed.
-+ *
-+ * The attributes in inodes and on blocks have a different header; the entries
-+ * are stored in the same format:
-+ *
-+ *   +------------------+
-+ *   | header           |
-+ *   | entry 1          | |
-+ *   | entry 2          | | growing downwards
-+ *   | entry 3          | v
-+ *   | four null bytes  |
-+ *   | . . .            |
-+ *   | value 1          | ^
-+ *   | value 3          | | growing upwards
-+ *   | value 2          | |
-+ *   +------------------+
-+ *
-+ * The header is followed by multiple entry descriptors. In disk blocks, the
-+ * entry descriptors are kept sorted. In inodes, they are unsorted. The
-+ * attribute values are aligned to the end of the block in no specific order.
-+ *
-+ * Locking strategy
-+ * ----------------
-+ * EXT3COW_I(inode)->i_file_acl is protected by EXT3COW_I(inode)->xattr_sem.
-+ * EA blocks are only changed if they are exclusive to an inode, so
-+ * holding xattr_sem also means that nothing but the EA block's reference
-+ * count can change. Multiple writers to the same block are synchronized
-+ * by the buffer lock.
-+ */
-+
-+#include <linux/init.h>
-+#include <linux/fs.h>
-+#include <linux/slab.h>
-+#include <linux/ext3cow_jbd.h>
-+#include <linux/ext3cow_fs.h>
-+#include <linux/mbcache.h>
-+#include <linux/quotaops.h>
-+#include <linux/rwsem.h>
-+#include "xattr.h"
-+#include "acl.h"
-+
-+#define BHDR(bh) ((struct ext3cow_xattr_header *)((bh)->b_data))
-+#define ENTRY(ptr) ((struct ext3cow_xattr_entry *)(ptr))
-+#define BFIRST(bh) ENTRY(BHDR(bh)+1)
-+#define IS_LAST_ENTRY(entry) (*(__u32 *)(entry) == 0)
-+
-+#define IHDR(inode, raw_inode) \
-+	((struct ext3cow_xattr_ibody_header *) \
-+		((void *)raw_inode + \
-+		 EXT3COW_GOOD_OLD_INODE_SIZE + \
-+		 EXT3COW_I(inode)->i_extra_isize))
-+#define IFIRST(hdr) ((struct ext3cow_xattr_entry *)((hdr)+1))
-+
-+#ifdef EXT3COW_XATTR_DEBUG
-+# define ea_idebug(inode, f...) do { \
-+		printk(KERN_DEBUG "inode %s:%lu: ", \
-+			inode->i_sb->s_id, inode->i_ino); \
-+		printk(f); \
-+		printk("\n"); \
-+	} while (0)
-+# define ea_bdebug(bh, f...) do { \
-+		char b[BDEVNAME_SIZE]; \
-+		printk(KERN_DEBUG "block %s:%lu: ", \
-+			bdevname(bh->b_bdev, b), \
-+			(unsigned long) bh->b_blocknr); \
-+		printk(f); \
-+		printk("\n"); \
-+	} while (0)
-+#else
-+# define ea_idebug(f...)
-+# define ea_bdebug(f...)
-+#endif
-+
-+static void ext3cow_xattr_cache_insert(struct buffer_head *);
-+static struct buffer_head *ext3cow_xattr_cache_find(struct inode *,
-+						 struct ext3cow_xattr_header *,
-+						 struct mb_cache_entry **);
-+static void ext3cow_xattr_rehash(struct ext3cow_xattr_header *,
-+			      struct ext3cow_xattr_entry *);
-+
-+static struct mb_cache *ext3cow_xattr_cache;
-+
-+static struct xattr_handler *ext3cow_xattr_handler_map[] = {
-+	[EXT3COW_XATTR_INDEX_USER]		     = &ext3cow_xattr_user_handler,
-+#ifdef CONFIG_EXT3COW_FS_POSIX_ACL
-+	[EXT3COW_XATTR_INDEX_POSIX_ACL_ACCESS]  = &ext3cow_xattr_acl_access_handler,
-+	[EXT3COW_XATTR_INDEX_POSIX_ACL_DEFAULT] = &ext3cow_xattr_acl_default_handler,
-+#endif
-+	[EXT3COW_XATTR_INDEX_TRUSTED]	     = &ext3cow_xattr_trusted_handler,
-+#ifdef CONFIG_EXT3COW_FS_SECURITY
-+	[EXT3COW_XATTR_INDEX_SECURITY]	     = &ext3cow_xattr_security_handler,
-+#endif
-+};
-+
-+struct xattr_handler *ext3cow_xattr_handlers[] = {
-+	&ext3cow_xattr_user_handler,
-+	&ext3cow_xattr_trusted_handler,
-+#ifdef CONFIG_EXT3COW_FS_POSIX_ACL
-+	&ext3cow_xattr_acl_access_handler,
-+	&ext3cow_xattr_acl_default_handler,
-+#endif
-+#ifdef CONFIG_EXT3COW_FS_SECURITY
-+	&ext3cow_xattr_security_handler,
-+#endif
-+	NULL
-+};
-+
-+static inline struct xattr_handler *
-+ext3cow_xattr_handler(int name_index)
-+{
-+	struct xattr_handler *handler = NULL;
-+
-+	if (name_index > 0 && name_index < ARRAY_SIZE(ext3cow_xattr_handler_map))
-+		handler = ext3cow_xattr_handler_map[name_index];
-+	return handler;
-+}
-+
-+/*
-+ * Inode operation listxattr()
-+ *
-+ * dentry->d_inode->i_mutex: don't care
-+ */
-+ssize_t
-+ext3cow_listxattr(struct dentry *dentry, char *buffer, size_t size)
-+{
-+	return ext3cow_xattr_list(dentry->d_inode, buffer, size);
-+}
-+
-+static int
-+ext3cow_xattr_check_names(struct ext3cow_xattr_entry *entry, void *end)
-+{
-+	while (!IS_LAST_ENTRY(entry)) {
-+		struct ext3cow_xattr_entry *next = EXT3COW_XATTR_NEXT(entry);
-+		if ((void *)next >= end)
-+			return -EIO;
-+		entry = next;
-+	}
-+	return 0;
-+}
-+
-+static inline int
-+ext3cow_xattr_check_block(struct buffer_head *bh)
-+{
-+	int error;
-+
-+	if (BHDR(bh)->h_magic != cpu_to_le32(EXT3COW_XATTR_MAGIC) ||
-+	    BHDR(bh)->h_blocks != cpu_to_le32(1))
-+		return -EIO;
-+	error = ext3cow_xattr_check_names(BFIRST(bh), bh->b_data + bh->b_size);
-+	return error;
-+}
-+
-+static inline int
-+ext3cow_xattr_check_entry(struct ext3cow_xattr_entry *entry, size_t size)
-+{
-+	size_t value_size = le32_to_cpu(entry->e_value_size);
-+
-+	if (entry->e_value_block != 0 || value_size > size ||
-+	    le16_to_cpu(entry->e_value_offs) + value_size > size)
-+		return -EIO;
-+	return 0;
-+}
-+
-+static int
-+ext3cow_xattr_find_entry(struct ext3cow_xattr_entry **pentry, int name_index,
-+		      const char *name, size_t size, int sorted)
-+{
-+	struct ext3cow_xattr_entry *entry;
-+	size_t name_len;
-+	int cmp = 1;
-+
-+	if (name == NULL)
-+		return -EINVAL;
-+	name_len = strlen(name);
-+	entry = *pentry;
-+	for (; !IS_LAST_ENTRY(entry); entry = EXT3COW_XATTR_NEXT(entry)) {
-+		cmp = name_index - entry->e_name_index;
-+		if (!cmp)
-+			cmp = name_len - entry->e_name_len;
-+		if (!cmp)
-+			cmp = memcmp(name, entry->e_name, name_len);
-+		if (cmp <= 0 && (sorted || cmp == 0))
-+			break;
-+	}
-+	*pentry = entry;
-+	if (!cmp && ext3cow_xattr_check_entry(entry, size))
-+			return -EIO;
-+	return cmp ? -ENODATA : 0;
-+}
-+
-+static int
-+ext3cow_xattr_block_get(struct inode *inode, int name_index, const char *name,
-+		     void *buffer, size_t buffer_size)
-+{
-+	struct buffer_head *bh = NULL;
-+	struct ext3cow_xattr_entry *entry;
-+	size_t size;
-+	int error;
-+
-+	ea_idebug(inode, "name=%d.%s, buffer=%p, buffer_size=%ld",
-+		  name_index, name, buffer, (long)buffer_size);
-+
-+	error = -ENODATA;
-+	if (!EXT3COW_I(inode)->i_file_acl)
-+		goto cleanup;
-+	ea_idebug(inode, "reading block %u", EXT3COW_I(inode)->i_file_acl);
-+	bh = sb_bread(inode->i_sb, EXT3COW_I(inode)->i_file_acl);
-+	if (!bh)
-+		goto cleanup;
-+	ea_bdebug(bh, "b_count=%d, refcount=%d",
-+		atomic_read(&(bh->b_count)), le32_to_cpu(BHDR(bh)->h_refcount));
-+	if (ext3cow_xattr_check_block(bh)) {
-+bad_block:	ext3cow_error(inode->i_sb, __FUNCTION__,
-+			   "inode %lu: bad block "E3FSBLK, inode->i_ino,
-+			   EXT3COW_I(inode)->i_file_acl);
-+		error = -EIO;
-+		goto cleanup;
-+	}
-+	ext3cow_xattr_cache_insert(bh);
-+	entry = BFIRST(bh);
-+	error = ext3cow_xattr_find_entry(&entry, name_index, name, bh->b_size, 1);
-+	if (error == -EIO)
-+		goto bad_block;
-+	if (error)
-+		goto cleanup;
-+	size = le32_to_cpu(entry->e_value_size);
-+	if (buffer) {
-+		error = -ERANGE;
-+		if (size > buffer_size)
-+			goto cleanup;
-+		memcpy(buffer, bh->b_data + le16_to_cpu(entry->e_value_offs),
-+		       size);
-+	}
-+	error = size;
-+
-+cleanup:
-+	brelse(bh);
-+	return error;
-+}
-+
-+static int
-+ext3cow_xattr_ibody_get(struct inode *inode, int name_index, const char *name,
-+		     void *buffer, size_t buffer_size)
-+{
-+	struct ext3cow_xattr_ibody_header *header;
-+	struct ext3cow_xattr_entry *entry;
-+	struct ext3cow_inode *raw_inode;
-+	struct ext3cow_iloc iloc;
-+	size_t size;
-+	void *end;
-+	int error;
-+
-+	if (!(EXT3COW_I(inode)->i_state & EXT3COW_STATE_XATTR))
-+		return -ENODATA;
-+	error = ext3cow_get_inode_loc(inode, &iloc);
-+	if (error)
-+		return error;
-+	raw_inode = ext3cow_raw_inode(&iloc);
-+	header = IHDR(inode, raw_inode);
-+	entry = IFIRST(header);
-+	end = (void *)raw_inode + EXT3COW_SB(inode->i_sb)->s_inode_size;
-+	error = ext3cow_xattr_check_names(entry, end);
-+	if (error)
-+		goto cleanup;
-+	error = ext3cow_xattr_find_entry(&entry, name_index, name,
-+				      end - (void *)entry, 0);
-+	if (error)
-+		goto cleanup;
-+	size = le32_to_cpu(entry->e_value_size);
-+	if (buffer) {
-+		error = -ERANGE;
-+		if (size > buffer_size)
-+			goto cleanup;
-+		memcpy(buffer, (void *)IFIRST(header) +
-+		       le16_to_cpu(entry->e_value_offs), size);
-+	}
-+	error = size;
-+
-+cleanup:
-+	brelse(iloc.bh);
-+	return error;
-+}
-+
-+/*
-+ * ext3cow_xattr_get()
-+ *
-+ * Copy an extended attribute into the buffer
-+ * provided, or compute the buffer size required.
-+ * Buffer is NULL to compute the size of the buffer required.
-+ *
-+ * Returns a negative error number on failure, or the number of bytes
-+ * used / required on success.
-+ */
-+int
-+ext3cow_xattr_get(struct inode *inode, int name_index, const char *name,
-+	       void *buffer, size_t buffer_size)
-+{
-+	int error;
-+
-+	down_read(&EXT3COW_I(inode)->xattr_sem);
-+	error = ext3cow_xattr_ibody_get(inode, name_index, name, buffer,
-+				     buffer_size);
-+	if (error == -ENODATA)
-+		error = ext3cow_xattr_block_get(inode, name_index, name, buffer,
-+					     buffer_size);
-+	up_read(&EXT3COW_I(inode)->xattr_sem);
-+	return error;
-+}
-+
-+static int
-+ext3cow_xattr_list_entries(struct inode *inode, struct ext3cow_xattr_entry *entry,
-+			char *buffer, size_t buffer_size)
-+{
-+	size_t rest = buffer_size;
-+
-+	for (; !IS_LAST_ENTRY(entry); entry = EXT3COW_XATTR_NEXT(entry)) {
-+		struct xattr_handler *handler =
-+			ext3cow_xattr_handler(entry->e_name_index);
-+
-+		if (handler) {
-+			size_t size = handler->list(inode, buffer, rest,
-+						    entry->e_name,
-+						    entry->e_name_len);
-+			if (buffer) {
-+				if (size > rest)
-+					return -ERANGE;
-+				buffer += size;
-+			}
-+			rest -= size;
-+		}
-+	}
-+	return buffer_size - rest;
-+}
-+
-+static int
-+ext3cow_xattr_block_list(struct inode *inode, char *buffer, size_t buffer_size)
-+{
-+	struct buffer_head *bh = NULL;
-+	int error;
-+
-+	ea_idebug(inode, "buffer=%p, buffer_size=%ld",
-+		  buffer, (long)buffer_size);
-+
-+	error = 0;
-+	if (!EXT3COW_I(inode)->i_file_acl)
-+		goto cleanup;
-+	ea_idebug(inode, "reading block %u", EXT3COW_I(inode)->i_file_acl);
-+	bh = sb_bread(inode->i_sb, EXT3COW_I(inode)->i_file_acl);
-+	error = -EIO;
-+	if (!bh)
-+		goto cleanup;
-+	ea_bdebug(bh, "b_count=%d, refcount=%d",
-+		atomic_read(&(bh->b_count)), le32_to_cpu(BHDR(bh)->h_refcount));
-+	if (ext3cow_xattr_check_block(bh)) {
-+		ext3cow_error(inode->i_sb, __FUNCTION__,
-+			   "inode %lu: bad block "E3FSBLK, inode->i_ino,
-+			   EXT3COW_I(inode)->i_file_acl);
-+		error = -EIO;
-+		goto cleanup;
-+	}
-+	ext3cow_xattr_cache_insert(bh);
-+	error = ext3cow_xattr_list_entries(inode, BFIRST(bh), buffer, buffer_size);
-+
-+cleanup:
-+	brelse(bh);
-+
-+	return error;
-+}
-+
-+static int
-+ext3cow_xattr_ibody_list(struct inode *inode, char *buffer, size_t buffer_size)
-+{
-+	struct ext3cow_xattr_ibody_header *header;
-+	struct ext3cow_inode *raw_inode;
-+	struct ext3cow_iloc iloc;
-+	void *end;
-+	int error;
-+
-+	if (!(EXT3COW_I(inode)->i_state & EXT3COW_STATE_XATTR))
-+		return 0;
-+	error = ext3cow_get_inode_loc(inode, &iloc);
-+	if (error)
-+		return error;
-+	raw_inode = ext3cow_raw_inode(&iloc);
-+	header = IHDR(inode, raw_inode);
-+	end = (void *)raw_inode + EXT3COW_SB(inode->i_sb)->s_inode_size;
-+	error = ext3cow_xattr_check_names(IFIRST(header), end);
-+	if (error)
-+		goto cleanup;
-+	error = ext3cow_xattr_list_entries(inode, IFIRST(header),
-+					buffer, buffer_size);
-+
-+cleanup:
-+	brelse(iloc.bh);
-+	return error;
-+}
-+
-+/*
-+ * ext3cow_xattr_list()
-+ *
-+ * Copy a list of attribute names into the buffer
-+ * provided, or compute the buffer size required.
-+ * Buffer is NULL to compute the size of the buffer required.
-+ *
-+ * Returns a negative error number on failure, or the number of bytes
-+ * used / required on success.
-+ */
-+int
-+ext3cow_xattr_list(struct inode *inode, char *buffer, size_t buffer_size)
-+{
-+	int i_error, b_error;
-+
-+	down_read(&EXT3COW_I(inode)->xattr_sem);
-+	i_error = ext3cow_xattr_ibody_list(inode, buffer, buffer_size);
-+	if (i_error < 0) {
-+		b_error = 0;
-+	} else {
-+		if (buffer) {
-+			buffer += i_error;
-+			buffer_size -= i_error;
-+		}
-+		b_error = ext3cow_xattr_block_list(inode, buffer, buffer_size);
-+		if (b_error < 0)
-+			i_error = 0;
-+	}
-+	up_read(&EXT3COW_I(inode)->xattr_sem);
-+	return i_error + b_error;
-+}
-+
-+/*
-+ * If the EXT3COW_FEATURE_COMPAT_EXT_ATTR feature of this file system is
-+ * not set, set it.
-+ */
-+static void ext3cow_xattr_update_super_block(handle_t *handle,
-+					  struct super_block *sb)
-+{
-+	if (EXT3COW_HAS_COMPAT_FEATURE(sb, EXT3COW_FEATURE_COMPAT_EXT_ATTR))
-+		return;
-+
-+	if (ext3cow_journal_get_write_access(handle, EXT3COW_SB(sb)->s_sbh) == 0) {
-+		EXT3COW_SET_COMPAT_FEATURE(sb, EXT3COW_FEATURE_COMPAT_EXT_ATTR);
-+		sb->s_dirt = 1;
-+		ext3cow_journal_dirty_metadata(handle, EXT3COW_SB(sb)->s_sbh);
-+	}
-+}
-+
-+/*
-+ * Release the xattr block BH: If the reference count is > 1, decrement
-+ * it; otherwise free the block.
-+ */
-+static void
-+ext3cow_xattr_release_block(handle_t *handle, struct inode *inode,
-+			 struct buffer_head *bh)
-+{
-+	struct mb_cache_entry *ce = NULL;
-+
-+	ce = mb_cache_entry_get(ext3cow_xattr_cache, bh->b_bdev, bh->b_blocknr);
-+	if (BHDR(bh)->h_refcount == cpu_to_le32(1)) {
-+		ea_bdebug(bh, "refcount now=0; freeing");
-+		if (ce)
-+			mb_cache_entry_free(ce);
-+		ext3cow_free_blocks(handle, inode, bh->b_blocknr, 1);
-+		get_bh(bh);
-+		ext3cow_forget(handle, 1, inode, bh, bh->b_blocknr);
-+	} else {
-+		if (ext3cow_journal_get_write_access(handle, bh) == 0) {
-+			lock_buffer(bh);
-+			BHDR(bh)->h_refcount = cpu_to_le32(
-+				le32_to_cpu(BHDR(bh)->h_refcount) - 1);
-+			ext3cow_journal_dirty_metadata(handle, bh);
-+			if (IS_SYNC(inode))
-+				handle->h_sync = 1;
-+			DQUOT_FREE_BLOCK(inode, 1);
-+			unlock_buffer(bh);
-+			ea_bdebug(bh, "refcount now=%d; releasing",
-+				  le32_to_cpu(BHDR(bh)->h_refcount));
-+		}
-+		if (ce)
-+			mb_cache_entry_release(ce);
-+	}
-+}
-+
-+struct ext3cow_xattr_info {
-+	int name_index;
-+	const char *name;
-+	const void *value;
-+	size_t value_len;
-+};
-+
-+struct ext3cow_xattr_search {
-+	struct ext3cow_xattr_entry *first;
-+	void *base;
-+	void *end;
-+	struct ext3cow_xattr_entry *here;
-+	int not_found;
-+};
-+
-+static int
-+ext3cow_xattr_set_entry(struct ext3cow_xattr_info *i, struct ext3cow_xattr_search *s)
-+{
-+	struct ext3cow_xattr_entry *last;
-+	size_t free, min_offs = s->end - s->base, name_len = strlen(i->name);
-+
-+	/* Compute min_offs and last. */
-+	last = s->first;
-+	for (; !IS_LAST_ENTRY(last); last = EXT3COW_XATTR_NEXT(last)) {
-+		if (!last->e_value_block && last->e_value_size) {
-+			size_t offs = le16_to_cpu(last->e_value_offs);
-+			if (offs < min_offs)
-+				min_offs = offs;
-+		}
-+	}
-+	free = min_offs - ((void *)last - s->base) - sizeof(__u32);
-+	if (!s->not_found) {
-+		if (!s->here->e_value_block && s->here->e_value_size) {
-+			size_t size = le32_to_cpu(s->here->e_value_size);
-+			free += EXT3COW_XATTR_SIZE(size);
-+		}
-+		free += EXT3COW_XATTR_LEN(name_len);
-+	}
-+	if (i->value) {
-+		if (free < EXT3COW_XATTR_SIZE(i->value_len) ||
-+		    free < EXT3COW_XATTR_LEN(name_len) +
-+			   EXT3COW_XATTR_SIZE(i->value_len))
-+			return -ENOSPC;
-+	}
-+
-+	if (i->value && s->not_found) {
-+		/* Insert the new name. */
-+		size_t size = EXT3COW_XATTR_LEN(name_len);
-+		size_t rest = (void *)last - (void *)s->here + sizeof(__u32);
-+		memmove((void *)s->here + size, s->here, rest);
-+		memset(s->here, 0, size);
-+		s->here->e_name_index = i->name_index;
-+		s->here->e_name_len = name_len;
-+		memcpy(s->here->e_name, i->name, name_len);
-+	} else {
-+		if (!s->here->e_value_block && s->here->e_value_size) {
-+			void *first_val = s->base + min_offs;
-+			size_t offs = le16_to_cpu(s->here->e_value_offs);
-+			void *val = s->base + offs;
-+			size_t size = EXT3COW_XATTR_SIZE(
-+				le32_to_cpu(s->here->e_value_size));
-+
-+			if (i->value && size == EXT3COW_XATTR_SIZE(i->value_len)) {
-+				/* The old and the new value have the same
-+				   size. Just replace. */
-+				s->here->e_value_size =
-+					cpu_to_le32(i->value_len);
-+				memset(val + size - EXT3COW_XATTR_PAD, 0,
-+				       EXT3COW_XATTR_PAD); /* Clear pad bytes. */
-+				memcpy(val, i->value, i->value_len);
-+				return 0;
-+			}
-+
-+			/* Remove the old value. */
-+			memmove(first_val + size, first_val, val - first_val);
-+			memset(first_val, 0, size);
-+			s->here->e_value_size = 0;
-+			s->here->e_value_offs = 0;
-+			min_offs += size;
-+
-+			/* Adjust all value offsets. */
-+			last = s->first;
-+			while (!IS_LAST_ENTRY(last)) {
-+				size_t o = le16_to_cpu(last->e_value_offs);
-+				if (!last->e_value_block &&
-+				    last->e_value_size && o < offs)
-+					last->e_value_offs =
-+						cpu_to_le16(o + size);
-+				last = EXT3COW_XATTR_NEXT(last);
-+			}
-+		}
-+		if (!i->value) {
-+			/* Remove the old name. */
-+			size_t size = EXT3COW_XATTR_LEN(name_len);
-+			last = ENTRY((void *)last - size);
-+			memmove(s->here, (void *)s->here + size,
-+				(void *)last - (void *)s->here + sizeof(__u32));
-+			memset(last, 0, size);
-+		}
-+	}
-+
-+	if (i->value) {
-+		/* Insert the new value. */
-+		s->here->e_value_size = cpu_to_le32(i->value_len);
-+		if (i->value_len) {
-+			size_t size = EXT3COW_XATTR_SIZE(i->value_len);
-+			void *val = s->base + min_offs - size;
-+			s->here->e_value_offs = cpu_to_le16(min_offs - size);
-+			memset(val + size - EXT3COW_XATTR_PAD, 0,
-+			       EXT3COW_XATTR_PAD); /* Clear the pad bytes. */
-+			memcpy(val, i->value, i->value_len);
-+		}
-+	}
-+	return 0;
-+}
-+
-+struct ext3cow_xattr_block_find {
-+	struct ext3cow_xattr_search s;
-+	struct buffer_head *bh;
-+};
-+
-+static int
-+ext3cow_xattr_block_find(struct inode *inode, struct ext3cow_xattr_info *i,
-+		      struct ext3cow_xattr_block_find *bs)
-+{
-+	struct super_block *sb = inode->i_sb;
-+	int error;
-+
-+	ea_idebug(inode, "name=%d.%s, value=%p, value_len=%ld",
-+		  i->name_index, i->name, i->value, (long)i->value_len);
-+
-+	if (EXT3COW_I(inode)->i_file_acl) {
-+		/* The inode already has an extended attribute block. */
-+		bs->bh = sb_bread(sb, EXT3COW_I(inode)->i_file_acl);
-+		error = -EIO;
-+		if (!bs->bh)
-+			goto cleanup;
-+		ea_bdebug(bs->bh, "b_count=%d, refcount=%d",
-+			atomic_read(&(bs->bh->b_count)),
-+			le32_to_cpu(BHDR(bs->bh)->h_refcount));
-+		if (ext3cow_xattr_check_block(bs->bh)) {
-+			ext3cow_error(sb, __FUNCTION__,
-+				"inode %lu: bad block "E3FSBLK, inode->i_ino,
-+				EXT3COW_I(inode)->i_file_acl);
-+			error = -EIO;
-+			goto cleanup;
-+		}
-+		/* Find the named attribute. */
-+		bs->s.base = BHDR(bs->bh);
-+		bs->s.first = BFIRST(bs->bh);
-+		bs->s.end = bs->bh->b_data + bs->bh->b_size;
-+		bs->s.here = bs->s.first;
-+		error = ext3cow_xattr_find_entry(&bs->s.here, i->name_index,
-+					      i->name, bs->bh->b_size, 1);
-+		if (error && error != -ENODATA)
-+			goto cleanup;
-+		bs->s.not_found = error;
-+	}
-+	error = 0;
-+
-+cleanup:
-+	return error;
-+}
-+
-+static int
-+ext3cow_xattr_block_set(handle_t *handle, struct inode *inode,
-+		     struct ext3cow_xattr_info *i,
-+		     struct ext3cow_xattr_block_find *bs)
-+{
-+	struct super_block *sb = inode->i_sb;
-+	struct buffer_head *new_bh = NULL;
-+	struct ext3cow_xattr_search *s = &bs->s;
-+	struct mb_cache_entry *ce = NULL;
-+	int error;
-+
-+#define header(x) ((struct ext3cow_xattr_header *)(x))
-+
-+	if (i->value && i->value_len > sb->s_blocksize)
-+		return -ENOSPC;
-+	if (s->base) {
-+		ce = mb_cache_entry_get(ext3cow_xattr_cache, bs->bh->b_bdev,
-+					bs->bh->b_blocknr);
-+		if (header(s->base)->h_refcount == cpu_to_le32(1)) {
-+			if (ce) {
-+				mb_cache_entry_free(ce);
-+				ce = NULL;
-+			}
-+			ea_bdebug(bs->bh, "modifying in-place");
-+			error = ext3cow_journal_get_write_access(handle, bs->bh);
-+			if (error)
-+				goto cleanup;
-+			lock_buffer(bs->bh);
-+			error = ext3cow_xattr_set_entry(i, s);
-+			if (!error) {
-+				if (!IS_LAST_ENTRY(s->first))
-+					ext3cow_xattr_rehash(header(s->base),
-+							  s->here);
-+				ext3cow_xattr_cache_insert(bs->bh);
-+			}
-+			unlock_buffer(bs->bh);
-+			if (error == -EIO)
-+				goto bad_block;
-+			if (!error)
-+				error = ext3cow_journal_dirty_metadata(handle,
-+								    bs->bh);
-+			if (error)
-+				goto cleanup;
-+			goto inserted;
-+		} else {
-+			int offset = (char *)s->here - bs->bh->b_data;
-+
-+			if (ce) {
-+				mb_cache_entry_release(ce);
-+				ce = NULL;
-+			}
-+			ea_bdebug(bs->bh, "cloning");
-+			s->base = kmalloc(bs->bh->b_size, GFP_KERNEL);
-+			error = -ENOMEM;
-+			if (s->base == NULL)
-+				goto cleanup;
-+			memcpy(s->base, BHDR(bs->bh), bs->bh->b_size);
-+			s->first = ENTRY(header(s->base)+1);
-+			header(s->base)->h_refcount = cpu_to_le32(1);
-+			s->here = ENTRY(s->base + offset);
-+			s->end = s->base + bs->bh->b_size;
-+		}
-+	} else {
-+		/* Allocate a buffer where we construct the new block. */
-+		s->base = kmalloc(sb->s_blocksize, GFP_KERNEL);
-+		/* assert(header == s->base) */
-+		error = -ENOMEM;
-+		if (s->base == NULL)
-+			goto cleanup;
-+		memset(s->base, 0, sb->s_blocksize);
-+		header(s->base)->h_magic = cpu_to_le32(EXT3COW_XATTR_MAGIC);
-+		header(s->base)->h_blocks = cpu_to_le32(1);
-+		header(s->base)->h_refcount = cpu_to_le32(1);
-+		s->first = ENTRY(header(s->base)+1);
-+		s->here = ENTRY(header(s->base)+1);
-+		s->end = s->base + sb->s_blocksize;
-+	}
-+
-+	error = ext3cow_xattr_set_entry(i, s);
-+	if (error == -EIO)
-+		goto bad_block;
-+	if (error)
-+		goto cleanup;
-+	if (!IS_LAST_ENTRY(s->first))
-+		ext3cow_xattr_rehash(header(s->base), s->here);
-+
-+inserted:
-+	if (!IS_LAST_ENTRY(s->first)) {
-+		new_bh = ext3cow_xattr_cache_find(inode, header(s->base), &ce);
-+		if (new_bh) {
-+			/* We found an identical block in the cache. */
-+			if (new_bh == bs->bh)
-+				ea_bdebug(new_bh, "keeping");
-+			else {
-+				/* The old block is released after updating
-+				   the inode. */
-+				error = -EDQUOT;
-+				if (DQUOT_ALLOC_BLOCK(inode, 1))
-+					goto cleanup;
-+				error = ext3cow_journal_get_write_access(handle,
-+								      new_bh);
-+				if (error)
-+					goto cleanup_dquot;
-+				lock_buffer(new_bh);
-+				BHDR(new_bh)->h_refcount = cpu_to_le32(1 +
-+					le32_to_cpu(BHDR(new_bh)->h_refcount));
-+				ea_bdebug(new_bh, "reusing; refcount now=%d",
-+					le32_to_cpu(BHDR(new_bh)->h_refcount));
-+				unlock_buffer(new_bh);
-+				error = ext3cow_journal_dirty_metadata(handle,
-+								    new_bh);
-+				if (error)
-+					goto cleanup_dquot;
-+			}
-+			mb_cache_entry_release(ce);
-+			ce = NULL;
-+		} else if (bs->bh && s->base == bs->bh->b_data) {
-+			/* We were modifying this block in-place. */
-+			ea_bdebug(bs->bh, "keeping this block");
-+			new_bh = bs->bh;
-+			get_bh(new_bh);
-+		} else {
-+			/* We need to allocate a new block */
-+			ext3cow_fsblk_t goal = le32_to_cpu(
-+					EXT3COW_SB(sb)->s_es->s_first_data_block) +
-+				(ext3cow_fsblk_t)EXT3COW_I(inode)->i_block_group *
-+				EXT3COW_BLOCKS_PER_GROUP(sb);
-+			ext3cow_fsblk_t block = ext3cow_new_block(handle, inode,
-+							goal, &error);
-+			if (error)
-+				goto cleanup;
-+			ea_idebug(inode, "creating block %d", block);
-+
-+			new_bh = sb_getblk(sb, block);
-+			if (!new_bh) {
-+getblk_failed:
-+				ext3cow_free_blocks(handle, inode, block, 1);
-+				error = -EIO;
-+				goto cleanup;
-+			}
-+			lock_buffer(new_bh);
-+			error = ext3cow_journal_get_create_access(handle, new_bh);
-+			if (error) {
-+				unlock_buffer(new_bh);
-+				goto getblk_failed;
-+			}
-+			memcpy(new_bh->b_data, s->base, new_bh->b_size);
-+			set_buffer_uptodate(new_bh);
-+			unlock_buffer(new_bh);
-+			ext3cow_xattr_cache_insert(new_bh);
-+			error = ext3cow_journal_dirty_metadata(handle, new_bh);
-+			if (error)
-+				goto cleanup;
-+		}
-+	}
-+
-+	/* Update the inode. */
-+	EXT3COW_I(inode)->i_file_acl = new_bh ? new_bh->b_blocknr : 0;
-+
-+	/* Drop the previous xattr block. */
-+	if (bs->bh && bs->bh != new_bh)
-+		ext3cow_xattr_release_block(handle, inode, bs->bh);
-+	error = 0;
-+
-+cleanup:
-+	if (ce)
-+		mb_cache_entry_release(ce);
-+	brelse(new_bh);
-+	if (!(bs->bh && s->base == bs->bh->b_data))
-+		kfree(s->base);
-+
-+	return error;
-+
-+cleanup_dquot:
-+	DQUOT_FREE_BLOCK(inode, 1);
-+	goto cleanup;
-+
-+bad_block:
-+	ext3cow_error(inode->i_sb, __FUNCTION__,
-+		   "inode %lu: bad block "E3FSBLK, inode->i_ino,
-+		   EXT3COW_I(inode)->i_file_acl);
-+	goto cleanup;
-+
-+#undef header
-+}
-+
-+struct ext3cow_xattr_ibody_find {
-+	struct ext3cow_xattr_search s;
-+	struct ext3cow_iloc iloc;
-+};
-+
-+static int
-+ext3cow_xattr_ibody_find(struct inode *inode, struct ext3cow_xattr_info *i,
-+		      struct ext3cow_xattr_ibody_find *is)
-+{
-+	struct ext3cow_xattr_ibody_header *header;
-+	struct ext3cow_inode *raw_inode;
-+	int error;
-+
-+	if (EXT3COW_I(inode)->i_extra_isize == 0)
-+		return 0;
-+	raw_inode = ext3cow_raw_inode(&is->iloc);
-+	header = IHDR(inode, raw_inode);
-+	is->s.base = is->s.first = IFIRST(header);
-+	is->s.here = is->s.first;
-+	is->s.end = (void *)raw_inode + EXT3COW_SB(inode->i_sb)->s_inode_size;
-+	if (EXT3COW_I(inode)->i_state & EXT3COW_STATE_XATTR) {
-+		error = ext3cow_xattr_check_names(IFIRST(header), is->s.end);
-+		if (error)
-+			return error;
-+		/* Find the named attribute. */
-+		error = ext3cow_xattr_find_entry(&is->s.here, i->name_index,
-+					      i->name, is->s.end -
-+					      (void *)is->s.base, 0);
-+		if (error && error != -ENODATA)
-+			return error;
-+		is->s.not_found = error;
-+	}
-+	return 0;
-+}
-+
-+static int
-+ext3cow_xattr_ibody_set(handle_t *handle, struct inode *inode,
-+		     struct ext3cow_xattr_info *i,
-+		     struct ext3cow_xattr_ibody_find *is)
-+{
-+	struct ext3cow_xattr_ibody_header *header;
-+	struct ext3cow_xattr_search *s = &is->s;
-+	int error;
-+
-+	if (EXT3COW_I(inode)->i_extra_isize == 0)
-+		return -ENOSPC;
-+	error = ext3cow_xattr_set_entry(i, s);
-+	if (error)
-+		return error;
-+	header = IHDR(inode, ext3cow_raw_inode(&is->iloc));
-+	if (!IS_LAST_ENTRY(s->first)) {
-+		header->h_magic = cpu_to_le32(EXT3COW_XATTR_MAGIC);
-+		EXT3COW_I(inode)->i_state |= EXT3COW_STATE_XATTR;
-+	} else {
-+		header->h_magic = cpu_to_le32(0);
-+		EXT3COW_I(inode)->i_state &= ~EXT3COW_STATE_XATTR;
-+	}
-+	return 0;
-+}
-+
-+/*
-+ * ext3cow_xattr_set_handle()
-+ *
-+ * Create, replace or remove an extended attribute for this inode. Buffer
-+ * is NULL to remove an existing extended attribute, and non-NULL to
-+ * either replace an existing extended attribute, or create a new extended
-+ * attribute. The flags XATTR_REPLACE and XATTR_CREATE
-+ * specify that an extended attribute must exist and must not exist
-+ * previous to the call, respectively.
-+ *
-+ * Returns 0, or a negative error number on failure.
-+ */
-+int
-+ext3cow_xattr_set_handle(handle_t *handle, struct inode *inode, int name_index,
-+		      const char *name, const void *value, size_t value_len,
-+		      int flags)
-+{
-+	struct ext3cow_xattr_info i = {
-+		.name_index = name_index,
-+		.name = name,
-+		.value = value,
-+		.value_len = value_len,
-+
-+	};
-+	struct ext3cow_xattr_ibody_find is = {
-+		.s = { .not_found = -ENODATA, },
-+	};
-+	struct ext3cow_xattr_block_find bs = {
-+		.s = { .not_found = -ENODATA, },
-+	};
-+	int error;
-+
-+	if (!name)
-+		return -EINVAL;
-+	if (strlen(name) > 255)
-+		return -ERANGE;
-+	down_write(&EXT3COW_I(inode)->xattr_sem);
-+	error = ext3cow_get_inode_loc(inode, &is.iloc);
-+	if (error)
-+		goto cleanup;
-+
-+	if (EXT3COW_I(inode)->i_state & EXT3COW_STATE_NEW) {
-+		struct ext3cow_inode *raw_inode = ext3cow_raw_inode(&is.iloc);
-+		memset(raw_inode, 0, EXT3COW_SB(inode->i_sb)->s_inode_size);
-+		EXT3COW_I(inode)->i_state &= ~EXT3COW_STATE_NEW;
-+	}
-+
-+	error = ext3cow_xattr_ibody_find(inode, &i, &is);
-+	if (error)
-+		goto cleanup;
-+	if (is.s.not_found)
-+		error = ext3cow_xattr_block_find(inode, &i, &bs);
-+	if (error)
-+		goto cleanup;
-+	if (is.s.not_found && bs.s.not_found) {
-+		error = -ENODATA;
-+		if (flags & XATTR_REPLACE)
-+			goto cleanup;
-+		error = 0;
-+		if (!value)
-+			goto cleanup;
-+	} else {
-+		error = -EEXIST;
-+		if (flags & XATTR_CREATE)
-+			goto cleanup;
-+	}
-+	error = ext3cow_journal_get_write_access(handle, is.iloc.bh);
-+	if (error)
-+		goto cleanup;
-+	if (!value) {
-+		if (!is.s.not_found)
-+			error = ext3cow_xattr_ibody_set(handle, inode, &i, &is);
-+		else if (!bs.s.not_found)
-+			error = ext3cow_xattr_block_set(handle, inode, &i, &bs);
-+	} else {
-+		error = ext3cow_xattr_ibody_set(handle, inode, &i, &is);
-+		if (!error && !bs.s.not_found) {
-+			i.value = NULL;
-+			error = ext3cow_xattr_block_set(handle, inode, &i, &bs);
-+		} else if (error == -ENOSPC) {
-+			error = ext3cow_xattr_block_set(handle, inode, &i, &bs);
-+			if (error)
-+				goto cleanup;
-+			if (!is.s.not_found) {
-+				i.value = NULL;
-+				error = ext3cow_xattr_ibody_set(handle, inode, &i,
-+							     &is);
-+			}
-+		}
-+	}
-+	if (!error) {
-+		ext3cow_xattr_update_super_block(handle, inode->i_sb);
-+		inode->i_ctime = CURRENT_TIME_SEC;
-+		error = ext3cow_mark_iloc_dirty(handle, inode, &is.iloc);
-+		/*
-+		 * The bh is consumed by ext3cow_mark_iloc_dirty, even with
-+		 * error != 0.
-+		 */
-+		is.iloc.bh = NULL;
-+		if (IS_SYNC(inode))
-+			handle->h_sync = 1;
-+	}
-+
-+cleanup:
-+	brelse(is.iloc.bh);
-+	brelse(bs.bh);
-+	up_write(&EXT3COW_I(inode)->xattr_sem);
-+	return error;
-+}
-+
-+/*
-+ * ext3cow_xattr_set()
-+ *
-+ * Like ext3cow_xattr_set_handle, but start from an inode. This extended
-+ * attribute modification is a filesystem transaction by itself.
-+ *
-+ * Returns 0, or a negative error number on failure.
-+ */
-+int
-+ext3cow_xattr_set(struct inode *inode, int name_index, const char *name,
-+	       const void *value, size_t value_len, int flags)
-+{
-+	handle_t *handle;
-+	int error, retries = 0;
-+
-+retry:
-+	handle = ext3cow_journal_start(inode, EXT3COW_DATA_TRANS_BLOCKS(inode->i_sb));
-+	if (IS_ERR(handle)) {
-+		error = PTR_ERR(handle);
-+	} else {
-+		int error2;
-+
-+		error = ext3cow_xattr_set_handle(handle, inode, name_index, name,
-+					      value, value_len, flags);
-+		error2 = ext3cow_journal_stop(handle);
-+		if (error == -ENOSPC &&
-+		    ext3cow_should_retry_alloc(inode->i_sb, &retries))
-+			goto retry;
-+		if (error == 0)
-+			error = error2;
-+	}
-+
-+	return error;
-+}
-+
-+/*
-+ * ext3cow_xattr_delete_inode()
-+ *
-+ * Free extended attribute resources associated with this inode. This
-+ * is called immediately before an inode is freed. We have exclusive
-+ * access to the inode.
-+ */
-+void
-+ext3cow_xattr_delete_inode(handle_t *handle, struct inode *inode)
-+{
-+	struct buffer_head *bh = NULL;
-+
-+	if (!EXT3COW_I(inode)->i_file_acl)
-+		goto cleanup;
-+	bh = sb_bread(inode->i_sb, EXT3COW_I(inode)->i_file_acl);
-+	if (!bh) {
-+		ext3cow_error(inode->i_sb, __FUNCTION__,
-+			"inode %lu: block "E3FSBLK" read error", inode->i_ino,
-+			EXT3COW_I(inode)->i_file_acl);
-+		goto cleanup;
-+	}
-+	if (BHDR(bh)->h_magic != cpu_to_le32(EXT3COW_XATTR_MAGIC) ||
-+	    BHDR(bh)->h_blocks != cpu_to_le32(1)) {
-+		ext3cow_error(inode->i_sb, __FUNCTION__,
-+			"inode %lu: bad block "E3FSBLK, inode->i_ino,
-+			EXT3COW_I(inode)->i_file_acl);
-+		goto cleanup;
-+	}
-+	ext3cow_xattr_release_block(handle, inode, bh);
-+	EXT3COW_I(inode)->i_file_acl = 0;
-+
-+cleanup:
-+	brelse(bh);
-+}
-+
-+/*
-+ * ext3cow_xattr_put_super()
-+ *
-+ * This is called when a file system is unmounted.
-+ */
-+void
-+ext3cow_xattr_put_super(struct super_block *sb)
-+{
-+	mb_cache_shrink(sb->s_bdev);
-+}
-+
-+/*
-+ * ext3cow_xattr_cache_insert()
-+ *
-+ * Create a new entry in the extended attribute cache, and insert
-+ * it unless such an entry is already in the cache.
-+ *
-+ * Returns 0, or a negative error number on failure.
-+ */
-+static void
-+ext3cow_xattr_cache_insert(struct buffer_head *bh)
-+{
-+	__u32 hash = le32_to_cpu(BHDR(bh)->h_hash);
-+	struct mb_cache_entry *ce;
-+	int error;
-+
-+	ce = mb_cache_entry_alloc(ext3cow_xattr_cache);
-+	if (!ce) {
-+		ea_bdebug(bh, "out of memory");
-+		return;
-+	}
-+	error = mb_cache_entry_insert(ce, bh->b_bdev, bh->b_blocknr, &hash);
-+	if (error) {
-+		mb_cache_entry_free(ce);
-+		if (error == -EBUSY) {
-+			ea_bdebug(bh, "already in cache");
-+			error = 0;
-+		}
-+	} else {
-+		ea_bdebug(bh, "inserting [%x]", (int)hash);
-+		mb_cache_entry_release(ce);
-+	}
-+}
-+
-+/*
-+ * ext3cow_xattr_cmp()
-+ *
-+ * Compare two extended attribute blocks for equality.
-+ *
-+ * Returns 0 if the blocks are equal, 1 if they differ, and
-+ * a negative error number on errors.
-+ */
-+static int
-+ext3cow_xattr_cmp(struct ext3cow_xattr_header *header1,
-+	       struct ext3cow_xattr_header *header2)
-+{
-+	struct ext3cow_xattr_entry *entry1, *entry2;
-+
-+	entry1 = ENTRY(header1+1);
-+	entry2 = ENTRY(header2+1);
-+	while (!IS_LAST_ENTRY(entry1)) {
-+		if (IS_LAST_ENTRY(entry2))
-+			return 1;
-+		if (entry1->e_hash != entry2->e_hash ||
-+		    entry1->e_name_index != entry2->e_name_index ||
-+		    entry1->e_name_len != entry2->e_name_len ||
-+		    entry1->e_value_size != entry2->e_value_size ||
-+		    memcmp(entry1->e_name, entry2->e_name, entry1->e_name_len))
-+			return 1;
-+		if (entry1->e_value_block != 0 || entry2->e_value_block != 0)
-+			return -EIO;
-+		if (memcmp((char *)header1 + le16_to_cpu(entry1->e_value_offs),
-+			   (char *)header2 + le16_to_cpu(entry2->e_value_offs),
-+			   le32_to_cpu(entry1->e_value_size)))
-+			return 1;
-+
-+		entry1 = EXT3COW_XATTR_NEXT(entry1);
-+		entry2 = EXT3COW_XATTR_NEXT(entry2);
-+	}
-+	if (!IS_LAST_ENTRY(entry2))
-+		return 1;
-+	return 0;
-+}
-+
-+/*
-+ * ext3cow_xattr_cache_find()
-+ *
-+ * Find an identical extended attribute block.
-+ *
-+ * Returns a pointer to the block found, or NULL if such a block was
-+ * not found or an error occurred.
-+ */
-+static struct buffer_head *
-+ext3cow_xattr_cache_find(struct inode *inode, struct ext3cow_xattr_header *header,
-+		      struct mb_cache_entry **pce)
-+{
-+	__u32 hash = le32_to_cpu(header->h_hash);
-+	struct mb_cache_entry *ce;
-+
-+	if (!header->h_hash)
-+		return NULL;  /* never share */
-+	ea_idebug(inode, "looking for cached blocks [%x]", (int)hash);
-+again:
-+	ce = mb_cache_entry_find_first(ext3cow_xattr_cache, 0,
-+				       inode->i_sb->s_bdev, hash);
-+	while (ce) {
-+		struct buffer_head *bh;
-+
-+		if (IS_ERR(ce)) {
-+			if (PTR_ERR(ce) == -EAGAIN)
-+				goto again;
-+			break;
-+		}
-+		bh = sb_bread(inode->i_sb, ce->e_block);
-+		if (!bh) {
-+			ext3cow_error(inode->i_sb, __FUNCTION__,
-+				"inode %lu: block %lu read error",
-+				inode->i_ino, (unsigned long) ce->e_block);
-+		} else if (le32_to_cpu(BHDR(bh)->h_refcount) >=
-+				EXT3COW_XATTR_REFCOUNT_MAX) {
-+			ea_idebug(inode, "block %lu refcount %d>=%d",
-+				  (unsigned long) ce->e_block,
-+				  le32_to_cpu(BHDR(bh)->h_refcount),
-+					  EXT3COW_XATTR_REFCOUNT_MAX);
-+		} else if (ext3cow_xattr_cmp(header, BHDR(bh)) == 0) {
-+			*pce = ce;
-+			return bh;
-+		}
-+		brelse(bh);
-+		ce = mb_cache_entry_find_next(ce, 0, inode->i_sb->s_bdev, hash);
-+	}
-+	return NULL;
-+}
-+
-+#define NAME_HASH_SHIFT 5
-+#define VALUE_HASH_SHIFT 16
-+
-+/*
-+ * ext3cow_xattr_hash_entry()
-+ *
-+ * Compute the hash of an extended attribute.
-+ */
-+static inline void ext3cow_xattr_hash_entry(struct ext3cow_xattr_header *header,
-+					 struct ext3cow_xattr_entry *entry)
-+{
-+	__u32 hash = 0;
-+	char *name = entry->e_name;
-+	int n;
-+
-+	for (n=0; n < entry->e_name_len; n++) {
-+		hash = (hash << NAME_HASH_SHIFT) ^
-+		       (hash >> (8*sizeof(hash) - NAME_HASH_SHIFT)) ^
-+		       *name++;
-+	}
-+
-+	if (entry->e_value_block == 0 && entry->e_value_size != 0) {
-+		__le32 *value = (__le32 *)((char *)header +
-+			le16_to_cpu(entry->e_value_offs));
-+		for (n = (le32_to_cpu(entry->e_value_size) +
-+		     EXT3COW_XATTR_ROUND) >> EXT3COW_XATTR_PAD_BITS; n; n--) {
-+			hash = (hash << VALUE_HASH_SHIFT) ^
-+			       (hash >> (8*sizeof(hash) - VALUE_HASH_SHIFT)) ^
-+			       le32_to_cpu(*value++);
-+		}
-+	}
-+	entry->e_hash = cpu_to_le32(hash);
-+}
-+
-+#undef NAME_HASH_SHIFT
-+#undef VALUE_HASH_SHIFT
-+
-+#define BLOCK_HASH_SHIFT 16
-+
-+/*
-+ * ext3cow_xattr_rehash()
-+ *
-+ * Re-compute the extended attribute hash value after an entry has changed.
-+ */
-+static void ext3cow_xattr_rehash(struct ext3cow_xattr_header *header,
-+			      struct ext3cow_xattr_entry *entry)
-+{
-+	struct ext3cow_xattr_entry *here;
-+	__u32 hash = 0;
-+
-+	ext3cow_xattr_hash_entry(header, entry);
-+	here = ENTRY(header+1);
-+	while (!IS_LAST_ENTRY(here)) {
-+		if (!here->e_hash) {
-+			/* Block is not shared if an entry's hash value == 0 */
-+			hash = 0;
-+			break;
-+		}
-+		hash = (hash << BLOCK_HASH_SHIFT) ^
-+		       (hash >> (8*sizeof(hash) - BLOCK_HASH_SHIFT)) ^
-+		       le32_to_cpu(here->e_hash);
-+		here = EXT3COW_XATTR_NEXT(here);
-+	}
-+	header->h_hash = cpu_to_le32(hash);
-+}
-+
-+#undef BLOCK_HASH_SHIFT
-+
-+int __init
-+init_ext3cow_xattr(void)
-+{
-+	ext3cow_xattr_cache = mb_cache_create("ext3cow_xattr", NULL,
-+		sizeof(struct mb_cache_entry) +
-+		sizeof(((struct mb_cache_entry *) 0)->e_indexes[0]), 1, 6);
-+	if (!ext3cow_xattr_cache)
-+		return -ENOMEM;
-+	return 0;
-+}
-+
-+void
-+exit_ext3cow_xattr(void)
-+{
-+	if (ext3cow_xattr_cache)
-+		mb_cache_destroy(ext3cow_xattr_cache);
-+	ext3cow_xattr_cache = NULL;
-+}
-diff -ruN linux-2.6.20.3/fs/ext3cow/xattr.h linux-2.6.20.3-ext3cow/fs/ext3cow/xattr.h
---- linux-2.6.20.3/fs/ext3cow/xattr.h	1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.20.3-ext3cow/fs/ext3cow/xattr.h	2008-03-09 11:14:49.000000000 -0400
-@@ -0,0 +1,145 @@
-+/*
-+  File: fs/ext3cow/xattr.h
-+
-+  On-disk format of extended attributes for the ext3cow filesystem.
-+
-+  (C) 2001 Andreas Gruenbacher, <a.gruenbacher@computer.org>
-+*/
-+
-+#include <linux/xattr.h>
-+
-+/* Magic value in attribute blocks */
-+#define EXT3COW_XATTR_MAGIC		0xEA020000
-+
-+/* Maximum number of references to one attribute block */
-+#define EXT3COW_XATTR_REFCOUNT_MAX		1024
-+
-+/* Name indexes */
-+#define EXT3COW_XATTR_INDEX_USER			1
-+#define EXT3COW_XATTR_INDEX_POSIX_ACL_ACCESS	2
-+#define EXT3COW_XATTR_INDEX_POSIX_ACL_DEFAULT	3
-+#define EXT3COW_XATTR_INDEX_TRUSTED		4
-+#define	EXT3COW_XATTR_INDEX_LUSTRE			5
-+#define EXT3COW_XATTR_INDEX_SECURITY	        6
-+
-+struct ext3cow_xattr_header {
-+	__le32	h_magic;	/* magic number for identification */
-+	__le32	h_refcount;	/* reference count */
-+	__le32	h_blocks;	/* number of disk blocks used */
-+	__le32	h_hash;		/* hash value of all attributes */
-+	__u32	h_reserved[4];	/* zero right now */
-+};
-+
-+struct ext3cow_xattr_ibody_header {
-+	__le32	h_magic;	/* magic number for identification */
-+};
-+
-+struct ext3cow_xattr_entry {
-+	__u8	e_name_len;	/* length of name */
-+	__u8	e_name_index;	/* attribute name index */
-+	__le16	e_value_offs;	/* offset in disk block of value */
-+	__le32	e_value_block;	/* disk block attribute is stored on (n/i) */
-+	__le32	e_value_size;	/* size of attribute value */
-+	__le32	e_hash;		/* hash value of name and value */
-+	char	e_name[0];	/* attribute name */
-+};
-+
-+#define EXT3COW_XATTR_PAD_BITS		2
-+#define EXT3COW_XATTR_PAD		(1<<EXT3COW_XATTR_PAD_BITS)
-+#define EXT3COW_XATTR_ROUND		(EXT3COW_XATTR_PAD-1)
-+#define EXT3COW_XATTR_LEN(name_len) \
-+	(((name_len) + EXT3COW_XATTR_ROUND + \
-+	sizeof(struct ext3cow_xattr_entry)) & ~EXT3COW_XATTR_ROUND)
-+#define EXT3COW_XATTR_NEXT(entry) \
-+	( (struct ext3cow_xattr_entry *)( \
-+	  (char *)(entry) + EXT3COW_XATTR_LEN((entry)->e_name_len)) )
-+#define EXT3COW_XATTR_SIZE(size) \
-+	(((size) + EXT3COW_XATTR_ROUND) & ~EXT3COW_XATTR_ROUND)
-+
-+# ifdef CONFIG_EXT3COW_FS_XATTR
-+
-+extern struct xattr_handler ext3cow_xattr_user_handler;
-+extern struct xattr_handler ext3cow_xattr_trusted_handler;
-+extern struct xattr_handler ext3cow_xattr_acl_access_handler;
-+extern struct xattr_handler ext3cow_xattr_acl_default_handler;
-+extern struct xattr_handler ext3cow_xattr_security_handler;
-+
-+extern ssize_t ext3cow_listxattr(struct dentry *, char *, size_t);
-+
-+extern int ext3cow_xattr_get(struct inode *, int, const char *, void *, size_t);
-+extern int ext3cow_xattr_list(struct inode *, char *, size_t);
-+extern int ext3cow_xattr_set(struct inode *, int, const char *, const void *, size_t, int);
-+extern int ext3cow_xattr_set_handle(handle_t *, struct inode *, int, const char *, const void *, size_t, int);
-+
-+extern void ext3cow_xattr_delete_inode(handle_t *, struct inode *);
-+extern void ext3cow_xattr_put_super(struct super_block *);
-+
-+extern int init_ext3cow_xattr(void);
-+extern void exit_ext3cow_xattr(void);
-+
-+extern struct xattr_handler *ext3cow_xattr_handlers[];
-+
-+# else  /* CONFIG_EXT3COW_FS_XATTR */
-+
-+static inline int
-+ext3cow_xattr_get(struct inode *inode, int name_index, const char *name,
-+	       void *buffer, size_t size, int flags)
-+{
-+	return -EOPNOTSUPP;
-+}
-+
-+static inline int
-+ext3cow_xattr_list(struct inode *inode, void *buffer, size_t size)
-+{
-+	return -EOPNOTSUPP;
-+}
-+
-+static inline int
-+ext3cow_xattr_set(struct inode *inode, int name_index, const char *name,
-+	       const void *value, size_t size, int flags)
-+{
-+	return -EOPNOTSUPP;
-+}
-+
-+static inline int
-+ext3cow_xattr_set_handle(handle_t *handle, struct inode *inode, int name_index,
-+	       const char *name, const void *value, size_t size, int flags)
-+{
-+	return -EOPNOTSUPP;
-+}
-+
-+static inline void
-+ext3cow_xattr_delete_inode(handle_t *handle, struct inode *inode)
-+{
-+}
-+
-+static inline void
-+ext3cow_xattr_put_super(struct super_block *sb)
-+{
-+}
-+
-+static inline int
-+init_ext3cow_xattr(void)
-+{
-+	return 0;
-+}
-+
-+static inline void
-+exit_ext3cow_xattr(void)
-+{
-+}
-+
-+#define ext3cow_xattr_handlers	NULL
-+
-+# endif  /* CONFIG_EXT3COW_FS_XATTR */
-+
-+#ifdef CONFIG_EXT3COW_FS_SECURITY
-+extern int ext3cow_init_security(handle_t *handle, struct inode *inode,
-+				struct inode *dir);
-+#else
-+static inline int ext3cow_init_security(handle_t *handle, struct inode *inode,
-+				struct inode *dir)
-+{
-+	return 0;
-+}
-+#endif
-diff -ruN linux-2.6.20.3/fs/ext3cow/xattr_security.c linux-2.6.20.3-ext3cow/fs/ext3cow/xattr_security.c
---- linux-2.6.20.3/fs/ext3cow/xattr_security.c	1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.20.3-ext3cow/fs/ext3cow/xattr_security.c	2008-03-09 11:14:48.000000000 -0400
-@@ -0,0 +1,77 @@
-+/*
-+ * linux/fs/ext3cow/xattr_security.c
-+ * Handler for storing security labels as extended attributes.
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/string.h>
-+#include <linux/fs.h>
-+#include <linux/smp_lock.h>
-+#include <linux/ext3cow_jbd.h>
-+#include <linux/ext3cow_fs.h>
-+#include <linux/security.h>
-+#include "xattr.h"
-+
-+static size_t
-+ext3cow_xattr_security_list(struct inode *inode, char *list, size_t list_size,
-+			 const char *name, size_t name_len)
-+{
-+	const size_t prefix_len = sizeof(XATTR_SECURITY_PREFIX)-1;
-+	const size_t total_len = prefix_len + name_len + 1;
-+
-+
-+	if (list && total_len <= list_size) {
-+		memcpy(list, XATTR_SECURITY_PREFIX, prefix_len);
-+		memcpy(list+prefix_len, name, name_len);
-+		list[prefix_len + name_len] = '\0';
-+	}
-+	return total_len;
-+}
-+
-+static int
-+ext3cow_xattr_security_get(struct inode *inode, const char *name,
-+		       void *buffer, size_t size)
-+{
-+	if (strcmp(name, "") == 0)
-+		return -EINVAL;
-+	return ext3cow_xattr_get(inode, EXT3COW_XATTR_INDEX_SECURITY, name,
-+			      buffer, size);
-+}
-+
-+static int
-+ext3cow_xattr_security_set(struct inode *inode, const char *name,
-+		       const void *value, size_t size, int flags)
-+{
-+	if (strcmp(name, "") == 0)
-+		return -EINVAL;
-+	return ext3cow_xattr_set(inode, EXT3COW_XATTR_INDEX_SECURITY, name,
-+			      value, size, flags);
-+}
-+
-+int
-+ext3cow_init_security(handle_t *handle, struct inode *inode, struct inode *dir)
-+{
-+	int err;
-+	size_t len;
-+	void *value;
-+	char *name;
-+
-+	err = security_inode_init_security(inode, dir, &name, &value, &len);
-+	if (err) {
-+		if (err == -EOPNOTSUPP)
-+			return 0;
-+		return err;
-+	}
-+	err = ext3cow_xattr_set_handle(handle, inode, EXT3COW_XATTR_INDEX_SECURITY,
-+				    name, value, len, 0);
-+	kfree(name);
-+	kfree(value);
-+	return err;
-+}
-+
-+struct xattr_handler ext3cow_xattr_security_handler = {
-+	.prefix	= XATTR_SECURITY_PREFIX,
-+	.list	= ext3cow_xattr_security_list,
-+	.get	= ext3cow_xattr_security_get,
-+	.set	= ext3cow_xattr_security_set,
-+};
-diff -ruN linux-2.6.20.3/fs/ext3cow/xattr_trusted.c linux-2.6.20.3-ext3cow/fs/ext3cow/xattr_trusted.c
---- linux-2.6.20.3/fs/ext3cow/xattr_trusted.c	1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.20.3-ext3cow/fs/ext3cow/xattr_trusted.c	2008-03-09 11:14:48.000000000 -0400
-@@ -0,0 +1,62 @@
-+/*
-+ * linux/fs/ext3cow/xattr_trusted.c
-+ * Handler for trusted extended attributes.
-+ *
-+ * Copyright (C) 2003 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/string.h>
-+#include <linux/capability.h>
-+#include <linux/fs.h>
-+#include <linux/smp_lock.h>
-+#include <linux/ext3cow_jbd.h>
-+#include <linux/ext3cow_fs.h>
-+#include "xattr.h"
-+
-+#define XATTR_TRUSTED_PREFIX "trusted."
-+
-+static size_t
-+ext3cow_xattr_trusted_list(struct inode *inode, char *list, size_t list_size,
-+			const char *name, size_t name_len)
-+{
-+	const size_t prefix_len = sizeof(XATTR_TRUSTED_PREFIX)-1;
-+	const size_t total_len = prefix_len + name_len + 1;
-+
-+	if (!capable(CAP_SYS_ADMIN))
-+		return 0;
-+
-+	if (list && total_len <= list_size) {
-+		memcpy(list, XATTR_TRUSTED_PREFIX, prefix_len);
-+		memcpy(list+prefix_len, name, name_len);
-+		list[prefix_len + name_len] = '\0';
-+	}
-+	return total_len;
-+}
-+
-+static int
-+ext3cow_xattr_trusted_get(struct inode *inode, const char *name,
-+		       void *buffer, size_t size)
-+{
-+	if (strcmp(name, "") == 0)
-+		return -EINVAL;
-+	return ext3cow_xattr_get(inode, EXT3COW_XATTR_INDEX_TRUSTED, name,
-+			      buffer, size);
-+}
-+
-+static int
-+ext3cow_xattr_trusted_set(struct inode *inode, const char *name,
-+		       const void *value, size_t size, int flags)
-+{
-+	if (strcmp(name, "") == 0)
-+		return -EINVAL;
-+	return ext3cow_xattr_set(inode, EXT3COW_XATTR_INDEX_TRUSTED, name,
-+			      value, size, flags);
-+}
-+
-+struct xattr_handler ext3cow_xattr_trusted_handler = {
-+	.prefix	= XATTR_TRUSTED_PREFIX,
-+	.list	= ext3cow_xattr_trusted_list,
-+	.get	= ext3cow_xattr_trusted_get,
-+	.set	= ext3cow_xattr_trusted_set,
-+};
-diff -ruN linux-2.6.20.3/fs/ext3cow/xattr_user.c linux-2.6.20.3-ext3cow/fs/ext3cow/xattr_user.c
---- linux-2.6.20.3/fs/ext3cow/xattr_user.c	1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.20.3-ext3cow/fs/ext3cow/xattr_user.c	2008-03-09 11:14:48.000000000 -0400
-@@ -0,0 +1,64 @@
-+/*
-+ * linux/fs/ext3cow/xattr_user.c
-+ * Handler for extended user attributes.
-+ *
-+ * Copyright (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/string.h>
-+#include <linux/fs.h>
-+#include <linux/smp_lock.h>
-+#include <linux/ext3cow_jbd.h>
-+#include <linux/ext3cow_fs.h>
-+#include "xattr.h"
-+
-+#define XATTR_USER_PREFIX "user."
-+
-+static size_t
-+ext3cow_xattr_user_list(struct inode *inode, char *list, size_t list_size,
-+		     const char *name, size_t name_len)
-+{
-+	const size_t prefix_len = sizeof(XATTR_USER_PREFIX)-1;
-+	const size_t total_len = prefix_len + name_len + 1;
-+
-+	if (!test_opt(inode->i_sb, XATTR_USER))
-+		return 0;
-+
-+	if (list && total_len <= list_size) {
-+		memcpy(list, XATTR_USER_PREFIX, prefix_len);
-+		memcpy(list+prefix_len, name, name_len);
-+		list[prefix_len + name_len] = '\0';
-+	}
-+	return total_len;
-+}
-+
-+static int
-+ext3cow_xattr_user_get(struct inode *inode, const char *name,
-+		    void *buffer, size_t size)
-+{
-+	if (strcmp(name, "") == 0)
-+		return -EINVAL;
-+	if (!test_opt(inode->i_sb, XATTR_USER))
-+		return -EOPNOTSUPP;
-+	return ext3cow_xattr_get(inode, EXT3COW_XATTR_INDEX_USER, name, buffer, size);
-+}
-+
-+static int
-+ext3cow_xattr_user_set(struct inode *inode, const char *name,
-+		    const void *value, size_t size, int flags)
-+{
-+	if (strcmp(name, "") == 0)
-+		return -EINVAL;
-+	if (!test_opt(inode->i_sb, XATTR_USER))
-+		return -EOPNOTSUPP;
-+	return ext3cow_xattr_set(inode, EXT3COW_XATTR_INDEX_USER, name,
-+			      value, size, flags);
-+}
-+
-+struct xattr_handler ext3cow_xattr_user_handler = {
-+	.prefix	= XATTR_USER_PREFIX,
-+	.list	= ext3cow_xattr_user_list,
-+	.get	= ext3cow_xattr_user_get,
-+	.set	= ext3cow_xattr_user_set,
-+};
-diff -ruN linux-2.6.20.3/fs/Kconfig linux-2.6.20.3-ext3cow/fs/Kconfig
---- linux-2.6.20.3/fs/Kconfig	2007-03-13 14:27:08.000000000 -0400
-+++ linux-2.6.20.3-ext3cow/fs/Kconfig	2008-03-09 11:14:25.000000000 -0400
-@@ -136,6 +136,77 @@
- 	  If you are not using a security module that requires using
- 	  extended attributes for file security labels, say N.
- 
-+
-+
-+config EXT3COW_FS
-+	tristate "Ext3cow journalling and versioning file system support"
-+	select JBD
-+	help
-+	  This is the journalling version of the Second extended file system
-+	  (often called ext3), the de facto standard Linux file system
-+	  (method to organize files on a storage device) for hard disks.
-+
-+	  The journalling code included in this driver means you do not have
-+	  to run e2fsck (file system checker) on your file systems after a
-+	  crash.  The journal keeps track of any changes that were being made
-+	  at the time the system crashed, and can ensure that your file system
-+	  is consistent without the need for a lengthy check.
-+
-+	  Other than adding the journal to the file system, the on-disk format
-+	  of ext3 is identical to ext2.  It is possible to freely switch
-+	  between using the ext3 driver and the ext2 driver, as long as the
-+	  file system has been cleanly unmounted, or e2fsck is run on the file
-+	  system.
-+
-+	  To add a journal on an existing ext2 file system or change the
-+	  behavior of ext3 file systems, you can use the tune2fs utility ("man
-+	  tune2fs").  To modify attributes of files and directories on ext3
-+	  file systems, use chattr ("man chattr").  You need to be using
-+	  e2fsprogs version 1.20 or later in order to create ext3 journals
-+	  (available at <http://sourceforge.net/projects/e2fsprogs/>).
-+
-+	  To compile this file system support as a module, choose M here: the
-+	  module will be called ext3.
-+
-+config EXT3COW_FS_XATTR
-+	bool "Ext3cow extended attributes"
-+	depends on EXT3COW_FS
-+	default y
-+	help
-+	  Extended attributes are name:value pairs associated with inodes by
-+	  the kernel or by users (see the attr(5) manual page, or visit
-+	  <http://acl.bestbits.at/> for details).
-+
-+	  If unsure, say N.
-+
-+	  You need this for POSIX ACL support on ext3cow.
-+
-+config EXT3COW_FS_POSIX_ACL
-+	bool "Ext3cow POSIX Access Control Lists"
-+	depends on EXT3COW_FS_XATTR
-+	select FS_POSIX_ACL
-+	help
-+	  Posix Access Control Lists (ACLs) support permissions for users and
-+	  groups beyond the owner/group/world scheme.
-+
-+	  To learn more about Access Control Lists, visit the Posix ACLs for
-+	  Linux website <http://acl.bestbits.at/>.
-+
-+	  If you don't know what Access Control Lists are, say N
-+
-+config EXT3COW_FS_SECURITY
-+	bool "Ext3cow Security Labels"
-+	depends on EXT3COW_FS_XATTR
-+	help
-+	  Security labels support alternative access control models
-+	  implemented by security modules like SELinux.  This option
-+	  enables an extended attribute handler for file security
-+	  labels in the ext3cow filesystem.
-+
-+	  If you are not using a security module that requires using
-+	  extended attributes for file security labels, say N.
-+
-+
- config EXT4DEV_FS
- 	tristate "Ext4dev/ext4 extended fs support development (EXPERIMENTAL)"
- 	depends on EXPERIMENTAL
-@@ -205,23 +276,23 @@
- 	tristate
- 	help
- 	  This is a generic journalling layer for block devices.  It is
--	  currently used by the ext3 and OCFS2 file systems, but it could
-+	  currently used by the ext3, ext3cow and OCFS2 file systems, but it could
- 	  also be used to add journal support to other file systems or block
- 	  devices such as RAID or LVM.
- 
--	  If you are using the ext3 or OCFS2 file systems, you need to
-+	  If you are using the ext3, ext3cow or OCFS2 file systems, you need to
- 	  say Y here. If you are not using ext3 OCFS2 then you will probably
- 	  want to say N.
- 
- 	  To compile this device as a module, choose M here: the module will be
--	  called jbd.  If you are compiling ext3 or OCFS2 into the kernel,
-+	  called jbd.  If you are compiling ext3, ext3cow or OCFS2 into the kernel,
- 	  you cannot compile this code as a module.
- 
- config JBD_DEBUG
- 	bool "JBD (ext3) debugging support"
- 	depends on JBD
- 	help
--	  If you are using the ext3 journaled file system (or potentially any
-+	  If you are using the ext3 or ext3cow journaled file system (or potentially any
- 	  other file system/device using JBD), this option allows you to
- 	  enable debugging output while the system is running, in order to
- 	  help track down any problems you are having.  By default the
-@@ -266,11 +337,12 @@
- 	  "echo 0 > /proc/sys/fs/jbd2-debug".
- 
- config FS_MBCACHE
--# Meta block cache for Extended Attributes (ext2/ext3/ext4)
-+# Meta block cache for Extended Attributes (ext2/ext3(cow)/ext4)
- 	tristate
--	depends on EXT2_FS_XATTR || EXT3_FS_XATTR || EXT4DEV_FS_XATTR
--	default y if EXT2_FS=y || EXT3_FS=y || EXT4DEV_FS=y
--	default m if EXT2_FS=m || EXT3_FS=m || EXT4DEV_FS=m
-+	depends on EXT2_FS_XATTR || EXT3_FS_XATTR || EXT3COW_FS_XATTR || EXT4DEV_FS_XATTR
-+	default y if EXT2_FS=y || EXT3_FS=y || EXT3COW_FS=y || EXT4DEV_FS=y
-+	default m if EXT2_FS=m || EXT3_FS=m || EXT3COW_FS=m || EXT4DEV_FS=m
-+
- 
- config REISERFS_FS
- 	tristate "Reiserfs support"
-diff -ruN linux-2.6.20.3/fs/Makefile linux-2.6.20.3-ext3cow/fs/Makefile
---- linux-2.6.20.3/fs/Makefile	2007-03-13 14:27:08.000000000 -0400
-+++ linux-2.6.20.3-ext3cow/fs/Makefile	2008-03-09 11:14:54.000000000 -0400
-@@ -63,6 +63,7 @@
- # Do not add any filesystems before this line
- obj-$(CONFIG_REISERFS_FS)	+= reiserfs/
- obj-$(CONFIG_EXT3_FS)		+= ext3/ # Before ext2 so root fs can be ext3
-+obj-$(CONFIG_EXT3COW_FS)		+= ext3cow/ # Before ext2 so root fs can be ext3
- obj-$(CONFIG_EXT4DEV_FS)	+= ext4/ # Before ext2 so root fs can be ext4dev
- obj-$(CONFIG_JBD)		+= jbd/
- obj-$(CONFIG_JBD2)		+= jbd2/
-diff -ruN linux-2.6.20.3/include/linux/ext3cow_fs.h linux-2.6.20.3-ext3cow/include/linux/ext3cow_fs.h
---- linux-2.6.20.3/include/linux/ext3cow_fs.h	1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.20.3-ext3cow/include/linux/ext3cow_fs.h	2008-03-09 11:10:57.000000000 -0400
-@@ -0,0 +1,948 @@
-+/*
-+ *  linux/include/linux/ext3cow_fs.h
-+ *
-+ * Copyright (C) 1992, 1993, 1994, 1995
-+ * Remy Card (card@masi.ibp.fr)
-+ * Laboratoire MASI - Institut Blaise Pascal
-+ * Universite Pierre et Marie Curie (Paris VI)
-+ *
-+ *  from
-+ *
-+ *  linux/include/linux/minix_fs.h
-+ *
-+ *  Copyright (C) 1991, 1992  Linus Torvalds
-+ */
-+
-+#ifndef _LINUX_EXT3COW_FS_H
-+#define _LINUX_EXT3COW_FS_H
-+
-+#include <linux/types.h>
-+#include <linux/magic.h>
-+
-+/*
-+ * The second extended filesystem constants/structures
-+ */
-+
-+/*
-+ * Define EXT3COWFS_DEBUG to produce debug messages
-+ */
-+#undef EXT3COWFS_DEBUG
-+
-+
-+/*
-+ * Define EXT3COW_RESERVATION to reserve data blocks for expanding files
-+ */
-+#define EXT3COW_DEFAULT_RESERVE_BLOCKS     8
-+/*max window size: 1024(direct blocks) + 3([t,d]indirect blocks) */
-+#define EXT3COW_MAX_RESERVE_BLOCKS         1027
-+#define EXT3COW_RESERVE_WINDOW_NOT_ALLOCATED 0
-+/*
-+ * Always enable hashed directories
-+ */
-+//#define CONFIG_EXT3COW_INDEX
-+
-+/*
-+ * Debug code
-+ */
-+#ifdef EXT3COWFS_DEBUG
-+#define ext3cow_debug(f, a...)						\
-+	do {								\
-+		printk (KERN_DEBUG "EXT3COW-fs DEBUG (%s, %d): %s:",	\
-+			__FILE__, __LINE__, __FUNCTION__);		\
-+		printk (KERN_DEBUG f, ## a);				\
-+	} while (0)
-+#else
-+#define ext3cow_debug(f, a...)	do {} while (0)
-+#endif
-+
-+/*
-+ * Special inodes numbers
-+ */
-+#define	EXT3COW_BAD_INO		 1	/* Bad blocks inode */
-+#define EXT3COW_ROOT_INO		 2	/* Root inode */
-+#define EXT3COW_BOOT_LOADER_INO	 5	/* Boot loader inode */
-+#define EXT3COW_UNDEL_DIR_INO	 6	/* Undelete directory inode */
-+#define EXT3COW_RESIZE_INO		 7	/* Reserved group descriptors inode */
-+#define EXT3COW_JOURNAL_INO	 8	/* Journal inode */
-+
-+/* First non-reserved inode for old ext3cow filesystems */
-+#define EXT3COW_GOOD_OLD_FIRST_INO	11
-+
-+/*
-+ * Maximal count of links to a file
-+ */
-+#define EXT3COW_LINK_MAX		32000
-+
-+/* For versioning -znjp */
-+#define EXT3COW_FLUX_TOKEN '@'
-+/* Macros for scoping - in seconds -znjp */
-+#define ONEHOUR   3600
-+#define YESTERDAY 86400
-+#define ONEWEEK   604800
-+#define ONEMONTH  2419200
-+#define ONEYEAR   31449600
-+
-+/*
-+ * Macro-instructions used to manage several block sizes
-+ */
-+#define EXT3COW_MIN_BLOCK_SIZE		1024
-+#define	EXT3COW_MAX_BLOCK_SIZE		4096
-+#define EXT3COW_MIN_BLOCK_LOG_SIZE		  10
-+#ifdef __KERNEL__
-+# define EXT3COW_BLOCK_SIZE(s)		((s)->s_blocksize)
-+#else
-+# define EXT3COW_BLOCK_SIZE(s)		(EXT3COW_MIN_BLOCK_SIZE << (s)->s_log_block_size)
-+#endif
-+//#define	EXT3COW_ADDR_PER_BLOCK(s)		(EXT3COW_BLOCK_SIZE(s) / sizeof (__u32))
-+#ifdef __KERNEL__
-+# define EXT3COW_BLOCK_SIZE_BITS(s)	((s)->s_blocksize_bits)
-+#else
-+# define EXT3COW_BLOCK_SIZE_BITS(s)	((s)->s_log_block_size + 10)
-+#endif
-+#ifdef __KERNEL__
-+#define	EXT3COW_ADDR_PER_BLOCK_BITS(s)	(EXT3COW_SB(s)->s_addr_per_block_bits)
-+#define EXT3COW_INODE_SIZE(s)		(EXT3COW_SB(s)->s_inode_size)
-+#define EXT3COW_FIRST_INO(s)		(EXT3COW_SB(s)->s_first_ino)
-+#else
-+#define EXT3COW_INODE_SIZE(s)	(((s)->s_rev_level == EXT3COW_GOOD_OLD_REV) ? \
-+				 EXT3COW_GOOD_OLD_INODE_SIZE : \
-+				 (s)->s_inode_size)
-+#define EXT3COW_FIRST_INO(s)	(((s)->s_rev_level == EXT3COW_GOOD_OLD_REV) ? \
-+				 EXT3COW_GOOD_OLD_FIRST_INO : \
-+				 (s)->s_first_ino)
-+#endif
-+/*
-+ * Macro-instructions for versioning support - znjp
-+ */
-+#define EXT3COW_COWBITMAP_SIZE (sizeof(__u32) * 8) /* one word */
-+#define EXT3COW_COWBITMAPS_PER_IBLOCK(s) \
-+  (( (EXT3COW_BLOCK_SIZE(s) / sizeof(__u32)) / (EXT3COW_COWBITMAP_SIZE)))
-+/* Accounts for COW bitmaps */
-+#define EXT3COW_ADDR_PER_BLOCK(s) ((EXT3COW_BLOCK_SIZE(s) / sizeof(__u32)) - EXT3COW_COWBITMAPS_PER_IBLOCK(s))
-+
-+/*
-+ * Macro-instructions used to manage fragments
-+ */
-+#define EXT3COW_MIN_FRAG_SIZE		1024
-+#define	EXT3COW_MAX_FRAG_SIZE		4096
-+#define EXT3COW_MIN_FRAG_LOG_SIZE		  10
-+#ifdef __KERNEL__
-+# define EXT3COW_FRAG_SIZE(s)		(EXT3COW_SB(s)->s_frag_size)
-+# define EXT3COW_FRAGS_PER_BLOCK(s)	(EXT3COW_SB(s)->s_frags_per_block)
-+#else
-+# define EXT3COW_FRAG_SIZE(s)		(EXT3COW_MIN_FRAG_SIZE << (s)->s_log_frag_size)
-+# define EXT3COW_FRAGS_PER_BLOCK(s)	(EXT3COW_BLOCK_SIZE(s) / EXT3COW_FRAG_SIZE(s))
-+#endif
-+
-+/*
-+ * Structure of a blocks group descriptor
-+ */
-+struct ext3cow_group_desc
-+{
-+	__le32	bg_block_bitmap;		/* Blocks bitmap block */
-+	__le32	bg_inode_bitmap;		/* Inodes bitmap block */
-+	__le32	bg_inode_table;		/* Inodes table block */
-+	__le16	bg_free_blocks_count;	/* Free blocks count */
-+	__le16	bg_free_inodes_count;	/* Free inodes count */
-+	__le16	bg_used_dirs_count;	/* Directories count */
-+	__u16	bg_pad;
-+	__le32	bg_reserved[3];
-+};
-+
-+/*
-+ * Macro-instructions used to manage group descriptors
-+ */
-+#ifdef __KERNEL__
-+# define EXT3COW_BLOCKS_PER_GROUP(s)	(EXT3COW_SB(s)->s_blocks_per_group)
-+# define EXT3COW_DESC_PER_BLOCK(s)		(EXT3COW_SB(s)->s_desc_per_block)
-+# define EXT3COW_INODES_PER_GROUP(s)	(EXT3COW_SB(s)->s_inodes_per_group)
-+# define EXT3COW_DESC_PER_BLOCK_BITS(s)	(EXT3COW_SB(s)->s_desc_per_block_bits)
-+#else
-+# define EXT3COW_BLOCKS_PER_GROUP(s)	((s)->s_blocks_per_group)
-+# define EXT3COW_DESC_PER_BLOCK(s)		(EXT3COW_BLOCK_SIZE(s) / sizeof (struct ext3cow_group_desc))
-+# define EXT3COW_INODES_PER_GROUP(s)	((s)->s_inodes_per_group)
-+#endif
-+
-+/*
-+ * Constants relative to the data blocks
-+ */
-+#define	EXT3COW_NDIR_BLOCKS		12
-+#define	EXT3COW_IND_BLOCK			EXT3COW_NDIR_BLOCKS
-+#define	EXT3COW_DIND_BLOCK			(EXT3COW_IND_BLOCK + 1)
-+#define	EXT3COW_TIND_BLOCK			(EXT3COW_DIND_BLOCK + 1)
-+#define	EXT3COW_N_BLOCKS			(EXT3COW_TIND_BLOCK + 1)
-+
-+/*
-+ * Inode flags
-+ */
-+#define	EXT3COW_SECRM_FL			0x00000001 /* Secure deletion */
-+#define	EXT3COW_UNRM_FL			0x00000002 /* Undelete */
-+#define	EXT3COW_COMPR_FL			0x00000004 /* Compress file */
-+#define EXT3COW_SYNC_FL			0x00000008 /* Synchronous updates */
-+#define EXT3COW_IMMUTABLE_FL		0x00000010 /* Immutable file */
-+#define EXT3COW_APPEND_FL			0x00000020 /* writes to file may only append */
-+#define EXT3COW_NODUMP_FL			0x00000040 /* do not dump file */
-+#define EXT3COW_NOATIME_FL			0x00000080 /* do not update atime */
-+/* Reserved for compression usage... */
-+#define EXT3COW_DIRTY_FL			0x00000100
-+#define EXT3COW_COMPRBLK_FL		0x00000200 /* One or more compressed clusters */
-+#define EXT3COW_NOCOMPR_FL			0x00000400 /* Don't compress */
-+#define EXT3COW_ECOMPR_FL			0x00000800 /* Compression error */
-+/* End compression flags --- maybe not all used */
-+#define EXT3COW_INDEX_FL			0x00001000 /* hash-indexed directory */
-+#define EXT3COW_IMAGIC_FL			0x00002000 /* AFS directory */
-+#define EXT3COW_JOURNAL_DATA_FL		0x00004000 /* file data should be journaled */
-+#define EXT3COW_NOTAIL_FL			0x00008000 /* file tail should not be merged */
-+#define EXT3COW_DIRSYNC_FL			0x00010000 /* dirsync behaviour (directories only) */
-+#define EXT3COW_TOPDIR_FL			0x00020000 /* Top of directory hierarchies*/
-+/* Used for Versioning - znjp */
-+#define EXT3COW_UNCHANGEABLE_FL 0x00040000
-+#define EXT3COW_UNVERSIONABLE_FL 0x00080000
-+#define EXT3COW_FAKEINODE_FL    0x00100000
-+#define EXT3COW_RESERVED_FL		0x80000000 /* reserved for ext3cow lib */
-+
-+#define EXT3COW_FL_USER_VISIBLE		0x0003DFFF /* User visible flags */
-+#define EXT3COW_FL_USER_MODIFIABLE		0x000380FF /* User modifiable flags */
-+
-+/*
-+ * Inode dynamic state flags
-+ */
-+#define EXT3COW_STATE_JDATA		0x00000001 /* journaled data exists */
-+#define EXT3COW_STATE_NEW			0x00000002 /* inode is newly created */
-+#define EXT3COW_STATE_XATTR		0x00000004 /* has in-inode xattrs */
-+
-+/* Used to pass group descriptor data when online resize is done */
-+struct ext3cow_new_group_input {
-+	__u32 group;            /* Group number for this data */
-+	__u32 block_bitmap;     /* Absolute block number of block bitmap */
-+	__u32 inode_bitmap;     /* Absolute block number of inode bitmap */
-+	__u32 inode_table;      /* Absolute block number of inode table start */
-+	__u32 blocks_count;     /* Total number of blocks in this group */
-+	__u16 reserved_blocks;  /* Number of reserved blocks in this group */
-+	__u16 unused;
-+};
-+
-+/* The struct ext3cow_new_group_input in kernel space, with free_blocks_count */
-+struct ext3cow_new_group_data {
-+	__u32 group;
-+	__u32 block_bitmap;
-+	__u32 inode_bitmap;
-+	__u32 inode_table;
-+	__u32 blocks_count;
-+	__u16 reserved_blocks;
-+	__u16 unused;
-+	__u32 free_blocks_count;
-+};
-+
-+
-+/*
-+ * ioctl commands
-+ */
-+#define	EXT3COW_IOC_GETFLAGS		FS_IOC_GETFLAGS
-+#define	EXT3COW_IOC_SETFLAGS		FS_IOC_SETFLAGS
-+#define	EXT3COW_IOC_GETVERSION		_IOR('f', 3, long)
-+#define	EXT3COW_IOC_SETVERSION		_IOW('f', 4, long)
-+#define EXT3COW_IOC_GROUP_EXTEND		_IOW('f', 7, unsigned long)
-+#define EXT3COW_IOC_GROUP_ADD		_IOW('f', 8,struct ext3cow_new_group_input)
-+#define	EXT3COW_IOC_GETVERSION_OLD		FS_IOC_GETVERSION
-+#define	EXT3COW_IOC_SETVERSION_OLD		FS_IOC_SETVERSION
-+#ifdef CONFIG_JBD_DEBUG
-+#define EXT3COW_IOC_WAIT_FOR_READONLY	_IOR('f', 99, long)
-+#endif
-+#define EXT3COW_IOC_GETRSVSZ		_IOR('f', 5, long)
-+#define EXT3COW_IOC_SETRSVSZ		_IOW('f', 6, long)
-+/* ioctls for versioning - znjp */
-+#define EXT3COW_IOC_TAKESNAPSHOT _IOR('f', 7, long)
-+#define EXT3COW_IOC_GETEPOCH _IOR('f', 8, long)
-+
-+/*
-+ * ioctl commands in 32 bit emulation
-+ */
-+#define EXT3COW_IOC32_GETFLAGS		FS_IOC32_GETFLAGS
-+#define EXT3COW_IOC32_SETFLAGS		FS_IOC32_SETFLAGS
-+#define EXT3COW_IOC32_GETVERSION		_IOR('f', 3, int)
-+#define EXT3COW_IOC32_SETVERSION		_IOW('f', 4, int)
-+#define EXT3COW_IOC32_GETRSVSZ		_IOR('f', 5, int)
-+#define EXT3COW_IOC32_SETRSVSZ		_IOW('f', 6, int)
-+#define EXT3COW_IOC32_GROUP_EXTEND		_IOW('f', 7, unsigned int)
-+#ifdef CONFIG_JBD_DEBUG
-+#define EXT3COW_IOC32_WAIT_FOR_READONLY	_IOR('f', 99, int)
-+#endif
-+#define EXT3COW_IOC32_GETVERSION_OLD	FS_IOC32_GETVERSION
-+#define EXT3COW_IOC32_SETVERSION_OLD	FS_IOC32_SETVERSION
-+
-+
-+/*
-+ *  Mount options
-+ */
-+struct ext3cow_mount_options {
-+	unsigned long s_mount_opt;
-+	uid_t s_resuid;
-+	gid_t s_resgid;
-+	unsigned long s_commit_interval;
-+#ifdef CONFIG_QUOTA
-+	int s_jquota_fmt;
-+	char *s_qf_names[MAXQUOTAS];
-+#endif
-+};
-+
-+/*
-+ * Structure of an inode on the disk
-+ */
-+struct ext3cow_inode {
-+	__le16	i_mode;		/* File mode */
-+	__le16	i_uid;		/* Low 16 bits of Owner Uid */
-+	__le32	i_size;		/* Size in bytes */
-+	__le32	i_atime;	/* Access time */
-+	__le32	i_ctime;	/* Creation time */
-+	__le32	i_mtime;	/* Modification time */
-+	__le32	i_dtime;	/* Deletion Time */
-+	__le16	i_gid;		/* Low 16 bits of Group Id */
-+	__le16	i_links_count;	/* Links count */
-+	__le32	i_blocks;	/* Blocks count */
-+	__le32	i_flags;	/* File flags */
-+	union {
-+		struct {
-+			//__u32  l_i_reserved1;
-+      /* Direct block COW bitmap -znjp */
-+      __u16 l_i_direct_cow_bitmap;
-+      __u16 l_i_pad1;
-+		} linux1;
-+		struct {
-+			__u32  h_i_translator;
-+		} hurd1;
-+		struct {
-+			__u32  m_i_reserved1;
-+		} masix1;
-+	} osd1;				/* OS dependent 1 */
-+	__le32	i_block[EXT3COW_N_BLOCKS];/* Pointers to blocks */
-+	__le32	i_generation;	/* File version (for NFS) */
-+	__le32	i_file_acl;	/* File ACL */
-+	__le32	i_dir_acl;	/* Directory ACL */
-+	__le32	i_faddr;	/* Fragment address */
-+	union {
-+		struct {
-+			//__u8	l_i_frag;	/* Fragment number */
-+			//__u8	l_i_fsize;	/* Fragment size */
-+			//__u16	i_pad1;
-+			__le16	l_i_uid_high;	/* these 2 fields    */
-+			__le16	l_i_gid_high;	/* were reserved2[0] */
-+			//__u32	l_i_reserved2;
-+      /* Epoch number for versioning -znjp */
-+      __le32 l_i_epoch_number;
-+      __u32 l_i_next_inode;
-+		} linux2;
-+		struct {
-+			__u8	h_i_frag;	/* Fragment number */
-+			__u8	h_i_fsize;	/* Fragment size */
-+			__u16	h_i_mode_high;
-+			__u16	h_i_uid_high;
-+			__u16	h_i_gid_high;
-+			__u32	h_i_author;
-+		} hurd2;
-+		struct {
-+			__u8	m_i_frag;	/* Fragment number */
-+			__u8	m_i_fsize;	/* Fragment size */
-+			__u16	m_pad1;
-+			__u32	m_i_reserved2[2];
-+		} masix2;
-+	} osd2;				/* OS dependent 2 */
-+	__le16	i_extra_isize;
-+	__le16	i_pad1;
-+};
-+
-+#define i_size_high	i_dir_acl
-+
-+#if defined(__KERNEL__) || defined(__linux__)
-+/* For versioning -znjp */
-+//#define i_reserved1	osd1.linux1.l_i_reserved1
-+#define i_cowbitmap osd1.linux1.l_i_direct_cow_bitmap
-+//#define i_frag		osd2.linux2.l_i_frag
-+//#define i_fsize		osd2.linux2.l_i_fsize
-+#define i_uid_low	i_uid
-+#define i_gid_low	i_gid
-+/* For versioning -znjp */
-+#define i_uid_high	osd2.linux2.l_i_uid_high
-+#define i_gid_high	osd2.linux2.l_i_gid_high
-+//#define i_reserved2	osd2.linux2.l_i_reserved2
-+#define i_epch_number osd2.linux2.l_i_epoch_number
-+#define i_nxt_inode osd2.linux2.l_i_next_inode
-+
-+#elif defined(__GNU__)
-+
-+#define i_translator	osd1.hurd1.h_i_translator
-+#define i_frag		osd2.hurd2.h_i_frag;
-+#define i_fsize		osd2.hurd2.h_i_fsize;
-+#define i_uid_high	osd2.hurd2.h_i_uid_high
-+#define i_gid_high	osd2.hurd2.h_i_gid_high
-+#define i_author	osd2.hurd2.h_i_author
-+
-+#elif defined(__masix__)
-+
-+#define i_reserved1	osd1.masix1.m_i_reserved1
-+#define i_frag		osd2.masix2.m_i_frag
-+#define i_fsize		osd2.masix2.m_i_fsize
-+#define i_reserved2	osd2.masix2.m_i_reserved2
-+
-+#endif /* defined(__KERNEL__) || defined(__linux__) */
-+
-+/*
-+ * File system states
-+ */
-+#define	EXT3COW_VALID_FS			0x0001	/* Unmounted cleanly */
-+#define	EXT3COW_ERROR_FS			0x0002	/* Errors detected */
-+#define	EXT3COW_ORPHAN_FS			0x0004	/* Orphans being recovered */
-+
-+/*
-+ * Mount flags
-+ */
-+#define EXT3COW_MOUNT_CHECK		0x00001	/* Do mount-time checks */
-+#define EXT3COW_MOUNT_OLDALLOC		0x00002  /* Don't use the new Orlov allocator */
-+#define EXT3COW_MOUNT_GRPID		0x00004	/* Create files with directory's group */
-+#define EXT3COW_MOUNT_DEBUG		0x00008	/* Some debugging messages */
-+#define EXT3COW_MOUNT_ERRORS_CONT		0x00010	/* Continue on errors */
-+#define EXT3COW_MOUNT_ERRORS_RO		0x00020	/* Remount fs ro on errors */
-+#define EXT3COW_MOUNT_ERRORS_PANIC		0x00040	/* Panic on errors */
-+#define EXT3COW_MOUNT_MINIX_DF		0x00080	/* Mimics the Minix statfs */
-+#define EXT3COW_MOUNT_NOLOAD		0x00100	/* Don't use existing journal*/
-+#define EXT3COW_MOUNT_ABORT		0x00200	/* Fatal error detected */
-+#define EXT3COW_MOUNT_DATA_FLAGS		0x00C00	/* Mode for data writes: */
-+#define EXT3COW_MOUNT_JOURNAL_DATA		0x00400	/* Write data to journal */
-+#define EXT3COW_MOUNT_ORDERED_DATA		0x00800	/* Flush data before commit */
-+#define EXT3COW_MOUNT_WRITEBACK_DATA	0x00C00	/* No data ordering */
-+#define EXT3COW_MOUNT_UPDATE_JOURNAL	0x01000	/* Update the journal format */
-+#define EXT3COW_MOUNT_NO_UID32		0x02000  /* Disable 32-bit UIDs */
-+#define EXT3COW_MOUNT_XATTR_USER		0x04000	/* Extended user attributes */
-+#define EXT3COW_MOUNT_POSIX_ACL		0x08000	/* POSIX Access Control Lists */
-+#define EXT3COW_MOUNT_RESERVATION		0x10000	/* Preallocation */
-+#define EXT3COW_MOUNT_BARRIER		0x20000 /* Use block barriers */
-+#define EXT3COW_MOUNT_NOBH			0x40000 /* No bufferheads */
-+#define EXT3COW_MOUNT_QUOTA		0x80000 /* Some quota option set */
-+#define EXT3COW_MOUNT_USRQUOTA		0x100000 /* "old" user quota */
-+#define EXT3COW_MOUNT_GRPQUOTA		0x200000 /* "old" group quota */
-+
-+/* Compatibility, for having both ext2_fs.h and ext3cow_fs.h included at once */
-+#ifndef _LINUX_EXT2_FS_H
-+#define clear_opt(o, opt)		o &= ~EXT3COW_MOUNT_##opt
-+#define set_opt(o, opt)			o |= EXT3COW_MOUNT_##opt
-+#define test_opt(sb, opt)		(EXT3COW_SB(sb)->s_mount_opt & \
-+					 EXT3COW_MOUNT_##opt)
-+#else
-+#define EXT2_MOUNT_NOLOAD		EXT3COW_MOUNT_NOLOAD
-+#define EXT2_MOUNT_ABORT		EXT3COW_MOUNT_ABORT
-+#define EXT2_MOUNT_DATA_FLAGS		EXT3COW_MOUNT_DATA_FLAGS
-+#endif
-+
-+#define ext3cow_set_bit			ext2_set_bit
-+#define ext3cow_set_bit_atomic		ext2_set_bit_atomic
-+#define ext3cow_clear_bit			ext2_clear_bit
-+#define ext3cow_clear_bit_atomic		ext2_clear_bit_atomic
-+#define ext3cow_test_bit			ext2_test_bit
-+#define ext3cow_find_first_zero_bit	ext2_find_first_zero_bit
-+#define ext3cow_find_next_zero_bit		ext2_find_next_zero_bit
-+
-+/*
-+ * Maximal mount counts between two filesystem checks
-+ */
-+#define EXT3COW_DFL_MAX_MNT_COUNT		20	/* Allow 20 mounts */
-+#define EXT3COW_DFL_CHECKINTERVAL		0	/* Don't use interval check */
-+
-+/*
-+ * Behaviour when detecting errors
-+ */
-+#define EXT3COW_ERRORS_CONTINUE		1	/* Continue execution */
-+#define EXT3COW_ERRORS_RO			2	/* Remount fs read-only */
-+#define EXT3COW_ERRORS_PANIC		3	/* Panic */
-+#define EXT3COW_ERRORS_DEFAULT		EXT3COW_ERRORS_CONTINUE
-+
-+/*
-+ * Structure of the super block
-+ */
-+struct ext3cow_super_block {
-+/*00*/	__le32	s_inodes_count;		/* Inodes count */
-+	__le32	s_blocks_count;		/* Blocks count */
-+	__le32	s_r_blocks_count;	/* Reserved blocks count */
-+	__le32	s_free_blocks_count;	/* Free blocks count */
-+/*10*/	__le32	s_free_inodes_count;	/* Free inodes count */
-+	__le32	s_first_data_block;	/* First Data Block */
-+	__le32	s_log_block_size;	/* Block size */
-+	__le32	s_log_frag_size;	/* Fragment size */
-+/*20*/	__le32	s_blocks_per_group;	/* # Blocks per group */
-+	__le32	s_frags_per_group;	/* # Fragments per group */
-+	__le32	s_inodes_per_group;	/* # Inodes per group */
-+	__le32	s_mtime;		/* Mount time */
-+/*30*/	__le32	s_wtime;		/* Write time */
-+	__le16	s_mnt_count;		/* Mount count */
-+	__le16	s_max_mnt_count;	/* Maximal mount count */
-+	__le16	s_magic;		/* Magic signature */
-+	__le16	s_state;		/* File system state */
-+	__le16	s_errors;		/* Behaviour when detecting errors */
-+	__le16	s_minor_rev_level;	/* minor revision level */
-+/*40*/	__le32	s_lastcheck;		/* time of last check */
-+	__le32	s_checkinterval;	/* max. time between checks */
-+	__le32	s_creator_os;		/* OS */
-+	__le32	s_rev_level;		/* Revision level */
-+/*50*/	__le16	s_def_resuid;		/* Default uid for reserved blocks */
-+	__le16	s_def_resgid;		/* Default gid for reserved blocks */
-+	/*
-+	 * These fields are for EXT3COW_DYNAMIC_REV superblocks only.
-+	 *
-+	 * Note: the difference between the compatible feature set and
-+	 * the incompatible feature set is that if there is a bit set
-+	 * in the incompatible feature set that the kernel doesn't
-+	 * know about, it should refuse to mount the filesystem.
-+	 *
-+	 * e2fsck's requirements are more strict; if it doesn't know
-+	 * about a feature in either the compatible or incompatible
-+	 * feature set, it must abort and not try to meddle with
-+	 * things it doesn't understand...
-+	 */
-+	__le32	s_first_ino;		/* First non-reserved inode */
-+	__le16   s_inode_size;		/* size of inode structure */
-+	__le16	s_block_group_nr;	/* block group # of this superblock */
-+	__le32	s_feature_compat;	/* compatible feature set */
-+/*60*/	__le32	s_feature_incompat;	/* incompatible feature set */
-+	__le32	s_feature_ro_compat;	/* readonly-compatible feature set */
-+/*68*/	__u8	s_uuid[16];		/* 128-bit uuid for volume */
-+/*78*/	char	s_volume_name[16];	/* volume name */
-+/*88*/	char	s_last_mounted[64];	/* directory where last mounted */
-+/*C8*/	__le32	s_algorithm_usage_bitmap; /* For compression */
-+	/*
-+	 * Performance hints.  Directory preallocation should only
-+	 * happen if the EXT3COW_FEATURE_COMPAT_DIR_PREALLOC flag is on.
-+	 */
-+	__u8	s_prealloc_blocks;	/* Nr of blocks to try to preallocate*/
-+	__u8	s_prealloc_dir_blocks;	/* Nr to preallocate for dirs */
-+	__le16	s_reserved_gdt_blocks;	/* Per group desc for online growth */
-+	/*
-+	 * Journaling support valid if EXT3COW_FEATURE_COMPAT_HAS_JOURNAL set.
-+	 */
-+/*D0*/	__u8	s_journal_uuid[16];	/* uuid of journal superblock */
-+/*E0*/	__le32	s_journal_inum;		/* inode number of journal file */
-+	__le32	s_journal_dev;		/* device number of journal file */
-+	__le32	s_last_orphan;		/* start of list of inodes to delete */
-+	__le32	s_hash_seed[4];		/* HTREE hash seed */
-+	__u8	s_def_hash_version;	/* Default hash version to use */
-+	__u8	s_reserved_char_pad;
-+	__u16	s_reserved_word_pad;
-+	__le32	s_default_mount_opts;
-+	__le32	s_first_meta_bg;	/* First metablock block group */
-+  /* Added for version - znjp */
-+  __le32 s_epoch_number;
-+	__u32	s_reserved[189];	/* Padding to the end of the block */
-+};
-+
-+#ifdef __KERNEL__
-+#include <linux/ext3cow_fs_i.h>
-+#include <linux/ext3cow_fs_sb.h>
-+static inline struct ext3cow_sb_info * EXT3COW_SB(struct super_block *sb)
-+{
-+	return sb->s_fs_info;
-+}
-+static inline struct ext3cow_inode_info *EXT3COW_I(struct inode *inode)
-+{
-+	return container_of(inode, struct ext3cow_inode_info, vfs_inode);
-+}
-+
-+static inline int ext3cow_valid_inum(struct super_block *sb, unsigned long ino)
-+{
-+	return ino == EXT3COW_ROOT_INO ||
-+		ino == EXT3COW_JOURNAL_INO ||
-+		ino == EXT3COW_RESIZE_INO ||
-+		(ino >= EXT3COW_FIRST_INO(sb) &&
-+		 ino <= le32_to_cpu(EXT3COW_SB(sb)->s_es->s_inodes_count));
-+}
-+#else
-+/* Assume that user mode programs are passing in an ext3cowfs superblock, not
-+ * a kernel struct super_block.  This will allow us to call the feature-test
-+ * macros from user land. */
-+#define EXT3COW_SB(sb)	(sb)
-+#endif
-+
-+#define NEXT_ORPHAN(inode) EXT3COW_I(inode)->i_dtime
-+
-+/*
-+ * Codes for operating systems
-+ */
-+#define EXT3COW_OS_LINUX		0
-+#define EXT3COW_OS_HURD		1
-+#define EXT3COW_OS_MASIX		2
-+#define EXT3COW_OS_FREEBSD		3
-+#define EXT3COW_OS_LITES		4
-+
-+/*
-+ * Revision levels
-+ */
-+#define EXT3COW_GOOD_OLD_REV	0	/* The good old (original) format */
-+#define EXT3COW_DYNAMIC_REV	1	/* V2 format w/ dynamic inode sizes */
-+
-+#define EXT3COW_CURRENT_REV	EXT3COW_GOOD_OLD_REV
-+#define EXT3COW_MAX_SUPP_REV	EXT3COW_DYNAMIC_REV
-+
-+#define EXT3COW_GOOD_OLD_INODE_SIZE 128
-+
-+/*
-+ * Feature set definitions
-+ */
-+
-+#define EXT3COW_HAS_COMPAT_FEATURE(sb,mask)			\
-+	( EXT3COW_SB(sb)->s_es->s_feature_compat & cpu_to_le32(mask) )
-+#define EXT3COW_HAS_RO_COMPAT_FEATURE(sb,mask)			\
-+	( EXT3COW_SB(sb)->s_es->s_feature_ro_compat & cpu_to_le32(mask) )
-+#define EXT3COW_HAS_INCOMPAT_FEATURE(sb,mask)			\
-+	( EXT3COW_SB(sb)->s_es->s_feature_incompat & cpu_to_le32(mask) )
-+#define EXT3COW_SET_COMPAT_FEATURE(sb,mask)			\
-+	EXT3COW_SB(sb)->s_es->s_feature_compat |= cpu_to_le32(mask)
-+#define EXT3COW_SET_RO_COMPAT_FEATURE(sb,mask)			\
-+	EXT3COW_SB(sb)->s_es->s_feature_ro_compat |= cpu_to_le32(mask)
-+#define EXT3COW_SET_INCOMPAT_FEATURE(sb,mask)			\
-+	EXT3COW_SB(sb)->s_es->s_feature_incompat |= cpu_to_le32(mask)
-+#define EXT3COW_CLEAR_COMPAT_FEATURE(sb,mask)			\
-+	EXT3COW_SB(sb)->s_es->s_feature_compat &= ~cpu_to_le32(mask)
-+#define EXT3COW_CLEAR_RO_COMPAT_FEATURE(sb,mask)			\
-+	EXT3COW_SB(sb)->s_es->s_feature_ro_compat &= ~cpu_to_le32(mask)
-+#define EXT3COW_CLEAR_INCOMPAT_FEATURE(sb,mask)			\
-+	EXT3COW_SB(sb)->s_es->s_feature_incompat &= ~cpu_to_le32(mask)
-+
-+#define EXT3COW_FEATURE_COMPAT_DIR_PREALLOC	0x0001
-+#define EXT3COW_FEATURE_COMPAT_IMAGIC_INODES	0x0002
-+#define EXT3COW_FEATURE_COMPAT_HAS_JOURNAL		0x0004
-+#define EXT3COW_FEATURE_COMPAT_EXT_ATTR		0x0008
-+#define EXT3COW_FEATURE_COMPAT_RESIZE_INODE	0x0010
-+#define EXT3COW_FEATURE_COMPAT_DIR_INDEX		0x0020
-+
-+#define EXT3COW_FEATURE_RO_COMPAT_SPARSE_SUPER	0x0001
-+#define EXT3COW_FEATURE_RO_COMPAT_LARGE_FILE	0x0002
-+#define EXT3COW_FEATURE_RO_COMPAT_BTREE_DIR	0x0004
-+
-+#define EXT3COW_FEATURE_INCOMPAT_COMPRESSION	0x0001
-+#define EXT3COW_FEATURE_INCOMPAT_FILETYPE		0x0002
-+#define EXT3COW_FEATURE_INCOMPAT_RECOVER		0x0004 /* Needs recovery */
-+#define EXT3COW_FEATURE_INCOMPAT_JOURNAL_DEV	0x0008 /* Journal device */
-+#define EXT3COW_FEATURE_INCOMPAT_META_BG		0x0010
-+
-+#define EXT3COW_FEATURE_COMPAT_SUPP	EXT2_FEATURE_COMPAT_EXT_ATTR
-+#define EXT3COW_FEATURE_INCOMPAT_SUPP	(EXT3COW_FEATURE_INCOMPAT_FILETYPE| \
-+					 EXT3COW_FEATURE_INCOMPAT_RECOVER| \
-+					 EXT3COW_FEATURE_INCOMPAT_META_BG)
-+#define EXT3COW_FEATURE_RO_COMPAT_SUPP	(EXT3COW_FEATURE_RO_COMPAT_SPARSE_SUPER| \
-+					 EXT3COW_FEATURE_RO_COMPAT_LARGE_FILE| \
-+					 EXT3COW_FEATURE_RO_COMPAT_BTREE_DIR)
-+
-+/*
-+ * Default values for user and/or group using reserved blocks
-+ */
-+#define	EXT3COW_DEF_RESUID		0
-+#define	EXT3COW_DEF_RESGID		0
-+
-+/*
-+ * Default mount options
-+ */
-+#define EXT3COW_DEFM_DEBUG		0x0001
-+#define EXT3COW_DEFM_BSDGROUPS	0x0002
-+#define EXT3COW_DEFM_XATTR_USER	0x0004
-+#define EXT3COW_DEFM_ACL		0x0008
-+#define EXT3COW_DEFM_UID16		0x0010
-+#define EXT3COW_DEFM_JMODE		0x0060
-+#define EXT3COW_DEFM_JMODE_DATA	0x0020
-+#define EXT3COW_DEFM_JMODE_ORDERED	0x0040
-+#define EXT3COW_DEFM_JMODE_WBACK	0x0060
-+
-+/*
-+ * Structure of a directory entry
-+ */
-+#define EXT3COW_NAME_LEN 255
-+
-+struct ext3cow_dir_entry {
-+	__le32	inode;			/* Inode number */
-+	__le16	rec_len;		/* Directory entry length */
-+	__le16	name_len;		/* Name length */
-+	char	name[EXT3COW_NAME_LEN];	/* File name */
-+};
-+
-+/*
-+ * The new version of the directory entry.  Since EXT3COW structures are
-+ * stored in intel byte order, and the name_len field could never be
-+ * bigger than 255 chars, it's safe to reclaim the extra byte for the
-+ * file_type field.
-+ */
-+struct ext3cow_dir_entry_2 {
-+	__le32	inode;			/* Inode number */
-+	__le16	rec_len;		/* Directory entry length */
-+	__u8	name_len;		/* Name length */
-+	__u8	file_type;
-+  /* Added for versioning - znjp */
-+  __u32 birth_epoch;
-+  __u32 death_epoch;
-+	char	name[EXT3COW_NAME_LEN];	/* File name */
-+};
-+
-+/*
-+ * Ext3 directory file types.  Only the low 3 bits are used.  The
-+ * other bits are reserved for now.
-+ */
-+#define EXT3COW_FT_UNKNOWN		0
-+#define EXT3COW_FT_REG_FILE	1
-+#define EXT3COW_FT_DIR		2
-+#define EXT3COW_FT_CHRDEV		3
-+#define EXT3COW_FT_BLKDEV		4
-+#define EXT3COW_FT_FIFO		5
-+#define EXT3COW_FT_SOCK		6
-+#define EXT3COW_FT_SYMLINK		7
-+
-+#define EXT3COW_FT_MAX		8
-+
-+/* Versioning macros - znjp */
-+#define EXT3COW_DIRENT_ALIVE 0
-+#define EXT3COW_IS_DIRENT_ALIVE(de) ((le32_to_cpu(de->death_epoch) == EXT3COW_DIRENT_ALIVE))
-+#define EXT3COW_IS_DIRENT_SCOPED(de, epoch) \
-+((le32_to_cpu(de->birth_epoch) <= epoch) && \
-+(EXT3COW_IS_DIRENT_ALIVE(de) || (!EXT3COW_IS_DIRENT_ALIVE(de) && \
-+le32_to_cpu(de->death_epoch) > epoch)))
-+#define EXT3COW_I_EPOCHNUMBER(inode) (((unsigned int)EXT3COW_I(inode)->i_epoch_number))
-+#define EXT3COW_S_EPOCHNUMBER(sb) (((unsigned int)EXT3COW_SB(sb)->s_epoch_number))
-+#define EXT3COW_I_NEXT_INODE(inode) (((unsigned int)EXT3COW_I(inode)->i_next_inode))
-+#define EXT3COW_IS_UNVERSIONABLE(inode) (((unsigned int)EXT3COW_I(inode)->i_flags & EXT3COW_UNVERSIONABLE_FL))
-+#define EXT3COW_IS_UNCHANGEABLE(inode) (((unsigned int)EXT3COW_I(inode)->i_flags & EXT3COW_UNCHANGEABLE_FL))
-+#define EXT3COW_IS_FAKEINODE(inode) (((unsigned int)EXT3COW_I(inode)->i_flags & EXT3COW_FAKEINODE_FL))
-+
-+
-+/*
-+ * EXT3COW_DIR_PAD defines the directory entries boundaries
-+ *
-+ * NOTE: It must be a multiple of 4
-+ */
-+#define EXT3COW_DIR_PAD			4
-+#define EXT3COW_DIR_ROUND			(EXT3COW_DIR_PAD - 1)
-+/* Added 8 to account for birth and death epochs -znjp */
-+#define EXT3COW_DIR_REC_LEN(name_len)	(((name_len) + 16 + EXT3COW_DIR_ROUND) & \
-+					 ~EXT3COW_DIR_ROUND)
-+/*
-+ * Hash Tree Directory indexing
-+ * (c) Daniel Phillips, 2001
-+ */
-+
-+#ifdef CONFIG_EXT3COW_INDEX
-+  #define is_dx(dir) (EXT3COW_HAS_COMPAT_FEATURE(dir->i_sb, \
-+					      EXT3COW_FEATURE_COMPAT_DIR_INDEX) && \
-+		      (EXT3COW_I(dir)->i_flags & EXT3COW_INDEX_FL))
-+#define EXT3COW_DIR_LINK_MAX(dir) (!is_dx(dir) && (dir)->i_nlink >= EXT3COW_LINK_MAX)
-+#define EXT3COW_DIR_LINK_EMPTY(dir) ((dir)->i_nlink == 2 || (dir)->i_nlink == 1)
-+#else
-+  #define is_dx(dir) 0
-+#define EXT3COW_DIR_LINK_MAX(dir) ((dir)->i_nlink >= EXT3COW_LINK_MAX)
-+#define EXT3COW_DIR_LINK_EMPTY(dir) ((dir)->i_nlink == 2)
-+#endif
-+
-+/* Legal values for the dx_root hash_version field: */
-+
-+#define DX_HASH_LEGACY		0
-+#define DX_HASH_HALF_MD4	1
-+#define DX_HASH_TEA		2
-+
-+#ifdef __KERNEL__
-+
-+/* hash info structure used by the directory hash */
-+struct dx_hash_info
-+{
-+	u32		hash;
-+	u32		minor_hash;
-+	int		hash_version;
-+	u32		*seed;
-+};
-+
-+#define EXT3COW_HTREE_EOF	0x7fffffff
-+
-+/*
-+ * Control parameters used by ext3cow_htree_next_block
-+ */
-+#define HASH_NB_ALWAYS		1
-+
-+
-+/*
-+ * Describe an inode's exact location on disk and in memory
-+ */
-+struct ext3cow_iloc
-+{
-+	struct buffer_head *bh;
-+	unsigned long offset;
-+	unsigned long block_group;
-+};
-+
-+static inline struct ext3cow_inode *ext3cow_raw_inode(struct ext3cow_iloc *iloc)
-+{
-+	return (struct ext3cow_inode *) (iloc->bh->b_data + iloc->offset);
-+}
-+
-+/*
-+ * This structure is stuffed into the struct file's private_data field
-+ * for directories.  It is where we put information so that we can do
-+ * readdir operations in hash tree order.
-+ */
-+struct dir_private_info {
-+	struct rb_root	root;
-+	struct rb_node	*curr_node;
-+	struct fname	*extra_fname;
-+	loff_t		last_pos;
-+	__u32		curr_hash;
-+	__u32		curr_minor_hash;
-+	__u32		next_hash;
-+};
-+
-+/* calculate the first block number of the group */
-+static inline ext3cow_fsblk_t
-+ext3cow_group_first_block_no(struct super_block *sb, unsigned long group_no)
-+{
-+	return group_no * (ext3cow_fsblk_t)EXT3COW_BLOCKS_PER_GROUP(sb) +
-+		le32_to_cpu(EXT3COW_SB(sb)->s_es->s_first_data_block);
-+}
-+
-+/*
-+ * Special error return code only used by dx_probe() and its callers.
-+ */
-+#define ERR_BAD_DX_DIR	-75000
-+
-+/*
-+ * Function prototypes
-+ */
-+
-+/*
-+ * Ok, these declarations are also in <linux/kernel.h> but none of the
-+ * ext3cow source programs needs to include it so they are duplicated here.
-+ */
-+# define NORET_TYPE    /**/
-+# define ATTRIB_NORET  __attribute__((noreturn))
-+# define NORET_AND     noreturn,
-+
-+/* balloc.c */
-+extern int ext3cow_bg_has_super(struct super_block *sb, int group);
-+extern unsigned long ext3cow_bg_num_gdb(struct super_block *sb, int group);
-+extern ext3cow_fsblk_t ext3cow_new_block (handle_t *handle, struct inode *inode,
-+			ext3cow_fsblk_t goal, int *errp);
-+extern ext3cow_fsblk_t ext3cow_new_blocks (handle_t *handle, struct inode *inode,
-+			ext3cow_fsblk_t goal, unsigned long *count, int *errp);
-+extern void ext3cow_free_blocks (handle_t *handle, struct inode *inode,
-+			ext3cow_fsblk_t block, unsigned long count);
-+extern void ext3cow_free_blocks_sb (handle_t *handle, struct super_block *sb,
-+				 ext3cow_fsblk_t block, unsigned long count,
-+				unsigned long *pdquot_freed_blocks);
-+extern ext3cow_fsblk_t ext3cow_count_free_blocks (struct super_block *);
-+extern void ext3cow_check_blocks_bitmap (struct super_block *);
-+extern struct ext3cow_group_desc * ext3cow_get_group_desc(struct super_block * sb,
-+						    unsigned int block_group,
-+						    struct buffer_head ** bh);
-+extern int ext3cow_should_retry_alloc(struct super_block *sb, int *retries);
-+extern void ext3cow_init_block_alloc_info(struct inode *);
-+extern void ext3cow_rsv_window_add(struct super_block *sb, struct ext3cow_reserve_window_node *rsv);
-+
-+
-+/* dir.c */
-+extern int ext3cow_check_dir_entry(const char *, struct inode *,
-+				struct ext3cow_dir_entry_2 *,
-+				struct buffer_head *, unsigned long);
-+extern int ext3cow_htree_store_dirent(struct file *dir_file, __u32 hash,
-+				    __u32 minor_hash,
-+				    struct ext3cow_dir_entry_2 *dirent);
-+extern void ext3cow_htree_free_dir_info(struct dir_private_info *p);
-+
-+/* fsync.c */
-+extern int ext3cow_sync_file (struct file *, struct dentry *, int);
-+
-+/* hash.c */
-+extern int ext3cowfs_dirhash(const char *name, int len, struct
-+			  dx_hash_info *hinfo);
-+
-+/* ialloc.c */
-+extern struct inode * ext3cow_new_inode (handle_t *, struct inode *, int);
-+extern void ext3cow_free_inode (handle_t *, struct inode *);
-+extern struct inode * ext3cow_orphan_get (struct super_block *, unsigned long);
-+extern unsigned long ext3cow_count_free_inodes (struct super_block *);
-+extern unsigned long ext3cow_count_dirs (struct super_block *);
-+extern void ext3cow_check_inodes_bitmap (struct super_block *);
-+extern unsigned long ext3cow_count_free (struct buffer_head *, unsigned);
-+
-+
-+/* inode.c */
-+int ext3cow_forget(handle_t *handle, int is_metadata, struct inode *inode,
-+		struct buffer_head *bh, ext3cow_fsblk_t blocknr);
-+struct buffer_head * ext3cow_getblk (handle_t *, struct inode *, long, int, int *);
-+struct buffer_head * ext3cow_bread (handle_t *, struct inode *, int, int, int *);
-+int ext3cow_get_blocks_handle(handle_t *handle, struct inode *inode,
-+	sector_t iblock, unsigned long maxblocks, struct buffer_head *bh_result,
-+	int create, int extend_disksize);
-+
-+extern void ext3cow_read_inode (struct inode *);
-+extern int  ext3cow_write_inode (struct inode *, int);
-+extern int  ext3cow_setattr (struct dentry *, struct iattr *);
-+extern void ext3cow_delete_inode (struct inode *);
-+extern int  ext3cow_sync_inode (handle_t *, struct inode *);
-+extern void ext3cow_discard_reservation (struct inode *);
-+extern void ext3cow_dirty_inode(struct inode *);
-+extern int ext3cow_change_inode_journal_flag(struct inode *, int);
-+extern int ext3cow_get_inode_loc(struct inode *, struct ext3cow_iloc *);
-+extern void ext3cow_truncate (struct inode *);
-+extern void ext3cow_set_inode_flags(struct inode *);
-+extern void ext3cow_set_aops(struct inode *inode);
-+
-+/* ioctl.c */
-+extern int ext3cow_ioctl (struct inode *, struct file *, unsigned int,
-+		       unsigned long);
-+extern long ext3cow_compat_ioctl (struct file *, unsigned int, unsigned long);
-+
-+/* namei.c */
-+extern int is_unchangeable(struct inode *, struct dentry *);
-+extern int ext3cow_orphan_add(handle_t *, struct inode *);
-+extern int ext3cow_orphan_del(handle_t *, struct inode *);
-+extern int ext3cow_htree_fill_tree(struct file *dir_file, __u32 start_hash,
-+				__u32 start_minor_hash, __u32 *next_hash);
-+extern struct inode *ext3cow_fake_inode(struct inode *, unsigned int);
-+extern int ext3cow_dup_inode(struct inode *, struct inode *);
-+extern int ext3cow_reclaim_dup_inode(struct inode *, struct inode *);
-+
-+/* resize.c */
-+extern int ext3cow_group_add(struct super_block *sb,
-+				struct ext3cow_new_group_data *input);
-+extern int ext3cow_group_extend(struct super_block *sb,
-+				struct ext3cow_super_block *es,
-+				ext3cow_fsblk_t n_blocks_count);
-+
-+/* super.c */
-+extern void ext3cow_error (struct super_block *, const char *, const char *, ...)
-+	__attribute__ ((format (printf, 3, 4)));
-+extern void __ext3cow_std_error (struct super_block *, const char *, int);
-+extern void ext3cow_abort (struct super_block *, const char *, const char *, ...)
-+	__attribute__ ((format (printf, 3, 4)));
-+extern void ext3cow_warning (struct super_block *, const char *, const char *, ...)
-+	__attribute__ ((format (printf, 3, 4)));
-+extern void ext3cow_update_dynamic_rev (struct super_block *sb);
-+extern unsigned int ext3cow_take_snapshot(struct super_block *sb);
-+
-+#define ext3cow_std_error(sb, errno)				\
-+do {								\
-+	if ((errno))						\
-+		__ext3cow_std_error((sb), __FUNCTION__, (errno));	\
-+} while (0)
-+
-+/*
-+ * Inodes and files operations
-+ */
-+
-+/* dir.c */
-+extern const struct file_operations ext3cow_dir_operations;
-+
-+/* file.c */
-+extern struct inode_operations ext3cow_file_inode_operations;
-+extern const struct file_operations ext3cow_file_operations;
-+
-+/* namei.c */
-+extern struct inode_operations ext3cow_dir_inode_operations;
-+extern struct inode_operations ext3cow_special_inode_operations;
-+
-+/* symlink.c */
-+extern struct inode_operations ext3cow_symlink_inode_operations;
-+extern struct inode_operations ext3cow_fast_symlink_inode_operations;
-+
-+
-+#endif	/* __KERNEL__ */
-+
-+#endif	/* _LINUX_EXT3COW_FS_H */
-diff -ruN linux-2.6.20.3/include/linux/ext3cow_fs_i.h linux-2.6.20.3-ext3cow/include/linux/ext3cow_fs_i.h
---- linux-2.6.20.3/include/linux/ext3cow_fs_i.h	1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.20.3-ext3cow/include/linux/ext3cow_fs_i.h	2008-03-09 11:10:55.000000000 -0400
-@@ -0,0 +1,152 @@
-+/*
-+ *  linux/include/linux/ext3cow_fs_i.h
-+ *
-+ * Copyright (C) 1992, 1993, 1994, 1995
-+ * Remy Card (card@masi.ibp.fr)
-+ * Laboratoire MASI - Institut Blaise Pascal
-+ * Universite Pierre et Marie Curie (Paris VI)
-+ *
-+ *  from
-+ *
-+ *  linux/include/linux/minix_fs_i.h
-+ *
-+ *  Copyright (C) 1991, 1992  Linus Torvalds
-+ */
-+
-+#ifndef _LINUX_EXT3COW_FS_I
-+#define _LINUX_EXT3COW_FS_I
-+
-+#include <linux/rwsem.h>
-+#include <linux/rbtree.h>
-+#include <linux/seqlock.h>
-+#include <linux/mutex.h>
-+
-+/* data type for block offset of block group */
-+typedef int ext3cow_grpblk_t;
-+
-+/* data type for filesystem-wide blocks number */
-+typedef unsigned long ext3cow_fsblk_t;
-+
-+#define E3FSBLK "%lu"
-+
-+struct ext3cow_reserve_window {
-+	ext3cow_fsblk_t	_rsv_start;	/* First byte reserved */
-+	ext3cow_fsblk_t	_rsv_end;	/* Last byte reserved or 0 */
-+};
-+
-+struct ext3cow_reserve_window_node {
-+	struct rb_node		rsv_node;
-+	__u32			rsv_goal_size;
-+	__u32			rsv_alloc_hit;
-+	struct ext3cow_reserve_window	rsv_window;
-+};
-+
-+struct ext3cow_block_alloc_info {
-+	/* information about reservation window */
-+	struct ext3cow_reserve_window_node	rsv_window_node;
-+	/*
-+	 * was i_next_alloc_block in ext3cow_inode_info
-+	 * is the logical (file-relative) number of the
-+	 * most-recently-allocated block in this file.
-+	 * We use this for detecting linearly ascending allocation requests.
-+	 */
-+	__u32                   last_alloc_logical_block;
-+	/*
-+	 * Was i_next_alloc_goal in ext3cow_inode_info
-+	 * is the *physical* companion to i_next_alloc_block.
-+	 * it the the physical block number of the block which was most-recentl
-+	 * allocated to this file.  This give us the goal (target) for the next
-+	 * allocation when we detect linearly ascending requests.
-+	 */
-+	ext3cow_fsblk_t		last_alloc_physical_block;
-+};
-+
-+#define rsv_start rsv_window._rsv_start
-+#define rsv_end rsv_window._rsv_end
-+
-+/*
-+ * third extended file system inode data in memory
-+ */
-+struct ext3cow_inode_info {
-+	__le32	i_data[15];	/* unconverted */
-+	__u32	i_flags;
-+#ifdef EXT3COW_FRAGMENTS
-+	__u32	i_faddr;
-+	__u8	i_frag_no;
-+	__u8	i_frag_size;
-+#endif
-+	ext3cow_fsblk_t	i_file_acl;
-+	__u32	i_dir_acl;
-+	__u32	i_dtime;
-+
-+	/*
-+	 * i_block_group is the number of the block group which contains
-+	 * this file's inode.  Constant across the lifetime of the inode,
-+	 * it is ued for making block allocation decisions - we try to
-+	 * place a file's data blocks near its inode block, and new inodes
-+	 * near to their parent directory's inode.
-+	 */
-+	__u32	i_block_group;
-+	__u32	i_state;		/* Dynamic state flags for ext3cow */
-+
-+	/* block reservation info */
-+	struct ext3cow_block_alloc_info *i_block_alloc_info;
-+
-+	__u32	i_dir_start_lookup;
-+
-+  /* For versioning -znjp */
-+  __u16 i_cow_bitmap;
-+  __u32 i_epoch_number;
-+  __u32 i_next_inode;
-+#ifdef CONFIG_EXT3COW_FS_XATTR
-+	/*
-+	 * Extended attributes can be read independently of the main file
-+	 * data. Taking i_mutex even when reading would cause contention
-+	 * between readers of EAs and writers of regular file data, so
-+	 * instead we synchronize on xattr_sem when reading or changing
-+	 * EAs.
-+	 */
-+	struct rw_semaphore xattr_sem;
-+#endif
-+#ifdef CONFIG_EXT3COW_FS_POSIX_ACL
-+	struct posix_acl	*i_acl;
-+	struct posix_acl	*i_default_acl;
-+#endif
-+
-+	struct list_head i_orphan;	/* unlinked but open inodes */
-+
-+	/*
-+	 * i_disksize keeps track of what the inode size is ON DISK, not
-+	 * in memory.  During truncate, i_size is set to the new size by
-+	 * the VFS prior to calling ext3cow_truncate(), but the filesystem won't
-+	 * set i_disksize to 0 until the truncate is actually under way.
-+	 *
-+	 * The intent is that i_disksize always represents the blocks which
-+	 * are used by this file.  This allows recovery to restart truncate
-+	 * on orphans if we crash during truncate.  We actually write i_disksize
-+	 * into the on-disk inode when writing inodes out, instead of i_size.
-+	 *
-+	 * The only time when i_disksize and i_size may be different is when
-+	 * a truncate is in progress.  The only things which change i_disksize
-+	 * are ext3cow_get_block (growth) and ext3cow_truncate (shrinkth).
-+	 */
-+	loff_t	i_disksize;
-+
-+	/* on-disk additional length */
-+	__u16 i_extra_isize;
-+
-+	/*
-+	 * truncate_mutex is for serialising ext3cow_truncate() against
-+	 * ext3cow_getblock().  In the 2.4 ext2 design, great chunks of inode's
-+	 * data tree are chopped off during truncate. We can't do that in
-+	 * ext3cow because whenever we perform intermediate commits during
-+	 * truncate, the inode and all the metadata blocks *must* be in a
-+	 * consistent state which allows truncation of the orphans to restart
-+	 * during recovery.  Hence we must fix the get_block-vs-truncate race
-+	 * by other means, so we have truncate_mutex.
-+	 */
-+	struct mutex truncate_mutex;
-+	struct inode vfs_inode;
-+};
-+
-+#endif	/* _LINUX_EXT3COW_FS_I */
-diff -ruN linux-2.6.20.3/include/linux/ext3cow_fs_sb.h linux-2.6.20.3-ext3cow/include/linux/ext3cow_fs_sb.h
---- linux-2.6.20.3/include/linux/ext3cow_fs_sb.h	1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.20.3-ext3cow/include/linux/ext3cow_fs_sb.h	2008-03-09 11:10:57.000000000 -0400
-@@ -0,0 +1,86 @@
-+/*
-+ *  linux/include/linux/ext3cow_fs_sb.h
-+ *
-+ * Copyright (C) 1992, 1993, 1994, 1995
-+ * Remy Card (card@masi.ibp.fr)
-+ * Laboratoire MASI - Institut Blaise Pascal
-+ * Universite Pierre et Marie Curie (Paris VI)
-+ *
-+ *  from
-+ *
-+ *  linux/include/linux/minix_fs_sb.h
-+ *
-+ *  Copyright (C) 1991, 1992  Linus Torvalds
-+ */
-+
-+#ifndef _LINUX_EXT3COW_FS_SB
-+#define _LINUX_EXT3COW_FS_SB
-+
-+#ifdef __KERNEL__
-+#include <linux/timer.h>
-+#include <linux/wait.h>
-+#include <linux/blockgroup_lock.h>
-+#include <linux/percpu_counter.h>
-+#endif
-+#include <linux/rbtree.h>
-+
-+/*
-+ * third extended-fs super-block data in memory
-+ */
-+struct ext3cow_sb_info {
-+	unsigned long s_frag_size;	/* Size of a fragment in bytes */
-+	unsigned long s_frags_per_block;/* Number of fragments per block */
-+	unsigned long s_inodes_per_block;/* Number of inodes per block */
-+	unsigned long s_frags_per_group;/* Number of fragments in a group */
-+	unsigned long s_blocks_per_group;/* Number of blocks in a group */
-+	unsigned long s_inodes_per_group;/* Number of inodes in a group */
-+	unsigned long s_itb_per_group;	/* Number of inode table blocks per group */
-+	unsigned long s_gdb_count;	/* Number of group descriptor blocks */
-+	unsigned long s_desc_per_block;	/* Number of group descriptors per block */
-+	unsigned long s_groups_count;	/* Number of groups in the fs */
-+	struct buffer_head * s_sbh;	/* Buffer containing the super block */
-+	struct ext3cow_super_block * s_es;	/* Pointer to the super block in the buffer */
-+	struct buffer_head ** s_group_desc;
-+	unsigned long  s_mount_opt;
-+	uid_t s_resuid;
-+	gid_t s_resgid;
-+	unsigned short s_mount_state;
-+	unsigned short s_pad;
-+	int s_addr_per_block_bits;
-+	int s_desc_per_block_bits;
-+	int s_inode_size;
-+	int s_first_ino;
-+	spinlock_t s_next_gen_lock;
-+	u32 s_next_generation;
-+	u32 s_hash_seed[4];
-+	int s_def_hash_version;
-+	struct percpu_counter s_freeblocks_counter;
-+	struct percpu_counter s_freeinodes_counter;
-+	struct percpu_counter s_dirs_counter;
-+	struct blockgroup_lock s_blockgroup_lock;
-+
-+	/* root of the per fs reservation window tree */
-+	spinlock_t s_rsv_window_lock;
-+	struct rb_root s_rsv_window_root;
-+	struct ext3cow_reserve_window_node s_rsv_window_head;
-+
-+  /* For versioning -znjp */
-+  u32 s_epoch_number;
-+
-+	/* Journaling */
-+	struct inode * s_journal_inode;
-+	struct journal_s * s_journal;
-+	struct list_head s_orphan;
-+	unsigned long s_commit_interval;
-+	struct block_device *journal_bdev;
-+#ifdef CONFIG_JBD_DEBUG
-+	struct timer_list turn_ro_timer;	/* For turning read-only (crash simulation) */
-+	wait_queue_head_t ro_wait_queue;	/* For people waiting for the fs to go read-only */
-+#endif
-+#ifdef CONFIG_QUOTA
-+	char *s_qf_names[MAXQUOTAS];		/* Names of quota files with journalled quota */
-+	int s_jquota_fmt;			/* Format of quota to use */
-+#endif
-+};
-+
-+#endif	/* _LINUX_EXT3COW_FS_SB */
-diff -ruN linux-2.6.20.3/include/linux/ext3cow_jbd.h linux-2.6.20.3-ext3cow/include/linux/ext3cow_jbd.h
---- linux-2.6.20.3/include/linux/ext3cow_jbd.h	1969-12-31 19:00:00.000000000 -0500
-+++ linux-2.6.20.3-ext3cow/include/linux/ext3cow_jbd.h	2008-03-09 11:10:56.000000000 -0400
-@@ -0,0 +1,226 @@
-+/*
-+ * linux/include/linux/ext3cow_jbd.h
-+ *
-+ * Written by Stephen C. Tweedie <sct@redhat.com>, 1999
-+ *
-+ * Copyright 1998--1999 Red Hat corp --- All Rights Reserved
-+ *
-+ * This file is part of the Linux kernel and is made available under
-+ * the terms of the GNU General Public License, version 2, or at your
-+ * option, any later version, incorporated herein by reference.
-+ *
-+ * Ext3-specific journaling extensions.
-+ */
-+
-+#ifndef _LINUX_EXT3COW_JBD_H
-+#define _LINUX_EXT3COW_JBD_H
-+
-+#include <linux/fs.h>
-+#include <linux/jbd.h>
-+#include <linux/ext3cow_fs.h>
-+
-+#define EXT3COW_JOURNAL(inode)	(EXT3COW_SB((inode)->i_sb)->s_journal)
-+
-+/* Define the number of blocks we need to account to a transaction to
-+ * modify one block of data.
-+ *
-+ * We may have to touch one inode, one bitmap buffer, up to three
-+ * indirection blocks, the group and superblock summaries, and the data
-+ * block to complete the transaction.  */
-+
-+#define EXT3COW_SINGLEDATA_TRANS_BLOCKS	8U
-+
-+/* Extended attribute operations touch at most two data buffers,
-+ * two bitmap buffers, and two group summaries, in addition to the inode
-+ * and the superblock, which are already accounted for. */
-+
-+#define EXT3COW_XATTR_TRANS_BLOCKS		6U
-+
-+/* Define the minimum size for a transaction which modifies data.  This
-+ * needs to take into account the fact that we may end up modifying two
-+ * quota files too (one for the group, one for the user quota).  The
-+ * superblock only gets updated once, of course, so don't bother
-+ * counting that again for the quota updates. */
-+
-+#define EXT3COW_DATA_TRANS_BLOCKS(sb)	(EXT3COW_SINGLEDATA_TRANS_BLOCKS + \
-+					 EXT3COW_XATTR_TRANS_BLOCKS - 2 + \
-+					 2*EXT3COW_QUOTA_TRANS_BLOCKS(sb))
-+
-+/* Delete operations potentially hit one directory's namespace plus an
-+ * entire inode, plus arbitrary amounts of bitmap/indirection data.  Be
-+ * generous.  We can grow the delete transaction later if necessary. */
-+
-+#define EXT3COW_DELETE_TRANS_BLOCKS(sb)	(2 * EXT3COW_DATA_TRANS_BLOCKS(sb) + 64)
-+
-+/* Define an arbitrary limit for the amount of data we will anticipate
-+ * writing to any given transaction.  For unbounded transactions such as
-+ * write(2) and truncate(2) we can write more than this, but we always
-+ * start off at the maximum transaction size and grow the transaction
-+ * optimistically as we go. */
-+
-+#define EXT3COW_MAX_TRANS_DATA		64U
-+
-+/* We break up a large truncate or write transaction once the handle's
-+ * buffer credits gets this low, we need either to extend the
-+ * transaction or to start a new one.  Reserve enough space here for
-+ * inode, bitmap, superblock, group and indirection updates for at least
-+ * one block, plus two quota updates.  Quota allocations are not
-+ * needed. */
-+
-+#define EXT3COW_RESERVE_TRANS_BLOCKS	12U
-+
-+#define EXT3COW_INDEX_EXTRA_TRANS_BLOCKS	8
-+
-+#ifdef CONFIG_QUOTA
-+/* Amount of blocks needed for quota update - we know that the structure was
-+ * allocated so we need to update only inode+data */
-+#define EXT3COW_QUOTA_TRANS_BLOCKS(sb) (test_opt(sb, QUOTA) ? 2 : 0)
-+/* Amount of blocks needed for quota insert/delete - we do some block writes
-+ * but inode, sb and group updates are done only once */
-+#define EXT3COW_QUOTA_INIT_BLOCKS(sb) (test_opt(sb, QUOTA) ? (DQUOT_INIT_ALLOC*\
-+		(EXT3COW_SINGLEDATA_TRANS_BLOCKS-3)+3+DQUOT_INIT_REWRITE) : 0)
-+#define EXT3COW_QUOTA_DEL_BLOCKS(sb) (test_opt(sb, QUOTA) ? (DQUOT_DEL_ALLOC*\
-+		(EXT3COW_SINGLEDATA_TRANS_BLOCKS-3)+3+DQUOT_DEL_REWRITE) : 0)
-+#else
-+#define EXT3COW_QUOTA_TRANS_BLOCKS(sb) 0
-+#define EXT3COW_QUOTA_INIT_BLOCKS(sb) 0
-+#define EXT3COW_QUOTA_DEL_BLOCKS(sb) 0
-+#endif
-+
-+int
-+ext3cow_mark_iloc_dirty(handle_t *handle,
-+		     struct inode *inode,
-+		     struct ext3cow_iloc *iloc);
-+
-+/*
-+ * On success, We end up with an outstanding reference count against
-+ * iloc->bh.  This _must_ be cleaned up later.
-+ */
-+
-+int ext3cow_reserve_inode_write(handle_t *handle, struct inode *inode,
-+			struct ext3cow_iloc *iloc);
-+
-+int ext3cow_mark_inode_dirty(handle_t *handle, struct inode *inode);
-+
-+/*
-+ * Wrapper functions with which ext3cow calls into JBD.  The intent here is
-+ * to allow these to be turned into appropriate stubs so ext3cow can control
-+ * ext2 filesystems, so ext2+ext3cow systems only nee one fs.  This work hasn't
-+ * been done yet.
-+ */
-+
-+static inline void ext3cow_journal_release_buffer(handle_t *handle,
-+						struct buffer_head *bh)
-+{
-+	journal_release_buffer(handle, bh);
-+}
-+
-+void ext3cow_journal_abort_handle(const char *caller, const char *err_fn,
-+		struct buffer_head *bh, handle_t *handle, int err);
-+
-+int __ext3cow_journal_get_undo_access(const char *where, handle_t *handle,
-+				struct buffer_head *bh);
-+
-+int __ext3cow_journal_get_write_access(const char *where, handle_t *handle,
-+				struct buffer_head *bh);
-+
-+int __ext3cow_journal_forget(const char *where, handle_t *handle,
-+				struct buffer_head *bh);
-+
-+int __ext3cow_journal_revoke(const char *where, handle_t *handle,
-+				unsigned long blocknr, struct buffer_head *bh);
-+
-+int __ext3cow_journal_get_create_access(const char *where,
-+				handle_t *handle, struct buffer_head *bh);
-+
-+int __ext3cow_journal_dirty_metadata(const char *where,
-+				handle_t *handle, struct buffer_head *bh);
-+
-+#define ext3cow_journal_get_undo_access(handle, bh) \
-+	__ext3cow_journal_get_undo_access(__FUNCTION__, (handle), (bh))
-+#define ext3cow_journal_get_write_access(handle, bh) \
-+	__ext3cow_journal_get_write_access(__FUNCTION__, (handle), (bh))
-+#define ext3cow_journal_revoke(handle, blocknr, bh) \
-+	__ext3cow_journal_revoke(__FUNCTION__, (handle), (blocknr), (bh))
-+#define ext3cow_journal_get_create_access(handle, bh) \
-+	__ext3cow_journal_get_create_access(__FUNCTION__, (handle), (bh))
-+#define ext3cow_journal_dirty_metadata(handle, bh) \
-+	__ext3cow_journal_dirty_metadata(__FUNCTION__, (handle), (bh))
-+#define ext3cow_journal_forget(handle, bh) \
-+	__ext3cow_journal_forget(__FUNCTION__, (handle), (bh))
-+
-+int ext3cow_journal_dirty_data(handle_t *handle, struct buffer_head *bh);
-+
-+handle_t *ext3cow_journal_start_sb(struct super_block *sb, int nblocks);
-+int __ext3cow_journal_stop(const char *where, handle_t *handle);
-+
-+static inline handle_t *ext3cow_journal_start(struct inode *inode, int nblocks)
-+{
-+	return ext3cow_journal_start_sb(inode->i_sb, nblocks);
-+}
-+
-+#define ext3cow_journal_stop(handle) \
-+	__ext3cow_journal_stop(__FUNCTION__, (handle))
-+
-+static inline handle_t *ext3cow_journal_current_handle(void)
-+{
-+	return journal_current_handle();
-+}
-+
-+static inline int ext3cow_journal_extend(handle_t *handle, int nblocks)
-+{
-+	return journal_extend(handle, nblocks);
-+}
-+
-+static inline int ext3cow_journal_restart(handle_t *handle, int nblocks)
-+{
-+	return journal_restart(handle, nblocks);
-+}
-+
-+static inline int ext3cow_journal_blocks_per_page(struct inode *inode)
-+{
-+	return journal_blocks_per_page(inode);
-+}
-+
-+static inline int ext3cow_journal_force_commit(journal_t *journal)
-+{
-+	return journal_force_commit(journal);
-+}
-+
-+/* super.c */
-+int ext3cow_force_commit(struct super_block *sb);
-+
-+static inline int ext3cow_should_journal_data(struct inode *inode)
-+{
-+	if (!S_ISREG(inode->i_mode))
-+		return 1;
-+	if (test_opt(inode->i_sb, DATA_FLAGS) == EXT3COW_MOUNT_JOURNAL_DATA)
-+		return 1;
-+	if (EXT3COW_I(inode)->i_flags & EXT3COW_JOURNAL_DATA_FL)
-+		return 1;
-+	return 0;
-+}
-+
-+static inline int ext3cow_should_order_data(struct inode *inode)
-+{
-+	if (!S_ISREG(inode->i_mode))
-+		return 0;
-+	if (EXT3COW_I(inode)->i_flags & EXT3COW_JOURNAL_DATA_FL)
-+		return 0;
-+	if (test_opt(inode->i_sb, DATA_FLAGS) == EXT3COW_MOUNT_ORDERED_DATA)
-+		return 1;
-+	return 0;
-+}
-+
-+static inline int ext3cow_should_writeback_data(struct inode *inode)
-+{
-+	if (!S_ISREG(inode->i_mode))
-+		return 0;
-+	if (EXT3COW_I(inode)->i_flags & EXT3COW_JOURNAL_DATA_FL)
-+		return 0;
-+	if (test_opt(inode->i_sb, DATA_FLAGS) == EXT3COW_MOUNT_WRITEBACK_DATA)
-+		return 1;
-+	return 0;
-+}
-+
-+#endif	/* _LINUX_EXT3COW_JBD_H */
-diff -ruN linux-2.6.20.3/include/linux/magic.h linux-2.6.20.3-ext3cow/include/linux/magic.h
---- linux-2.6.20.3/include/linux/magic.h	2007-03-13 14:27:08.000000000 -0400
-+++ linux-2.6.20.3-ext3cow/include/linux/magic.h	2008-03-09 11:10:57.000000000 -0400
-@@ -9,6 +9,7 @@
- #define EFS_SUPER_MAGIC		0x414A53
- #define EXT2_SUPER_MAGIC	0xEF53
- #define EXT3_SUPER_MAGIC	0xEF53
-+#define EXT3COW_SUPER_MAGIC	0xEF53
- #define EXT4_SUPER_MAGIC	0xEF53
- #define HPFS_SUPER_MAGIC	0xf995e849
- #define ISOFS_SUPER_MAGIC	0x9660
-
diff --git a/pkgs/os-specific/linux/kernel/linux-2.6.20.nix b/pkgs/os-specific/linux/kernel/linux-2.6.20.nix
index 365453e5872e6..f8979feae05c5 100644
--- a/pkgs/os-specific/linux/kernel/linux-2.6.20.nix
+++ b/pkgs/os-specific/linux/kernel/linux-2.6.20.nix
@@ -1,77 +1,21 @@
-{ stdenv, fetchurl, perl, mktemp, module_init_tools
+args @ {stdenv, fetchurl, userModeLinux ? false, ...}:
 
-  # A list of patches to apply to the kernel.  Each element of this list
-  # should be an attribute set {name, patch} where `name' is a
-  # symbolic name and `patch' is the actual patch.  The patch may
-  # optionally be compressed with gzip or bzip2.
-, kernelPatches ? []
+import ./generic.nix (
 
-, # Whether to build a User-Mode Linux kernel.
-  userModeLinux ? false
-
-, # Allows you to set your own kernel version suffix (e.g.,
-  # "-my-kernel").
-  localVersion ? ""
-
-, # Your own kernel configuration file, if you don't want to use the
-  # default. 
-  kernelConfig ? null  
-}:
-
-assert stdenv.system == "i686-linux" || stdenv.system == "x86_64-linux";
-
-let
-
-  lib = import ../../../lib;
-
-  version = "2.6.20.12";
-
-in
-
-stdenv.mkDerivation {
-  name = if userModeLinux then "user-mode-linux-${version}" else "linux-${version}";
-  builder = ./builder.sh;
-  
-  src = fetchurl {
-    url = "mirror://kernel/linux/kernel/v2.6/linux-${version}.tar.bz2";
-    sha256 = "1s7vdpg2897q5pcyxxypqcnibwpbdawbimkf3pngmahj8wr9c03x";
-  };
+  rec {
+    version = "2.6.20.21";
   
-  patches = map (p: p.patch) kernelPatches;
-  
-  extraConfig = lib.concatStrings (map (p: "\n" + (if p ? extraConfig then p.extraConfig else "") + "\n") kernelPatches);
-
-  config =
-    if kernelConfig != null then kernelConfig else
-    if userModeLinux then ./config-2.6.20-uml else
-    if stdenv.system == "i686-linux" then ./config-2.6.20-i686-smp else
-    if stdenv.system == "x86_64-linux" then ./config-2.6.20-x86_64-smp else
-    abort "No kernel configuration for your platform!";
-  
-  buildInputs = [perl mktemp];
-  
-  arch =
-    if userModeLinux then "um" else
-    if stdenv.system == "i686-linux" then "i386" else
-    if stdenv.system == "x86_64-linux" then "x86_64" else
-    abort "Platform ${stdenv.system} is not supported.";
-
-  makeFlags = if userModeLinux then "ARCH=um SHELL=bash HAVE_AIO_ABI=" else "";
-
-  inherit module_init_tools;
-
-  allowLocalVersion = false; # don't allow patches to set a suffix
-  inherit localVersion; # but do allow the user to set one.
-
-  meta = {
-    description =
-      (if userModeLinux then
-        "User-Mode Linux"
-       else
-        "The Linux kernel") +
-      (if kernelPatches == [] then "" else
-        " (with patches: "
-        + lib.concatStrings (lib.intersperse ", " (map (x: x.name) kernelPatches))
-        + ")");
-  };
-}
+    src = fetchurl {
+      url = "mirror://kernel/linux/kernel/v2.6/linux-${version}.tar.bz2";
+      sha256 = "1ympa2sgnx0sxs30g42zlkv53kfilpc732qqxchcwgv2p0y24hnp";
+    };
+
+    config =
+      if userModeLinux then ./config-2.6.20-uml else
+      if stdenv.system == "i686-linux" then ./config-2.6.20-i686-smp else
+      if stdenv.system == "x86_64-linux" then ./config-2.6.20-x86_64-smp else
+      abort "No kernel configuration for your platform!";
+  }
+
+  // args
+)
diff --git a/pkgs/os-specific/linux/kernel/linux-2.6.21.nix b/pkgs/os-specific/linux/kernel/linux-2.6.21.nix
index e7fc2943a5cde..a63d39c2df7fc 100644
--- a/pkgs/os-specific/linux/kernel/linux-2.6.21.nix
+++ b/pkgs/os-specific/linux/kernel/linux-2.6.21.nix
@@ -1,76 +1,21 @@
-{ stdenv, fetchurl, perl, mktemp, module_init_tools
+args @ {stdenv, fetchurl, userModeLinux ? false, ...}:
 
-  # A list of patches to apply to the kernel.  Each element of this list
-  # should be an attribute set {name, patch} where `name' is a
-  # symbolic name and `patch' is the actual patch.  The patch may
-  # optionally be compressed with gzip or bzip2.
-, kernelPatches ? []
+import ./generic.nix (
 
-, # Whether to build a User-Mode Linux kernel.
-  userModeLinux ? false
-
-, # Allows you to set your own kernel version suffix (e.g.,
-  # "-my-kernel").
-  localVersion ? ""
-
-, # Your own kernel configuration file, if you don't want to use the
-  # default. 
-  kernelConfig ? null  
-}:
-
-assert stdenv.system == "i686-linux" || stdenv.system == "x86_64-linux";
-
-let
-
-  lib = import ../../../lib;
-
-  version = "2.6.21.7";
-
-in
-
-stdenv.mkDerivation {
-  name = if userModeLinux then "user-mode-linux-${version}" else "linux-${version}";
-  builder = ./builder.sh;
+  rec {
+    version = "2.6.21.7";
   
-  src = fetchurl {
-    url = "mirror://kernel/linux/kernel/v2.6/linux-${version}.tar.bz2";
-    sha256 = "1c8ndsz35qd8vyng3xsxjjkjv5bnzyvc9b5vd85fz5v0bjp8hx50";
-  };
-  
-  patches = map (p: p.patch) kernelPatches;
-  extraConfig = lib.concatStrings (map (p: "\n" + (if p ? extraConfig then p.extraConfig else "") + "\n") kernelPatches);
-
-  config =
-    if kernelConfig != null then kernelConfig else
-    if userModeLinux then ./config-2.6.21-uml else
-    if stdenv.system == "i686-linux" then ./config-2.6.21-i686-smp else
-    if stdenv.system == "x86_64-linux" then ./config-2.6.21-x86_64-smp else
-    abort "No kernel configuration for your platform!";
-  
-  buildInputs = [perl mktemp];
-  
-  arch =
-    if userModeLinux then "um" else
-    if stdenv.system == "i686-linux" then "i386" else
-    if stdenv.system == "x86_64-linux" then "x86_64" else
-    abort "Platform ${stdenv.system} is not supported.";
-
-  makeFlags = if userModeLinux then "ARCH=um SHELL=bash" else "";
-
-  inherit module_init_tools;
-
-  allowLocalVersion = false; # don't allow patches to set a suffix
-  inherit localVersion; # but do allow the user to set one.
-
-  meta = {
-    description =
-      (if userModeLinux then
-        "User-Mode Linux"
-       else
-        "The Linux kernel") +
-      (if kernelPatches == [] then "" else
-        " (with patches: "
-        + lib.concatStrings (lib.intersperse ", " (map (x: x.name) kernelPatches))
-        + ")");
-  };
-}
+    src = fetchurl {
+      url = "mirror://kernel/linux/kernel/v2.6/linux-${version}.tar.bz2";
+      sha256 = "1c8ndsz35qd8vyng3xsxjjkjv5bnzyvc9b5vd85fz5v0bjp8hx50";
+    };
+
+    config =
+      if userModeLinux then ./config-2.6.21-uml else
+      if stdenv.system == "i686-linux" then ./config-2.6.21-i686-smp else
+      if stdenv.system == "x86_64-linux" then ./config-2.6.21-x86_64-smp else
+      abort "No kernel configuration for your platform!";
+  }
+
+  // args
+)
diff --git a/pkgs/os-specific/linux/kernel/linux-2.6.22.nix b/pkgs/os-specific/linux/kernel/linux-2.6.22.nix
index 1abc1470616e3..898d9e472badb 100644
--- a/pkgs/os-specific/linux/kernel/linux-2.6.22.nix
+++ b/pkgs/os-specific/linux/kernel/linux-2.6.22.nix
@@ -1,84 +1,21 @@
-{ stdenv, fetchurl, perl, mktemp, module_init_tools
+args @ {stdenv, fetchurl, userModeLinux ? false, ...}:
 
-  # A list of patches to apply to the kernel.  Each element of this list
-  # should be an attribute set {name, patch} where `name' is a
-  # symbolic name and `patch' is the actual patch.  The patch may
-  # optionally be compressed with gzip or bzip2.
-, kernelPatches ? []
+import ./generic.nix (
 
-, # Whether to build a User-Mode Linux kernel.
-  userModeLinux ? false
-
-, # Allows you to set your own kernel version suffix (e.g.,
-  # "-my-kernel").
-  localVersion ? ""
-
-, # Your own kernel configuration file, if you don't want to use the
-  # default. 
-  kernelConfig ? null
-
-, # A list of additional statements to be appended to the
-  # configuration file.
-  extraConfig ? []
-}:
-
-assert stdenv.system == "i686-linux" || stdenv.system == "x86_64-linux";
-
-let
-
-  lib = import ../../../lib;
-
-  version = "2.6.22.18";
-
-in
-
-stdenv.mkDerivation {
-  name = if userModeLinux then "user-mode-linux-${version}" else "linux-${version}";
-  builder = ./builder.sh;
+  rec {
+    version = "2.6.22.19";
   
-  src = fetchurl {
-    url = "mirror://kernel/linux/kernel/v2.6/linux-${version}.tar.bz2";
-    sha256 = "09acj1xr16j9y91gzwzcjhanhcpyac1ah2lc42mfi7d8c0plagry";
-  };
-  
-  patches = map (p: p.patch) kernelPatches;
-  extraConfig =
-    let addNewlines = map (s: "\n" + s + "\n");
-        configFromPatches =
-          map (p: if p ? extraConfig then p.extraConfig else "") kernelPatches;
-    in lib.concatStrings (addNewlines (configFromPatches ++ extraConfig));
-
-  config =
-    if kernelConfig != null then kernelConfig else
-    if userModeLinux then ./config-2.6.22-uml else
-    if stdenv.system == "i686-linux" then ./config-2.6.22-i686-smp else
-    if stdenv.system == "x86_64-linux" then ./config-2.6.22-x86_64-smp else
-    abort "No kernel configuration for your platform!";
-  
-  buildInputs = [perl mktemp];
-  
-  arch =
-    if userModeLinux then "um" else
-    if stdenv.system == "i686-linux" then "i386" else
-    if stdenv.system == "x86_64-linux" then "x86_64" else
-    abort "Platform ${stdenv.system} is not supported.";
-
-  makeFlags = if userModeLinux then "ARCH=um SHELL=bash" else "";
-
-  inherit module_init_tools;
-
-  allowLocalVersion = false; # don't allow patches to set a suffix
-  inherit localVersion; # but do allow the user to set one.
-
-  meta = {
-    description =
-      (if userModeLinux then
-        "User-Mode Linux"
-       else
-        "The Linux kernel") +
-      (if kernelPatches == [] then "" else
-        " (with patches: "
-        + lib.concatStrings (lib.intersperse ", " (map (x: x.name) kernelPatches))
-        + ")");
-  };
-}
+    src = fetchurl {
+      url = "mirror://kernel/linux/kernel/v2.6/linux-${version}.tar.bz2";
+      sha256 = "0jwax5aqfmdfg5pa40zx94x7n5ykr8m5rqczb1m5mc8j98hvnycq";
+    };
+
+    config =
+      if userModeLinux then ./config-2.6.22-uml else
+      if stdenv.system == "i686-linux" then ./config-2.6.22-i686-smp else
+      if stdenv.system == "x86_64-linux" then ./config-2.6.22-x86_64-smp else
+      abort "No kernel configuration for your platform!";
+  }
+
+  // args
+)
diff --git a/pkgs/os-specific/linux/kernel/linux-2.6.23.nix b/pkgs/os-specific/linux/kernel/linux-2.6.23.nix
index b6756c113dd1e..c05e959ddb3a8 100644
--- a/pkgs/os-specific/linux/kernel/linux-2.6.23.nix
+++ b/pkgs/os-specific/linux/kernel/linux-2.6.23.nix
@@ -1,91 +1,21 @@
-{ stdenv, fetchurl, perl, mktemp, module_init_tools
+args @ {stdenv, fetchurl, userModeLinux ? false, ...}:
 
-  # A list of patches to apply to the kernel.  Each element of this list
-  # should be an attribute set {name, patch} where `name' is a
-  # symbolic name and `patch' is the actual patch.  The patch may
-  # optionally be compressed with gzip or bzip2.
-, kernelPatches ? []
+import ./generic.nix (
 
-, # Whether to build a User-Mode Linux kernel.
-  userModeLinux ? false
-
-, # Allows you to set your own kernel version suffix (e.g.,
-  # "-my-kernel").
-  localVersion ? ""
-
-, # Your own kernel configuration file, if you don't want to use the
-  # default. 
-  kernelConfig ? null
-
-, # A list of additional statements to be appended to the
-  # configuration file.
-  extraConfig ? []
-}:
-
-assert stdenv.system == "i686-linux" || stdenv.system == "x86_64-linux";
-
-let
-
-  lib = import ../../../lib;
-
-  version = "2.6.23.17";
-
-in
-
-stdenv.mkDerivation {
-  name = if userModeLinux then "user-mode-linux-${version}" else "linux-${version}";
-
-  passthru = {
-    inherit version;
-    # Combine the `features' attribute sets of all the kernel patches.
-    features = lib.fold (x: y: (if x ? features then x.features else {}) // y) {} kernelPatches;
-  };
+  rec {
+    version = "2.6.23.17";
   
-  builder = ./builder.sh;
-  
-  src = fetchurl {
-    url = "mirror://kernel/linux/kernel/v2.6/linux-${version}.tar.bz2";
-    sha256 = "0lww6ywgl353xlaxcc3hg5d2q1vcydbqhddvkfpphr07zr7mwl32";
-  };
-  
-  patches = map (p: p.patch) kernelPatches;
-  extraConfig =
-    let addNewlines = map (s: "\n" + s + "\n");
-        configFromPatches =
-          map (p: if p ? extraConfig then p.extraConfig else "") kernelPatches;
-    in lib.concatStrings (addNewlines (configFromPatches ++ extraConfig));
-
-  config =
-    if kernelConfig != null then kernelConfig else
-    if userModeLinux then ./config-2.6.23-uml else
-    if stdenv.system == "i686-linux" then ./config-2.6.23-i686-smp else
-    if stdenv.system == "x86_64-linux" then ./config-2.6.23-x86_64-smp else
-    abort "No kernel configuration for your platform!";
-  
-  buildInputs = [perl mktemp];
-  
-  arch =
-    if userModeLinux then "um" else
-    if stdenv.system == "i686-linux" then "i386" else
-    if stdenv.system == "x86_64-linux" then "x86_64" else
-    abort "Platform ${stdenv.system} is not supported.";
-
-  makeFlags = if userModeLinux then "ARCH=um SHELL=bash" else "";
-
-  inherit module_init_tools;
-
-  allowLocalVersion = false; # don't allow patches to set a suffix
-  inherit localVersion; # but do allow the user to set one.
-
-  meta = {
-    description =
-      (if userModeLinux then
-        "User-Mode Linux"
-       else
-        "The Linux kernel") +
-      (if kernelPatches == [] then "" else
-        " (with patches: "
-        + lib.concatStrings (lib.intersperse ", " (map (x: x.name) kernelPatches))
-        + ")");
-  };
-}
+    src = fetchurl {
+      url = "mirror://kernel/linux/kernel/v2.6/linux-${version}.tar.bz2";
+      sha256 = "0lww6ywgl353xlaxcc3hg5d2q1vcydbqhddvkfpphr07zr7mwl32";
+    };
+
+    config =
+      if userModeLinux then ./config-2.6.23-uml else
+      if stdenv.system == "i686-linux" then ./config-2.6.23-i686-smp else
+      if stdenv.system == "x86_64-linux" then ./config-2.6.23-x86_64-smp else
+      abort "No kernel configuration for your platform!";
+  }
+
+  // args
+)
diff --git a/pkgs/os-specific/linux/kernel/linux-2.6.25.nix b/pkgs/os-specific/linux/kernel/linux-2.6.25.nix
index 3556ee5d34d37..680304582db87 100644
--- a/pkgs/os-specific/linux/kernel/linux-2.6.25.nix
+++ b/pkgs/os-specific/linux/kernel/linux-2.6.25.nix
@@ -1,95 +1,25 @@
-{ stdenv, fetchurl, perl, mktemp, module_init_tools
+args @ {stdenv, fetchurl, userModeLinux ? false, ...}:
 
-  # A list of patches to apply to the kernel.  Each element of this list
-  # should be an attribute set {name, patch} where `name' is a
-  # symbolic name and `patch' is the actual patch.  The patch may
-  # optionally be compressed with gzip or bzip2.
-, kernelPatches ? []
+import ./generic.nix (
 
-, # Whether to build a User-Mode Linux kernel.
-  userModeLinux ? false
-
-, # Allows you to set your own kernel version suffix (e.g.,
-  # "-my-kernel").
-  localVersion ? ""
-
-, # Your own kernel configuration file, if you don't want to use the
-  # default. 
-  kernelConfig ? null
-
-, # A list of additional statements to be appended to the
-  # configuration file.
-  extraConfig ? []
-}:
-
-assert stdenv.system == "i686-linux" || stdenv.system == "x86_64-linux";
-
-let
-
-  lib = stdenv.lib;
-
-  version = "2.6.25.17";
-
-  baseFeatures = {
-    iwlwifi = true;
-  };
-
-in
-
-stdenv.mkDerivation {
-  name = if userModeLinux then "user-mode-linux-${version}" else "linux-${version}";
-
-  passthru = {
-    inherit version;
-    # Combine the `features' attribute sets of all the kernel patches.
-    features = lib.fold (x: y: (if x ? features then x.features else {}) // y) baseFeatures kernelPatches;
-  };
-  
-  builder = ./builder.sh;
-  
-  src = fetchurl {
-    url = "mirror://kernel/linux/kernel/v2.6/linux-${version}.tar.bz2";
-    sha256 = "15jx163rryvvdy65wgfpws8l5cqrczfygsz6v5280i5glhy1dh77";
-  };
-  
-  patches = map (p: p.patch) kernelPatches;
-  extraConfig =
-    let addNewlines = map (s: "\n" + s + "\n");
-        configFromPatches =
-          map (p: if p ? extraConfig then p.extraConfig else "") kernelPatches;
-    in lib.concatStrings (addNewlines (configFromPatches ++ extraConfig));
-
-  config =
-    if kernelConfig != null then kernelConfig else
-    if userModeLinux then ./config-2.6.25-uml else
-    if stdenv.system == "i686-linux" then ./config-2.6.25-i686-smp else
-    if stdenv.system == "x86_64-linux" then ./config-2.6.25-x86_64-smp else
-    abort "No kernel configuration for your platform!";
+  rec {
+    version = "2.6.25.20";
   
-  buildInputs = [perl mktemp];
-  
-  arch =
-    if userModeLinux then "um" else
-    if stdenv.system == "i686-linux" then "i386" else
-    if stdenv.system == "x86_64-linux" then "x86_64" else
-    abort "Platform ${stdenv.system} is not supported.";
-
-  makeFlags = if userModeLinux then "ARCH=um SHELL=bash" else "";
-
-  inherit module_init_tools;
-
-  allowLocalVersion = false; # don't allow patches to set a suffix
-  inherit localVersion; # but do allow the user to set one.
-
-  meta = {
-    description =
-      (if userModeLinux then
-        "User-Mode Linux"
-       else
-        "The Linux kernel") +
-      (if kernelPatches == [] then "" else
-        " (with patches: "
-        + lib.concatStrings (lib.intersperse ", " (map (x: x.name) kernelPatches))
-        + ")");
-  };
-}
+    src = fetchurl {
+      url = "mirror://kernel/linux/kernel/v2.6/linux-${version}.tar.bz2";
+      sha256 = "07knyjhvanvclk6xdwi07vfvsmiqciqaj26cn78ayiqqqr9d4f6y";
+    };
+
+    features = {
+      iwlwifi = true;
+    };
+ 
+    config =
+      if userModeLinux then ./config-2.6.25-uml else
+      if stdenv.system == "i686-linux" then ./config-2.6.25-i686-smp else
+      if stdenv.system == "x86_64-linux" then ./config-2.6.25-x86_64-smp else
+      abort "No kernel configuration for your platform!";
+  }
+
+  // args
+)
diff --git a/pkgs/os-specific/linux/kernel/linux-2.6.26.nix b/pkgs/os-specific/linux/kernel/linux-2.6.26.nix
index b5c45f60edc19..ded4297a1d3c2 100644
--- a/pkgs/os-specific/linux/kernel/linux-2.6.26.nix
+++ b/pkgs/os-specific/linux/kernel/linux-2.6.26.nix
@@ -1,95 +1,26 @@
-{ stdenv, fetchurl, perl, mktemp, module_init_tools
+args @ {stdenv, fetchurl, userModeLinux ? false, ...}:
 
-  # A list of patches to apply to the kernel.  Each element of this list
-  # should be an attribute set {name, patch} where `name' is a
-  # symbolic name and `patch' is the actual patch.  The patch may
-  # optionally be compressed with gzip or bzip2.
-, kernelPatches ? []
+assert !userModeLinux;
 
-, # Whether to build a User-Mode Linux kernel.
-  userModeLinux ? false
+import ./generic.nix (
 
-, # Allows you to set your own kernel version suffix (e.g.,
-  # "-my-kernel").
-  localVersion ? ""
-
-, # Your own kernel configuration file, if you don't want to use the
-  # default. 
-  kernelConfig ? null
-
-, # A list of additional statements to be appended to the
-  # configuration file.
-  extraConfig ? []
-}:
-
-assert stdenv.system == "i686-linux" || stdenv.system == "x86_64-linux";
-
-let
-
-  lib = stdenv.lib;
-
-  version = "2.6.26.7";
-
-  baseFeatures = {
-    iwlwifi = true;
-  };
-
-in
-
-stdenv.mkDerivation {
-  name = if userModeLinux then "user-mode-linux-${version}" else "linux-${version}";
-
-  passthru = {
-    inherit version;
-    # Combine the `features' attribute sets of all the kernel patches.
-    features = lib.fold (x: y: (if x ? features then x.features else {}) // y) baseFeatures kernelPatches;
-  };
+  rec {
+    version = "2.6.26.8";
   
-  builder = ./builder.sh;
-  
-  src = fetchurl {
-    url = "mirror://kernel/linux/kernel/v2.6/linux-${version}.tar.bz2";
-    sha256 = "1za4xq9q4gngmdxxwi728hdp30wjkwg4sh07fgyrs4nakjbjsgsj";
-  };
-  
-  patches = map (p: p.patch) kernelPatches;
-  extraConfig =
-    let addNewlines = map (s: "\n" + s + "\n");
-        configFromPatches =
-          map (p: if p ? extraConfig then p.extraConfig else "") kernelPatches;
-    in lib.concatStrings (addNewlines (configFromPatches ++ extraConfig));
-
-  config =
-    if kernelConfig != null then kernelConfig else
-    if userModeLinux then ./config-2.6.26-uml else
-    if stdenv.system == "i686-linux" then ./config-2.6.26-i686-smp else
-    if stdenv.system == "x86_64-linux" then ./config-2.6.26-x86_64-smp else
-    abort "No kernel configuration for your platform!";
-  
-  buildInputs = [perl mktemp];
-  
-  arch =
-    if userModeLinux then "um" else
-    if stdenv.system == "i686-linux" then "i386" else
-    if stdenv.system == "x86_64-linux" then "x86_64" else
-    abort "Platform ${stdenv.system} is not supported.";
-
-  makeFlags = if userModeLinux then "ARCH=um SHELL=bash" else "";
-
-  inherit module_init_tools;
-
-  allowLocalVersion = false; # don't allow patches to set a suffix
-  inherit localVersion; # but do allow the user to set one.
-
-  meta = {
-    description =
-      (if userModeLinux then
-        "User-Mode Linux"
-       else
-        "The Linux kernel") +
-      (if kernelPatches == [] then "" else
-        " (with patches: "
-        + lib.concatStrings (lib.intersperse ", " (map (x: x.name) kernelPatches))
-        + ")");
-  };
-}
+    src = fetchurl {
+      url = "mirror://kernel/linux/kernel/v2.6/linux-${version}.tar.bz2";
+      sha256 = "1jcdg3r7szrk010px7acwi98xhaj00hblv132sllpg89i8vr2aag";
+    };
+
+    features = {
+      iwlwifi = true;
+    };
+ 
+    config =
+      if stdenv.system == "i686-linux" then ./config-2.6.26-i686-smp else
+      if stdenv.system == "x86_64-linux" then ./config-2.6.26-x86_64-smp else
+      abort "No kernel configuration for your platform!";
+  }
+
+  // args
+)
diff --git a/pkgs/os-specific/linux/kernel/linux-2.6.27.nix b/pkgs/os-specific/linux/kernel/linux-2.6.27.nix
index 30d198ab7f390..a1e77b1b94bc8 100644
--- a/pkgs/os-specific/linux/kernel/linux-2.6.27.nix
+++ b/pkgs/os-specific/linux/kernel/linux-2.6.27.nix
@@ -1,95 +1,26 @@
-{ stdenv, fetchurl, perl, mktemp, module_init_tools
+args @ {stdenv, fetchurl, userModeLinux ? false, ...}:
 
-  # A list of patches to apply to the kernel.  Each element of this list
-  # should be an attribute set {name, patch} where `name' is a
-  # symbolic name and `patch' is the actual patch.  The patch may
-  # optionally be compressed with gzip or bzip2.
-, kernelPatches ? []
+assert !userModeLinux;
 
-, # Whether to build a User-Mode Linux kernel.
-  userModeLinux ? false
+import ./generic.nix (
 
-, # Allows you to set your own kernel version suffix (e.g.,
-  # "-my-kernel").
-  localVersion ? ""
-
-, # Your own kernel configuration file, if you don't want to use the
-  # default. 
-  kernelConfig ? null
-
-, # A list of additional statements to be appended to the
-  # configuration file.
-  extraConfig ? []
-}:
-
-assert stdenv.system == "i686-linux" || stdenv.system == "x86_64-linux";
-
-let
-
-  lib = stdenv.lib;
-
-  version = "2.6.27.7";
-
-  baseFeatures = {
-    iwlwifi = true;
-  };
-
-in
-
-stdenv.mkDerivation {
-  name = if userModeLinux then "user-mode-linux-${version}" else "linux-${version}";
-
-  passthru = {
-    inherit version;
-    # Combine the `features' attribute sets of all the kernel patches.
-    features = lib.fold (x: y: (if x ? features then x.features else {}) // y) baseFeatures kernelPatches;
-  };
+  rec {
+    version = "2.6.27.11";
   
-  builder = ./builder.sh;
-  
-  src = fetchurl {
-    url = "mirror://kernel/linux/kernel/v2.6/linux-${version}.tar.bz2";
-    sha256 = "0l59jf8nb3ds1gaqd643k17j4n8pg4i0pmyb4hyczyszhpy7aw4f";
-  };
-  
-  patches = map (p: p.patch) kernelPatches;
-  extraConfig =
-    let addNewlines = map (s: "\n" + s + "\n");
-        configFromPatches =
-          map (p: if p ? extraConfig then p.extraConfig else "") kernelPatches;
-    in lib.concatStrings (addNewlines (configFromPatches ++ extraConfig));
-
-  config =
-    if kernelConfig != null then kernelConfig else
-    if userModeLinux then ./config-2.6.27-uml else
-    if stdenv.system == "i686-linux" then ./config-2.6.27-i686-smp else
-    if stdenv.system == "x86_64-linux" then ./config-2.6.27-x86_64-smp else
-    abort "No kernel configuration for your platform!";
-  
-  buildInputs = [perl mktemp];
-  
-  arch =
-    if userModeLinux then "um" else
-    if stdenv.system == "i686-linux" then "i386" else
-    if stdenv.system == "x86_64-linux" then "x86_64" else
-    abort "Platform ${stdenv.system} is not supported.";
-
-  makeFlags = if userModeLinux then "ARCH=um SHELL=bash" else "";
-
-  inherit module_init_tools;
-
-  allowLocalVersion = false; # don't allow patches to set a suffix
-  inherit localVersion; # but do allow the user to set one.
-
-  meta = {
-    description =
-      (if userModeLinux then
-        "User-Mode Linux"
-       else
-        "The Linux kernel") +
-      (if kernelPatches == [] then "" else
-        " (with patches: "
-        + lib.concatStrings (lib.intersperse ", " (map (x: x.name) kernelPatches))
-        + ")");
-  };
-}
+    src = fetchurl {
+      url = "mirror://kernel/linux/kernel/v2.6/linux-${version}.tar.bz2";
+      sha256 = "0mwcycipbs7n9zzzarnlikyl0k7pcs8yk8n5mhz92illxgzzihjn";
+    };
+
+    features = {
+      iwlwifi = true;
+    };
+ 
+    config =
+      if stdenv.system == "i686-linux" then ./config-2.6.27-i686-smp else
+      if stdenv.system == "x86_64-linux" then ./config-2.6.27-x86_64-smp else
+      abort "No kernel configuration for your platform!";
+  }
+
+  // args
+)
diff --git a/pkgs/os-specific/linux/kernel/linux-2.6.28.nix b/pkgs/os-specific/linux/kernel/linux-2.6.28.nix
new file mode 100644
index 0000000000000..bb42312b63330
--- /dev/null
+++ b/pkgs/os-specific/linux/kernel/linux-2.6.28.nix
@@ -0,0 +1,26 @@
+args @ {stdenv, fetchurl, userModeLinux ? false, ...}:
+
+assert !userModeLinux;
+
+import ./generic.nix (
+
+  rec {
+    version = "2.6.28";
+  
+    src = fetchurl {
+      url = "mirror://kernel/linux/kernel/v2.6/linux-${version}.tar.bz2";
+      sha256 = "1023nl992s4qmnwzbfz385azzpph58azi5rw4w0wwzzybv2rf3df";
+    };
+
+    features = {
+      iwlwifi = true;
+    };
+ 
+    config =
+      if stdenv.system == "i686-linux" then ./config-2.6.28-i686-smp else
+      if stdenv.system == "x86_64-linux" then ./config-2.6.28-x86_64-smp else
+      abort "No kernel configuration for your platform!";
+  }
+
+  // args
+)
diff --git a/pkgs/os-specific/linux/kernel/linux.nix b/pkgs/os-specific/linux/kernel/linux.nix
deleted file mode 100644
index 788d54583426e..0000000000000
--- a/pkgs/os-specific/linux/kernel/linux.nix
+++ /dev/null
@@ -1,101 +0,0 @@
-{ stdenv, fetchurl, perl, mktemp, module_init_tools, lib
-
-  # The base source file
-, src
-
-  # A list of patches to apply to the kernel.  Each element of this list
-  # should be an attribute set {name, patch} where `name' is a
-  # symbolic name and `patch' is the actual patch.  The patch may
-  # optionally be compressed with gzip or bzip2.
-, kernelPatches ? []
-
-  # A list of commands to run on patched kernel before 
-  # mke oldconfig
-, preConfigure? ""
-
-, # Whether to build a User-Mode Linux kernel.
-  userModeLinux ? false
-
-, # Whether to build a Xen kernel.
-  xen ? false
-
-, # Allows you to set your own kernel version for output
-  version ? "unknown"
-
-  # To change how kernel thinks of itself
-, localVersion ? ""
-
-, # Your own kernel configuration file, if you don't want to use the
-  # default. 
-  kernelConfig ? null
-
-, # A list of additional statements to be appended to the
-  # configuration file.
-  extraConfig ? []
-
-, features ? []
-}:
-
-assert stdenv.system == "i686-linux" || stdenv.system == "x86_64-linux";
-
-let
-
-  lib = import ../../../lib;
-
-in
-
-stdenv.mkDerivation {
-  name = if userModeLinux then "user-mode-linux-${version}" else "linux-${version}";
-  builder = ./builder-custom.sh;
-
-  passthru = {
-    inherit version;
-    # Combine the `features' attribute sets of all the kernel patches.
-    features = lib.fold (x: y: (if x ? features then x.features else {}) // y) features kernelPatches;
-  };
-  
-  inherit src;
-  preConfigure = preConfigure;
-
-  patches = map (p: p.patch) kernelPatches;
-  extraConfig =
-    let addNewlines = map (s: "\n" + s + "\n");
-        configFromPatches =
-          map (p: if p ? extraConfig then p.extraConfig else "") kernelPatches;
-    in lib.concatStrings (addNewlines (configFromPatches ++ extraConfig));
-
-  config =
-    if kernelConfig != null then kernelConfig else
-    if userModeLinux then ./config-2.6.23-uml else
-    if stdenv.system == "i686-linux" then ./config-2.6.23-i686-smp else
-    if stdenv.system == "x86_64-linux" then ./config-2.6.23-x86_64-smp else
-    abort "No kernel configuration for your platform!";
-  
-  buildInputs = [perl mktemp];
-  
-  arch =
-    if userModeLinux then "um" else
-    if xen then "xen" else
-    if stdenv.system == "i686-linux" then "i386" else
-    if stdenv.system == "x86_64-linux" then "x86_64" else
-    abort "Platform ${stdenv.system} is not supported.";
-
-  makeFlags = if userModeLinux then "ARCH=um SHELL=bash" else "";
-
-  inherit module_init_tools;
-
-  allowLocalVersion = false; # don't allow patches to set a suffix
-  inherit localVersion; # but do allow the user to set one.
-
-  meta = {
-    description =
-      (if userModeLinux then
-        "User-Mode Linux"
-       else
-        "The Linux kernel") +
-      (if kernelPatches == [] then "" else
-        " (with patches: "
-        + lib.concatStrings (lib.intersperse ", " (map (x: x.name) kernelPatches))
-        + ")");
-  };
-}
diff --git a/pkgs/os-specific/linux/kernel/patch-2.6.21-ck1 b/pkgs/os-specific/linux/kernel/patch-2.6.21-ck1
deleted file mode 100644
index 0bf63f5aca376..0000000000000
--- a/pkgs/os-specific/linux/kernel/patch-2.6.21-ck1
+++ /dev/null
@@ -1,5040 +0,0 @@
-Index: linux-2.6.21-ck1/Makefile
-===================================================================
---- linux-2.6.21-ck1.orig/Makefile	2007-05-04 12:10:52.000000000 +1000
-+++ linux-2.6.21-ck1/Makefile	2007-05-04 12:21:37.000000000 +1000
-@@ -1,7 +1,7 @@
- VERSION = 2
- PATCHLEVEL = 6
- SUBLEVEL = 21
--EXTRAVERSION =
-+EXTRAVERSION = -ck1
- NAME = Nocturnal Monster Puppy
- 
- # *DOCUMENTATION*
-Index: linux-2.6.21-ck1/kernel/workqueue.c
-===================================================================
---- linux-2.6.21-ck1.orig/kernel/workqueue.c	2007-05-04 12:10:52.000000000 +1000
-+++ linux-2.6.21-ck1/kernel/workqueue.c	2007-05-04 12:10:54.000000000 +1000
-@@ -355,8 +355,6 @@ static int worker_thread(void *__cwq)
- 	if (!cwq->freezeable)
- 		current->flags |= PF_NOFREEZE;
- 
--	set_user_nice(current, -5);
--
- 	/* Block and flush all signals */
- 	sigfillset(&blocked);
- 	sigprocmask(SIG_BLOCK, &blocked, NULL);
-Index: linux-2.6.21-ck1/fs/proc/array.c
-===================================================================
---- linux-2.6.21-ck1.orig/fs/proc/array.c	2007-05-04 12:10:52.000000000 +1000
-+++ linux-2.6.21-ck1/fs/proc/array.c	2007-05-04 12:10:54.000000000 +1000
-@@ -165,7 +165,6 @@ static inline char * task_state(struct t
- 	rcu_read_lock();
- 	buffer += sprintf(buffer,
- 		"State:\t%s\n"
--		"SleepAVG:\t%lu%%\n"
- 		"Tgid:\t%d\n"
- 		"Pid:\t%d\n"
- 		"PPid:\t%d\n"
-@@ -173,7 +172,6 @@ static inline char * task_state(struct t
- 		"Uid:\t%d\t%d\t%d\t%d\n"
- 		"Gid:\t%d\t%d\t%d\t%d\n",
- 		get_task_state(p),
--		(p->sleep_avg/1024)*100/(1020000000/1024),
- 	       	p->tgid, p->pid,
- 	       	pid_alive(p) ? rcu_dereference(p->real_parent)->tgid : 0,
- 		pid_alive(p) && p->ptrace ? rcu_dereference(p->parent)->pid : 0,
-Index: linux-2.6.21-ck1/include/linux/init_task.h
-===================================================================
---- linux-2.6.21-ck1.orig/include/linux/init_task.h	2007-05-04 12:10:52.000000000 +1000
-+++ linux-2.6.21-ck1/include/linux/init_task.h	2007-05-04 12:24:19.000000000 +1000
-@@ -102,13 +102,15 @@ extern struct group_info init_groups;
- 	.prio		= MAX_PRIO-20,					\
- 	.static_prio	= MAX_PRIO-20,					\
- 	.normal_prio	= MAX_PRIO-20,					\
-+	.rotation	= 0,						\
- 	.policy		= SCHED_NORMAL,					\
- 	.cpus_allowed	= CPU_MASK_ALL,					\
- 	.mm		= NULL,						\
- 	.active_mm	= &init_mm,					\
- 	.run_list	= LIST_HEAD_INIT(tsk.run_list),			\
- 	.ioprio		= 0,						\
--	.time_slice	= HZ,						\
-+	.time_slice	= 1000000000,						\
-+	.quota		= 1000000000,						\
- 	.tasks		= LIST_HEAD_INIT(tsk.tasks),			\
- 	.ptrace_children= LIST_HEAD_INIT(tsk.ptrace_children),		\
- 	.ptrace_list	= LIST_HEAD_INIT(tsk.ptrace_list),		\
-@@ -135,6 +137,7 @@ extern struct group_info init_groups;
- 		.signal = {{0}}},					\
- 	.blocked	= {{0}},					\
- 	.alloc_lock	= __SPIN_LOCK_UNLOCKED(tsk.alloc_lock),		\
-+	.mutexes_held	= 0,						\
- 	.journal_info	= NULL,						\
- 	.cpu_timers	= INIT_CPU_TIMERS(tsk.cpu_timers),		\
- 	.fs_excl	= ATOMIC_INIT(0),				\
-Index: linux-2.6.21-ck1/include/linux/sched.h
-===================================================================
---- linux-2.6.21-ck1.orig/include/linux/sched.h	2007-05-04 12:10:52.000000000 +1000
-+++ linux-2.6.21-ck1/include/linux/sched.h	2007-05-04 12:24:19.000000000 +1000
-@@ -34,9 +34,14 @@
- #define SCHED_FIFO		1
- #define SCHED_RR		2
- #define SCHED_BATCH		3
-+#define SCHED_ISO		4
-+#define SCHED_IDLEPRIO		5
- 
- #ifdef __KERNEL__
- 
-+#define SCHED_MAX		SCHED_IDLEPRIO
-+#define SCHED_RANGE(policy)	((policy) <= SCHED_MAX)
-+
- struct sched_param {
- 	int sched_priority;
- };
-@@ -149,8 +154,7 @@ extern unsigned long weighted_cpuload(co
- #define EXIT_ZOMBIE		16
- #define EXIT_DEAD		32
- /* in tsk->state again */
--#define TASK_NONINTERACTIVE	64
--#define TASK_DEAD		128
-+#define TASK_DEAD		64
- 
- #define __set_task_state(tsk, state_value)		\
- 	do { (tsk)->state = (state_value); } while (0)
-@@ -522,14 +526,19 @@ struct signal_struct {
- 
- #define MAX_USER_RT_PRIO	100
- #define MAX_RT_PRIO		MAX_USER_RT_PRIO
-+#define PRIO_RANGE		(40)
-+#define ISO_PRIO		(MAX_RT_PRIO - 1)
- 
--#define MAX_PRIO		(MAX_RT_PRIO + 40)
-+#define MAX_PRIO		(MAX_RT_PRIO + PRIO_RANGE)
- 
--#define rt_prio(prio)		unlikely((prio) < MAX_RT_PRIO)
-+#define rt_prio(prio)		unlikely((prio) < ISO_PRIO)
- #define rt_task(p)		rt_prio((p)->prio)
- #define batch_task(p)		(unlikely((p)->policy == SCHED_BATCH))
--#define is_rt_policy(p)		((p) != SCHED_NORMAL && (p) != SCHED_BATCH)
-+#define is_rt_policy(policy)	((policy) == SCHED_FIFO || \
-+					(policy) == SCHED_RR)
- #define has_rt_policy(p)	unlikely(is_rt_policy((p)->policy))
-+#define iso_task(p)		unlikely((p)->policy == SCHED_ISO)
-+#define idleprio_task(p)	unlikely((p)->policy == SCHED_IDLEPRIO)
- 
- /*
-  * Some day this will be a full-fledged user tracking system..
-@@ -740,6 +749,22 @@ extern unsigned int max_cache_size;
- 
- #endif	/* CONFIG_SMP */
- 
-+/*
-+ * A runqueue laden with a single nice 0 task scores a weighted_cpuload of
-+ * SCHED_LOAD_SCALE. This function returns 1 if any cpu is laden with a
-+ * task of nice 0 or enough lower priority tasks to bring up the
-+ * weighted_cpuload
-+ */
-+static inline int above_background_load(void)
-+{
-+	unsigned long cpu;
-+
-+	for_each_online_cpu(cpu) {
-+		if (weighted_cpuload(cpu) >= SCHED_LOAD_SCALE)
-+			return 1;
-+	}
-+	return 0;
-+}
- 
- struct io_context;			/* See blkdev.h */
- struct cpuset;
-@@ -788,13 +813,6 @@ struct mempolicy;
- struct pipe_inode_info;
- struct uts_namespace;
- 
--enum sleep_type {
--	SLEEP_NORMAL,
--	SLEEP_NONINTERACTIVE,
--	SLEEP_INTERACTIVE,
--	SLEEP_INTERRUPTED,
--};
--
- struct prio_array;
- 
- struct task_struct {
-@@ -814,20 +832,33 @@ struct task_struct {
- 	int load_weight;	/* for niceness load balancing purposes */
- 	int prio, static_prio, normal_prio;
- 	struct list_head run_list;
-+	/*
-+	 * This bitmap shows what priorities this task has received quota
-+	 * from for this major priority rotation on its current runqueue.
-+	 */
-+	DECLARE_BITMAP(bitmap, PRIO_RANGE + 1);
- 	struct prio_array *array;
-+	/* Which major runqueue rotation did this task run */
-+	unsigned long rotation;
- 
- 	unsigned short ioprio;
- #ifdef CONFIG_BLK_DEV_IO_TRACE
- 	unsigned int btrace_seq;
- #endif
--	unsigned long sleep_avg;
- 	unsigned long long timestamp, last_ran;
- 	unsigned long long sched_time; /* sched_clock time spent running */
--	enum sleep_type sleep_type;
- 
- 	unsigned long policy;
- 	cpumask_t cpus_allowed;
--	unsigned int time_slice, first_time_slice;
-+	/*
-+	 * How much this task is entitled to run at the current priority
-+	 * before being requeued at a lower priority.
-+	 */
-+	int time_slice;
-+	/* Is this the very first time_slice this task has ever run. */
-+	unsigned int first_time_slice;
-+	/* How much this task receives at each priority level */
-+	int quota;
- 
- #if defined(CONFIG_SCHEDSTATS) || defined(CONFIG_TASK_DELAY_ACCT)
- 	struct sched_info sched_info;
-@@ -992,6 +1023,7 @@ struct task_struct {
- 	struct held_lock held_locks[MAX_LOCK_DEPTH];
- 	unsigned int lockdep_recursion;
- #endif
-+	unsigned long mutexes_held;
- 
- /* journalling filesystem info */
- 	void *journal_info;
-@@ -1156,8 +1188,10 @@ static inline void put_task_struct(struc
- #define PF_SWAPWRITE	0x00800000	/* Allowed to write to swap */
- #define PF_SPREAD_PAGE	0x01000000	/* Spread page cache over cpuset */
- #define PF_SPREAD_SLAB	0x02000000	/* Spread some slab caches over cpuset */
-+#define PF_ISOREF	0x04000000	/* SCHED_ISO task has used up quota */
- #define PF_MEMPOLICY	0x10000000	/* Non-default NUMA mempolicy */
- #define PF_MUTEX_TESTER	0x20000000	/* Thread belongs to the rt mutex tester */
-+#define PF_NONSLEEP	0x40000000	/* Waiting on in-kernel activity */
- 
- /*
-  * Only the _current_ task can read/write to tsk->flags, but other
-Index: linux-2.6.21-ck1/kernel/sched.c
-===================================================================
---- linux-2.6.21-ck1.orig/kernel/sched.c	2007-05-04 12:10:52.000000000 +1000
-+++ linux-2.6.21-ck1/kernel/sched.c	2007-05-04 12:24:22.000000000 +1000
-@@ -16,6 +16,7 @@
-  *		by Davide Libenzi, preemptible kernel bits by Robert Love.
-  *  2003-09-03	Interactivity tuning by Con Kolivas.
-  *  2004-04-02	Scheduler domains code by Nick Piggin
-+ *  2007-03-02	Staircase deadline scheduling policy by Con Kolivas
-  */
- 
- #include <linux/mm.h>
-@@ -52,6 +53,7 @@
- #include <linux/tsacct_kern.h>
- #include <linux/kprobes.h>
- #include <linux/delayacct.h>
-+#include <linux/log2.h>
- #include <asm/tlb.h>
- 
- #include <asm/unistd.h>
-@@ -83,126 +85,85 @@ unsigned long long __attribute__((weak))
- #define USER_PRIO(p)		((p)-MAX_RT_PRIO)
- #define TASK_USER_PRIO(p)	USER_PRIO((p)->static_prio)
- #define MAX_USER_PRIO		(USER_PRIO(MAX_PRIO))
-+#define SCHED_PRIO(p)		((p)+MAX_RT_PRIO)
- 
--/*
-- * Some helpers for converting nanosecond timing to jiffy resolution
-- */
--#define NS_TO_JIFFIES(TIME)	((TIME) / (1000000000 / HZ))
-+/* Some helpers for converting to/from various scales.*/
- #define JIFFIES_TO_NS(TIME)	((TIME) * (1000000000 / HZ))
--
--/*
-- * These are the 'tuning knobs' of the scheduler:
-- *
-- * Minimum timeslice is 5 msecs (or 1 jiffy, whichever is larger),
-- * default timeslice is 100 msecs, maximum timeslice is 800 msecs.
-- * Timeslices get refilled after they expire.
-- */
--#define MIN_TIMESLICE		max(5 * HZ / 1000, 1)
--#define DEF_TIMESLICE		(100 * HZ / 1000)
--#define ON_RUNQUEUE_WEIGHT	 30
--#define CHILD_PENALTY		 95
--#define PARENT_PENALTY		100
--#define EXIT_WEIGHT		  3
--#define PRIO_BONUS_RATIO	 25
--#define MAX_BONUS		(MAX_USER_PRIO * PRIO_BONUS_RATIO / 100)
--#define INTERACTIVE_DELTA	  2
--#define MAX_SLEEP_AVG		(DEF_TIMESLICE * MAX_BONUS)
--#define STARVATION_LIMIT	(MAX_SLEEP_AVG)
--#define NS_MAX_SLEEP_AVG	(JIFFIES_TO_NS(MAX_SLEEP_AVG))
--
--/*
-- * If a task is 'interactive' then we reinsert it in the active
-- * array after it has expired its current timeslice. (it will not
-- * continue to run immediately, it will still roundrobin with
-- * other interactive tasks.)
-- *
-- * This part scales the interactivity limit depending on niceness.
-- *
-- * We scale it linearly, offset by the INTERACTIVE_DELTA delta.
-- * Here are a few examples of different nice levels:
-- *
-- *  TASK_INTERACTIVE(-20): [1,1,1,1,1,1,1,1,1,0,0]
-- *  TASK_INTERACTIVE(-10): [1,1,1,1,1,1,1,0,0,0,0]
-- *  TASK_INTERACTIVE(  0): [1,1,1,1,0,0,0,0,0,0,0]
-- *  TASK_INTERACTIVE( 10): [1,1,0,0,0,0,0,0,0,0,0]
-- *  TASK_INTERACTIVE( 19): [0,0,0,0,0,0,0,0,0,0,0]
-- *
-- * (the X axis represents the possible -5 ... 0 ... +5 dynamic
-- *  priority range a task can explore, a value of '1' means the
-- *  task is rated interactive.)
-- *
-- * Ie. nice +19 tasks can never get 'interactive' enough to be
-- * reinserted into the active array. And only heavily CPU-hog nice -20
-- * tasks will be expired. Default nice 0 tasks are somewhere between,
-- * it takes some effort for them to get interactive, but it's not
-- * too hard.
-- */
--
--#define CURRENT_BONUS(p) \
--	(NS_TO_JIFFIES((p)->sleep_avg) * MAX_BONUS / \
--		MAX_SLEEP_AVG)
--
--#define GRANULARITY	(10 * HZ / 1000 ? : 1)
--
--#ifdef CONFIG_SMP
--#define TIMESLICE_GRANULARITY(p)	(GRANULARITY * \
--		(1 << (((MAX_BONUS - CURRENT_BONUS(p)) ? : 1) - 1)) * \
--			num_online_cpus())
--#else
--#define TIMESLICE_GRANULARITY(p)	(GRANULARITY * \
--		(1 << (((MAX_BONUS - CURRENT_BONUS(p)) ? : 1) - 1)))
--#endif
--
--#define SCALE(v1,v1_max,v2_max) \
--	(v1) * (v2_max) / (v1_max)
--
--#define DELTA(p) \
--	(SCALE(TASK_NICE(p) + 20, 40, MAX_BONUS) - 20 * MAX_BONUS / 40 + \
--		INTERACTIVE_DELTA)
--
--#define TASK_INTERACTIVE(p) \
--	((p)->prio <= (p)->static_prio - DELTA(p))
--
--#define INTERACTIVE_SLEEP(p) \
--	(JIFFIES_TO_NS(MAX_SLEEP_AVG * \
--		(MAX_BONUS / 2 + DELTA((p)) + 1) / MAX_BONUS - 1))
--
--#define TASK_PREEMPTS_CURR(p, rq) \
--	((p)->prio < (rq)->curr->prio)
--
--#define SCALE_PRIO(x, prio) \
--	max(x * (MAX_PRIO - prio) / (MAX_USER_PRIO / 2), MIN_TIMESLICE)
--
--static unsigned int static_prio_timeslice(int static_prio)
--{
--	if (static_prio < NICE_TO_PRIO(0))
--		return SCALE_PRIO(DEF_TIMESLICE * 4, static_prio);
--	else
--		return SCALE_PRIO(DEF_TIMESLICE, static_prio);
--}
--
--/*
-- * task_timeslice() scales user-nice values [ -20 ... 0 ... 19 ]
-- * to time slice values: [800ms ... 100ms ... 5ms]
-- *
-- * The higher a thread's priority, the bigger timeslices
-- * it gets during one round of execution. But even the lowest
-- * priority thread gets MIN_TIMESLICE worth of execution time.
-+#define MS_TO_NS(TIME)		((TIME) * 1000000)
-+#define MS_TO_US(TIME)		((TIME) * 1000)
-+#define US_TO_MS(TIME)		((TIME) / 1000)
-+
-+#define TASK_PREEMPTS_CURR(p, curr)	((p)->prio < (curr)->prio)
-+
-+/*
-+ * This is the time all tasks within the same priority round robin.
-+ * Value is in ms and set to a minimum of 8ms. Scales with number of cpus.
-+ * Tunable via /proc interface.
-+ */
-+int rr_interval __read_mostly = 6;
-+int sched_interactive __read_mostly = 1;
-+
-+/*
-+ * sched_iso_cpu - sysctl which determines the cpu percentage SCHED_ISO tasks
-+ * are allowed to run (over ISO_PERIOD seconds) as real time tasks.
-+ * sched_iso_period - sysctl which determines the number of seconds over
-+ * which cpu usage of SCHED_ISO tasks is averaged to determine if they are
-+ * exceeding their allowable bandwidth.
-+*/
-+int sched_iso_cpu __read_mostly = 80;
-+int sched_iso_period __read_mostly = 5;
-+
-+#define ISO_PERIOD	((sched_iso_period * HZ) + 1)
-+
-+/*
-+ * This contains a bitmap for each dynamic priority level with empty slots
-+ * for the valid priorities each different nice level can have. It allows
-+ * us to stagger the slots where differing priorities run in a way that
-+ * keeps latency differences between different nice levels at a minimum.
-+ * The purpose of a pre-generated matrix is for rapid lookup of next slot in
-+ * O(1) time without having to recalculate every time priority gets demoted.
-+ * All nice levels use priority slot 39 as this allows less niced tasks to
-+ * get all priority slots better than that before expiration is forced.
-+ * ie, where 0 means a slot for that priority, priority running from left to
-+ * right is from prio 0 to prio 39:
-+ * nice -20 0000000000000000000000000000000000000000
-+ * nice -10 1000100010001000100010001000100010010000
-+ * nice   0 1010101010101010101010101010101010101010
-+ * nice   5 1011010110110101101101011011010110110110
-+ * nice  10 1110111011101110111011101110111011101110
-+ * nice  15 1111111011111110111111101111111011111110
-+ * nice  19 1111111111111111111111111111111111111110
-  */
-+static unsigned long prio_matrix[PRIO_RANGE][BITS_TO_LONGS(PRIO_RANGE)]
-+				 __read_mostly;
- 
--static inline unsigned int task_timeslice(struct task_struct *p)
--{
--	return static_prio_timeslice(p->static_prio);
--}
-+struct rq;
- 
- /*
-  * These are the runqueue data structures:
-  */
--
- struct prio_array {
--	unsigned int nr_active;
--	DECLARE_BITMAP(bitmap, MAX_PRIO+1); /* include 1 bit for delimiter */
--	struct list_head queue[MAX_PRIO];
-+	/* Tasks queued at each priority */
-+	struct list_head queue[MAX_PRIO + 1];
-+
-+	/*
-+	 * The bitmap of priorities queued for this array. While the expired
-+	 * array will never have realtime tasks on it, it is simpler to have
-+	 * equal sized bitmaps for a cheap array swap. Include 1 bit for
-+	 * delimiter.
-+	 */
-+	DECLARE_BITMAP(prio_bitmap, MAX_PRIO + 1);
-+
-+	/*
-+	 * The best static priority (of the dynamic priority tasks) queued
-+	 * this array.
-+	 */
-+	int best_static_prio;
-+
-+#ifdef CONFIG_SMP
-+	/* For convenience looks back at rq */
-+	struct rq *rq;
-+#endif
- };
- 
- /*
-@@ -234,14 +195,28 @@ struct rq {
- 	 */
- 	unsigned long nr_uninterruptible;
- 
--	unsigned long expired_timestamp;
- 	/* Cached timestamp set by update_cpu_clock() */
- 	unsigned long long most_recent_timestamp;
- 	struct task_struct *curr, *idle;
- 	unsigned long next_balance;
- 	struct mm_struct *prev_mm;
--	struct prio_array *active, *expired, arrays[2];
--	int best_expired_prio;
-+
-+	struct prio_array *active, *expired, *idleprio, arrays[2];
-+	unsigned long *dyn_bitmap, *exp_bitmap;
-+
-+	/*
-+	 * The current dynamic priority level this runqueue is at per static
-+	 * priority level.
-+	 */
-+	int prio_level[PRIO_RANGE];
-+
-+	/* How many times we have rotated the priority queue */
-+	unsigned long prio_rotation;
-+	unsigned long iso_ticks;
-+	unsigned short iso_refractory;
-+
-+	/* Number of idleprio tasks running */
-+	unsigned long nr_idleprio;
- 	atomic_t nr_iowait;
- 
- #ifdef CONFIG_SMP
-@@ -579,12 +554,9 @@ static inline struct rq *this_rq_lock(vo
- #if defined(CONFIG_SCHEDSTATS) || defined(CONFIG_TASK_DELAY_ACCT)
- /*
-  * Called when a process is dequeued from the active array and given
-- * the cpu.  We should note that with the exception of interactive
-- * tasks, the expired queue will become the active queue after the active
-- * queue is empty, without explicitly dequeuing and requeuing tasks in the
-- * expired queue.  (Interactive tasks may be requeued directly to the
-- * active queue, thus delaying tasks in the expired queue from running;
-- * see scheduler_tick()).
-+ * the cpu.  We should note that the expired queue will become the active
-+ * queue after the active queue is empty, without explicitly dequeuing and
-+ * requeuing tasks in the expired queue.
-  *
-  * This function is only called from sched_info_arrive(), rather than
-  * dequeue_task(). Even though a task may be queued and dequeued multiple
-@@ -682,71 +654,304 @@ sched_info_switch(struct task_struct *pr
- #define sched_info_switch(t, next)	do { } while (0)
- #endif /* CONFIG_SCHEDSTATS || CONFIG_TASK_DELAY_ACCT */
- 
-+static int idleprio_suitable(struct task_struct *p)
-+{
-+	return (!p->mutexes_held && !freezing(p) && !signal_pending(p) &&
-+		!(p->flags & (PF_NONSLEEP | PF_EXITING)));
-+}
-+
-+static int idleprio(const struct task_struct *p)
-+{
-+	return (p->prio == MAX_PRIO);
-+}
-+
-+static inline int task_queued(struct task_struct *task)
-+{
-+	return !list_empty(&task->run_list);
-+}
-+
-+static inline void set_dynamic_bit(struct task_struct *p, struct rq *rq)
-+{
-+	__set_bit(p->prio, p->array->prio_bitmap);
-+}
-+
- /*
-- * Adding/removing a task to/from a priority array:
-+ * Removing from a runqueue.
-  */
--static void dequeue_task(struct task_struct *p, struct prio_array *array)
-+static void dequeue_task(struct task_struct *p, struct rq *rq)
- {
--	array->nr_active--;
--	list_del(&p->run_list);
--	if (list_empty(array->queue + p->prio))
--		__clear_bit(p->prio, array->bitmap);
-+	list_del_init(&p->run_list);
-+	if (idleprio_task(p) && idleprio(p))
-+		rq->nr_idleprio--;
-+	else if (list_empty(p->array->queue + p->prio))
-+		__clear_bit(p->prio, p->array->prio_bitmap);
- }
- 
--static void enqueue_task(struct task_struct *p, struct prio_array *array)
-+static void reset_first_time_slice(struct task_struct *p)
- {
--	sched_info_queued(p);
--	list_add_tail(&p->run_list, array->queue + p->prio);
--	__set_bit(p->prio, array->bitmap);
--	array->nr_active++;
-+	if (unlikely(p->first_time_slice))
-+		p->first_time_slice = 0;
-+}
-+
-+/*
-+ * The task is being queued on a fresh array so it has its entitlement
-+ * bitmap cleared.
-+ */
-+static void task_new_array(struct task_struct *p, struct rq *rq,
-+			   struct prio_array *array)
-+{
-+	bitmap_zero(p->bitmap, PRIO_RANGE);
-+	p->rotation = rq->prio_rotation;
-+	p->time_slice = p->quota;
- 	p->array = array;
-+	reset_first_time_slice(p);
-+}
-+
-+/* Find the first slot from the relevant prio_matrix entry */
-+static int first_prio_slot(struct task_struct *p)
-+{
-+	if (unlikely(p->policy == SCHED_BATCH))
-+		return p->static_prio;
-+	return SCHED_PRIO(find_first_zero_bit(
-+		prio_matrix[USER_PRIO(p->static_prio)], PRIO_RANGE));
- }
- 
- /*
-- * Put task to the end of the run list without the overhead of dequeue
-- * followed by enqueue.
-+ * In sched_interactive mode priority allocation occurs per process per rq
-+ * array swap. In !sched_interactive mode all waking tasks must obey the
-+ * current prio level of all other tasks running per array swap.
-  */
--static void requeue_task(struct task_struct *p, struct prio_array *array)
-+static int minprio(struct rq *rq, int uprio)
- {
--	list_move_tail(&p->run_list, array->queue + p->prio);
-+	if (sched_interactive)
-+		return MAX_RT_PRIO;
-+	return rq->prio_level[uprio];
- }
- 
--static inline void
--enqueue_task_head(struct task_struct *p, struct prio_array *array)
-+/*
-+ * Find the first unused slot by this task that is also in its prio_matrix
-+ * level. SCHED_BATCH tasks do not use the priority matrix. They only take
-+ * priority slots from their static_prio and above.
-+ */
-+static int next_entitled_slot(struct task_struct *p, struct rq *rq)
- {
--	list_add(&p->run_list, array->queue + p->prio);
--	__set_bit(p->prio, array->bitmap);
--	array->nr_active++;
--	p->array = array;
-+	int search_prio = MAX_RT_PRIO, uprio = USER_PRIO(p->static_prio);
-+	struct prio_array *array = rq->active;
-+	DECLARE_BITMAP(tmp, PRIO_RANGE);
-+
-+	/*
-+	 * Go straight to expiration if there are higher priority tasks
-+	 * already expired.
-+	 */
-+	if (p->static_prio > rq->expired->best_static_prio)
-+		return MAX_PRIO;
-+	if (!rq->prio_level[uprio])
-+		rq->prio_level[uprio] = MAX_RT_PRIO;
-+	/*
-+	 * Only priorities equal to the prio_level and above for their
-+	 * static_prio are acceptable, and only if it's not better than
-+	 * a queued better static_prio's prio_level.
-+	 */
-+	if (p->static_prio < array->best_static_prio) {
-+		if (likely(p->policy != SCHED_BATCH))
-+			array->best_static_prio = p->static_prio;
-+	} else if (p->static_prio == array->best_static_prio) {
-+		search_prio = minprio(rq, uprio);
-+	} else {
-+		int i;
-+
-+		search_prio = minprio(rq, uprio);
-+		/* A bound O(n) function, worst case n is 40 */
-+		for (i = array->best_static_prio; i <= p->static_prio ; i++) {
-+			if (!rq->prio_level[USER_PRIO(i)])
-+				rq->prio_level[USER_PRIO(i)] = MAX_RT_PRIO;
-+			search_prio = max(search_prio,
-+				      rq->prio_level[USER_PRIO(i)]);
-+		}
-+	}
-+	if (unlikely(p->policy == SCHED_BATCH)) {
-+		search_prio = max(search_prio, p->static_prio);
-+		return SCHED_PRIO(find_next_zero_bit(p->bitmap, PRIO_RANGE,
-+				  USER_PRIO(search_prio)));
-+	}
-+	bitmap_or(tmp, p->bitmap, prio_matrix[uprio], PRIO_RANGE);
-+	return SCHED_PRIO(find_next_zero_bit(tmp, PRIO_RANGE,
-+		USER_PRIO(search_prio)));
-+}
-+
-+static void queue_expired(struct task_struct *p, struct rq *rq)
-+{
-+	task_new_array(p, rq, rq->expired);
-+	p->prio = p->normal_prio = first_prio_slot(p);
-+	if (p->static_prio < rq->expired->best_static_prio)
-+		rq->expired->best_static_prio = p->static_prio;
-+	reset_first_time_slice(p);
- }
- 
-+#ifdef CONFIG_SMP
- /*
-- * __normal_prio - return the priority that is based on the static
-- * priority but is modified by bonuses/penalties.
-- *
-- * We scale the actual sleep average [0 .... MAX_SLEEP_AVG]
-- * into the -5 ... 0 ... +5 bonus/penalty range.
-- *
-- * We use 25% of the full 0...39 priority range so that:
-- *
-- * 1) nice +19 interactive tasks do not preempt nice 0 CPU hogs.
-- * 2) nice -20 CPU hogs do not get preempted by nice 0 tasks.
-- *
-- * Both properties are important to certain workloads.
-+ * If we're waking up a task that was previously on a different runqueue,
-+ * update its data appropriately. Note we may be reading data from src_rq->
-+ * outside of lock, but the occasional inaccurate result should be harmless.
-  */
-+ static void update_if_moved(struct task_struct *p, struct rq *rq)
-+{
-+	struct rq *src_rq = p->array->rq;
- 
--static inline int __normal_prio(struct task_struct *p)
-+	if (src_rq == rq)
-+		return;
-+	/*
-+	 * Only need to set p->array when p->rotation == rq->prio_rotation as
-+	 * they will be set in recalc_task_prio when != rq->prio_rotation.
-+	 */
-+	if (p->rotation == src_rq->prio_rotation) {
-+		p->rotation = rq->prio_rotation;
-+		if (p->array == src_rq->expired)
-+			p->array = rq->expired;
-+		else
-+			p->array = rq->active;
-+	} else
-+		p->rotation = 0;
-+}
-+#else
-+static inline void update_if_moved(struct task_struct *p, struct rq *rq)
-+{
-+}
-+#endif
-+
-+static inline int isoprio_suitable(struct task_struct *p)
- {
--	int bonus, prio;
-+	return !(p->flags & PF_ISOREF);
-+}
- 
--	bonus = CURRENT_BONUS(p) - MAX_BONUS / 2;
-+static int task_timeslice(struct task_struct *p);
- 
--	prio = p->static_prio - bonus;
--	if (prio < MAX_RT_PRIO)
--		prio = MAX_RT_PRIO;
--	if (prio > MAX_PRIO-1)
--		prio = MAX_PRIO-1;
--	return prio;
-+/*
-+ * recalc_task_prio determines what priority a non rt_task will be
-+ * queued at. If the task has already been running during this runqueue's
-+ * major rotation (rq->prio_rotation) then it continues at the same
-+ * priority if it has tick entitlement left. If it does not have entitlement
-+ * left, it finds the next priority slot according to its nice value that it
-+ * has not extracted quota from. If it has not run during this major
-+ * rotation, it starts at the next_entitled_slot and has its bitmap quota
-+ * cleared. If it does not have any slots left it has all its slots reset and
-+ * is queued on the expired at its first_prio_slot.
-+ */
-+static void recalc_task_prio(struct task_struct *p, struct rq *rq)
-+{
-+	struct prio_array *array = rq->active;
-+	int queue_prio;
-+
-+	if (iso_task(p)) {
-+		if (isoprio_suitable(p)) {
-+			/*
-+			 * If SCHED_ISO tasks have not used up their real time
-+			 * quota they have run just better than highest
-+			 * SCHED_NORMAL priority. Otherwise they run as
-+			 * SCHED_NORMAL.
-+			 */
-+			p->prio = p->normal_prio = ISO_PRIO;
-+			p->array = rq->active;
-+			if (p->time_slice <= 0)
-+				p->time_slice = p->quota;
-+			return;
-+		} else if (p->prio == ISO_PRIO) {
-+			/* Just about to be demoted to SCHED_NORMAL */
-+			p->time_slice = 0;
-+		}
-+	} else if (idleprio_task(p)) {
-+		if (idleprio_suitable(p)) {
-+			/*
-+			 * If suitable idleprio_tasks are queued at MAX_PRIO
-+			 * only on the idleprio array. Their time_slice is
-+			 * their full task_timeslice as they cooperatively
-+			 * multitask.
-+			 */
-+			p->prio = p->normal_prio = MAX_PRIO;
-+			p->array = rq->idleprio;
-+			if (p->time_slice <= 0)
-+				p->time_slice = task_timeslice(p);
-+			return;
-+		}
-+		/*
-+		 * If unsuitable idleprio_tasks are queued equivalent to
-+		 * nice 19 tasks on the expired array.
-+		 */
-+		p->flags &= ~PF_NONSLEEP;
-+		p->prio = p->normal_prio = MAX_PRIO - 1;
-+		p->array = rq->expired;
-+		if (p->time_slice <= 0 || p->time_slice > p->quota)
-+			p->time_slice = p->quota;
-+		return;
-+	}
-+
-+	update_if_moved(p, rq);
-+	if (p->rotation == rq->prio_rotation) {
-+		if (p->array == array) {
-+			if (p->time_slice > 0)
-+				return;
-+			p->time_slice = p->quota;
-+		} else if (p->array == rq->expired) {
-+			queue_expired(p, rq);
-+			return;
-+		} else
-+			task_new_array(p, rq, array);
-+	} else
-+		task_new_array(p, rq, array);
-+
-+	queue_prio = next_entitled_slot(p, rq);
-+	if (queue_prio >= MAX_PRIO) {
-+		queue_expired(p, rq);
-+		return;
-+	}
-+	p->prio = p->normal_prio = queue_prio;
-+	__set_bit(USER_PRIO(p->prio), p->bitmap);
-+}
-+
-+/*
-+ * Adding to a runqueue. The dynamic priority queue that it is added to is
-+ * determined by recalc_task_prio() above.
-+ */
-+static inline void __enqueue_task(struct task_struct *p, struct rq *rq)
-+{
-+	if (rt_task(p))
-+		p->array = rq->active;
-+	else
-+		recalc_task_prio(p, rq);
-+
-+	if (idleprio_task(p) && idleprio(p))
-+		rq->nr_idleprio++;
-+	sched_info_queued(p);
-+	set_dynamic_bit(p, rq);
-+}
-+
-+static void enqueue_task(struct task_struct *p, struct rq *rq)
-+{
-+	__enqueue_task(p, rq);
-+	list_add_tail(&p->run_list, p->array->queue + p->prio);
-+}
-+
-+static inline void enqueue_task_head(struct task_struct *p, struct rq *rq)
-+{
-+	__enqueue_task(p, rq);
-+	list_add(&p->run_list, p->array->queue + p->prio);
-+}
-+
-+/*
-+ * requeue_task is only called when p->static_prio does not change. p->prio
-+ * can change with dynamic tasks.
-+ */
-+static void requeue_task(struct task_struct *p, struct rq *rq,
-+			 struct prio_array *old_array, int old_prio)
-+{
-+	if (p->array == rq->expired)
-+		queue_expired(p, rq);
-+	list_move_tail(&p->run_list, p->array->queue + p->prio);
-+	if (!rt_task(p)) {
-+		if (list_empty(old_array->queue + old_prio))
-+			__clear_bit(old_prio, old_array->prio_bitmap);
-+		set_dynamic_bit(p, rq);
-+	}
- }
- 
- /*
-@@ -759,20 +964,29 @@ static inline int __normal_prio(struct t
-  */
- 
- /*
-- * Assume: static_prio_timeslice(NICE_TO_PRIO(0)) == DEF_TIMESLICE
-- * If static_prio_timeslice() is ever changed to break this assumption then
-- * this code will need modification
-- */
--#define TIME_SLICE_NICE_ZERO DEF_TIMESLICE
--#define LOAD_WEIGHT(lp) \
--	(((lp) * SCHED_LOAD_SCALE) / TIME_SLICE_NICE_ZERO)
--#define PRIO_TO_LOAD_WEIGHT(prio) \
--	LOAD_WEIGHT(static_prio_timeslice(prio))
--#define RTPRIO_TO_LOAD_WEIGHT(rp) \
--	(PRIO_TO_LOAD_WEIGHT(MAX_RT_PRIO) + LOAD_WEIGHT(rp))
-+ * task_timeslice - the total duration a task can run during one major
-+ * rotation. Returns value in milliseconds as the smallest value can be 1.
-+ */
-+static int task_timeslice(struct task_struct *p)
-+{
-+	int slice = p->quota;	/* quota is in us */
-+
-+	if (!rt_task(p))
-+		slice += (PRIO_RANGE - 1 - TASK_USER_PRIO(p)) * slice;
-+	return US_TO_MS(slice);
-+}
-+
-+/*
-+ * The load weight is basically the task_timeslice in ms. Realtime tasks are
-+ * special cased to be proportionately larger than nice -20 by their
-+ * rt_priority. The weight for rt tasks can only be arbitrary at best.
-+ */
-+#define RTPRIO_TO_LOAD_WEIGHT(rp)	(rr_interval * 20 * (40 + rp))
- 
- static void set_load_weight(struct task_struct *p)
- {
-+	int load_weight;
-+
- 	if (has_rt_policy(p)) {
- #ifdef CONFIG_SMP
- 		if (p == task_rq(p)->migration_thread)
-@@ -781,12 +995,19 @@ static void set_load_weight(struct task_
- 			 * Giving its load any weight will skew balancing
- 			 * adversely.
- 			 */
--			p->load_weight = 0;
-+			load_weight = 0;
- 		else
- #endif
--			p->load_weight = RTPRIO_TO_LOAD_WEIGHT(p->rt_priority);
-+			load_weight = RTPRIO_TO_LOAD_WEIGHT(p->rt_priority);
- 	} else
--		p->load_weight = PRIO_TO_LOAD_WEIGHT(p->static_prio);
-+		load_weight = task_timeslice(p);
-+	/*
-+	 * idleprio tasks have much lower weight than SCHED_NORMAL tasks but
-+	 * still need to be weighted to allow balancing to occur.
-+	 */
-+	if (likely(!idleprio_task(p)))
-+		load_weight *= PRIO_RANGE;
-+	p->load_weight = load_weight;
- }
- 
- static inline void
-@@ -814,28 +1035,38 @@ static inline void dec_nr_running(struct
- }
- 
- /*
-- * Calculate the expected normal priority: i.e. priority
-- * without taking RT-inheritance into account. Might be
-- * boosted by interactivity modifiers. Changes upon fork,
-- * setprio syscalls, and whenever the interactivity
-- * estimator recalculates.
-+ * __activate_task - move a task to the runqueue.
-  */
--static inline int normal_prio(struct task_struct *p)
-+static inline void __activate_task(struct task_struct *p, struct rq *rq)
- {
--	int prio;
-+	enqueue_task(p, rq);
-+	inc_nr_running(p, rq);
-+}
- 
-+/*
-+ * __activate_idle_task - move idle task to the _front_ of runqueue.
-+ */
-+static inline void __activate_idle_task(struct task_struct *p, struct rq *rq)
-+{
-+	enqueue_task_head(p, rq);
-+	inc_nr_running(p, rq);
-+}
-+
-+static inline int normal_prio(struct task_struct *p)
-+{
- 	if (has_rt_policy(p))
--		prio = MAX_RT_PRIO-1 - p->rt_priority;
-+		return MAX_RT_PRIO-1 - p->rt_priority;
-+	/* Other tasks all have normal_prio set in recalc_task_prio */
-+	if (likely(p->prio >= MAX_RT_PRIO && p->prio < MAX_PRIO))
-+		return p->prio;
- 	else
--		prio = __normal_prio(p);
--	return prio;
-+		return p->static_prio;
- }
- 
- /*
-  * Calculate the current priority, i.e. the priority
-  * taken into account by the scheduler. This value might
-- * be boosted by RT tasks, or might be boosted by
-- * interactivity modifiers. Will be RT if the task got
-+ * be boosted by RT tasks as it will be RT if the task got
-  * RT-boosted. If not then it returns p->normal_prio.
-  */
- static int effective_prio(struct task_struct *p)
-@@ -852,111 +1083,41 @@ static int effective_prio(struct task_st
- }
- 
- /*
-- * __activate_task - move a task to the runqueue.
-+ * All tasks have quotas based on rr_interval. RT tasks all get rr_interval.
-+ * From nice 1 to 19 they are smaller than it only if they are at least one
-+ * tick still. Below nice 0 they get progressively larger.
-+ * ie nice -6..0 = rr_interval. nice -10 = 2.5 * rr_interval
-+ * nice -20 = 10 * rr_interval. nice 1-19 = rr_interval / 2.
-+ * Value returned is in microseconds.
-  */
--static void __activate_task(struct task_struct *p, struct rq *rq)
-+static inline unsigned int rr_quota(struct task_struct *p)
- {
--	struct prio_array *target = rq->active;
-+	int nice = TASK_NICE(p), rr = rr_interval;
- 
--	if (batch_task(p))
--		target = rq->expired;
--	enqueue_task(p, target);
--	inc_nr_running(p, rq);
--}
--
--/*
-- * __activate_idle_task - move idle task to the _front_ of runqueue.
-- */
--static inline void __activate_idle_task(struct task_struct *p, struct rq *rq)
--{
--	enqueue_task_head(p, rq->active);
--	inc_nr_running(p, rq);
-+	if (!rt_task(p)) {
-+		if (nice < -6) {
-+			rr *= nice * nice;
-+			rr /= 40;
-+		} else if (nice > 0)
-+			rr = rr / 2 ? : 1;
-+	}
-+	return MS_TO_US(rr);
- }
- 
--/*
-- * Recalculate p->normal_prio and p->prio after having slept,
-- * updating the sleep-average too:
-- */
--static int recalc_task_prio(struct task_struct *p, unsigned long long now)
-+/* Every time we set the quota we need to set the load weight */
-+static void set_quota(struct task_struct *p)
- {
--	/* Caller must always ensure 'now >= p->timestamp' */
--	unsigned long sleep_time = now - p->timestamp;
--
--	if (batch_task(p))
--		sleep_time = 0;
--
--	if (likely(sleep_time > 0)) {
--		/*
--		 * This ceiling is set to the lowest priority that would allow
--		 * a task to be reinserted into the active array on timeslice
--		 * completion.
--		 */
--		unsigned long ceiling = INTERACTIVE_SLEEP(p);
--
--		if (p->mm && sleep_time > ceiling && p->sleep_avg < ceiling) {
--			/*
--			 * Prevents user tasks from achieving best priority
--			 * with one single large enough sleep.
--			 */
--			p->sleep_avg = ceiling;
--			/*
--			 * Using INTERACTIVE_SLEEP() as a ceiling places a
--			 * nice(0) task 1ms sleep away from promotion, and
--			 * gives it 700ms to round-robin with no chance of
--			 * being demoted.  This is more than generous, so
--			 * mark this sleep as non-interactive to prevent the
--			 * on-runqueue bonus logic from intervening should
--			 * this task not receive cpu immediately.
--			 */
--			p->sleep_type = SLEEP_NONINTERACTIVE;
--		} else {
--			/*
--			 * Tasks waking from uninterruptible sleep are
--			 * limited in their sleep_avg rise as they
--			 * are likely to be waiting on I/O
--			 */
--			if (p->sleep_type == SLEEP_NONINTERACTIVE && p->mm) {
--				if (p->sleep_avg >= ceiling)
--					sleep_time = 0;
--				else if (p->sleep_avg + sleep_time >=
--					 ceiling) {
--						p->sleep_avg = ceiling;
--						sleep_time = 0;
--				}
--			}
--
--			/*
--			 * This code gives a bonus to interactive tasks.
--			 *
--			 * The boost works by updating the 'average sleep time'
--			 * value here, based on ->timestamp. The more time a
--			 * task spends sleeping, the higher the average gets -
--			 * and the higher the priority boost gets as well.
--			 */
--			p->sleep_avg += sleep_time;
--
--		}
--		if (p->sleep_avg > NS_MAX_SLEEP_AVG)
--			p->sleep_avg = NS_MAX_SLEEP_AVG;
--	}
--
--	return effective_prio(p);
-+	p->quota = rr_quota(p);
-+	set_load_weight(p);
- }
- 
- /*
-  * activate_task - move a task to the runqueue and do priority recalculation
-- *
-- * Update all the scheduling statistics stuff. (sleep average
-- * calculation, priority modifiers, etc.)
-  */
- static void activate_task(struct task_struct *p, struct rq *rq, int local)
- {
--	unsigned long long now;
--
--	if (rt_task(p))
--		goto out;
-+	unsigned long long now = sched_clock();
- 
--	now = sched_clock();
- #ifdef CONFIG_SMP
- 	if (!local) {
- 		/* Compensate for drifting sched_clock */
-@@ -977,32 +1138,9 @@ static void activate_task(struct task_st
- 				     (now - p->timestamp) >> 20);
- 	}
- 
--	p->prio = recalc_task_prio(p, now);
--
--	/*
--	 * This checks to make sure it's not an uninterruptible task
--	 * that is now waking up.
--	 */
--	if (p->sleep_type == SLEEP_NORMAL) {
--		/*
--		 * Tasks which were woken up by interrupts (ie. hw events)
--		 * are most likely of interactive nature. So we give them
--		 * the credit of extending their sleep time to the period
--		 * of time they spend on the runqueue, waiting for execution
--		 * on a CPU, first time around:
--		 */
--		if (in_interrupt())
--			p->sleep_type = SLEEP_INTERRUPTED;
--		else {
--			/*
--			 * Normal first-time wakeups get a credit too for
--			 * on-runqueue time, but it will be weighted down:
--			 */
--			p->sleep_type = SLEEP_INTERACTIVE;
--		}
--	}
-+	set_quota(p);
-+	p->prio = effective_prio(p);
- 	p->timestamp = now;
--out:
- 	__activate_task(p, rq);
- }
- 
-@@ -1012,8 +1150,7 @@ out:
- static void deactivate_task(struct task_struct *p, struct rq *rq)
- {
- 	dec_nr_running(p, rq);
--	dequeue_task(p, p->array);
--	p->array = NULL;
-+	dequeue_task(p, rq);
- }
- 
- /*
-@@ -1095,7 +1232,7 @@ migrate_task(struct task_struct *p, int 
- 	 * If the task is not on a runqueue (and not running), then
- 	 * it is sufficient to simply update the task's cpu field.
- 	 */
--	if (!p->array && !task_running(rq, p)) {
-+	if (!task_queued(p) && !task_running(rq, p)) {
- 		set_task_cpu(p, dest_cpu);
- 		return 0;
- 	}
-@@ -1126,7 +1263,7 @@ void wait_task_inactive(struct task_stru
- repeat:
- 	rq = task_rq_lock(p, &flags);
- 	/* Must be off runqueue entirely, not preempted. */
--	if (unlikely(p->array || task_running(rq, p))) {
-+	if (unlikely(task_queued(p) || task_running(rq, p))) {
- 		/* If it's preempted, we yield.  It could be a while. */
- 		preempted = !task_running(rq, p);
- 		task_rq_unlock(rq, &flags);
-@@ -1391,6 +1528,31 @@ static inline int wake_idle(int cpu, str
- }
- #endif
- 
-+/*
-+ * We need to have a special definition for an idle runqueue when testing
-+ * for preemption on CONFIG_HOTPLUG_CPU as the idle task may be scheduled as
-+ * a realtime task in sched_idle_next.
-+ */
-+#ifdef CONFIG_HOTPLUG_CPU
-+#define rq_idle(rq)	((rq)->curr == (rq)->idle && !rt_task((rq)->curr))
-+#else
-+#define rq_idle(rq)	((rq)->curr == (rq)->idle)
-+#endif
-+
-+static inline int task_preempts_curr(struct task_struct *p, struct rq *rq)
-+{
-+	struct task_struct *curr = rq->curr;
-+
-+	return ((p->array == task_rq(p)->active &&
-+		TASK_PREEMPTS_CURR(p, curr)) || rq_idle(rq));
-+}
-+
-+static inline void try_preempt(struct task_struct *p, struct rq *rq)
-+{
-+	if (task_preempts_curr(p, rq))
-+		resched_task(rq->curr);
-+}
-+
- /***
-  * try_to_wake_up - wake up a thread
-  * @p: the to-be-woken-up thread
-@@ -1422,7 +1584,7 @@ static int try_to_wake_up(struct task_st
- 	if (!(old_state & state))
- 		goto out;
- 
--	if (p->array)
-+	if (task_queued(p))
- 		goto out_running;
- 
- 	cpu = task_cpu(p);
-@@ -1515,7 +1677,7 @@ out_set_cpu:
- 		old_state = p->state;
- 		if (!(old_state & state))
- 			goto out;
--		if (p->array)
-+		if (task_queued(p))
- 			goto out_running;
- 
- 		this_cpu = smp_processor_id();
-@@ -1524,25 +1686,9 @@ out_set_cpu:
- 
- out_activate:
- #endif /* CONFIG_SMP */
--	if (old_state == TASK_UNINTERRUPTIBLE) {
-+	if (old_state == TASK_UNINTERRUPTIBLE)
- 		rq->nr_uninterruptible--;
--		/*
--		 * Tasks on involuntary sleep don't earn
--		 * sleep_avg beyond just interactive state.
--		 */
--		p->sleep_type = SLEEP_NONINTERACTIVE;
--	} else
--
--	/*
--	 * Tasks that have marked their sleep as noninteractive get
--	 * woken up with their sleep average not weighted in an
--	 * interactive way.
--	 */
--		if (old_state & TASK_NONINTERACTIVE)
--			p->sleep_type = SLEEP_NONINTERACTIVE;
- 
--
--	activate_task(p, rq, cpu == this_cpu);
- 	/*
- 	 * Sync wakeups (i.e. those types of wakeups where the waker
- 	 * has indicated that it will leave the CPU in short order)
-@@ -1551,15 +1697,22 @@ out_activate:
- 	 * the waker guarantees that the freshly woken up task is going
- 	 * to be considered on this CPU.)
- 	 */
--	if (!sync || cpu != this_cpu) {
--		if (TASK_PREEMPTS_CURR(p, rq))
--			resched_task(rq->curr);
--	}
-+	activate_task(p, rq, cpu == this_cpu);
-+	if (!sync || cpu != this_cpu)
-+		try_preempt(p, rq);
- 	success = 1;
- 
- out_running:
- 	p->state = TASK_RUNNING;
- out:
-+	/*
-+	 * Special case when freezing we need to reschedule idleprio tasks
-+	 * as SCHED_NORMAL or else they'll never freeze
-+	 */
-+	if (idleprio_task(p) && freezing(p) && idleprio(p)) {
-+		dequeue_task(p, rq);
-+		enqueue_task(p, rq);
-+	}
- 	task_rq_unlock(rq, &flags);
- 
- 	return success;
-@@ -1577,7 +1730,6 @@ int fastcall wake_up_state(struct task_s
- 	return try_to_wake_up(p, state, 0);
- }
- 
--static void task_running_tick(struct rq *rq, struct task_struct *p);
- /*
-  * Perform scheduler related setup for a newly forked process p.
-  * p is forked by current.
-@@ -1605,7 +1757,6 @@ void fastcall sched_fork(struct task_str
- 	p->prio = current->normal_prio;
- 
- 	INIT_LIST_HEAD(&p->run_list);
--	p->array = NULL;
- #if defined(CONFIG_SCHEDSTATS) || defined(CONFIG_TASK_DELAY_ACCT)
- 	if (unlikely(sched_info_on()))
- 		memset(&p->sched_info, 0, sizeof(p->sched_info));
-@@ -1617,30 +1768,31 @@ void fastcall sched_fork(struct task_str
- 	/* Want to start with kernel preemption disabled. */
- 	task_thread_info(p)->preempt_count = 1;
- #endif
-+	if (unlikely(p->policy == SCHED_FIFO))
-+		goto out;
- 	/*
- 	 * Share the timeslice between parent and child, thus the
- 	 * total amount of pending timeslices in the system doesn't change,
- 	 * resulting in more scheduling fairness.
- 	 */
- 	local_irq_disable();
--	p->time_slice = (current->time_slice + 1) >> 1;
--	/*
--	 * The remainder of the first timeslice might be recovered by
--	 * the parent if the child exits early enough.
--	 */
--	p->first_time_slice = 1;
--	current->time_slice >>= 1;
--	p->timestamp = sched_clock();
--	if (unlikely(!current->time_slice)) {
-+	if (current->time_slice > 0) {
-+		current->time_slice /= 2;
-+		if (current->time_slice)
-+			p->time_slice = current->time_slice;
-+		else
-+			p->time_slice = 1;
- 		/*
--		 * This case is rare, it happens when the parent has only
--		 * a single jiffy left from its timeslice. Taking the
--		 * runqueue lock is not a problem.
-+		 * The remainder of the first timeslice might be recovered by
-+		 * the parent if the child exits early enough.
- 		 */
--		current->time_slice = 1;
--		task_running_tick(cpu_rq(cpu), current);
--	}
-+		p->first_time_slice = 1;
-+	} else
-+		p->time_slice = 0;
-+
-+	p->timestamp = sched_clock();
- 	local_irq_enable();
-+out:
- 	put_cpu();
- }
- 
-@@ -1662,38 +1814,16 @@ void fastcall wake_up_new_task(struct ta
- 	this_cpu = smp_processor_id();
- 	cpu = task_cpu(p);
- 
--	/*
--	 * We decrease the sleep average of forking parents
--	 * and children as well, to keep max-interactive tasks
--	 * from forking tasks that are max-interactive. The parent
--	 * (current) is done further down, under its lock.
--	 */
--	p->sleep_avg = JIFFIES_TO_NS(CURRENT_BONUS(p) *
--		CHILD_PENALTY / 100 * MAX_SLEEP_AVG / MAX_BONUS);
--
--	p->prio = effective_prio(p);
--
- 	if (likely(cpu == this_cpu)) {
-+		activate_task(p, rq, 1);
- 		if (!(clone_flags & CLONE_VM)) {
- 			/*
- 			 * The VM isn't cloned, so we're in a good position to
- 			 * do child-runs-first in anticipation of an exec. This
- 			 * usually avoids a lot of COW overhead.
- 			 */
--			if (unlikely(!current->array))
--				__activate_task(p, rq);
--			else {
--				p->prio = current->prio;
--				p->normal_prio = current->normal_prio;
--				list_add_tail(&p->run_list, &current->run_list);
--				p->array = current->array;
--				p->array->nr_active++;
--				inc_nr_running(p, rq);
--			}
- 			set_need_resched();
--		} else
--			/* Run child last */
--			__activate_task(p, rq);
-+		}
- 		/*
- 		 * We skip the following code due to cpu == this_cpu
- 	 	 *
-@@ -1710,19 +1840,16 @@ void fastcall wake_up_new_task(struct ta
- 		 */
- 		p->timestamp = (p->timestamp - this_rq->most_recent_timestamp)
- 					+ rq->most_recent_timestamp;
--		__activate_task(p, rq);
--		if (TASK_PREEMPTS_CURR(p, rq))
--			resched_task(rq->curr);
-+		activate_task(p, rq, 0);
-+		try_preempt(p, rq);
- 
- 		/*
- 		 * Parent and child are on different CPUs, now get the
--		 * parent runqueue to update the parent's ->sleep_avg:
-+		 * parent runqueue to update the parent's ->flags:
- 		 */
- 		task_rq_unlock(rq, &flags);
- 		this_rq = task_rq_lock(current, &flags);
- 	}
--	current->sleep_avg = JIFFIES_TO_NS(CURRENT_BONUS(current) *
--		PARENT_PENALTY / 100 * MAX_SLEEP_AVG / MAX_BONUS);
- 	task_rq_unlock(this_rq, &flags);
- }
- 
-@@ -1737,23 +1864,17 @@ void fastcall wake_up_new_task(struct ta
-  */
- void fastcall sched_exit(struct task_struct *p)
- {
-+	struct task_struct *parent;
- 	unsigned long flags;
- 	struct rq *rq;
- 
--	/*
--	 * If the child was a (relative-) CPU hog then decrease
--	 * the sleep_avg of the parent as well.
--	 */
--	rq = task_rq_lock(p->parent, &flags);
--	if (p->first_time_slice && task_cpu(p) == task_cpu(p->parent)) {
--		p->parent->time_slice += p->time_slice;
--		if (unlikely(p->parent->time_slice > task_timeslice(p)))
--			p->parent->time_slice = task_timeslice(p);
--	}
--	if (p->sleep_avg < p->parent->sleep_avg)
--		p->parent->sleep_avg = p->parent->sleep_avg /
--		(EXIT_WEIGHT + 1) * EXIT_WEIGHT + p->sleep_avg /
--		(EXIT_WEIGHT + 1);
-+	parent = p->parent;
-+	rq = task_rq_lock(parent, &flags);
-+	if (p->first_time_slice > 0 && task_cpu(p) == task_cpu(parent)) {
-+		parent->time_slice += p->time_slice;
-+		if (unlikely(parent->time_slice > parent->quota))
-+			parent->time_slice = parent->quota;
-+	}
- 	task_rq_unlock(rq, &flags);
- }
- 
-@@ -2085,23 +2206,17 @@ void sched_exec(void)
-  * pull_task - move a task from a remote runqueue to the local runqueue.
-  * Both runqueues must be locked.
-  */
--static void pull_task(struct rq *src_rq, struct prio_array *src_array,
--		      struct task_struct *p, struct rq *this_rq,
--		      struct prio_array *this_array, int this_cpu)
-+static void pull_task(struct rq *src_rq, struct task_struct *p,
-+		      struct rq *this_rq, int this_cpu)
- {
--	dequeue_task(p, src_array);
-+	dequeue_task(p, src_rq);
- 	dec_nr_running(p, src_rq);
- 	set_task_cpu(p, this_cpu);
- 	inc_nr_running(p, this_rq);
--	enqueue_task(p, this_array);
-+	enqueue_task(p, this_rq);
- 	p->timestamp = (p->timestamp - src_rq->most_recent_timestamp)
- 				+ this_rq->most_recent_timestamp;
--	/*
--	 * Note that idle threads have a prio of MAX_PRIO, for this test
--	 * to be always true for them.
--	 */
--	if (TASK_PREEMPTS_CURR(p, this_rq))
--		resched_task(this_rq->curr);
-+	try_preempt(p, this_rq);
- }
- 
- /*
-@@ -2144,7 +2259,16 @@ int can_migrate_task(struct task_struct 
- 	return 1;
- }
- 
--#define rq_best_prio(rq) min((rq)->curr->prio, (rq)->best_expired_prio)
-+static inline int rq_best_prio(struct rq *rq)
-+{
-+	int best_prio, exp_prio;
-+
-+	best_prio = sched_find_first_bit(rq->dyn_bitmap);
-+	exp_prio = find_next_bit(rq->exp_bitmap, MAX_PRIO, MAX_RT_PRIO);
-+	if (unlikely(best_prio > exp_prio))
-+		best_prio = exp_prio;
-+	return best_prio;
-+}
- 
- /*
-  * move_tasks tries to move up to max_nr_move tasks and max_load_move weighted
-@@ -2160,7 +2284,7 @@ static int move_tasks(struct rq *this_rq
- {
- 	int idx, pulled = 0, pinned = 0, this_best_prio, best_prio,
- 	    best_prio_seen, skip_for_load;
--	struct prio_array *array, *dst_array;
-+	struct prio_array *array;
- 	struct list_head *head, *curr;
- 	struct task_struct *tmp;
- 	long rem_load_move;
-@@ -2187,31 +2311,29 @@ static int move_tasks(struct rq *this_rq
- 	 * be cache-cold, thus switching CPUs has the least effect
- 	 * on them.
- 	 */
--	if (busiest->expired->nr_active) {
--		array = busiest->expired;
--		dst_array = this_rq->expired;
--	} else {
--		array = busiest->active;
--		dst_array = this_rq->active;
--	}
--
-+	array = busiest->expired;
- new_array:
--	/* Start searching at priority 0: */
--	idx = 0;
-+	/* Expired arrays don't have RT tasks so they're always MAX_RT_PRIO+ */
-+	if (array == busiest->expired)
-+		idx = MAX_RT_PRIO;
-+	else
-+		idx = 0;
- skip_bitmap:
- 	if (!idx)
--		idx = sched_find_first_bit(array->bitmap);
-+		idx = sched_find_first_bit(array->prio_bitmap);
- 	else
--		idx = find_next_bit(array->bitmap, MAX_PRIO, idx);
--	if (idx >= MAX_PRIO) {
--		if (array == busiest->expired && busiest->active->nr_active) {
-+		idx = find_next_bit(array->prio_bitmap, MAX_PRIO, idx);
-+	if (idx == MAX_PRIO) {
-+		if (array == busiest->idleprio && busiest->nr_idleprio)
-+			goto found_idleprio;
-+		if (array == busiest->expired) {
- 			array = busiest->active;
--			dst_array = this_rq->active;
- 			goto new_array;
- 		}
- 		goto out;
- 	}
- 
-+found_idleprio:
- 	head = array->queue + idx;
- 	curr = head->prev;
- skip_queue:
-@@ -2233,11 +2355,22 @@ skip_queue:
- 		best_prio_seen |= idx == best_prio;
- 		if (curr != head)
- 			goto skip_queue;
-+		if (idx == MAX_PRIO) {
-+			/*
-+			 * Occurs either when balancing idleprio tasks or
-+			 * there really are no more tasks to find.
-+			 */
-+			if (array == busiest->expired) {
-+				array = busiest->active;
-+				goto new_array;
-+			}
-+			goto out;
-+		}
- 		idx++;
- 		goto skip_bitmap;
- 	}
- 
--	pull_task(busiest, array, tmp, this_rq, dst_array, this_cpu);
-+	pull_task(busiest, tmp, this_rq, this_cpu);
- 	pulled++;
- 	rem_load_move -= tmp->load_weight;
- 
-@@ -2250,6 +2383,13 @@ skip_queue:
- 			this_best_prio = idx;
- 		if (curr != head)
- 			goto skip_queue;
-+		if (idx == MAX_PRIO) {
-+			if (array == busiest->expired) {
-+				array = busiest->active;
-+				goto new_array;
-+			}
-+			goto out;
-+		}
- 		idx++;
- 		goto skip_bitmap;
- 	}
-@@ -3013,11 +3153,36 @@ EXPORT_PER_CPU_SYMBOL(kstat);
- /*
-  * This is called on clock ticks and on context switches.
-  * Bank in p->sched_time the ns elapsed since the last tick or switch.
-+ * CPU scheduler quota accounting is also performed here in microseconds.
-+ * The value returned from sched_clock() occasionally gives bogus values so
-+ * some sanity checking is required.
-  */
--static inline void
--update_cpu_clock(struct task_struct *p, struct rq *rq, unsigned long long now)
-+static void
-+update_cpu_clock(struct task_struct *p, struct rq *rq, unsigned long long now,
-+		 int tick)
- {
--	p->sched_time += now - p->last_ran;
-+	long time_diff = now - p->last_ran;
-+
-+	if (tick) {
-+		/*
-+		 * Called from scheduler_tick() there should be less than two
-+		 * jiffies worth, and not negative/overflow.
-+		 */
-+		if (time_diff > JIFFIES_TO_NS(2) || time_diff < 0)
-+			time_diff = JIFFIES_TO_NS(1);
-+	} else {
-+		/*
-+		 * Called from context_switch there should be less than one
-+		 * jiffy worth, and not negative/overflow. There should be
-+		 * some time banked here so use a nominal 1us.
-+		 */
-+		if (time_diff > JIFFIES_TO_NS(1) || time_diff < 1)
-+			time_diff = 1000;
-+	}
-+	/* time_slice accounting is done in usecs to avoid overflow on 32bit */
-+	if (p != rq->idle && p->policy != SCHED_FIFO)
-+		p->time_slice -= time_diff / 1000;
-+	p->sched_time += time_diff;
- 	p->last_ran = rq->most_recent_timestamp = now;
- }
- 
-@@ -3038,27 +3203,6 @@ unsigned long long current_sched_time(co
- }
- 
- /*
-- * We place interactive tasks back into the active array, if possible.
-- *
-- * To guarantee that this does not starve expired tasks we ignore the
-- * interactivity of a task if the first expired task had to wait more
-- * than a 'reasonable' amount of time. This deadline timeout is
-- * load-dependent, as the frequency of array switched decreases with
-- * increasing number of running tasks. We also ignore the interactivity
-- * if a better static_prio task has expired:
-- */
--static inline int expired_starving(struct rq *rq)
--{
--	if (rq->curr->static_prio > rq->best_expired_prio)
--		return 1;
--	if (!STARVATION_LIMIT || !rq->expired_timestamp)
--		return 0;
--	if (jiffies - rq->expired_timestamp > STARVATION_LIMIT * rq->nr_running)
--		return 1;
--	return 0;
--}
--
--/*
-  * Account user cpu time to a process.
-  * @p: the process that the cpu time gets accounted to
-  * @hardirq_offset: the offset to subtract from hardirq_count()
-@@ -3073,7 +3217,7 @@ void account_user_time(struct task_struc
- 
- 	/* Add user time to cpustat. */
- 	tmp = cputime_to_cputime64(cputime);
--	if (TASK_NICE(p) > 0)
-+	if (TASK_NICE(p) > 0 || idleprio_task(p))
- 		cpustat->nice = cputime64_add(cpustat->nice, tmp);
- 	else
- 		cpustat->user = cputime64_add(cpustat->user, tmp);
-@@ -3131,87 +3275,94 @@ void account_steal_time(struct task_stru
- 		cpustat->steal = cputime64_add(cpustat->steal, tmp);
- }
- 
--static void task_running_tick(struct rq *rq, struct task_struct *p)
-+/*
-+ * The task has used up its quota of running in this prio_level so it must be
-+ * dropped a priority level, all managed by recalc_task_prio().
-+ */
-+static void task_expired_entitlement(struct rq *rq, struct task_struct *p)
- {
--	if (p->array != rq->active) {
--		/* Task has expired but was not scheduled yet */
--		set_tsk_need_resched(p);
-+	int overrun;
-+
-+	reset_first_time_slice(p);
-+	if (rt_task(p)) {
-+		p->time_slice += p->quota;
-+		list_move_tail(&p->run_list, p->array->queue + p->prio);
- 		return;
- 	}
--	spin_lock(&rq->lock);
-+	overrun = p->time_slice;
-+	dequeue_task(p, rq);
-+	enqueue_task(p, rq);
- 	/*
--	 * The task was running during this tick - update the
--	 * time slice counter. Note: we do not update a thread's
--	 * priority until it either goes to sleep or uses up its
--	 * timeslice. This makes it possible for interactive tasks
--	 * to use up their timeslices at their highest priority levels.
-+	 * Subtract any extra time this task ran over its time_slice; ie
-+	 * overrun will either be 0 or negative.
- 	 */
--	if (rt_task(p)) {
--		/*
--		 * RR tasks need a special form of timeslice management.
--		 * FIFO tasks have no timeslices.
--		 */
--		if ((p->policy == SCHED_RR) && !--p->time_slice) {
--			p->time_slice = task_timeslice(p);
--			p->first_time_slice = 0;
--			set_tsk_need_resched(p);
-+	p->time_slice += overrun;
-+}
- 
--			/* put it at the end of the queue: */
--			requeue_task(p, rq->active);
--		}
--		goto out_unlock;
-+/*
-+ * Test if SCHED_ISO tasks have run longer than their alloted period as RT
-+ * tasks and set the refractory flag if necessary. There is 10% hysteresis
-+ * for unsetting the flag.
-+ */
-+static unsigned int test_ret_isorefractory(struct rq *rq)
-+{
-+	if (likely(!rq->iso_refractory)) {
-+		if (rq->iso_ticks / ISO_PERIOD > sched_iso_cpu)
-+			rq->iso_refractory = 1;
-+	} else {
-+		if (rq->iso_ticks / ISO_PERIOD < (sched_iso_cpu * 90 / 100))
-+			rq->iso_refractory = 0;
- 	}
--	if (!--p->time_slice) {
--		dequeue_task(p, rq->active);
--		set_tsk_need_resched(p);
--		p->prio = effective_prio(p);
--		p->time_slice = task_timeslice(p);
--		p->first_time_slice = 0;
-+	return rq->iso_refractory;
-+}
- 
--		if (!rq->expired_timestamp)
--			rq->expired_timestamp = jiffies;
--		if (!TASK_INTERACTIVE(p) || expired_starving(rq)) {
--			enqueue_task(p, rq->expired);
--			if (p->static_prio < rq->best_expired_prio)
--				rq->best_expired_prio = p->static_prio;
--		} else
--			enqueue_task(p, rq->active);
--	} else {
--		/*
--		 * Prevent a too long timeslice allowing a task to monopolize
--		 * the CPU. We do this by splitting up the timeslice into
--		 * smaller pieces.
--		 *
--		 * Note: this does not mean the task's timeslices expire or
--		 * get lost in any way, they just might be preempted by
--		 * another task of equal priority. (one with higher
--		 * priority would have preempted this task already.) We
--		 * requeue this task to the end of the list on this priority
--		 * level, which is in essence a round-robin of tasks with
--		 * equal priority.
--		 *
--		 * This only applies to tasks in the interactive
--		 * delta range with at least TIMESLICE_GRANULARITY to requeue.
--		 */
--		if (TASK_INTERACTIVE(p) && !((task_timeslice(p) -
--			p->time_slice) % TIMESLICE_GRANULARITY(p)) &&
--			(p->time_slice >= TIMESLICE_GRANULARITY(p)) &&
--			(p->array == rq->active)) {
-+/* No SCHED_ISO task was running so decrease rq->iso_ticks */
-+static inline void no_iso_tick(struct rq *rq)
-+{
-+	rq->iso_ticks = rq->iso_ticks * (ISO_PERIOD - 1) / ISO_PERIOD;
-+}
- 
--			requeue_task(p, rq->active);
--			set_tsk_need_resched(p);
--		}
-+/* This manages tasks that have run out of timeslice during a scheduler_tick */
-+static void task_running_tick(struct rq *rq, struct task_struct *p)
-+{
-+	/*
-+	 * If a SCHED_ISO task is running we increment the iso_ticks. In
-+	 * order to prevent SCHED_ISO tasks from causing starvation in the
-+	 * presence of true RT tasks we account those as iso_ticks as well.
-+	 */
-+	if ((rt_task(p) || (iso_task(p) && !rq->iso_refractory))) {
-+		if (rq->iso_ticks <= (ISO_PERIOD * 100) - 100)
-+			rq->iso_ticks += 100;
-+	} else
-+		no_iso_tick(rq);
-+
-+	if (iso_task(p)) {
-+		if (unlikely(test_ret_isorefractory(rq))) {
-+			if (isoprio_suitable(p)) {
-+				/*
-+				 * SCHED_ISO task is running as RT and limit
-+				 * has been hit. Set the PF_ISOREF flag and
-+				 * force it to reschedule as SCHED_NORMAL
-+				 * by zeroing its time_slice
-+				 */
-+				p->flags |= PF_ISOREF;
-+				p->time_slice = 0;
-+			}
-+		} else
-+			p->flags &= ~PF_ISOREF;
- 	}
--out_unlock:
--	spin_unlock(&rq->lock);
-+	/* SCHED_FIFO tasks never run out of timeslice. */
-+	if (p->time_slice > 0 || p->policy == SCHED_FIFO)
-+		return;
-+	/* p->time_slice <= 0 */
-+	set_tsk_need_resched(p);
-+	if (likely(task_queued(p)))
-+		task_expired_entitlement(rq, p);
- }
- 
- /*
-  * This function gets called by the timer code, with HZ frequency.
-  * We call it with interrupts disabled.
-- *
-- * It also gets called by the fork code, when changing the parent's
-- * timeslices.
-  */
- void scheduler_tick(void)
- {
-@@ -3220,10 +3371,14 @@ void scheduler_tick(void)
- 	int cpu = smp_processor_id();
- 	struct rq *rq = cpu_rq(cpu);
- 
--	update_cpu_clock(p, rq, now);
-+	update_cpu_clock(p, rq, now, 1);
- 
-+	spin_lock(&rq->lock);
- 	if (p != rq->idle)
- 		task_running_tick(rq, p);
-+	else
-+		no_iso_tick(rq);
-+	spin_unlock(&rq->lock);
- #ifdef CONFIG_SMP
- 	update_load(rq);
- 	if (time_after_eq(jiffies, rq->next_balance))
-@@ -3269,10 +3424,80 @@ EXPORT_SYMBOL(sub_preempt_count);
- 
- #endif
- 
--static inline int interactive_sleep(enum sleep_type sleep_type)
-+static void reset_prio_levels(struct rq *rq)
-+{
-+	rq->active->best_static_prio = MAX_PRIO - 1;
-+	rq->expired->best_static_prio = MAX_PRIO - 1;
-+	memset(rq->prio_level, 0, sizeof(int) * PRIO_RANGE);
-+}
-+
-+/*
-+ * Only tasks running are SCHED_IDLEPRIO. Set the active array to the
-+ * idleprio array and if it isn't already active
-+ */
-+static struct task_struct *next_idleprio_task(struct rq *rq)
- {
--	return (sleep_type == SLEEP_INTERACTIVE ||
--		sleep_type == SLEEP_INTERRUPTED);
-+	struct prio_array *array = rq->active;
-+	struct list_head *queue;
-+
-+	if (array != rq->idleprio) {
-+		rq->active = rq->idleprio;
-+		rq->expired = array;
-+		array = rq->active;
-+		rq->exp_bitmap = rq->expired->prio_bitmap;
-+		rq->dyn_bitmap = rq->active->prio_bitmap;
-+	}
-+	rq->prio_rotation++;
-+	reset_prio_levels(rq);
-+	queue = array->queue + MAX_PRIO;
-+	return list_entry(queue->next, struct task_struct, run_list);
-+}
-+
-+/*
-+ * next_dynamic_task finds the next suitable dynamic task.
-+ */
-+static inline struct task_struct *next_dynamic_task(struct rq *rq, int idx)
-+{
-+	struct prio_array *array = rq->active;
-+	struct task_struct *next;
-+	struct list_head *queue;
-+	int nstatic;
-+
-+retry:
-+	if (unlikely(rq->nr_running == rq->nr_idleprio))
-+		return next_idleprio_task(rq);
-+	if (idx >= MAX_PRIO) {
-+		/* There are no more tasks in the active array. Swap arrays */
-+		array = rq->expired;
-+		rq->expired = rq->active;
-+		rq->active = array;
-+		rq->exp_bitmap = rq->expired->prio_bitmap;
-+		rq->dyn_bitmap = rq->active->prio_bitmap;
-+		rq->prio_rotation++;
-+		idx = find_next_bit(rq->dyn_bitmap, MAX_PRIO, MAX_RT_PRIO);
-+		reset_prio_levels(rq);
-+	}
-+	queue = array->queue + idx;
-+	next = list_entry(queue->next, struct task_struct, run_list);
-+	if (unlikely(next->time_slice <= 0 && !(iso_task(next) &&
-+	    isoprio_suitable(next)))) {
-+		/*
-+		 * Unlucky enough that this task ran out of time_slice
-+		 * before it hit a scheduler_tick so it should have its
-+		 * priority reassessed and choose another task (possibly
-+		 * the same one)
-+		 */
-+		task_expired_entitlement(rq, next);
-+		idx = find_next_bit(rq->dyn_bitmap, MAX_PRIO, MAX_RT_PRIO);
-+		goto retry;
-+	}
-+	next->rotation = rq->prio_rotation;
-+	nstatic = next->static_prio;
-+	if (nstatic < array->best_static_prio)
-+		array->best_static_prio = nstatic;
-+	if (idx > rq->prio_level[USER_PRIO(nstatic)])
-+		rq->prio_level[USER_PRIO(nstatic)] = idx;
-+	return next;
- }
- 
- /*
-@@ -3281,13 +3506,11 @@ static inline int interactive_sleep(enum
- asmlinkage void __sched schedule(void)
- {
- 	struct task_struct *prev, *next;
--	struct prio_array *array;
- 	struct list_head *queue;
- 	unsigned long long now;
--	unsigned long run_time;
--	int cpu, idx, new_prio;
- 	long *switch_count;
- 	struct rq *rq;
-+	int cpu, idx;
- 
- 	/*
- 	 * Test if we are atomic.  Since do_exit() needs to call into
-@@ -3323,18 +3546,6 @@ need_resched_nonpreemptible:
- 
- 	schedstat_inc(rq, sched_cnt);
- 	now = sched_clock();
--	if (likely((long long)(now - prev->timestamp) < NS_MAX_SLEEP_AVG)) {
--		run_time = now - prev->timestamp;
--		if (unlikely((long long)(now - prev->timestamp) < 0))
--			run_time = 0;
--	} else
--		run_time = NS_MAX_SLEEP_AVG;
--
--	/*
--	 * Tasks charged proportionately less run_time at high sleep_avg to
--	 * delay them losing their interactive status
--	 */
--	run_time /= (CURRENT_BONUS(prev) ? : 1);
- 
- 	spin_lock_irq(&rq->lock);
- 
-@@ -3345,8 +3556,10 @@ need_resched_nonpreemptible:
- 				unlikely(signal_pending(prev))))
- 			prev->state = TASK_RUNNING;
- 		else {
--			if (prev->state == TASK_UNINTERRUPTIBLE)
-+			if (prev->state == TASK_UNINTERRUPTIBLE) {
-+				prev->flags |= PF_NONSLEEP;
- 				rq->nr_uninterruptible++;
-+			}
- 			deactivate_task(prev, rq);
- 		}
- 	}
-@@ -3356,59 +3569,29 @@ need_resched_nonpreemptible:
- 		idle_balance(cpu, rq);
- 		if (!rq->nr_running) {
- 			next = rq->idle;
--			rq->expired_timestamp = 0;
- 			goto switch_tasks;
- 		}
- 	}
- 
--	array = rq->active;
--	if (unlikely(!array->nr_active)) {
--		/*
--		 * Switch the active and expired arrays.
--		 */
--		schedstat_inc(rq, sched_switch);
--		rq->active = rq->expired;
--		rq->expired = array;
--		array = rq->active;
--		rq->expired_timestamp = 0;
--		rq->best_expired_prio = MAX_PRIO;
-+	idx = sched_find_first_bit(rq->dyn_bitmap);
-+	if (likely(idx > ISO_PRIO))
-+		next = next_dynamic_task(rq, idx);
-+	else {
-+		queue = rq->active->queue + idx;
-+		next = list_entry(queue->next, struct task_struct, run_list);
- 	}
--
--	idx = sched_find_first_bit(array->bitmap);
--	queue = array->queue + idx;
--	next = list_entry(queue->next, struct task_struct, run_list);
--
--	if (!rt_task(next) && interactive_sleep(next->sleep_type)) {
--		unsigned long long delta = now - next->timestamp;
--		if (unlikely((long long)(now - next->timestamp) < 0))
--			delta = 0;
--
--		if (next->sleep_type == SLEEP_INTERACTIVE)
--			delta = delta * (ON_RUNQUEUE_WEIGHT * 128 / 100) / 128;
--
--		array = next->array;
--		new_prio = recalc_task_prio(next, next->timestamp + delta);
--
--		if (unlikely(next->prio != new_prio)) {
--			dequeue_task(next, array);
--			next->prio = new_prio;
--			enqueue_task(next, array);
--		}
--	}
--	next->sleep_type = SLEEP_NORMAL;
- switch_tasks:
--	if (next == rq->idle)
-+	if (next == rq->idle) {
-+		reset_prio_levels(rq);
-+		rq->prio_rotation++;
- 		schedstat_inc(rq, sched_goidle);
-+	}
- 	prefetch(next);
- 	prefetch_stack(next);
- 	clear_tsk_need_resched(prev);
- 	rcu_qsctr_inc(task_cpu(prev));
- 
--	update_cpu_clock(prev, rq, now);
--
--	prev->sleep_avg -= run_time;
--	if ((long)prev->sleep_avg <= 0)
--		prev->sleep_avg = 0;
-+	update_cpu_clock(prev, rq, now, 0);
- 	prev->timestamp = prev->last_ran = now;
- 
- 	sched_info_switch(prev, next);
-@@ -3844,29 +4027,22 @@ EXPORT_SYMBOL(sleep_on_timeout);
-  */
- void rt_mutex_setprio(struct task_struct *p, int prio)
- {
--	struct prio_array *array;
- 	unsigned long flags;
-+	int queued, oldprio;
- 	struct rq *rq;
--	int oldprio;
- 
- 	BUG_ON(prio < 0 || prio > MAX_PRIO);
- 
- 	rq = task_rq_lock(p, &flags);
- 
- 	oldprio = p->prio;
--	array = p->array;
--	if (array)
--		dequeue_task(p, array);
-+	queued = task_queued(p);
-+	if (queued)
-+		dequeue_task(p, rq);
- 	p->prio = prio;
- 
--	if (array) {
--		/*
--		 * If changing to an RT priority then queue it
--		 * in the active array!
--		 */
--		if (rt_task(p))
--			array = rq->active;
--		enqueue_task(p, array);
-+	if (queued) {
-+		enqueue_task(p, rq);
- 		/*
- 		 * Reschedule if we are currently running on this runqueue and
- 		 * our priority decreased, or if we are not currently running on
-@@ -3875,8 +4051,8 @@ void rt_mutex_setprio(struct task_struct
- 		if (task_running(rq, p)) {
- 			if (p->prio > oldprio)
- 				resched_task(rq->curr);
--		} else if (TASK_PREEMPTS_CURR(p, rq))
--			resched_task(rq->curr);
-+		} else
-+			try_preempt(p, rq);
- 	}
- 	task_rq_unlock(rq, &flags);
- }
-@@ -3885,8 +4061,7 @@ void rt_mutex_setprio(struct task_struct
- 
- void set_user_nice(struct task_struct *p, long nice)
- {
--	struct prio_array *array;
--	int old_prio, delta;
-+	int queued, old_prio,delta;
- 	unsigned long flags;
- 	struct rq *rq;
- 
-@@ -3907,26 +4082,27 @@ void set_user_nice(struct task_struct *p
- 		p->static_prio = NICE_TO_PRIO(nice);
- 		goto out_unlock;
- 	}
--	array = p->array;
--	if (array) {
--		dequeue_task(p, array);
-+	queued = task_queued(p);
-+	if (queued) {
-+		dequeue_task(p, rq);
- 		dec_raw_weighted_load(rq, p);
- 	}
- 
- 	p->static_prio = NICE_TO_PRIO(nice);
--	set_load_weight(p);
- 	old_prio = p->prio;
- 	p->prio = effective_prio(p);
-+	set_quota(p);
- 	delta = p->prio - old_prio;
- 
--	if (array) {
--		enqueue_task(p, array);
-+	if (queued) {
-+		enqueue_task(p, rq);
- 		inc_raw_weighted_load(rq, p);
- 		/*
- 		 * If the task increased its priority or is running and
- 		 * lowered its priority, then reschedule its CPU:
- 		 */
--		if (delta < 0 || (delta > 0 && task_running(rq, p)))
-+		if (delta < 0 || ((delta > 0 || idleprio_task(p)) &&
-+		    task_running(rq, p)))
- 			resched_task(rq->curr);
- 	}
- out_unlock:
-@@ -3996,7 +4172,7 @@ asmlinkage long sys_nice(int increment)
-  *
-  * This is the priority value as seen by users in /proc.
-  * RT tasks are offset by -200. Normal tasks are centered
-- * around 0, value goes from -16 to +15.
-+ * around 0, value goes from 0 to +39.
-  */
- int task_prio(const struct task_struct *p)
- {
-@@ -4043,19 +4219,14 @@ static inline struct task_struct *find_p
- /* Actually do priority change: must hold rq lock. */
- static void __setscheduler(struct task_struct *p, int policy, int prio)
- {
--	BUG_ON(p->array);
-+	BUG_ON(task_queued(p));
- 
- 	p->policy = policy;
- 	p->rt_priority = prio;
- 	p->normal_prio = normal_prio(p);
- 	/* we are holding p->pi_lock already */
- 	p->prio = rt_mutex_getprio(p);
--	/*
--	 * SCHED_BATCH tasks are treated as perpetual CPU hogs:
--	 */
--	if (policy == SCHED_BATCH)
--		p->sleep_avg = 0;
--	set_load_weight(p);
-+	set_quota(p);
- }
- 
- /**
-@@ -4069,19 +4240,27 @@ static void __setscheduler(struct task_s
- int sched_setscheduler(struct task_struct *p, int policy,
- 		       struct sched_param *param)
- {
--	int retval, oldprio, oldpolicy = -1;
--	struct prio_array *array;
-+	struct sched_param zero_param = { .sched_priority = 0 };
-+	int queued, retval, oldprio, oldpolicy = -1;
- 	unsigned long flags;
- 	struct rq *rq;
- 
- 	/* may grab non-irq protected spin_locks */
- 	BUG_ON(in_interrupt());
-+	if (is_rt_policy(policy) && !capable(CAP_SYS_NICE)) {
-+		/*
-+		 * If the caller requested an RT policy without having the
-+		 * necessary rights, we downgrade the policy to SCHED_ISO.
-+		 * We also set the parameter to zero to pass the checks.
-+		 */
-+		policy = SCHED_ISO;
-+		param = &zero_param;
-+	}
- recheck:
- 	/* double check policy once rq lock held */
- 	if (policy < 0)
- 		policy = oldpolicy = p->policy;
--	else if (policy != SCHED_FIFO && policy != SCHED_RR &&
--			policy != SCHED_NORMAL && policy != SCHED_BATCH)
-+	else if (!SCHED_RANGE(policy))
- 		return -EINVAL;
- 	/*
- 	 * Valid priorities for SCHED_FIFO and SCHED_RR are
-@@ -4116,6 +4295,31 @@ recheck:
- 			if (param->sched_priority > p->rt_priority &&
- 			    param->sched_priority > rlim_rtprio)
- 				return -EPERM;
-+		} else {
-+			switch (p->policy) {
-+				/*
-+				 * Can only downgrade policies but not back to
-+				 * SCHED_NORMAL
-+				 */
-+				case SCHED_ISO:
-+					if (policy == SCHED_ISO)
-+						goto out;
-+					if (policy == SCHED_NORMAL)
-+						return -EPERM;
-+					break;
-+				case SCHED_BATCH:
-+					if (policy == SCHED_BATCH)
-+						goto out;
-+					if (policy != SCHED_IDLEPRIO)
-+					    	return -EPERM;
-+					break;
-+				case SCHED_IDLEPRIO:
-+					if (policy == SCHED_IDLEPRIO)
-+						goto out;
-+					return -EPERM;
-+				default:
-+					break;
-+			}
- 		}
- 
- 		/* can't change other user's priorities */
-@@ -4124,6 +4328,11 @@ recheck:
- 			return -EPERM;
- 	}
- 
-+	if (!(p->mm) && policy == SCHED_IDLEPRIO) {
-+		/* Don't allow kernel threads to be SCHED_IDLEPRIO. */
-+		return -EINVAL;
-+	}
-+
- 	retval = security_task_setscheduler(p, policy, param);
- 	if (retval)
- 		return retval;
-@@ -4144,12 +4353,12 @@ recheck:
- 		spin_unlock_irqrestore(&p->pi_lock, flags);
- 		goto recheck;
- 	}
--	array = p->array;
--	if (array)
-+	queued = task_queued(p);
-+	if (queued)
- 		deactivate_task(p, rq);
- 	oldprio = p->prio;
- 	__setscheduler(p, policy, param->sched_priority);
--	if (array) {
-+	if (queued) {
- 		__activate_task(p, rq);
- 		/*
- 		 * Reschedule if we are currently running on this runqueue and
-@@ -4159,14 +4368,15 @@ recheck:
- 		if (task_running(rq, p)) {
- 			if (p->prio > oldprio)
- 				resched_task(rq->curr);
--		} else if (TASK_PREEMPTS_CURR(p, rq))
--			resched_task(rq->curr);
-+		} else
-+			try_preempt(p, rq);
- 	}
- 	__task_rq_unlock(rq);
- 	spin_unlock_irqrestore(&p->pi_lock, flags);
- 
- 	rt_mutex_adjust_pi(p);
- 
-+out:
- 	return 0;
- }
- EXPORT_SYMBOL_GPL(sched_setscheduler);
-@@ -4433,41 +4643,34 @@ asmlinkage long sys_sched_getaffinity(pi
-  * sys_sched_yield - yield the current processor to other threads.
-  *
-  * This function yields the current CPU by moving the calling thread
-- * to the expired array. If there are no other threads running on this
-- * CPU then this function will return.
-+ * to the expired array if SCHED_NORMAL or the end of its current priority
-+ * queue if a realtime task. If there are no other threads running on this
-+ * cpu this function will return.
-  */
- asmlinkage long sys_sched_yield(void)
- {
- 	struct rq *rq = this_rq_lock();
--	struct prio_array *array = current->array, *target = rq->expired;
-+	struct task_struct *p = current;
- 
- 	schedstat_inc(rq, yld_cnt);
--	/*
--	 * We implement yielding by moving the task into the expired
--	 * queue.
--	 *
--	 * (special rule: RT tasks will just roundrobin in the active
--	 *  array.)
--	 */
--	if (rt_task(current))
--		target = rq->active;
--
--	if (array->nr_active == 1) {
--		schedstat_inc(rq, yld_act_empty);
--		if (!rq->expired->nr_active)
--			schedstat_inc(rq, yld_both_empty);
--	} else if (!rq->expired->nr_active)
--		schedstat_inc(rq, yld_exp_empty);
--
--	if (array != target) {
--		dequeue_task(current, array);
--		enqueue_task(current, target);
--	} else
--		/*
--		 * requeue_task is cheaper so perform that if possible.
--		 */
--		requeue_task(current, array);
-+	if (rq->nr_running == 1)
-+		schedstat_inc(rq, yld_both_empty);
-+	else {
-+		struct prio_array *old_array = p->array;
-+		int old_prio = p->prio;
-+
-+		if (idleprio_task(p)) {
-+			dequeue_task(p, rq);
-+			enqueue_task(p, rq);
-+			goto out_release;
-+		}
-+		/* p->prio will be updated in requeue_task via queue_expired */
-+		if (!rt_task(p))
-+			p->array = rq->expired;
-+		requeue_task(p, rq, old_array, old_prio);
-+	}
- 
-+out_release:
- 	/*
- 	 * Since we are going to call schedule() anyway, there's
- 	 * no need to preempt or enable interrupts:
-@@ -4619,6 +4822,8 @@ asmlinkage long sys_sched_get_priority_m
- 		break;
- 	case SCHED_NORMAL:
- 	case SCHED_BATCH:
-+	case SCHED_ISO:
-+	case SCHED_IDLEPRIO:
- 		ret = 0;
- 		break;
- 	}
-@@ -4643,6 +4848,8 @@ asmlinkage long sys_sched_get_priority_m
- 		break;
- 	case SCHED_NORMAL:
- 	case SCHED_BATCH:
-+	case SCHED_ISO:
-+	case SCHED_IDLEPRIO:
- 		ret = 0;
- 	}
- 	return ret;
-@@ -4676,8 +4883,8 @@ long sys_sched_rr_get_interval(pid_t pid
- 	if (retval)
- 		goto out_unlock;
- 
--	jiffies_to_timespec(p->policy == SCHED_FIFO ?
--				0 : task_timeslice(p), &t);
-+	t = ns_to_timespec(p->policy == SCHED_FIFO ? 0 :
-+			   MS_TO_NS(task_timeslice(p)));
- 	read_unlock(&tasklist_lock);
- 	retval = copy_to_user(interval, &t, sizeof(t)) ? -EFAULT : 0;
- out_nounlock:
-@@ -4771,10 +4978,10 @@ void __cpuinit init_idle(struct task_str
- 	struct rq *rq = cpu_rq(cpu);
- 	unsigned long flags;
- 
--	idle->timestamp = sched_clock();
--	idle->sleep_avg = 0;
--	idle->array = NULL;
--	idle->prio = idle->normal_prio = MAX_PRIO;
-+	bitmap_zero(idle->bitmap, PRIO_RANGE);
-+	idle->timestamp = idle->last_ran = sched_clock();
-+	idle->array = rq->active;
-+	idle->prio = idle->normal_prio = NICE_TO_PRIO(0);
- 	idle->state = TASK_RUNNING;
- 	idle->cpus_allowed = cpumask_of_cpu(cpu);
- 	set_task_cpu(idle, cpu);
-@@ -4893,7 +5100,7 @@ static int __migrate_task(struct task_st
- 		goto out;
- 
- 	set_task_cpu(p, dest_cpu);
--	if (p->array) {
-+	if (task_queued(p)) {
- 		/*
- 		 * Sync timestamp with rq_dest's before activating.
- 		 * The same thing could be achieved by doing this step
-@@ -4904,8 +5111,7 @@ static int __migrate_task(struct task_st
- 				+ rq_dest->most_recent_timestamp;
- 		deactivate_task(p, rq_src);
- 		__activate_task(p, rq_dest);
--		if (TASK_PREEMPTS_CURR(p, rq_dest))
--			resched_task(rq_dest->curr);
-+		try_preempt(p, rq_dest);
- 	}
- 	ret = 1;
- out:
-@@ -5194,7 +5400,7 @@ migration_call(struct notifier_block *nf
- 		/* Idle task back to normal (off runqueue, low prio) */
- 		rq = task_rq_lock(rq->idle, &flags);
- 		deactivate_task(rq->idle, rq);
--		rq->idle->static_prio = MAX_PRIO;
-+		rq->idle->static_prio = NICE_TO_PRIO(0);
- 		__setscheduler(rq->idle, SCHED_NORMAL, 0);
- 		migrate_dead_tasks(cpu);
- 		task_rq_unlock(rq, &flags);
-@@ -6706,6 +6912,13 @@ void __init sched_init_smp(void)
- 	/* Move init over to a non-isolated CPU */
- 	if (set_cpus_allowed(current, non_isolated_cpus) < 0)
- 		BUG();
-+
-+	/*
-+	 * Assume that every added cpu gives us slightly less overall latency
-+	 * allowing us to increase the base rr_interval, but in a non linear
-+	 * fashion.
-+	 */
-+	rr_interval *= 1 + ilog2(num_online_cpus());
- }
- #else
- void __init sched_init_smp(void)
-@@ -6727,6 +6940,16 @@ void __init sched_init(void)
- {
- 	int i, j, k;
- 
-+	/* Generate the priority matrix */
-+	for (i = 0; i < PRIO_RANGE; i++) {
-+		bitmap_fill(prio_matrix[i], PRIO_RANGE);
-+		j = PRIO_RANGE * PRIO_RANGE / (PRIO_RANGE - i);
-+		for (k = 0; k <= PRIO_RANGE * (PRIO_RANGE - 1); k += j) {
-+			__clear_bit(PRIO_RANGE - 1 - (k / PRIO_RANGE),
-+				    prio_matrix[i]);
-+		}
-+	}
-+
- 	for_each_possible_cpu(i) {
- 		struct prio_array *array;
- 		struct rq *rq;
-@@ -6734,12 +6957,20 @@ void __init sched_init(void)
- 		rq = cpu_rq(i);
- 		spin_lock_init(&rq->lock);
- 		lockdep_set_class(&rq->lock, &rq->rq_lock_key);
-+		rq->iso_ticks = 0;
- 		rq->nr_running = 0;
-+		rq->nr_idleprio = 0;
-+		rq->prio_rotation = 0;
- 		rq->active = rq->arrays;
-+		rq->idleprio = rq->active;
- 		rq->expired = rq->arrays + 1;
--		rq->best_expired_prio = MAX_PRIO;
-+		reset_prio_levels(rq);
-+		rq->dyn_bitmap = rq->active->prio_bitmap;
-+		rq->exp_bitmap = rq->expired->prio_bitmap;
- 
- #ifdef CONFIG_SMP
-+		rq->active->rq = rq;
-+		rq->expired->rq = rq;
- 		rq->sd = NULL;
- 		for (j = 1; j < 3; j++)
- 			rq->cpu_load[j] = 0;
-@@ -6752,16 +6983,16 @@ void __init sched_init(void)
- 		atomic_set(&rq->nr_iowait, 0);
- 
- 		for (j = 0; j < 2; j++) {
-+
- 			array = rq->arrays + j;
--			for (k = 0; k < MAX_PRIO; k++) {
-+			for (k = 0; k <= MAX_PRIO; k++)
- 				INIT_LIST_HEAD(array->queue + k);
--				__clear_bit(k, array->bitmap);
--			}
--			// delimiter for bitsearch
--			__set_bit(MAX_PRIO, array->bitmap);
-+			bitmap_zero(array->prio_bitmap, MAX_PRIO);
-+			/* delimiter for bitsearch */
-+			__set_bit(MAX_PRIO, array->prio_bitmap);
- 		}
--	}
- 
-+	}
- 	set_load_weight(&init_task);
- 
- #ifdef CONFIG_SMP
-@@ -6815,24 +7046,24 @@ EXPORT_SYMBOL(__might_sleep);
- #ifdef CONFIG_MAGIC_SYSRQ
- void normalize_rt_tasks(void)
- {
--	struct prio_array *array;
- 	struct task_struct *p;
- 	unsigned long flags;
- 	struct rq *rq;
-+	int queued;
- 
- 	read_lock_irq(&tasklist_lock);
- 	for_each_process(p) {
--		if (!rt_task(p))
-+		if (!rt_task(p) && !iso_task(p))
- 			continue;
- 
- 		spin_lock_irqsave(&p->pi_lock, flags);
- 		rq = __task_rq_lock(p);
- 
--		array = p->array;
--		if (array)
-+		queued = task_queued(p);
-+		if (queued)
- 			deactivate_task(p, task_rq(p));
- 		__setscheduler(p, SCHED_NORMAL, 0);
--		if (array) {
-+		if (queued) {
- 			__activate_task(p, task_rq(p));
- 			resched_task(rq->curr);
- 		}
-Index: linux-2.6.21-ck1/Documentation/sysctl/kernel.txt
-===================================================================
---- linux-2.6.21-ck1.orig/Documentation/sysctl/kernel.txt	2007-05-04 12:10:52.000000000 +1000
-+++ linux-2.6.21-ck1/Documentation/sysctl/kernel.txt	2007-05-04 12:10:55.000000000 +1000
-@@ -25,6 +25,9 @@ show up in /proc/sys/kernel:
- - domainname
- - hostname
- - hotplug
-+- interactive
-+- iso_cpu
-+- iso_period
- - java-appletviewer           [ binfmt_java, obsolete ]
- - java-interpreter            [ binfmt_java, obsolete ]
- - kstack_depth_to_print       [ X86 only ]
-@@ -43,6 +46,7 @@ show up in /proc/sys/kernel:
- - printk
- - real-root-dev               ==> Documentation/initrd.txt
- - reboot-cmd                  [ SPARC only ]
-+- rr_interval
- - rtsig-max
- - rtsig-nr
- - sem
-@@ -164,6 +168,40 @@ Default value is "/sbin/hotplug".
- 
- ==============================================================
- 
-+interactive:
-+
-+The staircase-deadline cpu scheduler can be set in either purely
-+forward-looking mode for absolutely rigid fairness and cpu distribution
-+according to nice level, or it can allow a small per-process history
-+to smooth out cpu usage perturbations common in interactive tasks by
-+enabling this sysctl. While small fairness issues can arise with this
-+enabled, overall fairness is usually still strongly maintained and
-+starvation is never possible. Enabling this can significantly smooth
-+out 3d graphics and games.
-+
-+Default value is 1 (enabled).
-+
-+==============================================================
-+
-+iso_cpu:
-+
-+This sets the percentage cpu that the unprivileged SCHED_ISO tasks can
-+run effectively at realtime priority, averaged over a rolling iso_period
-+seconds.
-+
-+Set to 80 (percent) by default.
-+
-+==============================================================
-+
-+iso_period:
-+
-+This sets the number of seconds over which SCHED_ISO cpu usage is averaged
-+to see if it exceeds its allocated cpu bandwidth.
-+
-+Set to 5 (seconds) by default.
-+
-+==============================================================
-+
- l2cr: (PPC only)
- 
- This flag controls the L2 cache of G3 processor boards. If
-@@ -288,6 +326,19 @@ rebooting. ???
- 
- ==============================================================
- 
-+rr_interval:
-+
-+This is the smallest duration that any cpu process scheduling unit
-+will run for. Increasing this value can increase throughput of cpu
-+bound tasks substantially but at the expense of increased latencies
-+overall. This value is in milliseconds and the default value chosen
-+depends on the number of cpus available at scheduler initialisation
-+with a minimum of 8.
-+
-+Valid values are from 1-5000.
-+
-+==============================================================
-+
- rtsig-max & rtsig-nr:
- 
- The file rtsig-max can be used to tune the maximum number
-Index: linux-2.6.21-ck1/kernel/sysctl.c
-===================================================================
---- linux-2.6.21-ck1.orig/kernel/sysctl.c	2007-05-04 12:10:52.000000000 +1000
-+++ linux-2.6.21-ck1/kernel/sysctl.c	2007-05-04 12:24:21.000000000 +1000
-@@ -22,6 +22,7 @@
- #include <linux/mm.h>
- #include <linux/swap.h>
- #include <linux/slab.h>
-+#include <linux/swap-prefetch.h>
- #include <linux/sysctl.h>
- #include <linux/proc_fs.h>
- #include <linux/capability.h>
-@@ -70,12 +71,17 @@ extern int suid_dumpable;
- extern char core_pattern[];
- extern int pid_max;
- extern int min_free_kbytes;
-+extern int vm_tail_largefiles;
- extern int printk_ratelimit_jiffies;
- extern int printk_ratelimit_burst;
- extern int pid_max_min, pid_max_max;
- extern int sysctl_drop_caches;
- extern int percpu_pagelist_fraction;
- extern int compat_log;
-+extern int rr_interval;
-+extern int sched_interactive;
-+extern int sched_iso_cpu;
-+extern int sched_iso_period;
- 
- /* this is needed for the proc_dointvec_minmax for [fs_]overflow UID and GID */
- static int maxolduid = 65535;
-@@ -159,6 +165,14 @@ int sysctl_legacy_va_layout;
- #endif
- 
- 
-+/* Constants for minimum and maximum testing.
-+   We use these as one-element integer vectors. */
-+static int __read_mostly zero;
-+static int __read_mostly one = 1;
-+static int __read_mostly one_hundred = 100;
-+static int __read_mostly five_thousand = 5000;
-+
-+
- /* The default sysctl tables: */
- 
- static ctl_table root_table[] = {
-@@ -499,6 +513,47 @@ static ctl_table kern_table[] = {
- 		.mode		= 0444,
- 		.proc_handler	= &proc_dointvec,
- 	},
-+	{
-+		.ctl_name	= CTL_UNNUMBERED,
-+		.procname	= "rr_interval",
-+		.data		= &rr_interval,
-+		.maxlen		= sizeof (int),
-+		.mode		= 0644,
-+		.proc_handler	= &proc_dointvec_minmax,
-+		.strategy	= &sysctl_intvec,
-+		.extra1		= &one,
-+		.extra2		= &five_thousand,
-+	},
-+	{
-+		.ctl_name	= CTL_UNNUMBERED,
-+		.procname	= "interactive",
-+		.data		= &sched_interactive,
-+		.maxlen		= sizeof(int),
-+		.mode		= 0644,
-+		.proc_handler	= &proc_dointvec,
-+	},
-+	{
-+		.ctl_name	= CTL_UNNUMBERED,
-+		.procname	= "iso_cpu",
-+		.data		= &sched_iso_cpu,
-+		.maxlen		= sizeof (int),
-+		.mode		= 0644,
-+		.proc_handler	= &proc_dointvec_minmax,
-+		.strategy	= &sysctl_intvec,
-+		.extra1		= &zero,
-+		.extra2		= &one_hundred,
-+	},
-+	{
-+		.ctl_name	= CTL_UNNUMBERED,
-+		.procname	= "iso_period",
-+		.data		= &sched_iso_period,
-+		.maxlen		= sizeof (int),
-+		.mode		= 0644,
-+		.proc_handler	= &proc_dointvec_minmax,
-+		.strategy	= &sysctl_intvec,
-+		.extra1		= &one,
-+		.extra2		= &one_hundred,
-+	},
- #if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_X86)
- 	{
- 		.ctl_name       = KERN_UNKNOWN_NMI_PANIC,
-@@ -607,12 +662,6 @@ static ctl_table kern_table[] = {
- 	{ .ctl_name = 0 }
- };
- 
--/* Constants for minimum and maximum testing in vm_table.
--   We use these as one-element integer vectors. */
--static int zero;
--static int one_hundred = 100;
--
--
- static ctl_table vm_table[] = {
- 	{
- 		.ctl_name	= VM_OVERCOMMIT_MEMORY,
-@@ -693,16 +742,32 @@ static ctl_table vm_table[] = {
- 		.proc_handler	= &proc_dointvec,
- 	},
- 	{
--		.ctl_name	= VM_SWAPPINESS,
--		.procname	= "swappiness",
--		.data		= &vm_swappiness,
--		.maxlen		= sizeof(vm_swappiness),
-+		.ctl_name	= CTL_UNNUMBERED,
-+		.procname	= "mapped",
-+		.data		= &vm_mapped,
-+		.maxlen		= sizeof(vm_mapped),
- 		.mode		= 0644,
- 		.proc_handler	= &proc_dointvec_minmax,
- 		.strategy	= &sysctl_intvec,
- 		.extra1		= &zero,
- 		.extra2		= &one_hundred,
- 	},
-+	{
-+		.ctl_name	= CTL_UNNUMBERED,
-+		.procname	= "hardmaplimit",
-+		.data		= &vm_hardmaplimit,
-+		.maxlen		= sizeof(int),
-+		.mode		= 0644,
-+		.proc_handler	= &proc_dointvec,
-+	},
-+	{
-+		.ctl_name	= CTL_UNNUMBERED,
-+		.procname	= "tail_largefiles",
-+		.data		= &vm_tail_largefiles,
-+		.maxlen		= sizeof(int),
-+		.mode		= 0644,
-+		.proc_handler	= &proc_dointvec,
-+	},
- #ifdef CONFIG_HUGETLB_PAGE
- 	 {
- 		.ctl_name	= VM_HUGETLB_PAGES,
-@@ -859,6 +924,16 @@ static ctl_table vm_table[] = {
- 		.extra1		= &zero,
- 	},
- #endif
-+#ifdef CONFIG_SWAP_PREFETCH
-+	{
-+		.ctl_name	= CTL_UNNUMBERED,
-+		.procname	= "swap_prefetch",
-+		.data		= &swap_prefetch,
-+		.maxlen		= sizeof(swap_prefetch),
-+		.mode		= 0644,
-+		.proc_handler	= &proc_dointvec,
-+	},
-+#endif
- 	{ .ctl_name = 0 }
- };
- 
-Index: linux-2.6.21-ck1/fs/pipe.c
-===================================================================
---- linux-2.6.21-ck1.orig/fs/pipe.c	2007-05-04 12:10:52.000000000 +1000
-+++ linux-2.6.21-ck1/fs/pipe.c	2007-05-04 12:10:54.000000000 +1000
-@@ -41,12 +41,7 @@ void pipe_wait(struct pipe_inode_info *p
- {
- 	DEFINE_WAIT(wait);
- 
--	/*
--	 * Pipes are system-local resources, so sleeping on them
--	 * is considered a noninteractive wait:
--	 */
--	prepare_to_wait(&pipe->wait, &wait,
--			TASK_INTERRUPTIBLE | TASK_NONINTERACTIVE);
-+	prepare_to_wait(&pipe->wait, &wait, TASK_INTERRUPTIBLE);
- 	if (pipe->inode)
- 		mutex_unlock(&pipe->inode->i_mutex);
- 	schedule();
-Index: linux-2.6.21-ck1/Documentation/sched-design.txt
-===================================================================
---- linux-2.6.21-ck1.orig/Documentation/sched-design.txt	2007-05-04 12:10:52.000000000 +1000
-+++ linux-2.6.21-ck1/Documentation/sched-design.txt	2007-05-04 12:10:54.000000000 +1000
-@@ -1,11 +1,14 @@
--		   Goals, Design and Implementation of the
--		      new ultra-scalable O(1) scheduler
-+ Goals, Design and Implementation of the ultra-scalable O(1) scheduler by
-+ Ingo Molnar and theStaircase Deadline cpu scheduler policy designed by
-+ Con Kolivas.
- 
- 
--  This is an edited version of an email Ingo Molnar sent to
--  lkml on 4 Jan 2002.  It describes the goals, design, and
--  implementation of Ingo's new ultra-scalable O(1) scheduler.
--  Last Updated: 18 April 2002.
-+  This was originally an edited version of an email Ingo Molnar sent to
-+  lkml on 4 Jan 2002.  It describes the goals, design, and implementation
-+  of Ingo's ultra-scalable O(1) scheduler. It now contains a description
-+  of the Staircase Deadline priority scheduler that was built on this
-+  design.
-+  Last Updated: Fri, 4 May 2007
- 
- 
- Goal
-@@ -163,3 +166,222 @@ certain code paths and data constructs. 
- code is smaller than the old one.
- 
- 	Ingo
-+
-+
-+Staircase Deadline cpu scheduler policy
-+================================================
-+
-+Design summary
-+==============
-+
-+A novel design which incorporates a foreground-background descending priority
-+system (the staircase) via a bandwidth allocation matrix according to nice
-+level.
-+
-+
-+Features
-+========
-+
-+A starvation free, strict fairness O(1) scalable design with interactivity
-+as good as the above restrictions can provide. There is no interactivity
-+estimator, no sleep/run measurements and only simple fixed accounting.
-+The design has strict enough a design and accounting that task behaviour
-+can be modelled and maximum scheduling latencies can be predicted by
-+the virtual deadline mechanism that manages runqueues. The prime concern
-+in this design is to maintain fairness at all costs determined by nice level,
-+yet to maintain as good interactivity as can be allowed within the
-+constraints of strict fairness.
-+
-+
-+Design description
-+==================
-+
-+SD works off the principle of providing each task a quota of runtime that it is
-+allowed to run at a number of priority levels determined by its static priority
-+(ie. its nice level). If the task uses up its quota it has its priority
-+decremented to the next level determined by a priority matrix. Once every
-+runtime quota has been consumed of every priority level, a task is queued on the
-+"expired" array. When no other tasks exist with quota, the expired array is
-+activated and fresh quotas are handed out. This is all done in O(1).
-+
-+Design details
-+==============
-+
-+Each task keeps a record of its own entitlement of cpu time. Most of the rest of
-+these details apply to non-realtime tasks as rt task management is straight
-+forward.
-+
-+Each runqueue keeps a record of what major epoch it is up to in the
-+rq->prio_rotation field which is incremented on each major epoch. It also
-+keeps a record of the current prio_level for each static priority task.
-+
-+Each task keeps a record of what major runqueue epoch it was last running
-+on in p->rotation. It also keeps a record of what priority levels it has
-+already been allocated quota from during this epoch in a bitmap p->bitmap.
-+
-+The only tunable that determines all other details is the RR_INTERVAL. This
-+is set to 8ms, and is scaled gently upwards with more cpus. This value is
-+tunable via a /proc interface.
-+
-+All tasks are initially given a quota based on RR_INTERVAL. This is equal to
-+RR_INTERVAL between nice values of -6 and 0, half that size above nice 0, and
-+progressively larger for nice values from -1 to -20. This is assigned to
-+p->quota and only changes with changes in nice level.
-+
-+As a task is first queued, it checks in recalc_task_prio to see if it has run at
-+this runqueue's current priority rotation. If it has not, it will have its
-+p->prio level set according to the first slot in a "priority matrix" and will be
-+given a p->time_slice equal to the p->quota, and has its allocation bitmap bit
-+set in p->bitmap for this prio level. It is then queued on the current active
-+priority array.
-+
-+If a task has already been running during this major epoch, and it has
-+p->time_slice left and the rq->prio_quota for the task's p->prio still
-+has quota, it will be placed back on the active array, but no more quota
-+will be added.
-+
-+If a task has been running during this major epoch, but does not have
-+p->time_slice left, it will find the next lowest priority in its bitmap that it
-+has not been allocated quota from. It then gets the a full quota in
-+p->time_slice. It is then queued on the current active priority array at the
-+newly determined lower priority.
-+
-+If a task has been running during this major epoch, and does not have
-+any entitlement left in p->bitmap and no time_slice left, it will have its
-+bitmap cleared, and be queued at its best prio again, but on the expired
-+priority array.
-+
-+When a task is queued, it has its relevant bit set in the array->prio_bitmap.
-+
-+p->time_slice is stored in nanosconds and is updated via update_cpu_clock on
-+schedule() and scheduler_tick. If p->time_slice is below zero then the
-+recalc_task_prio is readjusted and the task rescheduled.
-+
-+
-+Priority Matrix
-+===============
-+
-+In order to minimise the latencies between tasks of different nice levels
-+running concurrently, the dynamic priority slots where different nice levels
-+are queued are dithered instead of being sequential. What this means is that
-+there are 40 priority slots where a task may run during one major rotation,
-+and the allocation of slots is dependant on nice level. In the
-+following table, a zero represents a slot where the task may run.
-+
-+PRIORITY:0..................20.................39
-+nice -20 0000000000000000000000000000000000000000
-+nice -10 1000100010001000100010001000100010010000
-+nice   0 1010101010101010101010101010101010101010
-+nice   5 1011010110110101101101011011010110110110
-+nice  10 1110111011101110111011101110111011101110
-+nice  15 1111111011111110111111101111111011111110
-+nice  19 1111111111111111111111111111111111111110
-+
-+As can be seen, a nice -20 task runs in every priority slot whereas a nice 19
-+task only runs one slot per major rotation. This dithered table allows for the
-+smallest possible maximum latencies between tasks of varying nice levels, thus
-+allowing vastly different nice levels to be used.
-+
-+SCHED_BATCH tasks are managed slightly differently, receiving only the top
-+slots from its priority bitmap giving it equal cpu as SCHED_NORMAL, but
-+slightly higher latencies.
-+
-+
-+Modelling deadline behaviour
-+============================
-+
-+As the accounting in this design is hard and not modified by sleep average
-+calculations or interactivity modifiers, it is possible to accurately
-+predict the maximum latency that a task may experience under different
-+conditions. This is a virtual deadline mechanism enforced by mandatory
-+timeslice expiration and not outside bandwidth measurement.
-+
-+The maximum duration a task can run during one major epoch is determined by its
-+nice value. Nice 0 tasks can run at 19 different priority levels for RR_INTERVAL
-+duration during each epoch. Nice 10 tasks can run at 9 priority levels for each
-+epoch, and so on. The table in the priority matrix above demonstrates how this
-+is enforced.
-+
-+Therefore the maximum duration a runqueue epoch can take is determined by
-+the number of tasks running, and their nice level. After that, the maximum
-+duration it can take before a task can wait before it get scheduled is
-+determined by the position of its first slot on the matrix.
-+
-+In the following examples, these are _worst case scenarios_ and would rarely
-+occur, but can be modelled nonetheless to determine the maximum possible
-+latency.
-+
-+So for example, if two nice 0 tasks are running, and one has just expired as
-+another is activated for the first time receiving a full quota for this
-+runqueue rotation, the first task will wait:
-+
-+nr_tasks * max_duration + nice_difference * rr_interval
-+1 * 19 * RR_INTERVAL + 0 = 152ms
-+
-+In the presence of a nice 10 task, a nice 0 task would wait a maximum of
-+1 * 10 * RR_INTERVAL + 0 = 80ms
-+
-+In the presence of a nice 0 task, a nice 10 task would wait a maximum of
-+1 * 19 * RR_INTERVAL + 1 * RR_INTERVAL = 160ms
-+
-+More useful than these values, though, are the average latencies which are
-+a matter of determining the average distance between priority slots of
-+different nice values and multiplying them by the tasks' quota. For example
-+in the presence of a nice -10 task, a nice 0 task will wait either one or
-+two slots. Given that nice -10 tasks have a quota 2.5 times the RR_INTERVAL,
-+this means the latencies will alternate between 2.5 and 5 RR_INTERVALs or
-+20 and 40ms respectively (on uniprocessor at 1000HZ).
-+
-+
-+Achieving interactivity
-+=======================
-+
-+A requirement of this scheduler design was to achieve good interactivity
-+despite being a completely fair deadline based design. The disadvantage of
-+designs that try to achieve interactivity is that they usually do so at
-+the expense of maintaining fairness. As cpu speeds increase, the requirement
-+for some sort of metered unfairness towards interactive tasks becomes a less
-+desirable phenomenon, but low latency and fairness remains mandatory to
-+good interactive performance.
-+
-+This design relies on the fact that interactive tasks, by their nature,
-+sleep often. Most fair scheduling designs end up penalising such tasks
-+indirectly giving them less than their fair possible share because of the
-+sleep, and have to use a mechanism of bonusing their priority to offset
-+this based on the duration they sleep. This becomes increasingly inaccurate
-+as the number of running tasks rises and more tasks spend time waiting on
-+runqueues rather than sleeping, and it is impossible to tell whether the
-+task that's waiting on a runqueue only intends to run for a short period and
-+then sleep again after than runqueue wait. Furthermore, all such designs rely
-+on a period of time to pass to accumulate some form of statistic on the task
-+before deciding on how much to give them preference. The shorter this period,
-+the more rapidly bursts of cpu ruin the interactive tasks behaviour. The
-+longer this period, the longer it takes for interactive tasks to get low
-+scheduling latencies and fair cpu.
-+
-+This design does not measure sleep time at all. Interactive tasks that sleep
-+often will wake up having consumed very little if any of their quota for
-+the current major priority rotation. The longer they have slept, the less
-+likely they are to even be on the current major priority rotation. Once
-+woken up, though, they get to use up a their full quota for that epoch,
-+whether part of a quota remains or a full quota. Overall, however, they
-+can still only run as much cpu time for that epoch as any other task of the
-+same nice level. This means that two tasks behaving completely differently
-+from fully cpu bound to waking/sleeping extremely frequently will still
-+get the same quota of cpu, but the latter will be using its quota for that
-+epoch in bursts rather than continuously. This guarantees that interactive
-+tasks get the same amount of cpu as cpu bound ones.
-+
-+The other requirement of interactive tasks is also to obtain low latencies
-+for when they are scheduled. Unlike fully cpu bound tasks and the maximum
-+latencies possible described in the modelling deadline behaviour section
-+above, tasks that sleep will wake up with quota available usually at the
-+current runqueue's priority_level or better. This means that the most latency
-+they are likely to see is one RR_INTERVAL, and often they will preempt the
-+current task if it is not of a sleeping nature. This then guarantees very
-+low latency for interactive tasks, and the lowest latencies for the least
-+cpu bound tasks.
-+
-+
-+Fri, 4 May 2007
-+Con Kolivas <kernel@kolivas.org>
-Index: linux-2.6.21-ck1/kernel/softirq.c
-===================================================================
---- linux-2.6.21-ck1.orig/kernel/softirq.c	2007-05-04 12:10:52.000000000 +1000
-+++ linux-2.6.21-ck1/kernel/softirq.c	2007-05-04 12:10:54.000000000 +1000
-@@ -488,7 +488,7 @@ void __init softirq_init(void)
- 
- static int ksoftirqd(void * __bind_cpu)
- {
--	set_user_nice(current, 19);
-+	set_user_nice(current, 15);
- 	current->flags |= PF_NOFREEZE;
- 
- 	set_current_state(TASK_INTERRUPTIBLE);
-Index: linux-2.6.21-ck1/kernel/fork.c
-===================================================================
---- linux-2.6.21-ck1.orig/kernel/fork.c	2007-05-04 12:24:01.000000000 +1000
-+++ linux-2.6.21-ck1/kernel/fork.c	2007-05-04 12:24:19.000000000 +1000
-@@ -1060,6 +1060,7 @@ static struct task_struct *copy_process(
- 	p->io_context = NULL;
- 	p->io_wait = NULL;
- 	p->audit_context = NULL;
-+	p->mutexes_held = 0;
- 	cpuset_fork(p);
- #ifdef CONFIG_NUMA
-  	p->mempolicy = mpol_copy(p->mempolicy);
-Index: linux-2.6.21-ck1/kernel/mutex.c
-===================================================================
---- linux-2.6.21-ck1.orig/kernel/mutex.c	2007-05-04 12:24:01.000000000 +1000
-+++ linux-2.6.21-ck1/kernel/mutex.c	2007-05-04 12:24:19.000000000 +1000
-@@ -60,6 +60,16 @@ EXPORT_SYMBOL(__mutex_init);
- static void fastcall noinline __sched
- __mutex_lock_slowpath(atomic_t *lock_count);
- 
-+static inline void inc_mutex_count(void)
-+{
-+	current->mutexes_held++;
-+}
-+
-+static inline void dec_mutex_count(void)
-+{
-+	current->mutexes_held--;
-+}
-+
- /***
-  * mutex_lock - acquire the mutex
-  * @lock: the mutex to be acquired
-@@ -89,6 +99,7 @@ void inline fastcall __sched mutex_lock(
- 	 * 'unlocked' into 'locked' state.
- 	 */
- 	__mutex_fastpath_lock(&lock->count, __mutex_lock_slowpath);
-+	inc_mutex_count();
- }
- 
- EXPORT_SYMBOL(mutex_lock);
-@@ -114,6 +125,7 @@ void fastcall __sched mutex_unlock(struc
- 	 * into 'unlocked' state:
- 	 */
- 	__mutex_fastpath_unlock(&lock->count, __mutex_unlock_slowpath);
-+	dec_mutex_count();
- }
- 
- EXPORT_SYMBOL(mutex_unlock);
-@@ -283,9 +295,14 @@ __mutex_lock_interruptible_slowpath(atom
-  */
- int fastcall __sched mutex_lock_interruptible(struct mutex *lock)
- {
-+	int ret;
-+
- 	might_sleep();
--	return __mutex_fastpath_lock_retval
-+	ret = __mutex_fastpath_lock_retval
- 			(&lock->count, __mutex_lock_interruptible_slowpath);
-+	if (likely(!ret))
-+		inc_mutex_count();
-+	return ret;
- }
- 
- EXPORT_SYMBOL(mutex_lock_interruptible);
-@@ -340,8 +357,12 @@ static inline int __mutex_trylock_slowpa
-  */
- int fastcall __sched mutex_trylock(struct mutex *lock)
- {
--	return __mutex_fastpath_trylock(&lock->count,
-+	int ret = __mutex_fastpath_trylock(&lock->count,
- 					__mutex_trylock_slowpath);
-+
-+	if (likely(ret))
-+		inc_mutex_count();
-+	return ret;
- }
- 
- EXPORT_SYMBOL(mutex_trylock);
-Index: linux-2.6.21-ck1/block/cfq-iosched.c
-===================================================================
---- linux-2.6.21-ck1.orig/block/cfq-iosched.c	2007-05-04 12:24:01.000000000 +1000
-+++ linux-2.6.21-ck1/block/cfq-iosched.c	2007-05-04 12:24:19.000000000 +1000
-@@ -1258,10 +1258,12 @@ static void cfq_init_prio_data(struct cf
- 			printk(KERN_ERR "cfq: bad prio %x\n", ioprio_class);
- 		case IOPRIO_CLASS_NONE:
- 			/*
--			 * no prio set, place us in the middle of the BE classes
-+			 * Select class and ioprio according to policy and nice
- 			 */
-+			cfqq->ioprio_class = task_policy_ioprio_class(tsk);
- 			cfqq->ioprio = task_nice_ioprio(tsk);
--			cfqq->ioprio_class = IOPRIO_CLASS_BE;
-+			if (cfqq->ioprio_class == IOPRIO_CLASS_IDLE)
-+				cfq_clear_cfqq_idle_window(cfqq);
- 			break;
- 		case IOPRIO_CLASS_RT:
- 			cfqq->ioprio = task_ioprio(tsk);
-Index: linux-2.6.21-ck1/include/linux/ioprio.h
-===================================================================
---- linux-2.6.21-ck1.orig/include/linux/ioprio.h	2007-05-04 12:24:01.000000000 +1000
-+++ linux-2.6.21-ck1/include/linux/ioprio.h	2007-05-04 12:24:19.000000000 +1000
-@@ -22,7 +22,7 @@
-  * class, the default for any process. IDLE is the idle scheduling class, it
-  * is only served when no one else is using the disk.
-  */
--enum {
-+enum ioprio_class {
- 	IOPRIO_CLASS_NONE,
- 	IOPRIO_CLASS_RT,
- 	IOPRIO_CLASS_BE,
-@@ -51,8 +51,25 @@ static inline int task_ioprio(struct tas
- 	return IOPRIO_PRIO_DATA(task->ioprio);
- }
- 
-+static inline enum ioprio_class
-+	task_policy_ioprio_class(struct task_struct *task)
-+{
-+	if (rt_task(task))
-+		return IOPRIO_CLASS_RT;
-+	if (idleprio_task(task))
-+		return IOPRIO_CLASS_IDLE;
-+	return IOPRIO_CLASS_BE;
-+}
-+
- static inline int task_nice_ioprio(struct task_struct *task)
- {
-+	if (rt_task(task))
-+		return (MAX_RT_PRIO - task->rt_priority) * IOPRIO_BE_NR /
-+			(MAX_RT_PRIO + 1);
-+	if (iso_task(task))
-+		return 0;
-+	if (idleprio_task(task))
-+		return IOPRIO_BE_NR - 1;
- 	return (task_nice(task) + 20) / 5;
- }
- 
-Index: linux-2.6.21-ck1/Documentation/sysctl/vm.txt
-===================================================================
---- linux-2.6.21-ck1.orig/Documentation/sysctl/vm.txt	2007-05-04 12:24:01.000000000 +1000
-+++ linux-2.6.21-ck1/Documentation/sysctl/vm.txt	2007-05-04 12:24:21.000000000 +1000
-@@ -22,6 +22,8 @@ Currently, these files are in /proc/sys/
- - dirty_background_ratio
- - dirty_expire_centisecs
- - dirty_writeback_centisecs
-+- hardmaplimit
-+- mapped
- - max_map_count
- - min_free_kbytes
- - laptop_mode
-@@ -31,12 +33,13 @@ Currently, these files are in /proc/sys/
- - min_unmapped_ratio
- - min_slab_ratio
- - panic_on_oom
-+- swap_prefetch
- 
- ==============================================================
- 
- dirty_ratio, dirty_background_ratio, dirty_expire_centisecs,
- dirty_writeback_centisecs, vfs_cache_pressure, laptop_mode,
--block_dump, swap_token_timeout, drop-caches:
-+block_dump, swap_token_timeout, drop-caches, tail_largefiles:
- 
- See Documentation/filesystems/proc.txt
- 
-@@ -86,6 +89,27 @@ for swap because we only cluster swap da
- 
- ==============================================================
- 
-+hardmaplimit:
-+
-+This flag makes the vm adhere to the mapped value as closely as possible
-+except in the most extreme vm stress where doing so would provoke an out
-+of memory condition (see mapped below).
-+
-+Enabled by default.
-+
-+==============================================================
-+
-+mapped:
-+
-+This is the percentage ram that is filled with mapped pages (applications)
-+before the vm will start reclaiming mapped pages by moving them to swap.
-+It is altered by the relative stress of the vm at the time so is not
-+strictly adhered to to prevent provoking out of memory kills.
-+
-+Set to 66 by default.
-+
-+==============================================================
-+
- max_map_count:
- 
- This file contains the maximum number of memory map areas a process
-@@ -205,3 +229,14 @@ rather than killing rogue processes, set
- 
- The default value is 0.
- 
-+==============================================================
-+
-+swap_prefetch
-+
-+This enables or disables the swap prefetching feature. When the virtual
-+memory subsystem has been extremely idle for at least 5 seconds it will start
-+copying back pages from swap into the swapcache and keep a copy in swap. In
-+practice it can take many minutes before the vm is idle enough.
-+
-+The default value is 1.
-+
-Index: linux-2.6.21-ck1/include/linux/swap.h
-===================================================================
---- linux-2.6.21-ck1.orig/include/linux/swap.h	2007-05-04 12:24:01.000000000 +1000
-+++ linux-2.6.21-ck1/include/linux/swap.h	2007-05-04 12:24:20.000000000 +1000
-@@ -180,6 +180,7 @@ extern unsigned int nr_free_pagecache_pa
- /* linux/mm/swap.c */
- extern void FASTCALL(lru_cache_add(struct page *));
- extern void FASTCALL(lru_cache_add_active(struct page *));
-+extern void FASTCALL(lru_cache_add_tail(struct page *));
- extern void FASTCALL(activate_page(struct page *));
- extern void FASTCALL(mark_page_accessed(struct page *));
- extern void lru_add_drain(void);
-@@ -188,9 +189,11 @@ extern int rotate_reclaimable_page(struc
- extern void swap_setup(void);
- 
- /* linux/mm/vmscan.c */
--extern unsigned long try_to_free_pages(struct zone **, gfp_t);
-+extern unsigned long try_to_free_pages(struct zone **, gfp_t,
-+				       struct task_struct *p);
- extern unsigned long shrink_all_memory(unsigned long nr_pages);
--extern int vm_swappiness;
-+extern int vm_mapped;
-+extern int vm_hardmaplimit;
- extern int remove_mapping(struct address_space *mapping, struct page *page);
- extern long vm_total_pages;
- 
-@@ -237,6 +240,7 @@ extern void free_pages_and_swap_cache(st
- extern struct page * lookup_swap_cache(swp_entry_t);
- extern struct page * read_swap_cache_async(swp_entry_t, struct vm_area_struct *vma,
- 					   unsigned long addr);
-+extern int add_to_swap_cache(struct page *page, swp_entry_t entry);
- /* linux/mm/swapfile.c */
- extern long total_swap_pages;
- extern unsigned int nr_swapfiles;
-Index: linux-2.6.21-ck1/init/Kconfig
-===================================================================
---- linux-2.6.21-ck1.orig/init/Kconfig	2007-05-04 12:24:01.000000000 +1000
-+++ linux-2.6.21-ck1/init/Kconfig	2007-05-04 12:24:20.000000000 +1000
-@@ -101,6 +101,28 @@ config SWAP
- 	  used to provide more virtual memory than the actual RAM present
- 	  in your computer.  If unsure say Y.
- 
-+config SWAP_PREFETCH
-+	bool "Support for prefetching swapped memory"
-+	depends on SWAP
-+	default y
-+	---help---
-+	  This option will allow the kernel to prefetch swapped memory pages
-+	  when idle. The pages will be kept on both swap and in swap_cache
-+	  thus avoiding the need for further I/O if either ram or swap space
-+	  is required.
-+
-+	  What this will do on workstations is slowly bring back applications
-+	  that have swapped out after memory intensive workloads back into
-+	  physical ram if you have free ram at a later stage and the machine
-+	  is relatively idle. This means that when you come back to your
-+	  computer after leaving it idle for a while, applications will come
-+	  to life faster. Note that your swap usage will appear to increase
-+	  but these are cached pages, can be dropped freely by the vm, and it
-+	  should stabilise around 50% swap usage maximum.
-+
-+	  Workstations and multiuser workstation servers will most likely want
-+	  to say Y.
-+
- config SYSVIPC
- 	bool "System V IPC"
- 	---help---
-Index: linux-2.6.21-ck1/mm/Makefile
-===================================================================
---- linux-2.6.21-ck1.orig/mm/Makefile	2007-05-04 12:24:01.000000000 +1000
-+++ linux-2.6.21-ck1/mm/Makefile	2007-05-04 12:24:20.000000000 +1000
-@@ -17,6 +17,7 @@ ifeq ($(CONFIG_MMU)$(CONFIG_BLOCK),yy)
- obj-y			+= bounce.o
- endif
- obj-$(CONFIG_SWAP)	+= page_io.o swap_state.o swapfile.o thrash.o
-+obj-$(CONFIG_SWAP_PREFETCH) += swap_prefetch.o
- obj-$(CONFIG_HUGETLBFS)	+= hugetlb.o
- obj-$(CONFIG_NUMA) 	+= mempolicy.o
- obj-$(CONFIG_SPARSEMEM)	+= sparse.o
-Index: linux-2.6.21-ck1/mm/swap.c
-===================================================================
---- linux-2.6.21-ck1.orig/mm/swap.c	2007-05-04 12:24:01.000000000 +1000
-+++ linux-2.6.21-ck1/mm/swap.c	2007-05-04 12:24:21.000000000 +1000
-@@ -17,6 +17,7 @@
- #include <linux/sched.h>
- #include <linux/kernel_stat.h>
- #include <linux/swap.h>
-+#include <linux/swap-prefetch.h>
- #include <linux/mman.h>
- #include <linux/pagemap.h>
- #include <linux/pagevec.h>
-@@ -176,6 +177,7 @@ EXPORT_SYMBOL(mark_page_accessed);
-  */
- static DEFINE_PER_CPU(struct pagevec, lru_add_pvecs) = { 0, };
- static DEFINE_PER_CPU(struct pagevec, lru_add_active_pvecs) = { 0, };
-+static DEFINE_PER_CPU(struct pagevec, lru_add_tail_pvecs) = { 0, };
- 
- void fastcall lru_cache_add(struct page *page)
- {
-@@ -197,6 +199,31 @@ void fastcall lru_cache_add_active(struc
- 	put_cpu_var(lru_add_active_pvecs);
- }
- 
-+static void __pagevec_lru_add_tail(struct pagevec *pvec)
-+{
-+	int i;
-+	struct zone *zone = NULL;
-+
-+	for (i = 0; i < pagevec_count(pvec); i++) {
-+		struct page *page = pvec->pages[i];
-+		struct zone *pagezone = page_zone(page);
-+
-+		if (pagezone != zone) {
-+			if (zone)
-+				spin_unlock_irq(&zone->lru_lock);
-+			zone = pagezone;
-+			spin_lock_irq(&zone->lru_lock);
-+		}
-+		BUG_ON(PageLRU(page));
-+		SetPageLRU(page);
-+		add_page_to_inactive_list_tail(zone, page);
-+	}
-+	if (zone)
-+		spin_unlock_irq(&zone->lru_lock);
-+	release_pages(pvec->pages, pvec->nr, pvec->cold);
-+	pagevec_reinit(pvec);
-+}
-+
- static void __lru_add_drain(int cpu)
- {
- 	struct pagevec *pvec = &per_cpu(lru_add_pvecs, cpu);
-@@ -207,6 +234,9 @@ static void __lru_add_drain(int cpu)
- 	pvec = &per_cpu(lru_add_active_pvecs, cpu);
- 	if (pagevec_count(pvec))
- 		__pagevec_lru_add_active(pvec);
-+	pvec = &per_cpu(lru_add_tail_pvecs, cpu);
-+	if (pagevec_count(pvec))
-+		__pagevec_lru_add_tail(pvec);
- }
- 
- void lru_add_drain(void)
-@@ -403,6 +433,20 @@ void __pagevec_lru_add_active(struct pag
- }
- 
- /*
-+ * Function used uniquely to put pages back to the lru at the end of the
-+ * inactive list to preserve the lru order.
-+ */
-+void fastcall lru_cache_add_tail(struct page *page)
-+{
-+	struct pagevec *pvec = &get_cpu_var(lru_add_tail_pvecs);
-+
-+	page_cache_get(page);
-+	if (!pagevec_add(pvec, page))
-+		__pagevec_lru_add_tail(pvec);
-+	put_cpu_var(lru_add_pvecs);
-+}
-+
-+/*
-  * Try to drop buffers from the pages in a pagevec
-  */
- void pagevec_strip(struct pagevec *pvec)
-@@ -514,6 +558,9 @@ void __init swap_setup(void)
- 	 * Right now other parts of the system means that we
- 	 * _really_ don't want to cluster much more
- 	 */
-+
-+	prepare_swap_prefetch();
-+
- #ifdef CONFIG_HOTPLUG_CPU
- 	hotcpu_notifier(cpu_swap_callback, 0);
- #endif
-Index: linux-2.6.21-ck1/mm/swap_prefetch.c
-===================================================================
---- /dev/null	1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.21-ck1/mm/swap_prefetch.c	2007-05-04 12:24:20.000000000 +1000
-@@ -0,0 +1,581 @@
-+/*
-+ * linux/mm/swap_prefetch.c
-+ *
-+ * Copyright (C) 2005-2006 Con Kolivas
-+ *
-+ * Written by Con Kolivas <kernel@kolivas.org>
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#include <linux/fs.h>
-+#include <linux/mm.h>
-+#include <linux/swap.h>
-+#include <linux/swap-prefetch.h>
-+#include <linux/ioprio.h>
-+#include <linux/kthread.h>
-+#include <linux/pagemap.h>
-+#include <linux/syscalls.h>
-+#include <linux/writeback.h>
-+#include <linux/vmstat.h>
-+#include <linux/freezer.h>
-+
-+/*
-+ * Time to delay prefetching if vm is busy or prefetching unsuccessful. There
-+ * needs to be at least this duration of idle time meaning in practice it can
-+ * be much longer
-+ */
-+#define PREFETCH_DELAY	(HZ * 5)
-+
-+/* sysctl - enable/disable swap prefetching */
-+int swap_prefetch __read_mostly = 1;
-+
-+struct swapped_root {
-+	unsigned long		busy;		/* vm busy */
-+	spinlock_t		lock;		/* protects all data */
-+	struct list_head	list;		/* MRU list of swapped pages */
-+	struct radix_tree_root	swap_tree;	/* Lookup tree of pages */
-+	unsigned int		count;		/* Number of entries */
-+	unsigned int		maxcount;	/* Maximum entries allowed */
-+	struct kmem_cache	*cache;		/* Of struct swapped_entry */
-+};
-+
-+static struct swapped_root swapped = {
-+	.lock		= SPIN_LOCK_UNLOCKED,
-+	.list  		= LIST_HEAD_INIT(swapped.list),
-+	.swap_tree	= RADIX_TREE_INIT(GFP_ATOMIC),
-+};
-+
-+static struct task_struct *kprefetchd_task;
-+
-+/*
-+ * We check to see no part of the vm is busy. If it is this will interrupt
-+ * trickle_swap and wait another PREFETCH_DELAY. Purposefully racy.
-+ */
-+inline void delay_swap_prefetch(void)
-+{
-+	if (!test_bit(0, &swapped.busy))
-+		__set_bit(0, &swapped.busy);
-+}
-+
-+/*
-+ * Drop behind accounting which keeps a list of the most recently used swap
-+ * entries.
-+ */
-+void add_to_swapped_list(struct page *page)
-+{
-+	struct swapped_entry *entry;
-+	unsigned long index, flags;
-+	int wakeup;
-+
-+	if (!swap_prefetch)
-+		return;
-+
-+	wakeup = 0;
-+
-+	spin_lock_irqsave(&swapped.lock, flags);
-+	if (swapped.count >= swapped.maxcount) {
-+		/*
-+		 * We limit the number of entries to 2/3 of physical ram.
-+		 * Once the number of entries exceeds this we start removing
-+		 * the least recently used entries.
-+		 */
-+		entry = list_entry(swapped.list.next,
-+			struct swapped_entry, swapped_list);
-+		radix_tree_delete(&swapped.swap_tree, entry->swp_entry.val);
-+		list_del(&entry->swapped_list);
-+		swapped.count--;
-+	} else {
-+		entry = kmem_cache_alloc(swapped.cache, GFP_ATOMIC);
-+		if (unlikely(!entry))
-+			/* bad, can't allocate more mem */
-+			goto out_locked;
-+	}
-+
-+	index = page_private(page);
-+	entry->swp_entry.val = index;
-+	/*
-+	 * On numa we need to store the node id to ensure that we prefetch to
-+	 * the same node it came from.
-+	 */
-+	store_swap_entry_node(entry, page);
-+
-+	if (likely(!radix_tree_insert(&swapped.swap_tree, index, entry))) {
-+		/*
-+		 * If this is the first entry, kprefetchd needs to be
-+		 * (re)started.
-+		 */
-+		if (!swapped.count)
-+			wakeup = 1;
-+		list_add(&entry->swapped_list, &swapped.list);
-+		swapped.count++;
-+	}
-+
-+out_locked:
-+	spin_unlock_irqrestore(&swapped.lock, flags);
-+
-+	/* Do the wakeup outside the lock to shorten lock hold time. */
-+	if (wakeup)
-+		wake_up_process(kprefetchd_task);
-+
-+	return;
-+}
-+
-+/*
-+ * Removes entries from the swapped_list. The radix tree allows us to quickly
-+ * look up the entry from the index without having to iterate over the whole
-+ * list.
-+ */
-+void remove_from_swapped_list(const unsigned long index)
-+{
-+	struct swapped_entry *entry;
-+	unsigned long flags;
-+
-+	if (list_empty(&swapped.list))
-+		return;
-+
-+	spin_lock_irqsave(&swapped.lock, flags);
-+	entry = radix_tree_delete(&swapped.swap_tree, index);
-+	if (likely(entry)) {
-+		list_del_init(&entry->swapped_list);
-+		swapped.count--;
-+		kmem_cache_free(swapped.cache, entry);
-+	}
-+	spin_unlock_irqrestore(&swapped.lock, flags);
-+}
-+
-+enum trickle_return {
-+	TRICKLE_SUCCESS,
-+	TRICKLE_FAILED,
-+	TRICKLE_DELAY,
-+};
-+
-+struct node_stats {
-+	unsigned long	last_free;
-+	/* Free ram after a cycle of prefetching */
-+	unsigned long	current_free;
-+	/* Free ram on this cycle of checking prefetch_suitable */
-+	unsigned long	prefetch_watermark;
-+	/* Maximum amount we will prefetch to */
-+	unsigned long	highfree[MAX_NR_ZONES];
-+	/* The amount of free ram before we start prefetching */
-+	unsigned long	lowfree[MAX_NR_ZONES];
-+	/* The amount of free ram where we will stop prefetching */
-+	unsigned long	*pointfree[MAX_NR_ZONES];
-+	/* highfree or lowfree depending on whether we've hit a watermark */
-+};
-+
-+/*
-+ * prefetch_stats stores the free ram data of each node and this is used to
-+ * determine if a node is suitable for prefetching into.
-+ */
-+struct prefetch_stats {
-+	nodemask_t	prefetch_nodes;
-+	/* Which nodes are currently suited to prefetching */
-+	unsigned long	prefetched_pages;
-+	/* Total pages we've prefetched on this wakeup of kprefetchd */
-+	struct node_stats node[MAX_NUMNODES];
-+};
-+
-+static struct prefetch_stats sp_stat;
-+
-+/*
-+ * This tries to read a swp_entry_t into swap cache for swap prefetching.
-+ * If it returns TRICKLE_DELAY we should delay further prefetching.
-+ */
-+static enum trickle_return trickle_swap_cache_async(const swp_entry_t entry,
-+	const int node)
-+{
-+	enum trickle_return ret = TRICKLE_FAILED;
-+	struct page *page;
-+
-+	read_lock_irq(&swapper_space.tree_lock);
-+	/* Entry may already exist */
-+	page = radix_tree_lookup(&swapper_space.page_tree, entry.val);
-+	read_unlock_irq(&swapper_space.tree_lock);
-+	if (page) {
-+		remove_from_swapped_list(entry.val);
-+		goto out;
-+	}
-+
-+	/*
-+	 * Get a new page to read from swap. We have already checked the
-+	 * watermarks so __alloc_pages will not call on reclaim.
-+	 */
-+	page = alloc_pages_node(node, GFP_HIGHUSER & ~__GFP_WAIT, 0);
-+	if (unlikely(!page)) {
-+		ret = TRICKLE_DELAY;
-+		goto out;
-+	}
-+
-+	if (add_to_swap_cache(page, entry)) {
-+		/* Failed to add to swap cache */
-+		goto out_release;
-+	}
-+
-+	/* Add them to the tail of the inactive list to preserve LRU order */
-+	lru_cache_add_tail(page);
-+	if (unlikely(swap_readpage(NULL, page))) {
-+		ret = TRICKLE_DELAY;
-+		goto out_release;
-+	}
-+
-+	sp_stat.prefetched_pages++;
-+	sp_stat.node[node].last_free--;
-+
-+	ret = TRICKLE_SUCCESS;
-+out_release:
-+	page_cache_release(page);
-+out:
-+	return ret;
-+}
-+
-+static void clear_last_prefetch_free(void)
-+{
-+	int node;
-+
-+	/*
-+	 * Reset the nodes suitable for prefetching to all nodes. We could
-+	 * update the data to take into account memory hotplug if desired..
-+	 */
-+	sp_stat.prefetch_nodes = node_online_map;
-+	for_each_node_mask(node, sp_stat.prefetch_nodes) {
-+		struct node_stats *ns = &sp_stat.node[node];
-+
-+		ns->last_free = 0;
-+	}
-+}
-+
-+static void clear_current_prefetch_free(void)
-+{
-+	int node;
-+
-+	sp_stat.prefetch_nodes = node_online_map;
-+	for_each_node_mask(node, sp_stat.prefetch_nodes) {
-+		struct node_stats *ns = &sp_stat.node[node];
-+
-+		ns->current_free = 0;
-+	}
-+}
-+
-+/*
-+ * This updates the high and low watermarks of amount of free ram in each
-+ * node used to start and stop prefetching. We prefetch from pages_high * 4
-+ * down to pages_high * 3.
-+ */
-+static void examine_free_limits(void)
-+{
-+	struct zone *z;
-+
-+	for_each_zone(z) {
-+		struct node_stats *ns;
-+		int idx;
-+
-+		if (!populated_zone(z))
-+			continue;
-+
-+		ns = &sp_stat.node[z->zone_pgdat->node_id];
-+		idx = zone_idx(z);
-+		ns->lowfree[idx] = z->pages_high * 3;
-+		ns->highfree[idx] = ns->lowfree[idx] + z->pages_high;
-+
-+		if (zone_page_state(z, NR_FREE_PAGES) > ns->highfree[idx]) {
-+			/*
-+			 * We've gotten above the high watermark of free pages
-+			 * so we can start prefetching till we get to the low
-+			 * watermark.
-+			 */
-+			ns->pointfree[idx] = &ns->lowfree[idx];
-+		}
-+	}
-+}
-+
-+/*
-+ * We want to be absolutely certain it's ok to start prefetching.
-+ */
-+static int prefetch_suitable(void)
-+{
-+	unsigned long limit;
-+	struct zone *z;
-+	int node, ret = 0, test_pagestate = 0;
-+
-+	/* Purposefully racy */
-+	if (test_bit(0, &swapped.busy)) {
-+		__clear_bit(0, &swapped.busy);
-+		goto out;
-+	}
-+
-+	/*
-+	 * get_page_state and above_background_load are expensive so we only
-+	 * perform them every SWAP_CLUSTER_MAX prefetched_pages.
-+	 * We test to see if we're above_background_load as disk activity
-+	 * even at low priority can cause interrupt induced scheduling
-+	 * latencies.
-+	 */
-+	if (!(sp_stat.prefetched_pages % SWAP_CLUSTER_MAX)) {
-+		if (above_background_load())
-+			goto out;
-+		test_pagestate = 1;
-+	}
-+
-+	clear_current_prefetch_free();
-+
-+	/*
-+	 * Have some hysteresis between where page reclaiming and prefetching
-+	 * will occur to prevent ping-ponging between them.
-+	 */
-+	for_each_zone(z) {
-+		struct node_stats *ns;
-+		unsigned long free;
-+		int idx;
-+
-+		if (!populated_zone(z))
-+			continue;
-+
-+		node = z->zone_pgdat->node_id;
-+		ns = &sp_stat.node[node];
-+		idx = zone_idx(z);
-+
-+		free = zone_page_state(z, NR_FREE_PAGES);
-+		if (free < *ns->pointfree[idx]) {
-+			/*
-+			 * Free pages have dropped below the low watermark so
-+			 * we won't start prefetching again till we hit the
-+			 * high watermark of free pages.
-+			 */
-+			ns->pointfree[idx] = &ns->highfree[idx];
-+			node_clear(node, sp_stat.prefetch_nodes);
-+			continue;
-+		}
-+		ns->current_free += free;
-+	}
-+
-+	/*
-+	 * We iterate over each node testing to see if it is suitable for
-+	 * prefetching and clear the nodemask if it is not.
-+	 */
-+	for_each_node_mask(node, sp_stat.prefetch_nodes) {
-+		struct node_stats *ns = &sp_stat.node[node];
-+
-+		/*
-+		 * We check to see that pages are not being allocated
-+		 * elsewhere at any significant rate implying any
-+		 * degree of memory pressure (eg during file reads)
-+		 */
-+		if (ns->last_free) {
-+			if (ns->current_free + SWAP_CLUSTER_MAX <
-+			    ns->last_free) {
-+				ns->last_free = ns->current_free;
-+				node_clear(node,
-+					sp_stat.prefetch_nodes);
-+				continue;
-+			}
-+		} else
-+			ns->last_free = ns->current_free;
-+
-+		if (!test_pagestate)
-+			continue;
-+
-+		/* We shouldn't prefetch when we are doing writeback */
-+		if (node_page_state(node, NR_WRITEBACK)) {
-+			node_clear(node, sp_stat.prefetch_nodes);
-+			continue;
-+		}
-+
-+		/*
-+		 * >2/3 of the ram on this node is mapped, slab, swapcache or
-+		 * dirty, we need to leave some free for pagecache.
-+		 */
-+		limit = node_page_state(node, NR_FILE_PAGES);
-+		limit += node_page_state(node, NR_SLAB_RECLAIMABLE);
-+		limit += node_page_state(node, NR_SLAB_UNRECLAIMABLE);
-+		limit += node_page_state(node, NR_FILE_DIRTY);
-+		limit += node_page_state(node, NR_UNSTABLE_NFS);
-+		limit += total_swapcache_pages;
-+		if (limit > ns->prefetch_watermark) {
-+			node_clear(node, sp_stat.prefetch_nodes);
-+			continue;
-+		}
-+	}
-+
-+	if (nodes_empty(sp_stat.prefetch_nodes))
-+		goto out;
-+
-+	/* Survived all that? Hooray we can prefetch! */
-+	ret = 1;
-+out:
-+	return ret;
-+}
-+
-+/*
-+ * Get previous swapped entry when iterating over all entries. swapped.lock
-+ * should be held and we should already ensure that entry exists.
-+ */
-+static inline struct swapped_entry *prev_swapped_entry
-+	(struct swapped_entry *entry)
-+{
-+	return list_entry(entry->swapped_list.prev->prev,
-+		struct swapped_entry, swapped_list);
-+}
-+
-+/*
-+ * trickle_swap is the main function that initiates the swap prefetching. It
-+ * first checks to see if the busy flag is set, and does not prefetch if it
-+ * is, as the flag implied we are low on memory or swapping in currently.
-+ * Otherwise it runs until prefetch_suitable fails which occurs when the
-+ * vm is busy, we prefetch to the watermark, or the list is empty or we have
-+ * iterated over all entries
-+ */
-+static enum trickle_return trickle_swap(void)
-+{
-+	enum trickle_return ret = TRICKLE_DELAY;
-+	struct swapped_entry *entry;
-+	unsigned long flags;
-+
-+	/*
-+	 * If laptop_mode is enabled don't prefetch to avoid hard drives
-+	 * doing unnecessary spin-ups
-+	 */
-+	if (!swap_prefetch || laptop_mode)
-+		return ret;
-+
-+	examine_free_limits();
-+	entry = NULL;
-+
-+	for ( ; ; ) {
-+		swp_entry_t swp_entry;
-+		int node;
-+
-+		if (!prefetch_suitable())
-+			break;
-+
-+		spin_lock_irqsave(&swapped.lock, flags);
-+		if (list_empty(&swapped.list)) {
-+			ret = TRICKLE_FAILED;
-+			spin_unlock_irqrestore(&swapped.lock, flags);
-+			break;
-+		}
-+
-+		if (!entry) {
-+			/*
-+			 * This sets the entry for the first iteration. It
-+			 * also is a safeguard against the entry disappearing
-+			 * while the lock is not held.
-+			 */
-+			entry = list_entry(swapped.list.prev,
-+				struct swapped_entry, swapped_list);
-+		} else if (entry->swapped_list.prev == swapped.list.next) {
-+			/*
-+			 * If we have iterated over all entries and there are
-+			 * still entries that weren't swapped out there may
-+			 * be a reason we could not swap them back in so
-+			 * delay attempting further prefetching.
-+			 */
-+			spin_unlock_irqrestore(&swapped.lock, flags);
-+			break;
-+		}
-+
-+		node = get_swap_entry_node(entry);
-+		if (!node_isset(node, sp_stat.prefetch_nodes)) {
-+			/*
-+			 * We found an entry that belongs to a node that is
-+			 * not suitable for prefetching so skip it.
-+			 */
-+			entry = prev_swapped_entry(entry);
-+			spin_unlock_irqrestore(&swapped.lock, flags);
-+			continue;
-+		}
-+		swp_entry = entry->swp_entry;
-+		entry = prev_swapped_entry(entry);
-+		spin_unlock_irqrestore(&swapped.lock, flags);
-+
-+		if (trickle_swap_cache_async(swp_entry, node) == TRICKLE_DELAY)
-+			break;
-+	}
-+
-+	if (sp_stat.prefetched_pages) {
-+		lru_add_drain();
-+		sp_stat.prefetched_pages = 0;
-+	}
-+	return ret;
-+}
-+
-+static int kprefetchd(void *__unused)
-+{
-+	struct sched_param param = { .sched_priority = 0 };
-+
-+	sched_setscheduler(current, SCHED_BATCH, &param);
-+	set_user_nice(current, 19);
-+	/* Set ioprio to lowest if supported by i/o scheduler */
-+	sys_ioprio_set(IOPRIO_WHO_PROCESS, 0, IOPRIO_CLASS_IDLE);
-+
-+	/* kprefetchd has nothing to do until it is woken up the first time */
-+	set_current_state(TASK_INTERRUPTIBLE);
-+	schedule();
-+
-+	do {
-+		try_to_freeze();
-+
-+		/*
-+		 * TRICKLE_FAILED implies no entries left - we do not schedule
-+		 * a wakeup, and further delay the next one.
-+		 */
-+		if (trickle_swap() == TRICKLE_FAILED) {
-+			set_current_state(TASK_INTERRUPTIBLE);
-+			schedule();
-+		}
-+		clear_last_prefetch_free();
-+		schedule_timeout_interruptible(PREFETCH_DELAY);
-+	} while (!kthread_should_stop());
-+
-+	return 0;
-+}
-+
-+/*
-+ * Create kmem cache for swapped entries
-+ */
-+void __init prepare_swap_prefetch(void)
-+{
-+	struct zone *zone;
-+
-+	swapped.cache = kmem_cache_create("swapped_entry",
-+		sizeof(struct swapped_entry), 0, SLAB_PANIC, NULL, NULL);
-+
-+	/*
-+	 * Set max number of entries to 2/3 the size of physical ram  as we
-+	 * only ever prefetch to consume 2/3 of the ram.
-+	 */
-+	swapped.maxcount = nr_free_pagecache_pages() / 3 * 2;
-+
-+	for_each_zone(zone) {
-+		unsigned long present;
-+		struct node_stats *ns;
-+		int idx;
-+
-+		present = zone->present_pages;
-+		if (!present)
-+			continue;
-+
-+		ns = &sp_stat.node[zone->zone_pgdat->node_id];
-+		ns->prefetch_watermark += present / 3 * 2;
-+		idx = zone_idx(zone);
-+		ns->pointfree[idx] = &ns->highfree[idx];
-+	}
-+}
-+
-+static int __init kprefetchd_init(void)
-+{
-+	kprefetchd_task = kthread_run(kprefetchd, NULL, "kprefetchd");
-+
-+	return 0;
-+}
-+
-+static void __exit kprefetchd_exit(void)
-+{
-+	kthread_stop(kprefetchd_task);
-+}
-+
-+module_init(kprefetchd_init);
-+module_exit(kprefetchd_exit);
-Index: linux-2.6.21-ck1/mm/swap_state.c
-===================================================================
---- linux-2.6.21-ck1.orig/mm/swap_state.c	2007-05-04 12:24:01.000000000 +1000
-+++ linux-2.6.21-ck1/mm/swap_state.c	2007-05-04 12:24:20.000000000 +1000
-@@ -10,6 +10,7 @@
- #include <linux/mm.h>
- #include <linux/kernel_stat.h>
- #include <linux/swap.h>
-+#include <linux/swap-prefetch.h>
- #include <linux/init.h>
- #include <linux/pagemap.h>
- #include <linux/buffer_head.h>
-@@ -82,6 +83,7 @@ static int __add_to_swap_cache(struct pa
- 		error = radix_tree_insert(&swapper_space.page_tree,
- 						entry.val, page);
- 		if (!error) {
-+			remove_from_swapped_list(entry.val);
- 			page_cache_get(page);
- 			SetPageLocked(page);
- 			SetPageSwapCache(page);
-@@ -95,11 +97,12 @@ static int __add_to_swap_cache(struct pa
- 	return error;
- }
- 
--static int add_to_swap_cache(struct page *page, swp_entry_t entry)
-+int add_to_swap_cache(struct page *page, swp_entry_t entry)
- {
- 	int error;
- 
- 	if (!swap_duplicate(entry)) {
-+		remove_from_swapped_list(entry.val);
- 		INC_CACHE_INFO(noent_race);
- 		return -ENOENT;
- 	}
-@@ -148,6 +151,9 @@ int add_to_swap(struct page * page, gfp_
- 	swp_entry_t entry;
- 	int err;
- 
-+	/* Swap prefetching is delayed if we're swapping pages */
-+	delay_swap_prefetch();
-+
- 	BUG_ON(!PageLocked(page));
- 
- 	for (;;) {
-@@ -320,6 +326,9 @@ struct page *read_swap_cache_async(swp_e
- 	struct page *found_page, *new_page = NULL;
- 	int err;
- 
-+	/* Swap prefetching is delayed if we're already reading from swap */
-+	delay_swap_prefetch();
-+
- 	do {
- 		/*
- 		 * First check the swap cache.  Since this is normally
-Index: linux-2.6.21-ck1/mm/vmscan.c
-===================================================================
---- linux-2.6.21-ck1.orig/mm/vmscan.c	2007-05-04 12:24:01.000000000 +1000
-+++ linux-2.6.21-ck1/mm/vmscan.c	2007-05-04 12:24:21.000000000 +1000
-@@ -16,6 +16,7 @@
- #include <linux/slab.h>
- #include <linux/kernel_stat.h>
- #include <linux/swap.h>
-+#include <linux/swap-prefetch.h>
- #include <linux/pagemap.h>
- #include <linux/init.h>
- #include <linux/highmem.h>
-@@ -36,6 +37,7 @@
- #include <linux/rwsem.h>
- #include <linux/delay.h>
- #include <linux/kthread.h>
-+#include <linux/timer.h>
- #include <linux/freezer.h>
- 
- #include <asm/tlbflush.h>
-@@ -63,7 +65,7 @@ struct scan_control {
- 	 * whole list at once. */
- 	int swap_cluster_max;
- 
--	int swappiness;
-+	int mapped;
- 
- 	int all_unreclaimable;
- };
-@@ -110,9 +112,10 @@ struct shrinker {
- #endif
- 
- /*
-- * From 0 .. 100.  Higher means more swappy.
-+ * From 0 .. 100.  Lower means more swappy.
-  */
--int vm_swappiness = 60;
-+int vm_mapped __read_mostly = 66;
-+int vm_hardmaplimit __read_mostly = 1;
- long vm_total_pages;	/* The total number of pages which the VM controls */
- 
- static LIST_HEAD(shrinker_list);
-@@ -424,6 +427,7 @@ int remove_mapping(struct address_space 
- 
- 	if (PageSwapCache(page)) {
- 		swp_entry_t swap = { .val = page_private(page) };
-+		add_to_swapped_list(page);
- 		__delete_from_swap_cache(page);
- 		write_unlock_irq(&mapping->tree_lock);
- 		swap_free(swap);
-@@ -807,10 +811,14 @@ static void shrink_active_list(unsigned 
- 		 * The distress ratio is important - we don't want to start
- 		 * going oom.
- 		 *
--		 * A 100% value of vm_swappiness overrides this algorithm
--		 * altogether.
-+		 * This distress value is ignored if we apply a hardmaplimit except
-+		 * in extreme distress.
-+		 *
-+		 * A 0% value of vm_mapped overrides this algorithm altogether.
- 		 */
--		swap_tendency = mapped_ratio / 2 + distress + sc->swappiness;
-+		swap_tendency = mapped_ratio * 100 / (sc->mapped + 1);
-+		if (!vm_hardmaplimit || distress == 100)
-+			swap_tendency += distress;
- 
- 		/*
- 		 * Now use this metric to decide whether to start moving mapped
-@@ -959,6 +967,41 @@ static unsigned long shrink_zone(int pri
- }
- 
- /*
-+ * Helper functions to adjust nice level of kswapd, based on the priority of
-+ * the task (p) that called it. If it is already higher priority we do not
-+ * demote its nice level since it is still working on behalf of a higher
-+ * priority task. With kernel threads we leave it at nice 0.
-+ *
-+ * We don't ever run kswapd real time, so if a real time task calls kswapd we
-+ * set it to highest SCHED_NORMAL priority.
-+ */
-+static int effective_sc_prio(struct task_struct *p)
-+{
-+	if (likely(p->mm)) {
-+		if (rt_task(p))
-+			return -20;
-+		if (idleprio_task(p))
-+			return 19;
-+		return task_nice(p);
-+	}
-+	return 0;
-+}
-+
-+static void set_kswapd_nice(struct task_struct *kswapd, struct task_struct *p,
-+			    int active)
-+{
-+	long nice = effective_sc_prio(p);
-+
-+	if (task_nice(kswapd) > nice || !active)
-+		set_user_nice(kswapd, nice);
-+}
-+
-+static int sc_priority(struct task_struct *p)
-+{
-+	return (DEF_PRIORITY + (DEF_PRIORITY * effective_sc_prio(p) / 40));
-+}
-+
-+/*
-  * This is the direct reclaim path, for page-allocating processes.  We only
-  * try to reclaim pages from zones which will satisfy the caller's allocation
-  * request.
-@@ -1015,7 +1058,8 @@ static unsigned long shrink_zones(int pr
-  * holds filesystem locks which prevent writeout this might not work, and the
-  * allocation attempt will fail.
-  */
--unsigned long try_to_free_pages(struct zone **zones, gfp_t gfp_mask)
-+unsigned long try_to_free_pages(struct zone **zones, gfp_t gfp_mask,
-+				struct task_struct *p)
- {
- 	int priority;
- 	int ret = 0;
-@@ -1023,15 +1067,20 @@ unsigned long try_to_free_pages(struct z
- 	unsigned long nr_reclaimed = 0;
- 	struct reclaim_state *reclaim_state = current->reclaim_state;
- 	unsigned long lru_pages = 0;
--	int i;
-+	int i, scan_priority = DEF_PRIORITY;
- 	struct scan_control sc = {
- 		.gfp_mask = gfp_mask,
- 		.may_writepage = !laptop_mode,
- 		.swap_cluster_max = SWAP_CLUSTER_MAX,
- 		.may_swap = 1,
--		.swappiness = vm_swappiness,
-+		.mapped = vm_mapped,
- 	};
- 
-+	if (p)
-+		scan_priority = sc_priority(p);
-+
-+	delay_swap_prefetch();
-+
- 	count_vm_event(ALLOCSTALL);
- 
- 	for (i = 0; zones[i] != NULL; i++) {
-@@ -1044,7 +1093,7 @@ unsigned long try_to_free_pages(struct z
- 				+ zone_page_state(zone, NR_INACTIVE);
- 	}
- 
--	for (priority = DEF_PRIORITY; priority >= 0; priority--) {
-+	for (priority = scan_priority; priority >= 0; priority--) {
- 		sc.nr_scanned = 0;
- 		if (!priority)
- 			disable_swap_token();
-@@ -1074,7 +1123,7 @@ unsigned long try_to_free_pages(struct z
- 		}
- 
- 		/* Take a nap, wait for some writeback to complete */
--		if (sc.nr_scanned && priority < DEF_PRIORITY - 2)
-+		if (sc.nr_scanned && priority < scan_priority - 2)
- 			congestion_wait(WRITE, HZ/10);
- 	}
- 	/* top priority shrink_caches still had more to do? don't OOM, then */
-@@ -1124,9 +1173,9 @@ out:
-  */
- static unsigned long balance_pgdat(pg_data_t *pgdat, int order)
- {
--	int all_zones_ok;
-+	int all_zones_ok = 0;
- 	int priority;
--	int i;
-+	int i, scan_priority;
- 	unsigned long total_scanned;
- 	unsigned long nr_reclaimed;
- 	struct reclaim_state *reclaim_state = current->reclaim_state;
-@@ -1134,7 +1183,7 @@ static unsigned long balance_pgdat(pg_da
- 		.gfp_mask = GFP_KERNEL,
- 		.may_swap = 1,
- 		.swap_cluster_max = SWAP_CLUSTER_MAX,
--		.swappiness = vm_swappiness,
-+		.mapped = vm_mapped,
- 	};
- 	/*
- 	 * temp_priority is used to remember the scanning priority at which
-@@ -1142,6 +1191,8 @@ static unsigned long balance_pgdat(pg_da
- 	 */
- 	int temp_priority[MAX_NR_ZONES];
- 
-+	scan_priority = sc_priority(pgdat->kswapd);
-+
- loop_again:
- 	total_scanned = 0;
- 	nr_reclaimed = 0;
-@@ -1149,9 +1200,9 @@ loop_again:
- 	count_vm_event(PAGEOUTRUN);
- 
- 	for (i = 0; i < pgdat->nr_zones; i++)
--		temp_priority[i] = DEF_PRIORITY;
-+		temp_priority[i] = scan_priority;
- 
--	for (priority = DEF_PRIORITY; priority >= 0; priority--) {
-+	for (priority = scan_priority; priority >= 0; priority--) {
- 		int end_zone = 0;	/* Inclusive.  0 = ZONE_DMA */
- 		unsigned long lru_pages = 0;
- 
-@@ -1167,15 +1218,22 @@ loop_again:
- 		 */
- 		for (i = pgdat->nr_zones - 1; i >= 0; i--) {
- 			struct zone *zone = pgdat->node_zones + i;
-+			unsigned long watermark;
- 
- 			if (!populated_zone(zone))
- 				continue;
- 
--			if (zone->all_unreclaimable && priority != DEF_PRIORITY)
-+			if (zone->all_unreclaimable && priority != scan_priority)
- 				continue;
- 
--			if (!zone_watermark_ok(zone, order, zone->pages_high,
--					       0, 0)) {
-+			/*
-+			 * The watermark is relaxed depending on the
-+			 * level of "priority" till it drops to
-+			 * pages_high.
-+			 */
-+			watermark = zone->pages_high + (zone->pages_high *
-+				    priority / scan_priority);
-+			if (!zone_watermark_ok(zone, order, watermark, 0, 0)) {
- 				end_zone = i;
- 				break;
- 			}
-@@ -1202,14 +1260,18 @@ loop_again:
- 		for (i = 0; i <= end_zone; i++) {
- 			struct zone *zone = pgdat->node_zones + i;
- 			int nr_slab;
-+			unsigned long watermark;
- 
- 			if (!populated_zone(zone))
- 				continue;
- 
--			if (zone->all_unreclaimable && priority != DEF_PRIORITY)
-+			if (zone->all_unreclaimable && priority != scan_priority)
- 				continue;
- 
--			if (!zone_watermark_ok(zone, order, zone->pages_high,
-+			watermark = zone->pages_high + (zone->pages_high *
-+				    priority / scan_priority);
-+
-+			if (!zone_watermark_ok(zone, order, watermark,
- 					       end_zone, 0))
- 				all_zones_ok = 0;
- 			temp_priority[i] = priority;
-@@ -1242,7 +1304,7 @@ loop_again:
- 		 * OK, kswapd is getting into trouble.  Take a nap, then take
- 		 * another pass across the zones.
- 		 */
--		if (total_scanned && priority < DEF_PRIORITY - 2)
-+		if (total_scanned && priority < scan_priority - 2)
- 			congestion_wait(WRITE, HZ/10);
- 
- 		/*
-@@ -1276,6 +1338,8 @@ out:
- 	return nr_reclaimed;
- }
- 
-+#define WT_EXPIRY	(HZ * 5)	/* Time to wakeup watermark_timer */
-+
- /*
-  * The background pageout daemon, started as a kernel thread
-  * from the init process. 
-@@ -1325,6 +1389,8 @@ static int kswapd(void *p)
- 
- 		try_to_freeze();
- 
-+		/* kswapd has been busy so delay watermark_timer */
-+		mod_timer(&pgdat->watermark_timer, jiffies + WT_EXPIRY);
- 		prepare_to_wait(&pgdat->kswapd_wait, &wait, TASK_INTERRUPTIBLE);
- 		new_order = pgdat->kswapd_max_order;
- 		pgdat->kswapd_max_order = 0;
-@@ -1335,6 +1401,7 @@ static int kswapd(void *p)
- 			 */
- 			order = new_order;
- 		} else {
-+			set_user_nice(tsk, 0);
- 			schedule();
- 			order = pgdat->kswapd_max_order;
- 		}
-@@ -1348,9 +1415,10 @@ static int kswapd(void *p)
- /*
-  * A zone is low on free memory, so wake its kswapd task to service it.
-  */
--void wakeup_kswapd(struct zone *zone, int order)
-+void wakeup_kswapd(struct zone *zone, int order, struct task_struct *p)
- {
- 	pg_data_t *pgdat;
-+	int active;
- 
- 	if (!populated_zone(zone))
- 		return;
-@@ -1362,7 +1430,9 @@ void wakeup_kswapd(struct zone *zone, in
- 		pgdat->kswapd_max_order = order;
- 	if (!cpuset_zone_allowed_hardwall(zone, GFP_KERNEL))
- 		return;
--	if (!waitqueue_active(&pgdat->kswapd_wait))
-+	active = waitqueue_active(&pgdat->kswapd_wait);
-+	set_kswapd_nice(pgdat->kswapd, p, active);
-+	if (!active)
- 		return;
- 	wake_up_interruptible(&pgdat->kswapd_wait);
- }
-@@ -1381,6 +1451,8 @@ static unsigned long shrink_all_zones(un
- 	struct zone *zone;
- 	unsigned long nr_to_scan, ret = 0;
- 
-+	delay_swap_prefetch();
-+
- 	for_each_zone(zone) {
- 
- 		if (!populated_zone(zone))
-@@ -1440,7 +1512,7 @@ unsigned long shrink_all_memory(unsigned
- 		.may_swap = 0,
- 		.swap_cluster_max = nr_pages,
- 		.may_writepage = 1,
--		.swappiness = vm_swappiness,
-+		.mapped = vm_mapped,
- 	};
- 
- 	current->reclaim_state = &reclaim_state;
-@@ -1475,7 +1547,7 @@ unsigned long shrink_all_memory(unsigned
- 		/* Force reclaiming mapped pages in the passes #3 and #4 */
- 		if (pass > 2) {
- 			sc.may_swap = 1;
--			sc.swappiness = 100;
-+			sc.mapped = 0;
- 		}
- 
- 		for (prio = DEF_PRIORITY; prio >= 0; prio--) {
-@@ -1539,20 +1611,57 @@ static int __devinit cpu_callback(struct
- }
- 
- /*
-+ * We wake up kswapd every WT_EXPIRY till free ram is above pages_lots
-+ */
-+static void watermark_wakeup(unsigned long data)
-+{
-+	pg_data_t *pgdat = (pg_data_t *)data;
-+	struct timer_list *wt = &pgdat->watermark_timer;
-+	int i;
-+
-+	if (!waitqueue_active(&pgdat->kswapd_wait) || above_background_load())
-+		goto out;
-+	for (i = pgdat->nr_zones - 1; i >= 0; i--) {
-+		struct zone *z = pgdat->node_zones + i;
-+
-+		if (!populated_zone(z) || is_highmem(z)) {
-+			/* We are better off leaving highmem full */
-+			continue;
-+		}
-+		if (!zone_watermark_ok(z, 0, z->pages_lots, 0, 0)) {
-+			wake_up_interruptible(&pgdat->kswapd_wait);
-+			goto out;
-+		}
-+	}
-+out:
-+	mod_timer(wt, jiffies + WT_EXPIRY);
-+	return;
-+}
-+
-+/*
-  * This kswapd start function will be called by init and node-hot-add.
-  * On node-hot-add, kswapd will moved to proper cpus if cpus are hot-added.
-  */
- int kswapd_run(int nid)
- {
- 	pg_data_t *pgdat = NODE_DATA(nid);
-+	struct timer_list *wt;
- 	int ret = 0;
- 
- 	if (pgdat->kswapd)
- 		return 0;
- 
-+	wt = &pgdat->watermark_timer;
-+	init_timer(wt);
-+	wt->data = (unsigned long)pgdat;
-+	wt->function = watermark_wakeup;
-+	wt->expires = jiffies + WT_EXPIRY;
-+	add_timer(wt);
-+
- 	pgdat->kswapd = kthread_run(kswapd, pgdat, "kswapd%d", nid);
- 	if (IS_ERR(pgdat->kswapd)) {
- 		/* failure at boot is fatal */
-+		del_timer(wt);
- 		BUG_ON(system_state == SYSTEM_BOOTING);
- 		printk("Failed to start kswapd on node %d\n",nid);
- 		ret = -1;
-@@ -1623,7 +1732,7 @@ static int __zone_reclaim(struct zone *z
- 		.swap_cluster_max = max_t(unsigned long, nr_pages,
- 					SWAP_CLUSTER_MAX),
- 		.gfp_mask = gfp_mask,
--		.swappiness = vm_swappiness,
-+		.mapped = vm_mapped,
- 	};
- 	unsigned long slab_reclaimable;
- 
-Index: linux-2.6.21-ck1/include/linux/mm_inline.h
-===================================================================
---- linux-2.6.21-ck1.orig/include/linux/mm_inline.h	2007-05-04 12:24:01.000000000 +1000
-+++ linux-2.6.21-ck1/include/linux/mm_inline.h	2007-05-04 12:24:20.000000000 +1000
-@@ -13,6 +13,13 @@ add_page_to_inactive_list(struct zone *z
- }
- 
- static inline void
-+add_page_to_inactive_list_tail(struct zone *zone, struct page *page)
-+{
-+	list_add_tail(&page->lru, &zone->inactive_list);
-+	__inc_zone_state(zone, NR_INACTIVE);
-+}
-+
-+static inline void
- del_page_from_active_list(struct zone *zone, struct page *page)
- {
- 	list_del(&page->lru);
-Index: linux-2.6.21-ck1/include/linux/swap-prefetch.h
-===================================================================
---- /dev/null	1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.21-ck1/include/linux/swap-prefetch.h	2007-05-04 12:24:20.000000000 +1000
-@@ -0,0 +1,55 @@
-+#ifndef SWAP_PREFETCH_H_INCLUDED
-+#define SWAP_PREFETCH_H_INCLUDED
-+
-+#ifdef CONFIG_SWAP_PREFETCH
-+/* mm/swap_prefetch.c */
-+extern int swap_prefetch;
-+struct swapped_entry {
-+	swp_entry_t		swp_entry;	/* The actual swap entry */
-+	struct list_head	swapped_list;	/* Linked list of entries */
-+#if MAX_NUMNODES > 1
-+	int			node;		/* Node id */
-+#endif
-+} __attribute__((packed));
-+
-+static inline void store_swap_entry_node(struct swapped_entry *entry,
-+	struct page *page)
-+{
-+#if MAX_NUMNODES > 1
-+	entry->node = page_to_nid(page);
-+#endif
-+}
-+
-+static inline int get_swap_entry_node(struct swapped_entry *entry)
-+{
-+#if MAX_NUMNODES > 1
-+	return entry->node;
-+#else
-+	return 0;
-+#endif
-+}
-+
-+extern void add_to_swapped_list(struct page *page);
-+extern void remove_from_swapped_list(const unsigned long index);
-+extern void delay_swap_prefetch(void);
-+extern void prepare_swap_prefetch(void);
-+
-+#else	/* CONFIG_SWAP_PREFETCH */
-+static inline void add_to_swapped_list(struct page *__unused)
-+{
-+}
-+
-+static inline void prepare_swap_prefetch(void)
-+{
-+}
-+
-+static inline void remove_from_swapped_list(const unsigned long __unused)
-+{
-+}
-+
-+static inline void delay_swap_prefetch(void)
-+{
-+}
-+#endif	/* CONFIG_SWAP_PREFETCH */
-+
-+#endif		/* SWAP_PREFETCH_H_INCLUDED */
-Index: linux-2.6.21-ck1/include/linux/sysctl.h
-===================================================================
---- linux-2.6.21-ck1.orig/include/linux/sysctl.h	2007-05-04 12:24:01.000000000 +1000
-+++ linux-2.6.21-ck1/include/linux/sysctl.h	2007-05-04 12:24:20.000000000 +1000
-@@ -190,7 +190,7 @@ enum
- 	VM_OVERCOMMIT_RATIO=16, /* percent of RAM to allow overcommit in */
- 	VM_PAGEBUF=17,		/* struct: Control pagebuf parameters */
- 	VM_HUGETLB_PAGES=18,	/* int: Number of available Huge Pages */
--	VM_SWAPPINESS=19,	/* Tendency to steal mapped memory */
-+	VM_MAPPED=19,		/* percent mapped min while evicting cache */
- 	VM_LOWMEM_RESERVE_RATIO=20,/* reservation ratio for lower memory zones */
- 	VM_MIN_FREE_KBYTES=21,	/* Minimum free kilobytes to maintain */
- 	VM_MAX_MAP_COUNT=22,	/* int: Maximum number of mmaps/address-space */
-Index: linux-2.6.21-ck1/include/linux/mmzone.h
-===================================================================
---- linux-2.6.21-ck1.orig/include/linux/mmzone.h	2007-05-04 12:24:01.000000000 +1000
-+++ linux-2.6.21-ck1/include/linux/mmzone.h	2007-05-04 12:24:21.000000000 +1000
-@@ -13,6 +13,7 @@
- #include <linux/init.h>
- #include <linux/seqlock.h>
- #include <linux/nodemask.h>
-+#include <linux/timer.h>
- #include <asm/atomic.h>
- #include <asm/page.h>
- 
-@@ -178,7 +179,7 @@ enum zone_type {
- 
- struct zone {
- 	/* Fields commonly accessed by the page allocator */
--	unsigned long		pages_min, pages_low, pages_high;
-+	unsigned long		pages_min, pages_low, pages_high, pages_lots;
- 	/*
- 	 * We don't know if the memory that we're going to allocate will be freeable
- 	 * or/and it will be released eventually, so to avoid totally wasting several
-@@ -449,6 +450,7 @@ typedef struct pglist_data {
- 	wait_queue_head_t kswapd_wait;
- 	struct task_struct *kswapd;
- 	int kswapd_max_order;
-+	struct timer_list watermark_timer;
- } pg_data_t;
- 
- #define node_present_pages(nid)	(NODE_DATA(nid)->node_present_pages)
-@@ -465,7 +467,7 @@ typedef struct pglist_data {
- void get_zone_counts(unsigned long *active, unsigned long *inactive,
- 			unsigned long *free);
- void build_all_zonelists(void);
--void wakeup_kswapd(struct zone *zone, int order);
-+void wakeup_kswapd(struct zone *zone, int order, struct task_struct *p);
- int zone_watermark_ok(struct zone *z, int order, unsigned long mark,
- 		int classzone_idx, int alloc_flags);
- enum memmap_context {
-Index: linux-2.6.21-ck1/mm/page_alloc.c
-===================================================================
---- linux-2.6.21-ck1.orig/mm/page_alloc.c	2007-05-04 12:24:01.000000000 +1000
-+++ linux-2.6.21-ck1/mm/page_alloc.c	2007-05-04 12:24:20.000000000 +1000
-@@ -1277,7 +1277,7 @@ restart:
- 		goto nopage;
- 
- 	for (z = zonelist->zones; *z; z++)
--		wakeup_kswapd(*z, order);
-+		wakeup_kswapd(*z, order, p);
- 
- 	/*
- 	 * OK, we're below the kswapd watermark and have kicked background
-@@ -1341,7 +1341,7 @@ nofail_alloc:
- 	reclaim_state.reclaimed_slab = 0;
- 	p->reclaim_state = &reclaim_state;
- 
--	did_some_progress = try_to_free_pages(zonelist->zones, gfp_mask);
-+	did_some_progress = try_to_free_pages(zonelist->zones, gfp_mask, p);
- 
- 	p->reclaim_state = NULL;
- 	p->flags &= ~PF_MEMALLOC;
-@@ -1597,6 +1597,7 @@ void show_free_areas(void)
- 			" min:%lukB"
- 			" low:%lukB"
- 			" high:%lukB"
-+			" lots:%lukB"
- 			" active:%lukB"
- 			" inactive:%lukB"
- 			" present:%lukB"
-@@ -1608,6 +1609,7 @@ void show_free_areas(void)
- 			K(zone->pages_min),
- 			K(zone->pages_low),
- 			K(zone->pages_high),
-+			K(zone->pages_lots),
- 			K(zone_page_state(zone, NR_ACTIVE)),
- 			K(zone_page_state(zone, NR_INACTIVE)),
- 			K(zone->present_pages),
-@@ -3146,6 +3148,7 @@ void setup_per_zone_pages_min(void)
- 
- 		zone->pages_low   = zone->pages_min + (tmp >> 2);
- 		zone->pages_high  = zone->pages_min + (tmp >> 1);
-+		zone->pages_lots  = zone->pages_min + tmp;
- 		spin_unlock_irqrestore(&zone->lru_lock, flags);
- 	}
- 
-Index: linux-2.6.21-ck1/fs/buffer.c
-===================================================================
---- linux-2.6.21-ck1.orig/fs/buffer.c	2007-05-04 12:24:01.000000000 +1000
-+++ linux-2.6.21-ck1/fs/buffer.c	2007-05-04 12:24:20.000000000 +1000
-@@ -363,7 +363,7 @@ static void free_more_memory(void)
- 	for_each_online_pgdat(pgdat) {
- 		zones = pgdat->node_zonelists[gfp_zone(GFP_NOFS)].zones;
- 		if (*zones)
--			try_to_free_pages(zones, GFP_NOFS);
-+			try_to_free_pages(zones, GFP_NOFS, NULL);
- 	}
- }
- 
-Index: linux-2.6.21-ck1/mm/filemap.c
-===================================================================
---- linux-2.6.21-ck1.orig/mm/filemap.c	2007-05-04 12:24:01.000000000 +1000
-+++ linux-2.6.21-ck1/mm/filemap.c	2007-05-04 12:24:21.000000000 +1000
-@@ -466,6 +466,16 @@ int add_to_page_cache_lru(struct page *p
- 	return ret;
- }
- 
-+int add_to_page_cache_lru_tail(struct page *page,
-+	struct address_space *mapping, pgoff_t offset, gfp_t gfp_mask)
-+{
-+	int ret = add_to_page_cache(page, mapping, offset, gfp_mask);
-+
-+	if (ret == 0)
-+		lru_cache_add_tail(page);
-+	return ret;
-+}
-+
- #ifdef CONFIG_NUMA
- struct page *__page_cache_alloc(gfp_t gfp)
- {
-@@ -836,6 +846,34 @@ static void shrink_readahead_size_eio(st
- 	ra->ra_pages /= 4;
- }
- 
-+/*
-+ * Sysctl which determines whether we should read from large files to the
-+ * tail of the inactive lru list.
-+ */
-+int vm_tail_largefiles __read_mostly = 1;
-+
-+static inline int nr_mapped(void)
-+{
-+	return global_page_state(NR_FILE_MAPPED) +
-+		global_page_state(NR_ANON_PAGES);
-+}
-+
-+/*
-+ * This examines how large in pages a file size is and returns 1 if it is
-+ * more than half the unmapped ram. Avoid doing read_page_state which is
-+ * expensive unless we already know it is likely to be large enough.
-+ */
-+static int large_isize(unsigned long nr_pages)
-+{
-+	if (nr_pages * 6 > vm_total_pages) {
-+		 unsigned long unmapped_ram = vm_total_pages - nr_mapped();
-+
-+		if (nr_pages * 2 > unmapped_ram)
-+			return 1;
-+	}
-+	return 0;
-+}
-+
- /**
-  * do_generic_mapping_read - generic file read routine
-  * @mapping:	address_space to be read
-@@ -1044,8 +1082,19 @@ no_cached_page:
- 				goto out;
- 			}
- 		}
--		error = add_to_page_cache_lru(cached_page, mapping,
--						index, GFP_KERNEL);
-+
-+		/*
-+		 * If we know the file is large we add the pages read to the
-+		 * end of the lru as we're unlikely to be able to cache the
-+		 * whole file in ram so make those pages the first to be
-+		 * dropped if not referenced soon.
-+		 */
-+		if (vm_tail_largefiles && large_isize(end_index))
-+			error = add_to_page_cache_lru_tail(cached_page,
-+						mapping, index, GFP_KERNEL);
-+		else
-+			error = add_to_page_cache_lru(cached_page, mapping,
-+							index, GFP_KERNEL);
- 		if (error) {
- 			if (error == -EEXIST)
- 				goto find_page;
-Index: linux-2.6.21-ck1/Documentation/filesystems/proc.txt
-===================================================================
---- linux-2.6.21-ck1.orig/Documentation/filesystems/proc.txt	2007-05-04 12:24:01.000000000 +1000
-+++ linux-2.6.21-ck1/Documentation/filesystems/proc.txt	2007-05-04 12:24:21.000000000 +1000
-@@ -1325,6 +1325,14 @@ To free pagecache, dentries and inodes:
- As this is a non-destructive operation and dirty objects are not freeable, the
- user should run `sync' first.
- 
-+tail_largefiles
-+---------------
-+
-+When enabled reads from large files to the tail end of the inactive lru list.
-+This means that any cache from reading large files is dropped very quickly,
-+preventing loss of mapped ram and useful pagecache when large files are read.
-+This does, however, make caching less effective when working with large files.
-+
- 
- 2.5 /proc/sys/dev - Device specific parameters
- ----------------------------------------------
-Index: linux-2.6.21-ck1/arch/i386/Kconfig
-===================================================================
---- linux-2.6.21-ck1.orig/arch/i386/Kconfig	2007-05-04 12:24:00.000000000 +1000
-+++ linux-2.6.21-ck1/arch/i386/Kconfig	2007-05-04 12:24:21.000000000 +1000
-@@ -546,7 +546,7 @@ endchoice
- 
- choice
- 	depends on EXPERIMENTAL
--	prompt "Memory split" if EMBEDDED
-+	prompt "Memory split"
- 	default VMSPLIT_3G
- 	help
- 	  Select the desired split between kernel and user memory.
-@@ -565,14 +565,14 @@ choice
- 	  option alone!
- 
- 	config VMSPLIT_3G
--		bool "3G/1G user/kernel split"
-+		bool "Default 896MB lowmem (3G/1G user/kernel split)"
- 	config VMSPLIT_3G_OPT
- 		depends on !HIGHMEM
--		bool "3G/1G user/kernel split (for full 1G low memory)"
-+		bool "1GB lowmem (3G/1G user/kernel split)"
- 	config VMSPLIT_2G
--		bool "2G/2G user/kernel split"
-+		bool "2GB lowmem (2G/2G user/kernel split)"
- 	config VMSPLIT_1G
--		bool "1G/3G user/kernel split"
-+		bool "3GB lowmem (1G/3G user/kernel split)"
- endchoice
- 
- config PAGE_OFFSET
-Index: linux-2.6.21-ck1/kernel/Kconfig.hz
-===================================================================
---- linux-2.6.21-ck1.orig/kernel/Kconfig.hz	2007-05-04 12:24:00.000000000 +1000
-+++ linux-2.6.21-ck1/kernel/Kconfig.hz	2007-05-04 12:24:21.000000000 +1000
-@@ -4,7 +4,7 @@
- 
- choice
- 	prompt "Timer frequency"
--	default HZ_250
-+	default HZ_1000
- 	help
- 	 Allows the configuration of the timer frequency. It is customary
- 	 to have the timer interrupt run at 1000 Hz but 100 Hz may be more
-@@ -13,8 +13,7 @@ choice
- 	 contention and cacheline bounces as a result of timer interrupts.
- 	 Note that the timer interrupt occurs on each processor in an SMP
- 	 environment leading to NR_CPUS * HZ number of timer interrupts
--	 per second.
--
-+	 per second.Laptops may also show improved battery life.
- 
- 	config HZ_100
- 		bool "100 HZ"
-@@ -23,13 +22,14 @@ choice
- 	  with lots of processors that may show reduced performance if
- 	  too many timer interrupts are occurring.
- 
--	config HZ_250
-+	config HZ_250_NODEFAULT
- 		bool "250 HZ"
- 	help
--	 250 Hz is a good compromise choice allowing server performance
--	 while also showing good interactive responsiveness even
--	 on SMP and NUMA systems. If you are going to be using NTSC video
--	 or multimedia, selected 300Hz instead.
-+	 250 HZ is a lousy compromise choice allowing server interactivity
-+	 while also showing desktop throughput and no extra power saving on
-+	 laptops. Good for when you can't make up your mind.
-+
-+	 Recommend 100 or 1000 instead.
- 
- 	config HZ_300
- 		bool "300 HZ"
-@@ -45,12 +45,76 @@ choice
- 	 1000 Hz is the preferred choice for desktop systems and other
- 	 systems requiring fast interactive responses to events.
- 
-+	config HZ_1500
-+		bool "1500 HZ"
-+	help
-+	 1500 Hz is an insane value to use to run broken software that is Hz
-+	 limited.
-+
-+	 Being over 1000, driver breakage is likely.
-+
-+	config HZ_2000
-+		bool "2000 HZ"
-+	help
-+	 2000 Hz is an insane value to use to run broken software that is Hz
-+	 limited.
-+
-+	 Being over 1000, driver breakage is likely.
-+
-+	config HZ_3000
-+		bool "3000 HZ"
-+	help
-+	 3000 Hz is an insane value to use to run broken software that is Hz
-+	 limited.
-+
-+	 Being over 1000, driver breakage is likely.
-+
-+	config HZ_4000
-+		bool "4000 HZ"
-+	help
-+	 4000 Hz is an insane value to use to run broken software that is Hz
-+	 limited.
-+
-+	 Being over 1000, driver breakage is likely.
-+
-+	config HZ_5000
-+		bool "5000 HZ"
-+	help
-+	 5000 Hz is an obscene value to use to run broken software that is Hz
-+	 limited.
-+
-+	 Being over 1000, driver breakage is likely.
-+
-+	config HZ_7500
-+		bool "7500 HZ"
-+	help
-+	 7500 Hz is an obscene value to use to run broken software that is Hz
-+	 limited.
-+
-+	 Being over 1000, driver breakage is likely.
-+
-+	config HZ_10000
-+		bool "10000 HZ"
-+	help
-+	 10000 Hz is an obscene value to use to run broken software that is Hz
-+	 limited.
-+
-+	 Being over 1000, driver breakage is likely.
-+
-+
- endchoice
- 
- config HZ
- 	int
- 	default 100 if HZ_100
--	default 250 if HZ_250
-+	default 250 if HZ_250_NODEFAULT
- 	default 300 if HZ_300
- 	default 1000 if HZ_1000
-+	default 1500 if HZ_1500
-+	default 2000 if HZ_2000
-+	default 3000 if HZ_3000
-+	default 4000 if HZ_4000
-+	default 5000 if HZ_5000
-+	default 7500 if HZ_7500
-+	default 10000 if HZ_10000
- 
-Index: linux-2.6.21-ck1/arch/i386/defconfig
-===================================================================
---- linux-2.6.21-ck1.orig/arch/i386/defconfig	2007-05-04 12:24:00.000000000 +1000
-+++ linux-2.6.21-ck1/arch/i386/defconfig	2007-05-04 12:24:21.000000000 +1000
-@@ -214,10 +214,10 @@ CONFIG_MTRR=y
- # CONFIG_IRQBALANCE is not set
- CONFIG_SECCOMP=y
- # CONFIG_HZ_100 is not set
--CONFIG_HZ_250=y
-+# CONFIG_HZ_250 is not set
- # CONFIG_HZ_300 is not set
--# CONFIG_HZ_1000 is not set
--CONFIG_HZ=250
-+CONFIG_HZ_1000=y
-+CONFIG_HZ=1000
- # CONFIG_KEXEC is not set
- # CONFIG_CRASH_DUMP is not set
- CONFIG_PHYSICAL_START=0x100000
-Index: linux-2.6.21-ck1/arch/x86_64/defconfig
-===================================================================
---- linux-2.6.21-ck1.orig/arch/x86_64/defconfig	2007-05-04 12:24:00.000000000 +1000
-+++ linux-2.6.21-ck1/arch/x86_64/defconfig	2007-05-04 12:24:21.000000000 +1000
-@@ -178,10 +178,10 @@ CONFIG_PHYSICAL_START=0x200000
- CONFIG_SECCOMP=y
- # CONFIG_CC_STACKPROTECTOR is not set
- # CONFIG_HZ_100 is not set
--CONFIG_HZ_250=y
-+# CONFIG_HZ_250 is not set
- # CONFIG_HZ_300 is not set
--# CONFIG_HZ_1000 is not set
--CONFIG_HZ=250
-+CONFIG_HZ_1000=y
-+CONFIG_HZ=1000
- # CONFIG_REORDER is not set
- CONFIG_K8_NB=y
- CONFIG_GENERIC_HARDIRQS=y
-Index: linux-2.6.21-ck1/include/linux/jiffies.h
-===================================================================
---- linux-2.6.21-ck1.orig/include/linux/jiffies.h	2007-05-04 12:24:00.000000000 +1000
-+++ linux-2.6.21-ck1/include/linux/jiffies.h	2007-05-04 12:24:21.000000000 +1000
-@@ -29,6 +29,12 @@
- # define SHIFT_HZ	9
- #elif HZ >= 768 && HZ < 1536
- # define SHIFT_HZ	10
-+#elif HZ >= 1536 && HZ < 3072
-+# define SHIFT_HZ	11
-+#elif HZ >= 3072 && HZ < 6144
-+# define SHIFT_HZ	12
-+#elif HZ >= 6144 && HZ < 12288
-+# define SHIFT_HZ	13
- #else
- # error You lose.
- #endif
-Index: linux-2.6.21-ck1/include/net/inet_timewait_sock.h
-===================================================================
---- linux-2.6.21-ck1.orig/include/net/inet_timewait_sock.h	2007-05-04 12:24:00.000000000 +1000
-+++ linux-2.6.21-ck1/include/net/inet_timewait_sock.h	2007-05-04 12:24:21.000000000 +1000
-@@ -38,8 +38,8 @@ struct inet_hashinfo;
-  * If time > 4sec, it is "slow" path, no recycling is required,
-  * so that we select tick to get range about 4 seconds.
-  */
--#if HZ <= 16 || HZ > 4096
--# error Unsupported: HZ <= 16 or HZ > 4096
-+#if HZ <= 16 || HZ > 16384
-+# error Unsupported: HZ <= 16 or HZ > 16384
- #elif HZ <= 32
- # define INET_TWDR_RECYCLE_TICK (5 + 2 - INET_TWDR_RECYCLE_SLOTS_LOG)
- #elif HZ <= 64
-@@ -54,8 +54,12 @@ struct inet_hashinfo;
- # define INET_TWDR_RECYCLE_TICK (10 + 2 - INET_TWDR_RECYCLE_SLOTS_LOG)
- #elif HZ <= 2048
- # define INET_TWDR_RECYCLE_TICK (11 + 2 - INET_TWDR_RECYCLE_SLOTS_LOG)
--#else
-+#elif HZ <= 4096
- # define INET_TWDR_RECYCLE_TICK (12 + 2 - INET_TWDR_RECYCLE_SLOTS_LOG)
-+#elif HZ <= 8192
-+# define INET_TWDR_RECYCLE_TICK (13 + 2 - INET_TWDR_RECYCLE_SLOTS_LOG)
-+#else
-+# define INET_TWDR_RECYCLE_TICK (14 + 2 - INET_TWDR_RECYCLE_SLOTS_LOG)
- #endif
- 
- /* TIME_WAIT reaping mechanism. */
-Index: linux-2.6.21-ck1/include/net/pkt_sched.h
-===================================================================
---- linux-2.6.21-ck1.orig/include/net/pkt_sched.h	2007-05-04 12:24:00.000000000 +1000
-+++ linux-2.6.21-ck1/include/net/pkt_sched.h	2007-05-04 12:24:21.000000000 +1000
-@@ -78,8 +78,14 @@ typedef long	psched_tdiff_t;
- #define PSCHED_JSCALE 12
- #elif HZ >= 384 && HZ < 768
- #define PSCHED_JSCALE 11
--#elif HZ >= 768
-+#elif HZ >= 768 && HZ < 1536
- #define PSCHED_JSCALE 10
-+#elif HZ >= 1536 && HZ < 3072
-+#define PSCHED_JSCALE 9
-+#elif HZ >= 3072 && HZ < 6144
-+#define PSCHED_JSCALE 8
-+#else
-+#define PSCHED_JSCALE 7
- #endif
- 
- #define PSCHED_GET_TIME(stamp) ((stamp) = (get_jiffies_64()<<PSCHED_JSCALE))
-Index: linux-2.6.21-ck1/init/calibrate.c
-===================================================================
---- linux-2.6.21-ck1.orig/init/calibrate.c	2007-05-04 12:24:00.000000000 +1000
-+++ linux-2.6.21-ck1/init/calibrate.c	2007-05-04 12:24:21.000000000 +1000
-@@ -122,12 +122,12 @@ void __devinit calibrate_delay(void)
- 		printk("Calibrating delay loop (skipped)... "
- 			"%lu.%02lu BogoMIPS preset\n",
- 			loops_per_jiffy/(500000/HZ),
--			(loops_per_jiffy/(5000/HZ)) % 100);
-+			(loops_per_jiffy * 10/(50000/HZ)) % 100);
- 	} else if ((loops_per_jiffy = calibrate_delay_direct()) != 0) {
- 		printk("Calibrating delay using timer specific routine.. ");
- 		printk("%lu.%02lu BogoMIPS (lpj=%lu)\n",
- 			loops_per_jiffy/(500000/HZ),
--			(loops_per_jiffy/(5000/HZ)) % 100,
-+			(loops_per_jiffy * 10/(50000/HZ)) % 100,
- 			loops_per_jiffy);
- 	} else {
- 		loops_per_jiffy = (1<<12);
-@@ -166,7 +166,7 @@ void __devinit calibrate_delay(void)
- 		/* Round the value and print it */
- 		printk("%lu.%02lu BogoMIPS (lpj=%lu)\n",
- 			loops_per_jiffy/(500000/HZ),
--			(loops_per_jiffy/(5000/HZ)) % 100,
-+			(loops_per_jiffy * 10/(50000/HZ)) % 100,
- 			loops_per_jiffy);
- 	}
- 
-Index: linux-2.6.21-ck1/arch/i386/kernel/cpu/proc.c
-===================================================================
---- linux-2.6.21-ck1.orig/arch/i386/kernel/cpu/proc.c	2007-05-04 12:24:00.000000000 +1000
-+++ linux-2.6.21-ck1/arch/i386/kernel/cpu/proc.c	2007-05-04 12:24:21.000000000 +1000
-@@ -158,7 +158,7 @@ static int show_cpuinfo(struct seq_file 
- 
- 	seq_printf(m, "\nbogomips\t: %lu.%02lu\n",
- 		     c->loops_per_jiffy/(500000/HZ),
--		     (c->loops_per_jiffy/(5000/HZ)) % 100);
-+		     (c->loops_per_jiffy * 10/(50000/HZ)) % 100);
- 	seq_printf(m, "clflush size\t: %u\n\n", c->x86_clflush_size);
- 
- 	return 0;
-Index: linux-2.6.21-ck1/arch/i386/kernel/smpboot.c
-===================================================================
---- linux-2.6.21-ck1.orig/arch/i386/kernel/smpboot.c	2007-05-04 12:24:00.000000000 +1000
-+++ linux-2.6.21-ck1/arch/i386/kernel/smpboot.c	2007-05-04 12:24:21.000000000 +1000
-@@ -1134,7 +1134,7 @@ static void __init smp_boot_cpus(unsigne
- 		"Total of %d processors activated (%lu.%02lu BogoMIPS).\n",
- 		cpucount+1,
- 		bogosum/(500000/HZ),
--		(bogosum/(5000/HZ))%100);
-+		(bogosum * 10/(50000/HZ))%100);
- 	
- 	Dprintk("Before bogocount - setting activated=1.\n");
- 
-Index: linux-2.6.21-ck1/include/linux/nfsd/stats.h
-===================================================================
---- linux-2.6.21-ck1.orig/include/linux/nfsd/stats.h	2007-05-04 12:24:00.000000000 +1000
-+++ linux-2.6.21-ck1/include/linux/nfsd/stats.h	2007-05-04 12:24:21.000000000 +1000
-@@ -35,8 +35,8 @@ struct nfsd_stats {
- 
- };
- 
--/* thread usage wraps very million seconds (approx one fortnight) */
--#define	NFSD_USAGE_WRAP	(HZ*1000000)
-+/* thread usage wraps every one hundred thousand seconds (approx one day) */
-+#define	NFSD_USAGE_WRAP	(HZ*100000)
- 
- #ifdef __KERNEL__
- 
-Index: linux-2.6.21-ck1/arch/x86_64/kernel/setup.c
-===================================================================
---- linux-2.6.21-ck1.orig/arch/x86_64/kernel/setup.c	2007-05-04 12:24:00.000000000 +1000
-+++ linux-2.6.21-ck1/arch/x86_64/kernel/setup.c	2007-05-04 12:24:22.000000000 +1000
-@@ -1053,7 +1053,7 @@ static int show_cpuinfo(struct seq_file 
- 		
- 	seq_printf(m, "\nbogomips\t: %lu.%02lu\n",
- 		   c->loops_per_jiffy/(500000/HZ),
--		   (c->loops_per_jiffy/(5000/HZ)) % 100);
-+		   (c->loops_per_jiffy * 10/(50000/HZ)) % 100);
- 
- 	if (c->x86_tlbsize > 0) 
- 		seq_printf(m, "TLB size\t: %d 4K pages\n", c->x86_tlbsize);
diff --git a/pkgs/os-specific/linux/kernel/patch-2.6.22-ck1 b/pkgs/os-specific/linux/kernel/patch-2.6.22-ck1
deleted file mode 100644
index 81fa14e2abe43..0000000000000
--- a/pkgs/os-specific/linux/kernel/patch-2.6.22-ck1
+++ /dev/null
@@ -1,5167 +0,0 @@
-Index: linux-2.6.22-ck1/include/linux/sched.h
-===================================================================
---- linux-2.6.22-ck1.orig/include/linux/sched.h	2007-07-10 14:55:00.000000000 +1000
-+++ linux-2.6.22-ck1/include/linux/sched.h	2007-07-10 14:55:21.000000000 +1000
-@@ -34,9 +34,14 @@
- #define SCHED_FIFO		1
- #define SCHED_RR		2
- #define SCHED_BATCH		3
-+#define SCHED_ISO		4
-+#define SCHED_IDLEPRIO		5
- 
- #ifdef __KERNEL__
- 
-+#define SCHED_MAX		SCHED_IDLEPRIO
-+#define SCHED_RANGE(policy)	((policy) <= SCHED_MAX)
-+
- struct sched_param {
- 	int sched_priority;
- };
-@@ -129,7 +134,7 @@
- extern unsigned long nr_active(void);
- extern unsigned long nr_iowait(void);
- extern unsigned long weighted_cpuload(const int cpu);
--
-+extern int above_background_load(void);
- 
- /*
-  * Task state bitmask. NOTE! These bits are also
-@@ -150,8 +155,7 @@
- #define EXIT_ZOMBIE		16
- #define EXIT_DEAD		32
- /* in tsk->state again */
--#define TASK_NONINTERACTIVE	64
--#define TASK_DEAD		128
-+#define TASK_DEAD		64
- 
- #define __set_task_state(tsk, state_value)		\
- 	do { (tsk)->state = (state_value); } while (0)
-@@ -537,14 +541,19 @@
- 
- #define MAX_USER_RT_PRIO	100
- #define MAX_RT_PRIO		MAX_USER_RT_PRIO
-+#define PRIO_RANGE		(40)
-+#define ISO_PRIO		(MAX_RT_PRIO - 1)
- 
--#define MAX_PRIO		(MAX_RT_PRIO + 40)
-+#define MAX_PRIO		(MAX_RT_PRIO + PRIO_RANGE)
- 
--#define rt_prio(prio)		unlikely((prio) < MAX_RT_PRIO)
-+#define rt_prio(prio)		unlikely((prio) < ISO_PRIO)
- #define rt_task(p)		rt_prio((p)->prio)
- #define batch_task(p)		(unlikely((p)->policy == SCHED_BATCH))
--#define is_rt_policy(p)		((p) != SCHED_NORMAL && (p) != SCHED_BATCH)
-+#define is_rt_policy(policy)	((policy) == SCHED_FIFO || \
-+					(policy) == SCHED_RR)
- #define has_rt_policy(p)	unlikely(is_rt_policy((p)->policy))
-+#define iso_task(p)		unlikely((p)->policy == SCHED_ISO)
-+#define idleprio_task(p)	unlikely((p)->policy == SCHED_IDLEPRIO)
- 
- /*
-  * Some day this will be a full-fledged user tracking system..
-@@ -809,13 +818,6 @@
- struct pipe_inode_info;
- struct uts_namespace;
- 
--enum sleep_type {
--	SLEEP_NORMAL,
--	SLEEP_NONINTERACTIVE,
--	SLEEP_INTERACTIVE,
--	SLEEP_INTERRUPTED,
--};
--
- struct prio_array;
- 
- struct task_struct {
-@@ -835,20 +837,33 @@
- 	int load_weight;	/* for niceness load balancing purposes */
- 	int prio, static_prio, normal_prio;
- 	struct list_head run_list;
-+	/*
-+	 * This bitmap shows what priorities this task has received quota
-+	 * from for this major priority rotation on its current runqueue.
-+	 */
-+	DECLARE_BITMAP(bitmap, PRIO_RANGE + 1);
- 	struct prio_array *array;
-+	/* Which major runqueue rotation did this task run */
-+	unsigned long rotation;
- 
- 	unsigned short ioprio;
- #ifdef CONFIG_BLK_DEV_IO_TRACE
- 	unsigned int btrace_seq;
- #endif
--	unsigned long sleep_avg;
- 	unsigned long long timestamp, last_ran;
- 	unsigned long long sched_time; /* sched_clock time spent running */
--	enum sleep_type sleep_type;
- 
- 	unsigned int policy;
- 	cpumask_t cpus_allowed;
--	unsigned int time_slice, first_time_slice;
-+	/*
-+	 * How much this task is entitled to run at the current priority
-+	 * before being requeued at a lower priority.
-+	 */
-+	int time_slice;
-+	/* Is this the very first time_slice this task has ever run. */
-+	unsigned int first_time_slice;
-+	/* How much this task receives at each priority level */
-+	int quota;
- 
- #if defined(CONFIG_SCHEDSTATS) || defined(CONFIG_TASK_DELAY_ACCT)
- 	struct sched_info sched_info;
-@@ -1013,6 +1028,7 @@
- 	struct held_lock held_locks[MAX_LOCK_DEPTH];
- 	unsigned int lockdep_recursion;
- #endif
-+	unsigned long mutexes_held;
- 
- /* journalling filesystem info */
- 	void *journal_info;
-@@ -1181,9 +1197,11 @@
- #define PF_SWAPWRITE	0x00800000	/* Allowed to write to swap */
- #define PF_SPREAD_PAGE	0x01000000	/* Spread page cache over cpuset */
- #define PF_SPREAD_SLAB	0x02000000	/* Spread some slab caches over cpuset */
-+#define PF_ISOREF	0x04000000	/* SCHED_ISO task has used up quota */
- #define PF_MEMPOLICY	0x10000000	/* Non-default NUMA mempolicy */
- #define PF_MUTEX_TESTER	0x20000000	/* Thread belongs to the rt mutex tester */
- #define PF_FREEZER_SKIP	0x40000000	/* Freezer should not count it as freezeable */
-+#define PF_NONSLEEP	0x80000000	/* Waiting on in-kernel activity */
- 
- /*
-  * Only the _current_ task can read/write to tsk->flags, but other
-@@ -1253,7 +1271,7 @@
- #endif
- 
- extern void set_user_nice(struct task_struct *p, long nice);
--extern int task_prio(const struct task_struct *p);
-+extern int task_prio(struct task_struct *p);
- extern int task_nice(const struct task_struct *p);
- extern int can_nice(const struct task_struct *p, const int nice);
- extern int task_curr(const struct task_struct *p);
-Index: linux-2.6.22-ck1/kernel/sched.c
-===================================================================
---- linux-2.6.22-ck1.orig/kernel/sched.c	2007-07-10 14:55:00.000000000 +1000
-+++ linux-2.6.22-ck1/kernel/sched.c	2007-07-10 14:55:24.000000000 +1000
-@@ -16,6 +16,7 @@
-  *		by Davide Libenzi, preemptible kernel bits by Robert Love.
-  *  2003-09-03	Interactivity tuning by Con Kolivas.
-  *  2004-04-02	Scheduler domains code by Nick Piggin
-+ *  2007-03-02	Staircase deadline scheduling policy by Con Kolivas
-  */
- 
- #include <linux/mm.h>
-@@ -53,8 +54,9 @@
- #include <linux/kprobes.h>
- #include <linux/delayacct.h>
- #include <linux/reciprocal_div.h>
--
-+#include <linux/log2.h>
- #include <asm/tlb.h>
-+
- #include <asm/unistd.h>
- 
- /*
-@@ -84,147 +86,85 @@
- #define USER_PRIO(p)		((p)-MAX_RT_PRIO)
- #define TASK_USER_PRIO(p)	USER_PRIO((p)->static_prio)
- #define MAX_USER_PRIO		(USER_PRIO(MAX_PRIO))
-+#define SCHED_PRIO(p)		((p)+MAX_RT_PRIO)
- 
--/*
-- * Some helpers for converting nanosecond timing to jiffy resolution
-- */
--#define NS_TO_JIFFIES(TIME)	((TIME) / (1000000000 / HZ))
-+/* Some helpers for converting to/from various scales.*/
- #define JIFFIES_TO_NS(TIME)	((TIME) * (1000000000 / HZ))
--
--/*
-- * These are the 'tuning knobs' of the scheduler:
-- *
-- * Minimum timeslice is 5 msecs (or 1 jiffy, whichever is larger),
-- * default timeslice is 100 msecs, maximum timeslice is 800 msecs.
-- * Timeslices get refilled after they expire.
-- */
--#define MIN_TIMESLICE		max(5 * HZ / 1000, 1)
--#define DEF_TIMESLICE		(100 * HZ / 1000)
--#define ON_RUNQUEUE_WEIGHT	 30
--#define CHILD_PENALTY		 95
--#define PARENT_PENALTY		100
--#define EXIT_WEIGHT		  3
--#define PRIO_BONUS_RATIO	 25
--#define MAX_BONUS		(MAX_USER_PRIO * PRIO_BONUS_RATIO / 100)
--#define INTERACTIVE_DELTA	  2
--#define MAX_SLEEP_AVG		(DEF_TIMESLICE * MAX_BONUS)
--#define STARVATION_LIMIT	(MAX_SLEEP_AVG)
--#define NS_MAX_SLEEP_AVG	(JIFFIES_TO_NS(MAX_SLEEP_AVG))
--
--/*
-- * If a task is 'interactive' then we reinsert it in the active
-- * array after it has expired its current timeslice. (it will not
-- * continue to run immediately, it will still roundrobin with
-- * other interactive tasks.)
-- *
-- * This part scales the interactivity limit depending on niceness.
-- *
-- * We scale it linearly, offset by the INTERACTIVE_DELTA delta.
-- * Here are a few examples of different nice levels:
-- *
-- *  TASK_INTERACTIVE(-20): [1,1,1,1,1,1,1,1,1,0,0]
-- *  TASK_INTERACTIVE(-10): [1,1,1,1,1,1,1,0,0,0,0]
-- *  TASK_INTERACTIVE(  0): [1,1,1,1,0,0,0,0,0,0,0]
-- *  TASK_INTERACTIVE( 10): [1,1,0,0,0,0,0,0,0,0,0]
-- *  TASK_INTERACTIVE( 19): [0,0,0,0,0,0,0,0,0,0,0]
-- *
-- * (the X axis represents the possible -5 ... 0 ... +5 dynamic
-- *  priority range a task can explore, a value of '1' means the
-- *  task is rated interactive.)
-- *
-- * Ie. nice +19 tasks can never get 'interactive' enough to be
-- * reinserted into the active array. And only heavily CPU-hog nice -20
-- * tasks will be expired. Default nice 0 tasks are somewhere between,
-- * it takes some effort for them to get interactive, but it's not
-- * too hard.
-- */
--
--#define CURRENT_BONUS(p) \
--	(NS_TO_JIFFIES((p)->sleep_avg) * MAX_BONUS / \
--		MAX_SLEEP_AVG)
--
--#define GRANULARITY	(10 * HZ / 1000 ? : 1)
--
--#ifdef CONFIG_SMP
--#define TIMESLICE_GRANULARITY(p)	(GRANULARITY * \
--		(1 << (((MAX_BONUS - CURRENT_BONUS(p)) ? : 1) - 1)) * \
--			num_online_cpus())
--#else
--#define TIMESLICE_GRANULARITY(p)	(GRANULARITY * \
--		(1 << (((MAX_BONUS - CURRENT_BONUS(p)) ? : 1) - 1)))
--#endif
--
--#define SCALE(v1,v1_max,v2_max) \
--	(v1) * (v2_max) / (v1_max)
--
--#define DELTA(p) \
--	(SCALE(TASK_NICE(p) + 20, 40, MAX_BONUS) - 20 * MAX_BONUS / 40 + \
--		INTERACTIVE_DELTA)
--
--#define TASK_INTERACTIVE(p) \
--	((p)->prio <= (p)->static_prio - DELTA(p))
--
--#define INTERACTIVE_SLEEP(p) \
--	(JIFFIES_TO_NS(MAX_SLEEP_AVG * \
--		(MAX_BONUS / 2 + DELTA((p)) + 1) / MAX_BONUS - 1))
--
--#define TASK_PREEMPTS_CURR(p, rq) \
--	((p)->prio < (rq)->curr->prio)
--
--#define SCALE_PRIO(x, prio) \
--	max(x * (MAX_PRIO - prio) / (MAX_USER_PRIO / 2), MIN_TIMESLICE)
--
--static unsigned int static_prio_timeslice(int static_prio)
--{
--	if (static_prio < NICE_TO_PRIO(0))
--		return SCALE_PRIO(DEF_TIMESLICE * 4, static_prio);
--	else
--		return SCALE_PRIO(DEF_TIMESLICE, static_prio);
--}
--
--#ifdef CONFIG_SMP
--/*
-- * Divide a load by a sched group cpu_power : (load / sg->__cpu_power)
-- * Since cpu_power is a 'constant', we can use a reciprocal divide.
-+#define MS_TO_NS(TIME)		((TIME) * 1000000)
-+#define MS_TO_US(TIME)		((TIME) * 1000)
-+#define US_TO_MS(TIME)		((TIME) / 1000)
-+
-+#define TASK_PREEMPTS_CURR(p, curr)	((p)->prio < (curr)->prio)
-+
-+/*
-+ * This is the time all tasks within the same priority round robin.
-+ * Value is in ms and set to a minimum of 10ms. Scales with number of cpus.
-+ * Tunable via /proc interface.
-+ */
-+int rr_interval __read_mostly = 6;
-+int sched_interactive __read_mostly = 1;
-+
-+/*
-+ * sched_iso_cpu - sysctl which determines the cpu percentage SCHED_ISO tasks
-+ * are allowed to run (over ISO_PERIOD seconds) as real time tasks.
-+ * sched_iso_period - sysctl which determines the number of seconds over
-+ * which cpu usage of SCHED_ISO tasks is averaged to determine if they are
-+ * exceeding their allowable bandwidth.
-+*/
-+int sched_iso_cpu __read_mostly = 80;
-+int sched_iso_period __read_mostly = 5;
-+
-+#define ISO_PERIOD	((sched_iso_period * HZ) + 1)
-+
-+/*
-+ * This contains a bitmap for each dynamic priority level with empty slots
-+ * for the valid priorities each different nice level can have. It allows
-+ * us to stagger the slots where differing priorities run in a way that
-+ * keeps latency differences between different nice levels at a minimum.
-+ * The purpose of a pre-generated matrix is for rapid lookup of next slot in
-+ * O(1) time without having to recalculate every time priority gets demoted.
-+ * All nice levels use priority slot 39 as this allows less niced tasks to
-+ * get all priority slots better than that before expiration is forced.
-+ * ie, where 0 means a slot for that priority, priority running from left to
-+ * right is from prio 0 to prio 39:
-+ * nice -20 0000000000000000000000000000000000000000
-+ * nice -10 1000100010001000100010001000100010010000
-+ * nice   0 1010101010101010101010101010101010101010
-+ * nice   5 1011010110110101101101011011010110110110
-+ * nice  10 1110111011101110111011101110111011101110
-+ * nice  15 1111111011111110111111101111111011111110
-+ * nice  19 1111111111111111111111111111111111111110
-  */
--static inline u32 sg_div_cpu_power(const struct sched_group *sg, u32 load)
--{
--	return reciprocal_divide(load, sg->reciprocal_cpu_power);
--}
-+static unsigned long prio_matrix[PRIO_RANGE][BITS_TO_LONGS(PRIO_RANGE)]
-+				 __read_mostly;
- 
--/*
-- * Each time a sched group cpu_power is changed,
-- * we must compute its reciprocal value
-- */
--static inline void sg_inc_cpu_power(struct sched_group *sg, u32 val)
--{
--	sg->__cpu_power += val;
--	sg->reciprocal_cpu_power = reciprocal_value(sg->__cpu_power);
--}
--#endif
-+struct rq;
- 
- /*
-- * task_timeslice() scales user-nice values [ -20 ... 0 ... 19 ]
-- * to time slice values: [800ms ... 100ms ... 5ms]
-- *
-- * The higher a thread's priority, the bigger timeslices
-- * it gets during one round of execution. But even the lowest
-- * priority thread gets MIN_TIMESLICE worth of execution time.
-+ * These are the runqueue data structures:
-  */
-+struct prio_array {
-+	/* Tasks queued at each priority */
-+	struct list_head queue[MAX_PRIO + 1];
- 
--static inline unsigned int task_timeslice(struct task_struct *p)
--{
--	return static_prio_timeslice(p->static_prio);
--}
-+	/*
-+	 * The bitmap of priorities queued for this array. While the expired
-+	 * array will never have realtime tasks on it, it is simpler to have
-+	 * equal sized bitmaps for a cheap array swap. Include 1 bit for
-+	 * delimiter.
-+	 */
-+	DECLARE_BITMAP(prio_bitmap, MAX_PRIO + 1);
- 
--/*
-- * These are the runqueue data structures:
-- */
-+	/*
-+	 * The best static priority (of the dynamic priority tasks) queued
-+	 * this array.
-+	 */
-+	int best_static_prio;
- 
--struct prio_array {
--	unsigned int nr_active;
--	DECLARE_BITMAP(bitmap, MAX_PRIO+1); /* include 1 bit for delimiter */
--	struct list_head queue[MAX_PRIO];
-+#ifdef CONFIG_SMP
-+	/* For convenience looks back at rq */
-+	struct rq *rq;
-+#endif
- };
- 
- /*
-@@ -260,14 +200,28 @@
- 	 */
- 	unsigned long nr_uninterruptible;
- 
--	unsigned long expired_timestamp;
- 	/* Cached timestamp set by update_cpu_clock() */
- 	unsigned long long most_recent_timestamp;
- 	struct task_struct *curr, *idle;
- 	unsigned long next_balance;
- 	struct mm_struct *prev_mm;
--	struct prio_array *active, *expired, arrays[2];
--	int best_expired_prio;
-+
-+	struct prio_array *active, *expired, *idleprio, arrays[2];
-+	unsigned long *dyn_bitmap, *exp_bitmap;
-+
-+	/*
-+	 * The current dynamic priority level this runqueue is at per static
-+	 * priority level.
-+	 */
-+	int prio_level[PRIO_RANGE];
-+
-+	/* How many times we have rotated the priority queue */
-+	unsigned long prio_rotation;
-+	unsigned long iso_ticks;
-+	unsigned short iso_refractory;
-+
-+	/* Number of idleprio tasks running */
-+	unsigned long nr_idleprio;
- 	atomic_t nr_iowait;
- 
- #ifdef CONFIG_SMP
-@@ -606,12 +560,9 @@
- #if defined(CONFIG_SCHEDSTATS) || defined(CONFIG_TASK_DELAY_ACCT)
- /*
-  * Called when a process is dequeued from the active array and given
-- * the cpu.  We should note that with the exception of interactive
-- * tasks, the expired queue will become the active queue after the active
-- * queue is empty, without explicitly dequeuing and requeuing tasks in the
-- * expired queue.  (Interactive tasks may be requeued directly to the
-- * active queue, thus delaying tasks in the expired queue from running;
-- * see scheduler_tick()).
-+ * the cpu.  We should note that the expired queue will become the active
-+ * queue after the active queue is empty, without explicitly dequeuing and
-+ * requeuing tasks in the expired queue.
-  *
-  * This function is only called from sched_info_arrive(), rather than
-  * dequeue_task(). Even though a task may be queued and dequeued multiple
-@@ -709,71 +660,304 @@
- #define sched_info_switch(t, next)	do { } while (0)
- #endif /* CONFIG_SCHEDSTATS || CONFIG_TASK_DELAY_ACCT */
- 
-+static int idleprio_suitable(struct task_struct *p)
-+{
-+	return (!p->mutexes_held && !freezing(p) && !signal_pending(p) &&
-+		!(p->flags & (PF_NONSLEEP | PF_EXITING)));
-+}
-+
-+static int idleprio(const struct task_struct *p)
-+{
-+	return (p->prio == MAX_PRIO);
-+}
-+
-+static inline int task_queued(struct task_struct *task)
-+{
-+	return !list_empty(&task->run_list);
-+}
-+
-+static inline void set_dynamic_bit(struct task_struct *p, struct rq *rq)
-+{
-+	__set_bit(p->prio, p->array->prio_bitmap);
-+}
-+
- /*
-- * Adding/removing a task to/from a priority array:
-+ * Removing from a runqueue.
-  */
--static void dequeue_task(struct task_struct *p, struct prio_array *array)
-+static void dequeue_task(struct task_struct *p, struct rq *rq)
- {
--	array->nr_active--;
--	list_del(&p->run_list);
--	if (list_empty(array->queue + p->prio))
--		__clear_bit(p->prio, array->bitmap);
-+	list_del_init(&p->run_list);
-+	if (idleprio_task(p) && idleprio(p))
-+		rq->nr_idleprio--;
-+	else if (list_empty(p->array->queue + p->prio))
-+		__clear_bit(p->prio, p->array->prio_bitmap);
- }
- 
--static void enqueue_task(struct task_struct *p, struct prio_array *array)
-+static void reset_first_time_slice(struct task_struct *p)
- {
--	sched_info_queued(p);
--	list_add_tail(&p->run_list, array->queue + p->prio);
--	__set_bit(p->prio, array->bitmap);
--	array->nr_active++;
-+	if (unlikely(p->first_time_slice))
-+		p->first_time_slice = 0;
-+}
-+
-+/*
-+ * The task is being queued on a fresh array so it has its entitlement
-+ * bitmap cleared.
-+ */
-+static void task_new_array(struct task_struct *p, struct rq *rq,
-+			   struct prio_array *array)
-+{
-+	bitmap_zero(p->bitmap, PRIO_RANGE);
-+	p->rotation = rq->prio_rotation;
-+	p->time_slice = p->quota;
- 	p->array = array;
-+	reset_first_time_slice(p);
-+}
-+
-+/* Find the first slot from the relevant prio_matrix entry */
-+static int first_prio_slot(struct task_struct *p)
-+{
-+	if (unlikely(p->policy == SCHED_BATCH))
-+		return p->static_prio;
-+	return SCHED_PRIO(find_first_zero_bit(
-+		prio_matrix[USER_PRIO(p->static_prio)], PRIO_RANGE));
- }
- 
- /*
-- * Put task to the end of the run list without the overhead of dequeue
-- * followed by enqueue.
-+ * In sched_interactive mode priority allocation occurs per process per rq
-+ * array swap. In !sched_interactive mode all waking tasks must obey the
-+ * current prio level of all other tasks running per array swap.
-  */
--static void requeue_task(struct task_struct *p, struct prio_array *array)
-+static int minprio(struct rq *rq, int uprio)
- {
--	list_move_tail(&p->run_list, array->queue + p->prio);
-+	if (sched_interactive)
-+		return MAX_RT_PRIO;
-+	return rq->prio_level[uprio];
- }
- 
--static inline void
--enqueue_task_head(struct task_struct *p, struct prio_array *array)
-+/*
-+ * Find the first unused slot by this task that is also in its prio_matrix
-+ * level. SCHED_BATCH tasks do not use the priority matrix. They only take
-+ * priority slots from their static_prio and above.
-+ */
-+static int next_entitled_slot(struct task_struct *p, struct rq *rq)
- {
--	list_add(&p->run_list, array->queue + p->prio);
--	__set_bit(p->prio, array->bitmap);
--	array->nr_active++;
--	p->array = array;
-+	int search_prio = MAX_RT_PRIO, uprio = USER_PRIO(p->static_prio);
-+	struct prio_array *array = rq->active;
-+	DECLARE_BITMAP(tmp, PRIO_RANGE);
-+
-+	/*
-+	 * Go straight to expiration if there are higher priority tasks
-+	 * already expired.
-+	 */
-+	if (p->static_prio > rq->expired->best_static_prio)
-+		return MAX_PRIO;
-+	if (!rq->prio_level[uprio])
-+		rq->prio_level[uprio] = MAX_RT_PRIO;
-+	/*
-+	 * Only priorities equal to the prio_level and above for their
-+	 * static_prio are acceptable, and only if it's not better than
-+	 * a queued better static_prio's prio_level.
-+	 */
-+	if (p->static_prio < array->best_static_prio) {
-+		if (likely(p->policy != SCHED_BATCH))
-+			array->best_static_prio = p->static_prio;
-+	} else if (p->static_prio == array->best_static_prio) {
-+		search_prio = minprio(rq, uprio);
-+	} else {
-+		int i;
-+
-+		search_prio = minprio(rq, uprio);
-+		/* A bound O(n) function, worst case n is 40 */
-+		for (i = array->best_static_prio; i <= p->static_prio ; i++) {
-+			if (!rq->prio_level[USER_PRIO(i)])
-+				rq->prio_level[USER_PRIO(i)] = MAX_RT_PRIO;
-+			search_prio = max(search_prio,
-+				      rq->prio_level[USER_PRIO(i)]);
-+		}
-+	}
-+	if (unlikely(p->policy == SCHED_BATCH)) {
-+		search_prio = max(search_prio, p->static_prio);
-+		return SCHED_PRIO(find_next_zero_bit(p->bitmap, PRIO_RANGE,
-+				  USER_PRIO(search_prio)));
-+	}
-+	bitmap_or(tmp, p->bitmap, prio_matrix[uprio], PRIO_RANGE);
-+	return SCHED_PRIO(find_next_zero_bit(tmp, PRIO_RANGE,
-+		USER_PRIO(search_prio)));
-+}
-+
-+static void queue_expired(struct task_struct *p, struct rq *rq)
-+{
-+	task_new_array(p, rq, rq->expired);
-+	p->prio = p->normal_prio = first_prio_slot(p);
-+	if (p->static_prio < rq->expired->best_static_prio)
-+		rq->expired->best_static_prio = p->static_prio;
-+	reset_first_time_slice(p);
- }
- 
-+#ifdef CONFIG_SMP
- /*
-- * __normal_prio - return the priority that is based on the static
-- * priority but is modified by bonuses/penalties.
-- *
-- * We scale the actual sleep average [0 .... MAX_SLEEP_AVG]
-- * into the -5 ... 0 ... +5 bonus/penalty range.
-- *
-- * We use 25% of the full 0...39 priority range so that:
-- *
-- * 1) nice +19 interactive tasks do not preempt nice 0 CPU hogs.
-- * 2) nice -20 CPU hogs do not get preempted by nice 0 tasks.
-- *
-- * Both properties are important to certain workloads.
-+ * If we're waking up a task that was previously on a different runqueue,
-+ * update its data appropriately. Note we may be reading data from src_rq->
-+ * outside of lock, but the occasional inaccurate result should be harmless.
-  */
-+ static void update_if_moved(struct task_struct *p, struct rq *rq)
-+{
-+	struct rq *src_rq = p->array->rq;
-+
-+	if (src_rq == rq)
-+		return;
-+	/*
-+	 * Only need to set p->array when p->rotation == rq->prio_rotation as
-+	 * they will be set in recalc_task_prio when != rq->prio_rotation.
-+	 */
-+	if (p->rotation == src_rq->prio_rotation) {
-+		p->rotation = rq->prio_rotation;
-+		if (p->array == src_rq->expired)
-+			p->array = rq->expired;
-+		else
-+			p->array = rq->active;
-+	} else
-+		p->rotation = 0;
-+}
-+#else
-+static inline void update_if_moved(struct task_struct *p, struct rq *rq)
-+{
-+}
-+#endif
- 
--static inline int __normal_prio(struct task_struct *p)
-+static inline int isoprio_suitable(struct task_struct *p)
- {
--	int bonus, prio;
-+	return !(p->flags & PF_ISOREF);
-+}
- 
--	bonus = CURRENT_BONUS(p) - MAX_BONUS / 2;
-+static int task_timeslice(struct task_struct *p);
- 
--	prio = p->static_prio - bonus;
--	if (prio < MAX_RT_PRIO)
--		prio = MAX_RT_PRIO;
--	if (prio > MAX_PRIO-1)
--		prio = MAX_PRIO-1;
--	return prio;
-+/*
-+ * recalc_task_prio determines what priority a non rt_task will be
-+ * queued at. If the task has already been running during this runqueue's
-+ * major rotation (rq->prio_rotation) then it continues at the same
-+ * priority if it has tick entitlement left. If it does not have entitlement
-+ * left, it finds the next priority slot according to its nice value that it
-+ * has not extracted quota from. If it has not run during this major
-+ * rotation, it starts at the next_entitled_slot and has its bitmap quota
-+ * cleared. If it does not have any slots left it has all its slots reset and
-+ * is queued on the expired at its first_prio_slot.
-+ */
-+static void recalc_task_prio(struct task_struct *p, struct rq *rq)
-+{
-+	struct prio_array *array = rq->active;
-+	int queue_prio;
-+
-+	if (iso_task(p)) {
-+		if (isoprio_suitable(p)) {
-+			/*
-+			 * If SCHED_ISO tasks have not used up their real time
-+			 * quota they have run just better than highest
-+			 * SCHED_NORMAL priority. Otherwise they run as
-+			 * SCHED_NORMAL.
-+			 */
-+			p->prio = p->normal_prio = ISO_PRIO;
-+			p->array = rq->active;
-+			if (p->time_slice <= 0)
-+				p->time_slice = p->quota;
-+			return;
-+		} else if (p->prio == ISO_PRIO) {
-+			/* Just about to be demoted to SCHED_NORMAL */
-+			p->time_slice = 0;
-+		}
-+	} else if (idleprio_task(p)) {
-+		if (idleprio_suitable(p)) {
-+			/*
-+			 * If suitable idleprio_tasks are queued at MAX_PRIO
-+			 * only on the idleprio array. Their time_slice is
-+			 * their full task_timeslice as they cooperatively
-+			 * multitask.
-+			 */
-+			p->prio = p->normal_prio = MAX_PRIO;
-+			p->array = rq->idleprio;
-+			if (p->time_slice <= 0)
-+				p->time_slice = task_timeslice(p);
-+			return;
-+		}
-+		/*
-+		 * If unsuitable idleprio_tasks are queued equivalent to
-+		 * nice 19 tasks on the expired array.
-+		 */
-+		p->flags &= ~PF_NONSLEEP;
-+		p->prio = p->normal_prio = MAX_PRIO - 1;
-+		p->array = rq->expired;
-+		if (p->time_slice <= 0 || p->time_slice > p->quota)
-+			p->time_slice = p->quota;
-+		return;
-+	}
-+
-+	update_if_moved(p, rq);
-+	if (p->rotation == rq->prio_rotation) {
-+		if (p->array == array) {
-+			if (p->time_slice > 0)
-+				return;
-+			p->time_slice = p->quota;
-+		} else if (p->array == rq->expired) {
-+			queue_expired(p, rq);
-+			return;
-+		} else
-+			task_new_array(p, rq, array);
-+	} else
-+		task_new_array(p, rq, array);
-+
-+	queue_prio = next_entitled_slot(p, rq);
-+	if (queue_prio >= MAX_PRIO) {
-+		queue_expired(p, rq);
-+		return;
-+	}
-+	p->prio = p->normal_prio = queue_prio;
-+	__set_bit(USER_PRIO(p->prio), p->bitmap);
-+}
-+
-+/*
-+ * Adding to a runqueue. The dynamic priority queue that it is added to is
-+ * determined by recalc_task_prio() above.
-+ */
-+static inline void __enqueue_task(struct task_struct *p, struct rq *rq)
-+{
-+	if (rt_task(p))
-+		p->array = rq->active;
-+	else
-+		recalc_task_prio(p, rq);
-+
-+	if (idleprio_task(p) && idleprio(p))
-+		rq->nr_idleprio++;
-+	sched_info_queued(p);
-+	set_dynamic_bit(p, rq);
-+}
-+
-+static void enqueue_task(struct task_struct *p, struct rq *rq)
-+{
-+	__enqueue_task(p, rq);
-+	list_add_tail(&p->run_list, p->array->queue + p->prio);
-+}
-+
-+static inline void enqueue_task_head(struct task_struct *p, struct rq *rq)
-+{
-+	__enqueue_task(p, rq);
-+	list_add(&p->run_list, p->array->queue + p->prio);
-+}
-+
-+/*
-+ * requeue_task is only called when p->static_prio does not change. p->prio
-+ * can change with dynamic tasks.
-+ */
-+static void requeue_task(struct task_struct *p, struct rq *rq,
-+			 struct prio_array *old_array, int old_prio)
-+{
-+	if (p->array == rq->expired)
-+		queue_expired(p, rq);
-+	list_move_tail(&p->run_list, p->array->queue + p->prio);
-+	if (!rt_task(p)) {
-+		if (list_empty(old_array->queue + old_prio))
-+			__clear_bit(old_prio, old_array->prio_bitmap);
-+		set_dynamic_bit(p, rq);
-+	}
- }
- 
- /*
-@@ -786,20 +970,29 @@
-  */
- 
- /*
-- * Assume: static_prio_timeslice(NICE_TO_PRIO(0)) == DEF_TIMESLICE
-- * If static_prio_timeslice() is ever changed to break this assumption then
-- * this code will need modification
-- */
--#define TIME_SLICE_NICE_ZERO DEF_TIMESLICE
--#define LOAD_WEIGHT(lp) \
--	(((lp) * SCHED_LOAD_SCALE) / TIME_SLICE_NICE_ZERO)
--#define PRIO_TO_LOAD_WEIGHT(prio) \
--	LOAD_WEIGHT(static_prio_timeslice(prio))
--#define RTPRIO_TO_LOAD_WEIGHT(rp) \
--	(PRIO_TO_LOAD_WEIGHT(MAX_RT_PRIO) + LOAD_WEIGHT(rp))
-+ * task_timeslice - the total duration a task can run during one major
-+ * rotation. Returns value in milliseconds as the smallest value can be 1.
-+ */
-+static int task_timeslice(struct task_struct *p)
-+{
-+	int slice = p->quota;	/* quota is in us */
-+
-+	if (!rt_task(p))
-+		slice += (PRIO_RANGE - 1 - TASK_USER_PRIO(p)) * slice;
-+	return US_TO_MS(slice);
-+}
-+
-+/*
-+ * The load weight is basically the task_timeslice in ms. Realtime tasks are
-+ * special cased to be proportionately larger than nice -20 by their
-+ * rt_priority. The weight for rt tasks can only be arbitrary at best.
-+ */
-+#define RTPRIO_TO_LOAD_WEIGHT(rp)	(rr_interval * 20 * (40 + rp))
- 
- static void set_load_weight(struct task_struct *p)
- {
-+	int load_weight;
-+
- 	if (has_rt_policy(p)) {
- #ifdef CONFIG_SMP
- 		if (p == task_rq(p)->migration_thread)
-@@ -808,12 +1001,19 @@
- 			 * Giving its load any weight will skew balancing
- 			 * adversely.
- 			 */
--			p->load_weight = 0;
-+			load_weight = 0;
- 		else
- #endif
--			p->load_weight = RTPRIO_TO_LOAD_WEIGHT(p->rt_priority);
-+			load_weight = RTPRIO_TO_LOAD_WEIGHT(p->rt_priority);
- 	} else
--		p->load_weight = PRIO_TO_LOAD_WEIGHT(p->static_prio);
-+		load_weight = task_timeslice(p);
-+	/*
-+	 * idleprio tasks have much lower weight than SCHED_NORMAL tasks but
-+	 * still need to be weighted to allow balancing to occur.
-+	 */
-+	if (likely(!idleprio_task(p)))
-+		load_weight *= PRIO_RANGE;
-+	p->load_weight = load_weight;
- }
- 
- static inline void
-@@ -841,28 +1041,38 @@
- }
- 
- /*
-- * Calculate the expected normal priority: i.e. priority
-- * without taking RT-inheritance into account. Might be
-- * boosted by interactivity modifiers. Changes upon fork,
-- * setprio syscalls, and whenever the interactivity
-- * estimator recalculates.
-+ * __activate_task - move a task to the runqueue.
-  */
--static inline int normal_prio(struct task_struct *p)
-+static inline void __activate_task(struct task_struct *p, struct rq *rq)
- {
--	int prio;
-+	enqueue_task(p, rq);
-+	inc_nr_running(p, rq);
-+}
- 
-+/*
-+ * __activate_idle_task - move idle task to the _front_ of runqueue.
-+ */
-+static inline void __activate_idle_task(struct task_struct *p, struct rq *rq)
-+{
-+	enqueue_task_head(p, rq);
-+	inc_nr_running(p, rq);
-+}
-+
-+static inline int normal_prio(struct task_struct *p)
-+{
- 	if (has_rt_policy(p))
--		prio = MAX_RT_PRIO-1 - p->rt_priority;
-+		return MAX_RT_PRIO-1 - p->rt_priority;
-+	/* Other tasks all have normal_prio set in recalc_task_prio */
-+	if (likely(p->prio >= MAX_RT_PRIO && p->prio < MAX_PRIO))
-+		return p->prio;
- 	else
--		prio = __normal_prio(p);
--	return prio;
-+		return p->static_prio;
- }
- 
- /*
-  * Calculate the current priority, i.e. the priority
-  * taken into account by the scheduler. This value might
-- * be boosted by RT tasks, or might be boosted by
-- * interactivity modifiers. Will be RT if the task got
-+ * be boosted by RT tasks as it will be RT if the task got
-  * RT-boosted. If not then it returns p->normal_prio.
-  */
- static int effective_prio(struct task_struct *p)
-@@ -878,112 +1088,70 @@
- 	return p->prio;
- }
- 
--/*
-- * __activate_task - move a task to the runqueue.
-- */
--static void __activate_task(struct task_struct *p, struct rq *rq)
-+static inline unsigned int nice_quota_ms(int nice)
- {
--	struct prio_array *target = rq->active;
-+	unsigned int rr = rr_interval;
- 
--	if (batch_task(p))
--		target = rq->expired;
--	enqueue_task(p, target);
--	inc_nr_running(p, rq);
-+	if (nice < -6) {
-+		rr *= nice * nice;
-+		rr /= 40;
-+	} else if (nice > 0)
-+		rr = rr / 2 ? : 1;
-+	return rr;
- }
- 
-+#define DEFAULT_WEIGHT	(nice_quota_ms(0) * 20 * PRIO_RANGE)
-+
- /*
-- * __activate_idle_task - move idle task to the _front_ of runqueue.
-+ * A runqueue laden with a single nice 0 task scores a weighted_cpuload of
-+ * SCHED_LOAD_SCALE. This function returns 1 if any cpu is laden with a
-+ * task of nice 0 or enough lower priority tasks to bring up the
-+ * weighted_cpuload
-  */
--static inline void __activate_idle_task(struct task_struct *p, struct rq *rq)
-+int above_background_load(void)
- {
--	enqueue_task_head(p, rq->active);
--	inc_nr_running(p, rq);
-+	unsigned long cpu;
-+
-+	for_each_online_cpu(cpu) {
-+		if (weighted_cpuload(cpu) >= DEFAULT_WEIGHT)
-+			return 1;
-+	}
-+	return 0;
- }
- 
- /*
-- * Recalculate p->normal_prio and p->prio after having slept,
-- * updating the sleep-average too:
-+ * All tasks have quotas based on rr_interval. RT tasks all get rr_interval.
-+ * From nice 1 to 19 they are smaller than it only if they are at least one
-+ * tick still. Below nice 0 they get progressively larger.
-+ * ie nice -6..0 = rr_interval. nice -10 = 2.5 * rr_interval
-+ * nice -20 = 10 * rr_interval. nice 1-19 = rr_interval / 2.
-+ * Value returned is in microseconds.
-  */
--static int recalc_task_prio(struct task_struct *p, unsigned long long now)
-+static inline unsigned int rr_quota(struct task_struct *p)
- {
--	/* Caller must always ensure 'now >= p->timestamp' */
--	unsigned long sleep_time = now - p->timestamp;
-+	unsigned int quota;
- 
--	if (batch_task(p))
--		sleep_time = 0;
--
--	if (likely(sleep_time > 0)) {
--		/*
--		 * This ceiling is set to the lowest priority that would allow
--		 * a task to be reinserted into the active array on timeslice
--		 * completion.
--		 */
--		unsigned long ceiling = INTERACTIVE_SLEEP(p);
--
--		if (p->mm && sleep_time > ceiling && p->sleep_avg < ceiling) {
--			/*
--			 * Prevents user tasks from achieving best priority
--			 * with one single large enough sleep.
--			 */
--			p->sleep_avg = ceiling;
--			/*
--			 * Using INTERACTIVE_SLEEP() as a ceiling places a
--			 * nice(0) task 1ms sleep away from promotion, and
--			 * gives it 700ms to round-robin with no chance of
--			 * being demoted.  This is more than generous, so
--			 * mark this sleep as non-interactive to prevent the
--			 * on-runqueue bonus logic from intervening should
--			 * this task not receive cpu immediately.
--			 */
--			p->sleep_type = SLEEP_NONINTERACTIVE;
--		} else {
--			/*
--			 * Tasks waking from uninterruptible sleep are
--			 * limited in their sleep_avg rise as they
--			 * are likely to be waiting on I/O
--			 */
--			if (p->sleep_type == SLEEP_NONINTERACTIVE && p->mm) {
--				if (p->sleep_avg >= ceiling)
--					sleep_time = 0;
--				else if (p->sleep_avg + sleep_time >=
--					 ceiling) {
--						p->sleep_avg = ceiling;
--						sleep_time = 0;
--				}
--			}
--
--			/*
--			 * This code gives a bonus to interactive tasks.
--			 *
--			 * The boost works by updating the 'average sleep time'
--			 * value here, based on ->timestamp. The more time a
--			 * task spends sleeping, the higher the average gets -
--			 * and the higher the priority boost gets as well.
--			 */
--			p->sleep_avg += sleep_time;
--
--		}
--		if (p->sleep_avg > NS_MAX_SLEEP_AVG)
--			p->sleep_avg = NS_MAX_SLEEP_AVG;
--	}
-+	if (rt_task(p))
-+		quota = rr_interval;
-+	else
-+		quota = nice_quota_ms(TASK_NICE(p));
-+	return MS_TO_US(quota);
-+}
- 
--	return effective_prio(p);
-+/* Every time we set the quota we need to set the load weight */
-+static void set_quota(struct task_struct *p)
-+{
-+	p->quota = rr_quota(p);
-+	set_load_weight(p);
- }
- 
- /*
-  * activate_task - move a task to the runqueue and do priority recalculation
-- *
-- * Update all the scheduling statistics stuff. (sleep average
-- * calculation, priority modifiers, etc.)
-  */
- static void activate_task(struct task_struct *p, struct rq *rq, int local)
- {
--	unsigned long long now;
--
--	if (rt_task(p))
--		goto out;
-+	unsigned long long now = sched_clock();
- 
--	now = sched_clock();
- #ifdef CONFIG_SMP
- 	if (!local) {
- 		/* Compensate for drifting sched_clock */
-@@ -1004,32 +1172,9 @@
- 				     (now - p->timestamp) >> 20);
- 	}
- 
--	p->prio = recalc_task_prio(p, now);
--
--	/*
--	 * This checks to make sure it's not an uninterruptible task
--	 * that is now waking up.
--	 */
--	if (p->sleep_type == SLEEP_NORMAL) {
--		/*
--		 * Tasks which were woken up by interrupts (ie. hw events)
--		 * are most likely of interactive nature. So we give them
--		 * the credit of extending their sleep time to the period
--		 * of time they spend on the runqueue, waiting for execution
--		 * on a CPU, first time around:
--		 */
--		if (in_interrupt())
--			p->sleep_type = SLEEP_INTERRUPTED;
--		else {
--			/*
--			 * Normal first-time wakeups get a credit too for
--			 * on-runqueue time, but it will be weighted down:
--			 */
--			p->sleep_type = SLEEP_INTERACTIVE;
--		}
--	}
-+	set_quota(p);
-+	p->prio = effective_prio(p);
- 	p->timestamp = now;
--out:
- 	__activate_task(p, rq);
- }
- 
-@@ -1039,8 +1184,7 @@
- static void deactivate_task(struct task_struct *p, struct rq *rq)
- {
- 	dec_nr_running(p, rq);
--	dequeue_task(p, p->array);
--	p->array = NULL;
-+	dequeue_task(p, rq);
- }
- 
- /*
-@@ -1133,7 +1277,7 @@
- 	 * If the task is not on a runqueue (and not running), then
- 	 * it is sufficient to simply update the task's cpu field.
- 	 */
--	if (!p->array && !task_running(rq, p)) {
-+	if (!task_queued(p) && !task_running(rq, p)) {
- 		set_task_cpu(p, dest_cpu);
- 		return 0;
- 	}
-@@ -1159,7 +1303,6 @@
- {
- 	unsigned long flags;
- 	struct rq *rq;
--	struct prio_array *array;
- 	int running;
- 
- repeat:
-@@ -1192,7 +1335,6 @@
- 	 */
- 	rq = task_rq_lock(p, &flags);
- 	running = task_running(rq, p);
--	array = p->array;
- 	task_rq_unlock(rq, &flags);
- 
- 	/*
-@@ -1215,7 +1357,7 @@
- 	 * running right now), it's preempted, and we should
- 	 * yield - it could be a while.
- 	 */
--	if (unlikely(array)) {
-+	if (unlikely(task_queued(p))) {
- 		yield();
- 		goto repeat;
- 	}
-@@ -1294,6 +1436,25 @@
- }
- 
- /*
-+ * Divide a load by a sched group cpu_power : (load / sg->__cpu_power)
-+ * Since cpu_power is a 'constant', we can use a reciprocal divide.
-+ */
-+static inline u32 sg_div_cpu_power(const struct sched_group *sg, u32 load)
-+{
-+	return reciprocal_divide(load, sg->reciprocal_cpu_power);
-+}
-+
-+/*
-+ * Each time a sched group cpu_power is changed,
-+ * we must compute its reciprocal value
-+ */
-+static inline void sg_inc_cpu_power(struct sched_group *sg, u32 val)
-+{
-+	sg->__cpu_power += val;
-+	sg->reciprocal_cpu_power = reciprocal_value(sg->__cpu_power);
-+}
-+
-+/*
-  * find_idlest_group finds and returns the least busy CPU group within the
-  * domain.
-  */
-@@ -1490,6 +1651,31 @@
- }
- #endif
- 
-+/*
-+ * We need to have a special definition for an idle runqueue when testing
-+ * for preemption on CONFIG_HOTPLUG_CPU as the idle task may be scheduled as
-+ * a realtime task in sched_idle_next.
-+ */
-+#ifdef CONFIG_HOTPLUG_CPU
-+#define rq_idle(rq)	((rq)->curr == (rq)->idle && !rt_task((rq)->curr))
-+#else
-+#define rq_idle(rq)	((rq)->curr == (rq)->idle)
-+#endif
-+
-+static inline int task_preempts_curr(struct task_struct *p, struct rq *rq)
-+{
-+	struct task_struct *curr = rq->curr;
-+
-+	return ((p->array == task_rq(p)->active &&
-+		TASK_PREEMPTS_CURR(p, curr)) || rq_idle(rq));
-+}
-+
-+static inline void try_preempt(struct task_struct *p, struct rq *rq)
-+{
-+	if (task_preempts_curr(p, rq))
-+		resched_task(rq->curr);
-+}
-+
- /***
-  * try_to_wake_up - wake up a thread
-  * @p: the to-be-woken-up thread
-@@ -1521,7 +1707,7 @@
- 	if (!(old_state & state))
- 		goto out;
- 
--	if (p->array)
-+	if (task_queued(p))
- 		goto out_running;
- 
- 	cpu = task_cpu(p);
-@@ -1614,7 +1800,7 @@
- 		old_state = p->state;
- 		if (!(old_state & state))
- 			goto out;
--		if (p->array)
-+		if (task_queued(p))
- 			goto out_running;
- 
- 		this_cpu = smp_processor_id();
-@@ -1623,25 +1809,9 @@
- 
- out_activate:
- #endif /* CONFIG_SMP */
--	if (old_state == TASK_UNINTERRUPTIBLE) {
-+	if (old_state == TASK_UNINTERRUPTIBLE)
- 		rq->nr_uninterruptible--;
--		/*
--		 * Tasks on involuntary sleep don't earn
--		 * sleep_avg beyond just interactive state.
--		 */
--		p->sleep_type = SLEEP_NONINTERACTIVE;
--	} else
--
--	/*
--	 * Tasks that have marked their sleep as noninteractive get
--	 * woken up with their sleep average not weighted in an
--	 * interactive way.
--	 */
--		if (old_state & TASK_NONINTERACTIVE)
--			p->sleep_type = SLEEP_NONINTERACTIVE;
--
- 
--	activate_task(p, rq, cpu == this_cpu);
- 	/*
- 	 * Sync wakeups (i.e. those types of wakeups where the waker
- 	 * has indicated that it will leave the CPU in short order)
-@@ -1650,15 +1820,22 @@
- 	 * the waker guarantees that the freshly woken up task is going
- 	 * to be considered on this CPU.)
- 	 */
--	if (!sync || cpu != this_cpu) {
--		if (TASK_PREEMPTS_CURR(p, rq))
--			resched_task(rq->curr);
--	}
-+	activate_task(p, rq, cpu == this_cpu);
-+	if (!sync || cpu != this_cpu)
-+		try_preempt(p, rq);
- 	success = 1;
- 
- out_running:
- 	p->state = TASK_RUNNING;
- out:
-+	/*
-+	 * Special case when freezing we need to reschedule idleprio tasks
-+	 * as SCHED_NORMAL or else they'll never freeze
-+	 */
-+	if (idleprio_task(p) && freezing(p) && idleprio(p)) {
-+		dequeue_task(p, rq);
-+		enqueue_task(p, rq);
-+	}
- 	task_rq_unlock(rq, &flags);
- 
- 	return success;
-@@ -1676,7 +1853,6 @@
- 	return try_to_wake_up(p, state, 0);
- }
- 
--static void task_running_tick(struct rq *rq, struct task_struct *p);
- /*
-  * Perform scheduler related setup for a newly forked process p.
-  * p is forked by current.
-@@ -1704,7 +1880,6 @@
- 	p->prio = current->normal_prio;
- 
- 	INIT_LIST_HEAD(&p->run_list);
--	p->array = NULL;
- #if defined(CONFIG_SCHEDSTATS) || defined(CONFIG_TASK_DELAY_ACCT)
- 	if (unlikely(sched_info_on()))
- 		memset(&p->sched_info, 0, sizeof(p->sched_info));
-@@ -1716,30 +1891,31 @@
- 	/* Want to start with kernel preemption disabled. */
- 	task_thread_info(p)->preempt_count = 1;
- #endif
-+	if (unlikely(p->policy == SCHED_FIFO))
-+		goto out;
- 	/*
- 	 * Share the timeslice between parent and child, thus the
- 	 * total amount of pending timeslices in the system doesn't change,
- 	 * resulting in more scheduling fairness.
- 	 */
- 	local_irq_disable();
--	p->time_slice = (current->time_slice + 1) >> 1;
--	/*
--	 * The remainder of the first timeslice might be recovered by
--	 * the parent if the child exits early enough.
--	 */
--	p->first_time_slice = 1;
--	current->time_slice >>= 1;
--	p->timestamp = sched_clock();
--	if (unlikely(!current->time_slice)) {
-+	if (current->time_slice > 0) {
-+		current->time_slice /= 2;
-+		if (current->time_slice)
-+			p->time_slice = current->time_slice;
-+		else
-+			p->time_slice = 1;
- 		/*
--		 * This case is rare, it happens when the parent has only
--		 * a single jiffy left from its timeslice. Taking the
--		 * runqueue lock is not a problem.
-+		 * The remainder of the first timeslice might be recovered by
-+		 * the parent if the child exits early enough.
- 		 */
--		current->time_slice = 1;
--		task_running_tick(cpu_rq(cpu), current);
--	}
-+		p->first_time_slice = 1;
-+	} else
-+		p->time_slice = 0;
-+
-+	p->timestamp = sched_clock();
- 	local_irq_enable();
-+out:
- 	put_cpu();
- }
- 
-@@ -1761,38 +1937,16 @@
- 	this_cpu = smp_processor_id();
- 	cpu = task_cpu(p);
- 
--	/*
--	 * We decrease the sleep average of forking parents
--	 * and children as well, to keep max-interactive tasks
--	 * from forking tasks that are max-interactive. The parent
--	 * (current) is done further down, under its lock.
--	 */
--	p->sleep_avg = JIFFIES_TO_NS(CURRENT_BONUS(p) *
--		CHILD_PENALTY / 100 * MAX_SLEEP_AVG / MAX_BONUS);
--
--	p->prio = effective_prio(p);
--
- 	if (likely(cpu == this_cpu)) {
-+		activate_task(p, rq, 1);
- 		if (!(clone_flags & CLONE_VM)) {
- 			/*
- 			 * The VM isn't cloned, so we're in a good position to
- 			 * do child-runs-first in anticipation of an exec. This
- 			 * usually avoids a lot of COW overhead.
- 			 */
--			if (unlikely(!current->array))
--				__activate_task(p, rq);
--			else {
--				p->prio = current->prio;
--				p->normal_prio = current->normal_prio;
--				list_add_tail(&p->run_list, &current->run_list);
--				p->array = current->array;
--				p->array->nr_active++;
--				inc_nr_running(p, rq);
--			}
- 			set_need_resched();
--		} else
--			/* Run child last */
--			__activate_task(p, rq);
-+		}
- 		/*
- 		 * We skip the following code due to cpu == this_cpu
- 	 	 *
-@@ -1809,19 +1963,16 @@
- 		 */
- 		p->timestamp = (p->timestamp - this_rq->most_recent_timestamp)
- 					+ rq->most_recent_timestamp;
--		__activate_task(p, rq);
--		if (TASK_PREEMPTS_CURR(p, rq))
--			resched_task(rq->curr);
-+		activate_task(p, rq, 0);
-+		try_preempt(p, rq);
- 
- 		/*
- 		 * Parent and child are on different CPUs, now get the
--		 * parent runqueue to update the parent's ->sleep_avg:
-+		 * parent runqueue to update the parent's ->flags:
- 		 */
- 		task_rq_unlock(rq, &flags);
- 		this_rq = task_rq_lock(current, &flags);
- 	}
--	current->sleep_avg = JIFFIES_TO_NS(CURRENT_BONUS(current) *
--		PARENT_PENALTY / 100 * MAX_SLEEP_AVG / MAX_BONUS);
- 	task_rq_unlock(this_rq, &flags);
- }
- 
-@@ -1836,23 +1987,17 @@
-  */
- void fastcall sched_exit(struct task_struct *p)
- {
-+	struct task_struct *parent;
- 	unsigned long flags;
- 	struct rq *rq;
- 
--	/*
--	 * If the child was a (relative-) CPU hog then decrease
--	 * the sleep_avg of the parent as well.
--	 */
--	rq = task_rq_lock(p->parent, &flags);
--	if (p->first_time_slice && task_cpu(p) == task_cpu(p->parent)) {
--		p->parent->time_slice += p->time_slice;
--		if (unlikely(p->parent->time_slice > task_timeslice(p)))
--			p->parent->time_slice = task_timeslice(p);
--	}
--	if (p->sleep_avg < p->parent->sleep_avg)
--		p->parent->sleep_avg = p->parent->sleep_avg /
--		(EXIT_WEIGHT + 1) * EXIT_WEIGHT + p->sleep_avg /
--		(EXIT_WEIGHT + 1);
-+	parent = p->parent;
-+	rq = task_rq_lock(parent, &flags);
-+	if (p->first_time_slice > 0 && task_cpu(p) == task_cpu(parent)) {
-+		parent->time_slice += p->time_slice;
-+		if (unlikely(parent->time_slice > parent->quota))
-+			parent->time_slice = parent->quota;
-+	}
- 	task_rq_unlock(rq, &flags);
- }
- 
-@@ -2184,23 +2329,17 @@
-  * pull_task - move a task from a remote runqueue to the local runqueue.
-  * Both runqueues must be locked.
-  */
--static void pull_task(struct rq *src_rq, struct prio_array *src_array,
--		      struct task_struct *p, struct rq *this_rq,
--		      struct prio_array *this_array, int this_cpu)
-+static void pull_task(struct rq *src_rq, struct task_struct *p,
-+		      struct rq *this_rq, int this_cpu)
- {
--	dequeue_task(p, src_array);
-+	dequeue_task(p, src_rq);
- 	dec_nr_running(p, src_rq);
- 	set_task_cpu(p, this_cpu);
- 	inc_nr_running(p, this_rq);
--	enqueue_task(p, this_array);
-+	enqueue_task(p, this_rq);
- 	p->timestamp = (p->timestamp - src_rq->most_recent_timestamp)
- 				+ this_rq->most_recent_timestamp;
--	/*
--	 * Note that idle threads have a prio of MAX_PRIO, for this test
--	 * to be always true for them.
--	 */
--	if (TASK_PREEMPTS_CURR(p, this_rq))
--		resched_task(this_rq->curr);
-+	try_preempt(p, this_rq);
- }
- 
- /*
-@@ -2243,7 +2382,16 @@
- 	return 1;
- }
- 
--#define rq_best_prio(rq) min((rq)->curr->prio, (rq)->best_expired_prio)
-+static inline int rq_best_prio(struct rq *rq)
-+{
-+	int best_prio, exp_prio;
-+
-+	best_prio = sched_find_first_bit(rq->dyn_bitmap);
-+	exp_prio = find_next_bit(rq->exp_bitmap, MAX_PRIO, MAX_RT_PRIO);
-+	if (unlikely(best_prio > exp_prio))
-+		best_prio = exp_prio;
-+	return best_prio;
-+}
- 
- /*
-  * move_tasks tries to move up to max_nr_move tasks and max_load_move weighted
-@@ -2259,7 +2407,7 @@
- {
- 	int idx, pulled = 0, pinned = 0, this_best_prio, best_prio,
- 	    best_prio_seen, skip_for_load;
--	struct prio_array *array, *dst_array;
-+	struct prio_array *array;
- 	struct list_head *head, *curr;
- 	struct task_struct *tmp;
- 	long rem_load_move;
-@@ -2286,31 +2434,29 @@
- 	 * be cache-cold, thus switching CPUs has the least effect
- 	 * on them.
- 	 */
--	if (busiest->expired->nr_active) {
--		array = busiest->expired;
--		dst_array = this_rq->expired;
--	} else {
--		array = busiest->active;
--		dst_array = this_rq->active;
--	}
--
-+	array = busiest->expired;
- new_array:
--	/* Start searching at priority 0: */
--	idx = 0;
-+	/* Expired arrays don't have RT tasks so they're always MAX_RT_PRIO+ */
-+	if (array == busiest->expired)
-+		idx = MAX_RT_PRIO;
-+	else
-+		idx = 0;
- skip_bitmap:
- 	if (!idx)
--		idx = sched_find_first_bit(array->bitmap);
-+		idx = sched_find_first_bit(array->prio_bitmap);
- 	else
--		idx = find_next_bit(array->bitmap, MAX_PRIO, idx);
--	if (idx >= MAX_PRIO) {
--		if (array == busiest->expired && busiest->active->nr_active) {
-+		idx = find_next_bit(array->prio_bitmap, MAX_PRIO, idx);
-+	if (idx == MAX_PRIO) {
-+		if (array == busiest->idleprio && busiest->nr_idleprio)
-+			goto found_idleprio;
-+		if (array == busiest->expired) {
- 			array = busiest->active;
--			dst_array = this_rq->active;
- 			goto new_array;
- 		}
- 		goto out;
- 	}
- 
-+found_idleprio:
- 	head = array->queue + idx;
- 	curr = head->prev;
- skip_queue:
-@@ -2332,11 +2478,22 @@
- 		best_prio_seen |= idx == best_prio;
- 		if (curr != head)
- 			goto skip_queue;
-+		if (idx == MAX_PRIO) {
-+			/*
-+			 * Occurs either when balancing idleprio tasks or
-+			 * there really are no more tasks to find.
-+			 */
-+			if (array == busiest->expired) {
-+				array = busiest->active;
-+				goto new_array;
-+			}
-+			goto out;
-+		}
- 		idx++;
- 		goto skip_bitmap;
- 	}
- 
--	pull_task(busiest, array, tmp, this_rq, dst_array, this_cpu);
-+	pull_task(busiest, tmp, this_rq, this_cpu);
- 	pulled++;
- 	rem_load_move -= tmp->load_weight;
- 
-@@ -2349,6 +2506,13 @@
- 			this_best_prio = idx;
- 		if (curr != head)
- 			goto skip_queue;
-+		if (idx == MAX_PRIO) {
-+			if (array == busiest->expired) {
-+				array = busiest->active;
-+				goto new_array;
-+			}
-+			goto out;
-+		}
- 		idx++;
- 		goto skip_bitmap;
- 	}
-@@ -3297,11 +3461,36 @@
- /*
-  * This is called on clock ticks and on context switches.
-  * Bank in p->sched_time the ns elapsed since the last tick or switch.
-+ * CPU scheduler quota accounting is also performed here in microseconds.
-+ * The value returned from sched_clock() occasionally gives bogus values so
-+ * some sanity checking is required.
-  */
--static inline void
--update_cpu_clock(struct task_struct *p, struct rq *rq, unsigned long long now)
-+static void
-+update_cpu_clock(struct task_struct *p, struct rq *rq, unsigned long long now,
-+		 int tick)
- {
--	p->sched_time += now - p->last_ran;
-+	long time_diff = now - p->last_ran;
-+
-+	if (tick) {
-+		/*
-+		 * Called from scheduler_tick() there should be less than two
-+		 * jiffies worth, and not negative/overflow.
-+		 */
-+		if (time_diff > JIFFIES_TO_NS(2) || time_diff < 0)
-+			time_diff = JIFFIES_TO_NS(1);
-+	} else {
-+		/*
-+		 * Called from context_switch there should be less than one
-+		 * jiffy worth, and not negative/overflow. There should be
-+		 * some time banked here so use a nominal 1us.
-+		 */
-+		if (time_diff > JIFFIES_TO_NS(1) || time_diff < 1)
-+			time_diff = 1000;
-+	}
-+	/* time_slice accounting is done in usecs to avoid overflow on 32bit */
-+	if (p != rq->idle && p->policy != SCHED_FIFO)
-+		p->time_slice -= time_diff / 1000;
-+	p->sched_time += time_diff;
- 	p->last_ran = rq->most_recent_timestamp = now;
- }
- 
-@@ -3322,27 +3511,6 @@
- }
- 
- /*
-- * We place interactive tasks back into the active array, if possible.
-- *
-- * To guarantee that this does not starve expired tasks we ignore the
-- * interactivity of a task if the first expired task had to wait more
-- * than a 'reasonable' amount of time. This deadline timeout is
-- * load-dependent, as the frequency of array switched decreases with
-- * increasing number of running tasks. We also ignore the interactivity
-- * if a better static_prio task has expired:
-- */
--static inline int expired_starving(struct rq *rq)
--{
--	if (rq->curr->static_prio > rq->best_expired_prio)
--		return 1;
--	if (!STARVATION_LIMIT || !rq->expired_timestamp)
--		return 0;
--	if (jiffies - rq->expired_timestamp > STARVATION_LIMIT * rq->nr_running)
--		return 1;
--	return 0;
--}
--
--/*
-  * Account user cpu time to a process.
-  * @p: the process that the cpu time gets accounted to
-  * @hardirq_offset: the offset to subtract from hardirq_count()
-@@ -3357,7 +3525,7 @@
- 
- 	/* Add user time to cpustat. */
- 	tmp = cputime_to_cputime64(cputime);
--	if (TASK_NICE(p) > 0)
-+	if (TASK_NICE(p) > 0 || idleprio_task(p))
- 		cpustat->nice = cputime64_add(cpustat->nice, tmp);
- 	else
- 		cpustat->user = cputime64_add(cpustat->user, tmp);
-@@ -3415,87 +3583,94 @@
- 		cpustat->steal = cputime64_add(cpustat->steal, tmp);
- }
- 
--static void task_running_tick(struct rq *rq, struct task_struct *p)
-+/*
-+ * The task has used up its quota of running in this prio_level so it must be
-+ * dropped a priority level, all managed by recalc_task_prio().
-+ */
-+static void task_expired_entitlement(struct rq *rq, struct task_struct *p)
- {
--	if (p->array != rq->active) {
--		/* Task has expired but was not scheduled yet */
--		set_tsk_need_resched(p);
-+	int overrun;
-+
-+	reset_first_time_slice(p);
-+	if (rt_task(p)) {
-+		p->time_slice += p->quota;
-+		list_move_tail(&p->run_list, p->array->queue + p->prio);
- 		return;
- 	}
--	spin_lock(&rq->lock);
-+	overrun = p->time_slice;
-+	dequeue_task(p, rq);
-+	enqueue_task(p, rq);
- 	/*
--	 * The task was running during this tick - update the
--	 * time slice counter. Note: we do not update a thread's
--	 * priority until it either goes to sleep or uses up its
--	 * timeslice. This makes it possible for interactive tasks
--	 * to use up their timeslices at their highest priority levels.
-+	 * Subtract any extra time this task ran over its time_slice; ie
-+	 * overrun will either be 0 or negative.
- 	 */
--	if (rt_task(p)) {
--		/*
--		 * RR tasks need a special form of timeslice management.
--		 * FIFO tasks have no timeslices.
--		 */
--		if ((p->policy == SCHED_RR) && !--p->time_slice) {
--			p->time_slice = task_timeslice(p);
--			p->first_time_slice = 0;
--			set_tsk_need_resched(p);
-+	p->time_slice += overrun;
-+}
- 
--			/* put it at the end of the queue: */
--			requeue_task(p, rq->active);
--		}
--		goto out_unlock;
-+/*
-+ * Test if SCHED_ISO tasks have run longer than their alloted period as RT
-+ * tasks and set the refractory flag if necessary. There is 10% hysteresis
-+ * for unsetting the flag.
-+ */
-+static unsigned int test_ret_isorefractory(struct rq *rq)
-+{
-+	if (likely(!rq->iso_refractory)) {
-+		if (rq->iso_ticks / ISO_PERIOD > sched_iso_cpu)
-+			rq->iso_refractory = 1;
-+	} else {
-+		if (rq->iso_ticks / ISO_PERIOD < (sched_iso_cpu * 90 / 100))
-+			rq->iso_refractory = 0;
- 	}
--	if (!--p->time_slice) {
--		dequeue_task(p, rq->active);
--		set_tsk_need_resched(p);
--		p->prio = effective_prio(p);
--		p->time_slice = task_timeslice(p);
--		p->first_time_slice = 0;
-+	return rq->iso_refractory;
-+}
- 
--		if (!rq->expired_timestamp)
--			rq->expired_timestamp = jiffies;
--		if (!TASK_INTERACTIVE(p) || expired_starving(rq)) {
--			enqueue_task(p, rq->expired);
--			if (p->static_prio < rq->best_expired_prio)
--				rq->best_expired_prio = p->static_prio;
--		} else
--			enqueue_task(p, rq->active);
--	} else {
--		/*
--		 * Prevent a too long timeslice allowing a task to monopolize
--		 * the CPU. We do this by splitting up the timeslice into
--		 * smaller pieces.
--		 *
--		 * Note: this does not mean the task's timeslices expire or
--		 * get lost in any way, they just might be preempted by
--		 * another task of equal priority. (one with higher
--		 * priority would have preempted this task already.) We
--		 * requeue this task to the end of the list on this priority
--		 * level, which is in essence a round-robin of tasks with
--		 * equal priority.
--		 *
--		 * This only applies to tasks in the interactive
--		 * delta range with at least TIMESLICE_GRANULARITY to requeue.
--		 */
--		if (TASK_INTERACTIVE(p) && !((task_timeslice(p) -
--			p->time_slice) % TIMESLICE_GRANULARITY(p)) &&
--			(p->time_slice >= TIMESLICE_GRANULARITY(p)) &&
--			(p->array == rq->active)) {
-+/* No SCHED_ISO task was running so decrease rq->iso_ticks */
-+static inline void no_iso_tick(struct rq *rq)
-+{
-+	rq->iso_ticks = rq->iso_ticks * (ISO_PERIOD - 1) / ISO_PERIOD;
-+}
- 
--			requeue_task(p, rq->active);
--			set_tsk_need_resched(p);
--		}
-+/* This manages tasks that have run out of timeslice during a scheduler_tick */
-+static void task_running_tick(struct rq *rq, struct task_struct *p)
-+{
-+	/*
-+	 * If a SCHED_ISO task is running we increment the iso_ticks. In
-+	 * order to prevent SCHED_ISO tasks from causing starvation in the
-+	 * presence of true RT tasks we account those as iso_ticks as well.
-+	 */
-+	if ((rt_task(p) || (iso_task(p) && !rq->iso_refractory))) {
-+		if (rq->iso_ticks <= (ISO_PERIOD * 100) - 100)
-+			rq->iso_ticks += 100;
-+	} else
-+		no_iso_tick(rq);
-+
-+	if (iso_task(p)) {
-+		if (unlikely(test_ret_isorefractory(rq))) {
-+			if (isoprio_suitable(p)) {
-+				/*
-+				 * SCHED_ISO task is running as RT and limit
-+				 * has been hit. Set the PF_ISOREF flag and
-+				 * force it to reschedule as SCHED_NORMAL
-+				 * by zeroing its time_slice
-+				 */
-+				p->flags |= PF_ISOREF;
-+				p->time_slice = 0;
-+			}
-+		} else
-+			p->flags &= ~PF_ISOREF;
- 	}
--out_unlock:
--	spin_unlock(&rq->lock);
-+	/* SCHED_FIFO tasks never run out of timeslice. */
-+	if (p->time_slice > 0 || p->policy == SCHED_FIFO)
-+		return;
-+	/* p->time_slice <= 0 */
-+	set_tsk_need_resched(p);
-+	if (likely(task_queued(p)))
-+		task_expired_entitlement(rq, p);
- }
- 
- /*
-  * This function gets called by the timer code, with HZ frequency.
-  * We call it with interrupts disabled.
-- *
-- * It also gets called by the fork code, when changing the parent's
-- * timeslices.
-  */
- void scheduler_tick(void)
- {
-@@ -3505,10 +3680,14 @@
- 	int idle_at_tick = idle_cpu(cpu);
- 	struct rq *rq = cpu_rq(cpu);
- 
--	update_cpu_clock(p, rq, now);
-+	update_cpu_clock(p, rq, now, 1);
- 
-+	spin_lock(&rq->lock);
- 	if (!idle_at_tick)
- 		task_running_tick(rq, p);
-+	else
-+		no_iso_tick(rq);
-+	spin_unlock(&rq->lock);
- #ifdef CONFIG_SMP
- 	update_load(rq);
- 	rq->idle_at_tick = idle_at_tick;
-@@ -3554,10 +3733,80 @@
- 
- #endif
- 
--static inline int interactive_sleep(enum sleep_type sleep_type)
-+static void reset_prio_levels(struct rq *rq)
- {
--	return (sleep_type == SLEEP_INTERACTIVE ||
--		sleep_type == SLEEP_INTERRUPTED);
-+	rq->active->best_static_prio = MAX_PRIO - 1;
-+	rq->expired->best_static_prio = MAX_PRIO - 1;
-+	memset(rq->prio_level, 0, sizeof(int) * PRIO_RANGE);
-+}
-+
-+/*
-+ * Only tasks running are SCHED_IDLEPRIO. Set the active array to the
-+ * idleprio array and if it isn't already active
-+ */
-+static struct task_struct *next_idleprio_task(struct rq *rq)
-+{
-+	struct prio_array *array = rq->active;
-+	struct list_head *queue;
-+
-+	if (array != rq->idleprio) {
-+		rq->active = rq->idleprio;
-+		rq->expired = array;
-+		array = rq->active;
-+		rq->exp_bitmap = rq->expired->prio_bitmap;
-+		rq->dyn_bitmap = rq->active->prio_bitmap;
-+	}
-+	rq->prio_rotation++;
-+	reset_prio_levels(rq);
-+	queue = array->queue + MAX_PRIO;
-+	return list_entry(queue->next, struct task_struct, run_list);
-+}
-+
-+/*
-+ * next_dynamic_task finds the next suitable dynamic task.
-+ */
-+static inline struct task_struct *next_dynamic_task(struct rq *rq, int idx)
-+{
-+	struct prio_array *array = rq->active;
-+	struct task_struct *next;
-+	struct list_head *queue;
-+	int nstatic;
-+
-+retry:
-+	if (unlikely(rq->nr_running == rq->nr_idleprio))
-+		return next_idleprio_task(rq);
-+	if (idx >= MAX_PRIO) {
-+		/* There are no more tasks in the active array. Swap arrays */
-+		array = rq->expired;
-+		rq->expired = rq->active;
-+		rq->active = array;
-+		rq->exp_bitmap = rq->expired->prio_bitmap;
-+		rq->dyn_bitmap = rq->active->prio_bitmap;
-+		rq->prio_rotation++;
-+		idx = find_next_bit(rq->dyn_bitmap, MAX_PRIO, MAX_RT_PRIO);
-+		reset_prio_levels(rq);
-+	}
-+	queue = array->queue + idx;
-+	next = list_entry(queue->next, struct task_struct, run_list);
-+	if (unlikely(next->time_slice <= 0 && !(iso_task(next) &&
-+	    isoprio_suitable(next)))) {
-+		/*
-+		 * Unlucky enough that this task ran out of time_slice
-+		 * before it hit a scheduler_tick so it should have its
-+		 * priority reassessed and choose another task (possibly
-+		 * the same one)
-+		 */
-+		task_expired_entitlement(rq, next);
-+		idx = find_next_bit(rq->dyn_bitmap, MAX_PRIO, MAX_RT_PRIO);
-+		goto retry;
-+	}
-+	next->rotation = rq->prio_rotation;
-+	nstatic = next->static_prio;
-+	if (nstatic < array->best_static_prio)
-+		array->best_static_prio = nstatic;
-+	if (idx > rq->prio_level[USER_PRIO(nstatic)])
-+		rq->prio_level[USER_PRIO(nstatic)] = idx;
-+	return next;
- }
- 
- /*
-@@ -3566,13 +3815,11 @@
- asmlinkage void __sched schedule(void)
- {
- 	struct task_struct *prev, *next;
--	struct prio_array *array;
- 	struct list_head *queue;
- 	unsigned long long now;
--	unsigned long run_time;
--	int cpu, idx, new_prio;
- 	long *switch_count;
- 	struct rq *rq;
-+	int cpu, idx;
- 
- 	/*
- 	 * Test if we are atomic.  Since do_exit() needs to call into
-@@ -3608,18 +3855,6 @@
- 
- 	schedstat_inc(rq, sched_cnt);
- 	now = sched_clock();
--	if (likely((long long)(now - prev->timestamp) < NS_MAX_SLEEP_AVG)) {
--		run_time = now - prev->timestamp;
--		if (unlikely((long long)(now - prev->timestamp) < 0))
--			run_time = 0;
--	} else
--		run_time = NS_MAX_SLEEP_AVG;
--
--	/*
--	 * Tasks charged proportionately less run_time at high sleep_avg to
--	 * delay them losing their interactive status
--	 */
--	run_time /= (CURRENT_BONUS(prev) ? : 1);
- 
- 	spin_lock_irq(&rq->lock);
- 
-@@ -3630,8 +3865,10 @@
- 				unlikely(signal_pending(prev))))
- 			prev->state = TASK_RUNNING;
- 		else {
--			if (prev->state == TASK_UNINTERRUPTIBLE)
-+			if (prev->state == TASK_UNINTERRUPTIBLE) {
-+				prev->flags |= PF_NONSLEEP;
- 				rq->nr_uninterruptible++;
-+			}
- 			deactivate_task(prev, rq);
- 		}
- 	}
-@@ -3641,59 +3878,29 @@
- 		idle_balance(cpu, rq);
- 		if (!rq->nr_running) {
- 			next = rq->idle;
--			rq->expired_timestamp = 0;
- 			goto switch_tasks;
- 		}
- 	}
- 
--	array = rq->active;
--	if (unlikely(!array->nr_active)) {
--		/*
--		 * Switch the active and expired arrays.
--		 */
--		schedstat_inc(rq, sched_switch);
--		rq->active = rq->expired;
--		rq->expired = array;
--		array = rq->active;
--		rq->expired_timestamp = 0;
--		rq->best_expired_prio = MAX_PRIO;
--	}
--
--	idx = sched_find_first_bit(array->bitmap);
--	queue = array->queue + idx;
--	next = list_entry(queue->next, struct task_struct, run_list);
--
--	if (!rt_task(next) && interactive_sleep(next->sleep_type)) {
--		unsigned long long delta = now - next->timestamp;
--		if (unlikely((long long)(now - next->timestamp) < 0))
--			delta = 0;
--
--		if (next->sleep_type == SLEEP_INTERACTIVE)
--			delta = delta * (ON_RUNQUEUE_WEIGHT * 128 / 100) / 128;
--
--		array = next->array;
--		new_prio = recalc_task_prio(next, next->timestamp + delta);
--
--		if (unlikely(next->prio != new_prio)) {
--			dequeue_task(next, array);
--			next->prio = new_prio;
--			enqueue_task(next, array);
--		}
-+	idx = sched_find_first_bit(rq->dyn_bitmap);
-+	if (likely(idx > ISO_PRIO))
-+		next = next_dynamic_task(rq, idx);
-+	else {
-+		queue = rq->active->queue + idx;
-+		next = list_entry(queue->next, struct task_struct, run_list);
- 	}
--	next->sleep_type = SLEEP_NORMAL;
- switch_tasks:
--	if (next == rq->idle)
-+	if (next == rq->idle) {
-+		reset_prio_levels(rq);
-+		rq->prio_rotation++;
- 		schedstat_inc(rq, sched_goidle);
-+	}
- 	prefetch(next);
- 	prefetch_stack(next);
- 	clear_tsk_need_resched(prev);
- 	rcu_qsctr_inc(task_cpu(prev));
- 
--	update_cpu_clock(prev, rq, now);
--
--	prev->sleep_avg -= run_time;
--	if ((long)prev->sleep_avg <= 0)
--		prev->sleep_avg = 0;
-+	update_cpu_clock(prev, rq, now, 0);
- 	prev->timestamp = prev->last_ran = now;
- 
- 	sched_info_switch(prev, next);
-@@ -4129,29 +4336,22 @@
-  */
- void rt_mutex_setprio(struct task_struct *p, int prio)
- {
--	struct prio_array *array;
- 	unsigned long flags;
-+	int queued, oldprio;
- 	struct rq *rq;
--	int oldprio;
- 
- 	BUG_ON(prio < 0 || prio > MAX_PRIO);
- 
- 	rq = task_rq_lock(p, &flags);
- 
- 	oldprio = p->prio;
--	array = p->array;
--	if (array)
--		dequeue_task(p, array);
-+	queued = task_queued(p);
-+	if (queued)
-+		dequeue_task(p, rq);
- 	p->prio = prio;
- 
--	if (array) {
--		/*
--		 * If changing to an RT priority then queue it
--		 * in the active array!
--		 */
--		if (rt_task(p))
--			array = rq->active;
--		enqueue_task(p, array);
-+	if (queued) {
-+		enqueue_task(p, rq);
- 		/*
- 		 * Reschedule if we are currently running on this runqueue and
- 		 * our priority decreased, or if we are not currently running on
-@@ -4160,8 +4360,8 @@
- 		if (task_running(rq, p)) {
- 			if (p->prio > oldprio)
- 				resched_task(rq->curr);
--		} else if (TASK_PREEMPTS_CURR(p, rq))
--			resched_task(rq->curr);
-+		} else
-+			try_preempt(p, rq);
- 	}
- 	task_rq_unlock(rq, &flags);
- }
-@@ -4170,8 +4370,7 @@
- 
- void set_user_nice(struct task_struct *p, long nice)
- {
--	struct prio_array *array;
--	int old_prio, delta;
-+	int queued, old_prio,delta;
- 	unsigned long flags;
- 	struct rq *rq;
- 
-@@ -4192,26 +4391,27 @@
- 		p->static_prio = NICE_TO_PRIO(nice);
- 		goto out_unlock;
- 	}
--	array = p->array;
--	if (array) {
--		dequeue_task(p, array);
-+	queued = task_queued(p);
-+	if (queued) {
-+		dequeue_task(p, rq);
- 		dec_raw_weighted_load(rq, p);
- 	}
- 
- 	p->static_prio = NICE_TO_PRIO(nice);
--	set_load_weight(p);
- 	old_prio = p->prio;
- 	p->prio = effective_prio(p);
-+	set_quota(p);
- 	delta = p->prio - old_prio;
- 
--	if (array) {
--		enqueue_task(p, array);
-+	if (queued) {
-+		enqueue_task(p, rq);
- 		inc_raw_weighted_load(rq, p);
- 		/*
- 		 * If the task increased its priority or is running and
- 		 * lowered its priority, then reschedule its CPU:
- 		 */
--		if (delta < 0 || (delta > 0 && task_running(rq, p)))
-+		if (delta < 0 || ((delta > 0 || idleprio_task(p)) &&
-+		    task_running(rq, p)))
- 			resched_task(rq->curr);
- 	}
- out_unlock:
-@@ -4281,11 +4481,23 @@
-  *
-  * This is the priority value as seen by users in /proc.
-  * RT tasks are offset by -200. Normal tasks are centered
-- * around 0, value goes from -16 to +15.
-+ * around 1, value goes from 0 to +79. Values higher than
-+ * 39 indicate task is on the expired array. This is done
-+ * lockless and may rarely return an active instead of
-+ * expired value.
-  */
--int task_prio(const struct task_struct *p)
-+int task_prio(struct task_struct *p)
- {
--	return p->prio - MAX_RT_PRIO;
-+	int prio = p->prio - MAX_RT_PRIO;
-+
-+	if (task_queued(p)) {
-+		struct rq *rq = task_rq(p);
-+		struct prio_array *array = p->array;
-+
-+		if (rq && rq->expired == array)
-+			prio += PRIO_RANGE;
-+	}
-+	return prio;
- }
- 
- /**
-@@ -4328,19 +4540,14 @@
- /* Actually do priority change: must hold rq lock. */
- static void __setscheduler(struct task_struct *p, int policy, int prio)
- {
--	BUG_ON(p->array);
-+	BUG_ON(task_queued(p));
- 
- 	p->policy = policy;
- 	p->rt_priority = prio;
- 	p->normal_prio = normal_prio(p);
- 	/* we are holding p->pi_lock already */
- 	p->prio = rt_mutex_getprio(p);
--	/*
--	 * SCHED_BATCH tasks are treated as perpetual CPU hogs:
--	 */
--	if (policy == SCHED_BATCH)
--		p->sleep_avg = 0;
--	set_load_weight(p);
-+	set_quota(p);
- }
- 
- /**
-@@ -4354,19 +4561,36 @@
- int sched_setscheduler(struct task_struct *p, int policy,
- 		       struct sched_param *param)
- {
--	int retval, oldprio, oldpolicy = -1;
--	struct prio_array *array;
-+	struct sched_param zero_param = { .sched_priority = 0 };
-+	int queued, retval, oldprio, oldpolicy = -1;
-+	unsigned long rlim_rtprio = 0;
- 	unsigned long flags;
- 	struct rq *rq;
- 
- 	/* may grab non-irq protected spin_locks */
- 	BUG_ON(in_interrupt());
-+	if (is_rt_policy(policy) && !capable(CAP_SYS_NICE)) {
-+		unsigned long lflags;
-+
-+		if (!lock_task_sighand(p, &lflags))
-+			return -ESRCH;
-+		rlim_rtprio = p->signal->rlim[RLIMIT_RTPRIO].rlim_cur;
-+		unlock_task_sighand(p, &lflags);
-+		if (rlim_rtprio)
-+			goto recheck;
-+		/*
-+		 * If the caller requested an RT policy without having the
-+		 * necessary rights, we downgrade the policy to SCHED_ISO.
-+		 * We also set the parameter to zero to pass the checks.
-+		 */
-+		policy = SCHED_ISO;
-+		param = &zero_param;
-+	}
- recheck:
- 	/* double check policy once rq lock held */
- 	if (policy < 0)
- 		policy = oldpolicy = p->policy;
--	else if (policy != SCHED_FIFO && policy != SCHED_RR &&
--			policy != SCHED_NORMAL && policy != SCHED_BATCH)
-+	else if (!SCHED_RANGE(policy))
- 		return -EINVAL;
- 	/*
- 	 * Valid priorities for SCHED_FIFO and SCHED_RR are
-@@ -4385,14 +4609,6 @@
- 	 */
- 	if (!capable(CAP_SYS_NICE)) {
- 		if (is_rt_policy(policy)) {
--			unsigned long rlim_rtprio;
--			unsigned long flags;
--
--			if (!lock_task_sighand(p, &flags))
--				return -ESRCH;
--			rlim_rtprio = p->signal->rlim[RLIMIT_RTPRIO].rlim_cur;
--			unlock_task_sighand(p, &flags);
--
- 			/* can't set/change the rt policy */
- 			if (policy != p->policy && !rlim_rtprio)
- 				return -EPERM;
-@@ -4401,6 +4617,31 @@
- 			if (param->sched_priority > p->rt_priority &&
- 			    param->sched_priority > rlim_rtprio)
- 				return -EPERM;
-+		} else {
-+			switch (p->policy) {
-+				/*
-+				 * Can only downgrade policies but not back to
-+				 * SCHED_NORMAL
-+				 */
-+				case SCHED_ISO:
-+					if (policy == SCHED_ISO)
-+						goto out;
-+					if (policy == SCHED_NORMAL)
-+						return -EPERM;
-+					break;
-+				case SCHED_BATCH:
-+					if (policy == SCHED_BATCH)
-+						goto out;
-+					if (policy != SCHED_IDLEPRIO)
-+					    	return -EPERM;
-+					break;
-+				case SCHED_IDLEPRIO:
-+					if (policy == SCHED_IDLEPRIO)
-+						goto out;
-+					return -EPERM;
-+				default:
-+					break;
-+			}
- 		}
- 
- 		/* can't change other user's priorities */
-@@ -4409,6 +4650,11 @@
- 			return -EPERM;
- 	}
- 
-+	if (!(p->mm) && policy == SCHED_IDLEPRIO) {
-+		/* Don't allow kernel threads to be SCHED_IDLEPRIO. */
-+		return -EINVAL;
-+	}
-+
- 	retval = security_task_setscheduler(p, policy, param);
- 	if (retval)
- 		return retval;
-@@ -4429,12 +4675,12 @@
- 		spin_unlock_irqrestore(&p->pi_lock, flags);
- 		goto recheck;
- 	}
--	array = p->array;
--	if (array)
-+	queued = task_queued(p);
-+	if (queued)
- 		deactivate_task(p, rq);
- 	oldprio = p->prio;
- 	__setscheduler(p, policy, param->sched_priority);
--	if (array) {
-+	if (queued) {
- 		__activate_task(p, rq);
- 		/*
- 		 * Reschedule if we are currently running on this runqueue and
-@@ -4444,14 +4690,15 @@
- 		if (task_running(rq, p)) {
- 			if (p->prio > oldprio)
- 				resched_task(rq->curr);
--		} else if (TASK_PREEMPTS_CURR(p, rq))
--			resched_task(rq->curr);
-+		} else
-+			try_preempt(p, rq);
- 	}
- 	__task_rq_unlock(rq);
- 	spin_unlock_irqrestore(&p->pi_lock, flags);
- 
- 	rt_mutex_adjust_pi(p);
- 
-+out:
- 	return 0;
- }
- EXPORT_SYMBOL_GPL(sched_setscheduler);
-@@ -4718,41 +4965,34 @@
-  * sys_sched_yield - yield the current processor to other threads.
-  *
-  * This function yields the current CPU by moving the calling thread
-- * to the expired array. If there are no other threads running on this
-- * CPU then this function will return.
-+ * to the expired array if SCHED_NORMAL or the end of its current priority
-+ * queue if a realtime task. If there are no other threads running on this
-+ * cpu this function will return.
-  */
- asmlinkage long sys_sched_yield(void)
- {
- 	struct rq *rq = this_rq_lock();
--	struct prio_array *array = current->array, *target = rq->expired;
-+	struct task_struct *p = current;
- 
- 	schedstat_inc(rq, yld_cnt);
--	/*
--	 * We implement yielding by moving the task into the expired
--	 * queue.
--	 *
--	 * (special rule: RT tasks will just roundrobin in the active
--	 *  array.)
--	 */
--	if (rt_task(current))
--		target = rq->active;
--
--	if (array->nr_active == 1) {
--		schedstat_inc(rq, yld_act_empty);
--		if (!rq->expired->nr_active)
--			schedstat_inc(rq, yld_both_empty);
--	} else if (!rq->expired->nr_active)
--		schedstat_inc(rq, yld_exp_empty);
--
--	if (array != target) {
--		dequeue_task(current, array);
--		enqueue_task(current, target);
--	} else
--		/*
--		 * requeue_task is cheaper so perform that if possible.
--		 */
--		requeue_task(current, array);
-+	if (rq->nr_running == 1)
-+		schedstat_inc(rq, yld_both_empty);
-+	else {
-+		struct prio_array *old_array = p->array;
-+		int old_prio = p->prio;
-+
-+		if (idleprio_task(p)) {
-+			dequeue_task(p, rq);
-+			enqueue_task(p, rq);
-+			goto out_release;
-+		}
-+		/* p->prio will be updated in requeue_task via queue_expired */
-+		if (!rt_task(p))
-+			p->array = rq->expired;
-+		requeue_task(p, rq, old_array, old_prio);
-+	}
- 
-+out_release:
- 	/*
- 	 * Since we are going to call schedule() anyway, there's
- 	 * no need to preempt or enable interrupts:
-@@ -4902,6 +5142,8 @@
- 		break;
- 	case SCHED_NORMAL:
- 	case SCHED_BATCH:
-+	case SCHED_ISO:
-+	case SCHED_IDLEPRIO:
- 		ret = 0;
- 		break;
- 	}
-@@ -4926,6 +5168,8 @@
- 		break;
- 	case SCHED_NORMAL:
- 	case SCHED_BATCH:
-+	case SCHED_ISO:
-+	case SCHED_IDLEPRIO:
- 		ret = 0;
- 	}
- 	return ret;
-@@ -4959,8 +5203,8 @@
- 	if (retval)
- 		goto out_unlock;
- 
--	jiffies_to_timespec(p->policy == SCHED_FIFO ?
--				0 : task_timeslice(p), &t);
-+	t = ns_to_timespec(p->policy == SCHED_FIFO ? 0 :
-+			   MS_TO_NS(task_timeslice(p)));
- 	read_unlock(&tasklist_lock);
- 	retval = copy_to_user(interval, &t, sizeof(t)) ? -EFAULT : 0;
- out_nounlock:
-@@ -5056,10 +5300,10 @@
- 	struct rq *rq = cpu_rq(cpu);
- 	unsigned long flags;
- 
--	idle->timestamp = sched_clock();
--	idle->sleep_avg = 0;
--	idle->array = NULL;
--	idle->prio = idle->normal_prio = MAX_PRIO;
-+	bitmap_zero(idle->bitmap, PRIO_RANGE);
-+	idle->timestamp = idle->last_ran = sched_clock();
-+	idle->array = rq->active;
-+	idle->prio = idle->normal_prio = NICE_TO_PRIO(0);
- 	idle->state = TASK_RUNNING;
- 	idle->cpus_allowed = cpumask_of_cpu(cpu);
- 	set_task_cpu(idle, cpu);
-@@ -5178,7 +5422,7 @@
- 		goto out;
- 
- 	set_task_cpu(p, dest_cpu);
--	if (p->array) {
-+	if (task_queued(p)) {
- 		/*
- 		 * Sync timestamp with rq_dest's before activating.
- 		 * The same thing could be achieved by doing this step
-@@ -5189,8 +5433,7 @@
- 				+ rq_dest->most_recent_timestamp;
- 		deactivate_task(p, rq_src);
- 		__activate_task(p, rq_dest);
--		if (TASK_PREEMPTS_CURR(p, rq_dest))
--			resched_task(rq_dest->curr);
-+		try_preempt(p, rq_dest);
- 	}
- 	ret = 1;
- out:
-@@ -5487,7 +5730,7 @@
- 		/* Idle task back to normal (off runqueue, low prio) */
- 		rq = task_rq_lock(rq->idle, &flags);
- 		deactivate_task(rq->idle, rq);
--		rq->idle->static_prio = MAX_PRIO;
-+		rq->idle->static_prio = NICE_TO_PRIO(0);
- 		__setscheduler(rq->idle, SCHED_NORMAL, 0);
- 		migrate_dead_tasks(cpu);
- 		task_rq_unlock(rq, &flags);
-@@ -7013,6 +7256,13 @@
- 	/* Move init over to a non-isolated CPU */
- 	if (set_cpus_allowed(current, non_isolated_cpus) < 0)
- 		BUG();
-+
-+	/*
-+	 * Assume that every added cpu gives us slightly less overall latency
-+	 * allowing us to increase the base rr_interval, but in a non linear
-+	 * fashion.
-+	 */
-+	rr_interval *= 1 + ilog2(num_online_cpus());
- }
- #else
- void __init sched_init_smp(void)
-@@ -7035,6 +7285,16 @@
- 	int i, j, k;
- 	int highest_cpu = 0;
- 
-+	/* Generate the priority matrix */
-+	for (i = 0; i < PRIO_RANGE; i++) {
-+		bitmap_fill(prio_matrix[i], PRIO_RANGE);
-+		j = PRIO_RANGE * PRIO_RANGE / (PRIO_RANGE - i);
-+		for (k = 0; k <= PRIO_RANGE * (PRIO_RANGE - 1); k += j) {
-+			__clear_bit(PRIO_RANGE - 1 - (k / PRIO_RANGE),
-+				    prio_matrix[i]);
-+		}
-+	}
-+
- 	for_each_possible_cpu(i) {
- 		struct prio_array *array;
- 		struct rq *rq;
-@@ -7042,12 +7302,20 @@
- 		rq = cpu_rq(i);
- 		spin_lock_init(&rq->lock);
- 		lockdep_set_class(&rq->lock, &rq->rq_lock_key);
-+		rq->iso_ticks = 0;
- 		rq->nr_running = 0;
-+		rq->nr_idleprio = 0;
-+		rq->prio_rotation = 0;
- 		rq->active = rq->arrays;
-+		rq->idleprio = rq->active;
- 		rq->expired = rq->arrays + 1;
--		rq->best_expired_prio = MAX_PRIO;
-+		reset_prio_levels(rq);
-+		rq->dyn_bitmap = rq->active->prio_bitmap;
-+		rq->exp_bitmap = rq->expired->prio_bitmap;
- 
- #ifdef CONFIG_SMP
-+		rq->active->rq = rq;
-+		rq->expired->rq = rq;
- 		rq->sd = NULL;
- 		for (j = 1; j < 3; j++)
- 			rq->cpu_load[j] = 0;
-@@ -7060,17 +7328,16 @@
- 		atomic_set(&rq->nr_iowait, 0);
- 
- 		for (j = 0; j < 2; j++) {
-+
- 			array = rq->arrays + j;
--			for (k = 0; k < MAX_PRIO; k++) {
-+			for (k = 0; k <= MAX_PRIO; k++)
- 				INIT_LIST_HEAD(array->queue + k);
--				__clear_bit(k, array->bitmap);
--			}
--			// delimiter for bitsearch
--			__set_bit(MAX_PRIO, array->bitmap);
-+			bitmap_zero(array->prio_bitmap, MAX_PRIO);
-+			/* delimiter for bitsearch */
-+			__set_bit(MAX_PRIO, array->prio_bitmap);
- 		}
- 		highest_cpu = i;
- 	}
--
- 	set_load_weight(&init_task);
- 
- #ifdef CONFIG_SMP
-@@ -7125,25 +7392,25 @@
- #ifdef CONFIG_MAGIC_SYSRQ
- void normalize_rt_tasks(void)
- {
--	struct prio_array *array;
- 	struct task_struct *g, *p;
- 	unsigned long flags;
- 	struct rq *rq;
-+	int queued;
- 
- 	read_lock_irq(&tasklist_lock);
- 
- 	do_each_thread(g, p) {
--		if (!rt_task(p))
-+		if (!rt_task(p) && !iso_task(p))
- 			continue;
- 
- 		spin_lock_irqsave(&p->pi_lock, flags);
- 		rq = __task_rq_lock(p);
- 
--		array = p->array;
--		if (array)
-+		queued = task_queued(p);
-+		if (queued)
- 			deactivate_task(p, task_rq(p));
- 		__setscheduler(p, SCHED_NORMAL, 0);
--		if (array) {
-+		if (queued) {
- 			__activate_task(p, task_rq(p));
- 			resched_task(rq->curr);
- 		}
-Index: linux-2.6.22-ck1/kernel/sysctl.c
-===================================================================
---- linux-2.6.22-ck1.orig/kernel/sysctl.c	2007-07-10 14:55:00.000000000 +1000
-+++ linux-2.6.22-ck1/kernel/sysctl.c	2007-07-10 14:55:23.000000000 +1000
-@@ -22,6 +22,7 @@
- #include <linux/mm.h>
- #include <linux/swap.h>
- #include <linux/slab.h>
-+#include <linux/swap-prefetch.h>
- #include <linux/sysctl.h>
- #include <linux/proc_fs.h>
- #include <linux/capability.h>
-@@ -70,6 +71,7 @@
- extern char core_pattern[];
- extern int pid_max;
- extern int min_free_kbytes;
-+extern int vm_tail_largefiles;
- extern int printk_ratelimit_jiffies;
- extern int printk_ratelimit_burst;
- extern int pid_max_min, pid_max_max;
-@@ -78,6 +80,10 @@
- extern int compat_log;
- extern int maps_protect;
- extern int sysctl_stat_interval;
-+extern int rr_interval;
-+extern int sched_interactive;
-+extern int sched_iso_cpu;
-+extern int sched_iso_period;
- 
- /* this is needed for the proc_dointvec_minmax for [fs_]overflow UID and GID */
- static int maxolduid = 65535;
-@@ -161,6 +167,14 @@
- #endif
- 
- 
-+/* Constants for minimum and maximum testing.
-+   We use these as one-element integer vectors. */
-+static int __read_mostly zero;
-+static int __read_mostly one = 1;
-+static int __read_mostly one_hundred = 100;
-+static int __read_mostly five_thousand = 5000;
-+
-+
- /* The default sysctl tables: */
- 
- static ctl_table root_table[] = {
-@@ -501,6 +515,47 @@
- 		.mode		= 0444,
- 		.proc_handler	= &proc_dointvec,
- 	},
-+	{
-+		.ctl_name	= CTL_UNNUMBERED,
-+		.procname	= "rr_interval",
-+		.data		= &rr_interval,
-+		.maxlen		= sizeof (int),
-+		.mode		= 0644,
-+		.proc_handler	= &proc_dointvec_minmax,
-+		.strategy	= &sysctl_intvec,
-+		.extra1		= &one,
-+		.extra2		= &five_thousand,
-+	},
-+	{
-+		.ctl_name	= CTL_UNNUMBERED,
-+		.procname	= "interactive",
-+		.data		= &sched_interactive,
-+		.maxlen		= sizeof(int),
-+		.mode		= 0644,
-+		.proc_handler	= &proc_dointvec,
-+	},
-+	{
-+		.ctl_name	= CTL_UNNUMBERED,
-+		.procname	= "iso_cpu",
-+		.data		= &sched_iso_cpu,
-+		.maxlen		= sizeof (int),
-+		.mode		= 0644,
-+		.proc_handler	= &proc_dointvec_minmax,
-+		.strategy	= &sysctl_intvec,
-+		.extra1		= &zero,
-+		.extra2		= &one_hundred,
-+	},
-+	{
-+		.ctl_name	= CTL_UNNUMBERED,
-+		.procname	= "iso_period",
-+		.data		= &sched_iso_period,
-+		.maxlen		= sizeof (int),
-+		.mode		= 0644,
-+		.proc_handler	= &proc_dointvec_minmax,
-+		.strategy	= &sysctl_intvec,
-+		.extra1		= &one,
-+		.extra2		= &one_hundred,
-+	},
- #if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_X86)
- 	{
- 		.ctl_name       = KERN_UNKNOWN_NMI_PANIC,
-@@ -619,14 +674,16 @@
- 	{ .ctl_name = 0 }
- };
- 
--/* Constants for minimum and maximum testing in vm_table.
--   We use these as one-element integer vectors. */
--static int zero;
--static int one_hundred = 100;
--
--
- static ctl_table vm_table[] = {
- 	{
-+		.ctl_name	= CTL_UNNUMBERED,
-+		.procname	= "tail_largefiles",
-+		.data		= &vm_tail_largefiles,
-+		.maxlen		= sizeof(int),
-+		.mode		= 0644,
-+		.proc_handler	= &proc_dointvec,
-+	},
-+	{
- 		.ctl_name	= VM_OVERCOMMIT_MEMORY,
- 		.procname	= "overcommit_memory",
- 		.data		= &sysctl_overcommit_memory,
-@@ -705,16 +762,24 @@
- 		.proc_handler	= &proc_dointvec,
- 	},
- 	{
--		.ctl_name	= VM_SWAPPINESS,
--		.procname	= "swappiness",
--		.data		= &vm_swappiness,
--		.maxlen		= sizeof(vm_swappiness),
-+		.ctl_name	= CTL_UNNUMBERED,
-+		.procname	= "mapped",
-+		.data		= &vm_mapped,
-+		.maxlen		= sizeof(vm_mapped),
- 		.mode		= 0644,
- 		.proc_handler	= &proc_dointvec_minmax,
- 		.strategy	= &sysctl_intvec,
- 		.extra1		= &zero,
- 		.extra2		= &one_hundred,
- 	},
-+	{
-+		.ctl_name	= CTL_UNNUMBERED,
-+		.procname	= "hardmaplimit",
-+		.data		= &vm_hardmaplimit,
-+		.maxlen		= sizeof(int),
-+		.mode		= 0644,
-+		.proc_handler	= &proc_dointvec,
-+	},
- #ifdef CONFIG_HUGETLB_PAGE
- 	 {
- 		.ctl_name	= VM_HUGETLB_PAGES,
-@@ -882,6 +947,32 @@
- 		.extra1		= &zero,
- 	},
- #endif
-+#ifdef CONFIG_SWAP_PREFETCH
-+	{
-+		.ctl_name	= CTL_UNNUMBERED,
-+		.procname	= "swap_prefetch",
-+		.data		= &swap_prefetch,
-+		.maxlen		= sizeof(swap_prefetch),
-+		.mode		= 0644,
-+		.proc_handler	= &proc_dointvec,
-+	},
-+	{
-+		.ctl_name	= CTL_UNNUMBERED,
-+		.procname	= "swap_prefetch_delay",
-+		.data		= &swap_prefetch_delay,
-+		.maxlen		= sizeof(swap_prefetch_delay),
-+		.mode		= 0644,
-+		.proc_handler	= &proc_dointvec,
-+	},
-+	{
-+		.ctl_name	= CTL_UNNUMBERED,
-+		.procname	= "swap_prefetch_sleep",
-+		.data		= &swap_prefetch_sleep,
-+		.maxlen		= sizeof(swap_prefetch_sleep),
-+		.mode		= 0644,
-+		.proc_handler	= &proc_dointvec,
-+	},
-+#endif
- 	{ .ctl_name = 0 }
- };
- 
-Index: linux-2.6.22-ck1/Documentation/sched-design.txt
-===================================================================
---- linux-2.6.22-ck1.orig/Documentation/sched-design.txt	2007-07-10 14:55:00.000000000 +1000
-+++ linux-2.6.22-ck1/Documentation/sched-design.txt	2007-07-10 14:55:02.000000000 +1000
-@@ -1,11 +1,14 @@
--		   Goals, Design and Implementation of the
--		      new ultra-scalable O(1) scheduler
-+ Goals, Design and Implementation of the ultra-scalable O(1) scheduler by
-+ Ingo Molnar and theStaircase Deadline cpu scheduler policy designed by
-+ Con Kolivas.
- 
- 
--  This is an edited version of an email Ingo Molnar sent to
--  lkml on 4 Jan 2002.  It describes the goals, design, and
--  implementation of Ingo's new ultra-scalable O(1) scheduler.
--  Last Updated: 18 April 2002.
-+  This was originally an edited version of an email Ingo Molnar sent to
-+  lkml on 4 Jan 2002.  It describes the goals, design, and implementation
-+  of Ingo's ultra-scalable O(1) scheduler. It now contains a description
-+  of the Staircase Deadline priority scheduler that was built on this
-+  design.
-+  Last Updated: Fri, 4 May 2007
- 
- 
- Goal
-@@ -163,3 +166,222 @@
- code is smaller than the old one.
- 
- 	Ingo
-+
-+
-+Staircase Deadline cpu scheduler policy
-+================================================
-+
-+Design summary
-+==============
-+
-+A novel design which incorporates a foreground-background descending priority
-+system (the staircase) via a bandwidth allocation matrix according to nice
-+level.
-+
-+
-+Features
-+========
-+
-+A starvation free, strict fairness O(1) scalable design with interactivity
-+as good as the above restrictions can provide. There is no interactivity
-+estimator, no sleep/run measurements and only simple fixed accounting.
-+The design has strict enough a design and accounting that task behaviour
-+can be modelled and maximum scheduling latencies can be predicted by
-+the virtual deadline mechanism that manages runqueues. The prime concern
-+in this design is to maintain fairness at all costs determined by nice level,
-+yet to maintain as good interactivity as can be allowed within the
-+constraints of strict fairness.
-+
-+
-+Design description
-+==================
-+
-+SD works off the principle of providing each task a quota of runtime that it is
-+allowed to run at a number of priority levels determined by its static priority
-+(ie. its nice level). If the task uses up its quota it has its priority
-+decremented to the next level determined by a priority matrix. Once every
-+runtime quota has been consumed of every priority level, a task is queued on the
-+"expired" array. When no other tasks exist with quota, the expired array is
-+activated and fresh quotas are handed out. This is all done in O(1).
-+
-+Design details
-+==============
-+
-+Each task keeps a record of its own entitlement of cpu time. Most of the rest of
-+these details apply to non-realtime tasks as rt task management is straight
-+forward.
-+
-+Each runqueue keeps a record of what major epoch it is up to in the
-+rq->prio_rotation field which is incremented on each major epoch. It also
-+keeps a record of the current prio_level for each static priority task.
-+
-+Each task keeps a record of what major runqueue epoch it was last running
-+on in p->rotation. It also keeps a record of what priority levels it has
-+already been allocated quota from during this epoch in a bitmap p->bitmap.
-+
-+The only tunable that determines all other details is the RR_INTERVAL. This
-+is set to 8ms, and is scaled gently upwards with more cpus. This value is
-+tunable via a /proc interface.
-+
-+All tasks are initially given a quota based on RR_INTERVAL. This is equal to
-+RR_INTERVAL between nice values of -6 and 0, half that size above nice 0, and
-+progressively larger for nice values from -1 to -20. This is assigned to
-+p->quota and only changes with changes in nice level.
-+
-+As a task is first queued, it checks in recalc_task_prio to see if it has run at
-+this runqueue's current priority rotation. If it has not, it will have its
-+p->prio level set according to the first slot in a "priority matrix" and will be
-+given a p->time_slice equal to the p->quota, and has its allocation bitmap bit
-+set in p->bitmap for this prio level. It is then queued on the current active
-+priority array.
-+
-+If a task has already been running during this major epoch, and it has
-+p->time_slice left and the rq->prio_quota for the task's p->prio still
-+has quota, it will be placed back on the active array, but no more quota
-+will be added.
-+
-+If a task has been running during this major epoch, but does not have
-+p->time_slice left, it will find the next lowest priority in its bitmap that it
-+has not been allocated quota from. It then gets the a full quota in
-+p->time_slice. It is then queued on the current active priority array at the
-+newly determined lower priority.
-+
-+If a task has been running during this major epoch, and does not have
-+any entitlement left in p->bitmap and no time_slice left, it will have its
-+bitmap cleared, and be queued at its best prio again, but on the expired
-+priority array.
-+
-+When a task is queued, it has its relevant bit set in the array->prio_bitmap.
-+
-+p->time_slice is stored in nanosconds and is updated via update_cpu_clock on
-+schedule() and scheduler_tick. If p->time_slice is below zero then the
-+recalc_task_prio is readjusted and the task rescheduled.
-+
-+
-+Priority Matrix
-+===============
-+
-+In order to minimise the latencies between tasks of different nice levels
-+running concurrently, the dynamic priority slots where different nice levels
-+are queued are dithered instead of being sequential. What this means is that
-+there are 40 priority slots where a task may run during one major rotation,
-+and the allocation of slots is dependant on nice level. In the
-+following table, a zero represents a slot where the task may run.
-+
-+PRIORITY:0..................20.................39
-+nice -20 0000000000000000000000000000000000000000
-+nice -10 1000100010001000100010001000100010010000
-+nice   0 1010101010101010101010101010101010101010
-+nice   5 1011010110110101101101011011010110110110
-+nice  10 1110111011101110111011101110111011101110
-+nice  15 1111111011111110111111101111111011111110
-+nice  19 1111111111111111111111111111111111111110
-+
-+As can be seen, a nice -20 task runs in every priority slot whereas a nice 19
-+task only runs one slot per major rotation. This dithered table allows for the
-+smallest possible maximum latencies between tasks of varying nice levels, thus
-+allowing vastly different nice levels to be used.
-+
-+SCHED_BATCH tasks are managed slightly differently, receiving only the top
-+slots from its priority bitmap giving it equal cpu as SCHED_NORMAL, but
-+slightly higher latencies.
-+
-+
-+Modelling deadline behaviour
-+============================
-+
-+As the accounting in this design is hard and not modified by sleep average
-+calculations or interactivity modifiers, it is possible to accurately
-+predict the maximum latency that a task may experience under different
-+conditions. This is a virtual deadline mechanism enforced by mandatory
-+timeslice expiration and not outside bandwidth measurement.
-+
-+The maximum duration a task can run during one major epoch is determined by its
-+nice value. Nice 0 tasks can run at 19 different priority levels for RR_INTERVAL
-+duration during each epoch. Nice 10 tasks can run at 9 priority levels for each
-+epoch, and so on. The table in the priority matrix above demonstrates how this
-+is enforced.
-+
-+Therefore the maximum duration a runqueue epoch can take is determined by
-+the number of tasks running, and their nice level. After that, the maximum
-+duration it can take before a task can wait before it get scheduled is
-+determined by the position of its first slot on the matrix.
-+
-+In the following examples, these are _worst case scenarios_ and would rarely
-+occur, but can be modelled nonetheless to determine the maximum possible
-+latency.
-+
-+So for example, if two nice 0 tasks are running, and one has just expired as
-+another is activated for the first time receiving a full quota for this
-+runqueue rotation, the first task will wait:
-+
-+nr_tasks * max_duration + nice_difference * rr_interval
-+1 * 19 * RR_INTERVAL + 0 = 152ms
-+
-+In the presence of a nice 10 task, a nice 0 task would wait a maximum of
-+1 * 10 * RR_INTERVAL + 0 = 80ms
-+
-+In the presence of a nice 0 task, a nice 10 task would wait a maximum of
-+1 * 19 * RR_INTERVAL + 1 * RR_INTERVAL = 160ms
-+
-+More useful than these values, though, are the average latencies which are
-+a matter of determining the average distance between priority slots of
-+different nice values and multiplying them by the tasks' quota. For example
-+in the presence of a nice -10 task, a nice 0 task will wait either one or
-+two slots. Given that nice -10 tasks have a quota 2.5 times the RR_INTERVAL,
-+this means the latencies will alternate between 2.5 and 5 RR_INTERVALs or
-+20 and 40ms respectively (on uniprocessor at 1000HZ).
-+
-+
-+Achieving interactivity
-+=======================
-+
-+A requirement of this scheduler design was to achieve good interactivity
-+despite being a completely fair deadline based design. The disadvantage of
-+designs that try to achieve interactivity is that they usually do so at
-+the expense of maintaining fairness. As cpu speeds increase, the requirement
-+for some sort of metered unfairness towards interactive tasks becomes a less
-+desirable phenomenon, but low latency and fairness remains mandatory to
-+good interactive performance.
-+
-+This design relies on the fact that interactive tasks, by their nature,
-+sleep often. Most fair scheduling designs end up penalising such tasks
-+indirectly giving them less than their fair possible share because of the
-+sleep, and have to use a mechanism of bonusing their priority to offset
-+this based on the duration they sleep. This becomes increasingly inaccurate
-+as the number of running tasks rises and more tasks spend time waiting on
-+runqueues rather than sleeping, and it is impossible to tell whether the
-+task that's waiting on a runqueue only intends to run for a short period and
-+then sleep again after than runqueue wait. Furthermore, all such designs rely
-+on a period of time to pass to accumulate some form of statistic on the task
-+before deciding on how much to give them preference. The shorter this period,
-+the more rapidly bursts of cpu ruin the interactive tasks behaviour. The
-+longer this period, the longer it takes for interactive tasks to get low
-+scheduling latencies and fair cpu.
-+
-+This design does not measure sleep time at all. Interactive tasks that sleep
-+often will wake up having consumed very little if any of their quota for
-+the current major priority rotation. The longer they have slept, the less
-+likely they are to even be on the current major priority rotation. Once
-+woken up, though, they get to use up a their full quota for that epoch,
-+whether part of a quota remains or a full quota. Overall, however, they
-+can still only run as much cpu time for that epoch as any other task of the
-+same nice level. This means that two tasks behaving completely differently
-+from fully cpu bound to waking/sleeping extremely frequently will still
-+get the same quota of cpu, but the latter will be using its quota for that
-+epoch in bursts rather than continuously. This guarantees that interactive
-+tasks get the same amount of cpu as cpu bound ones.
-+
-+The other requirement of interactive tasks is also to obtain low latencies
-+for when they are scheduled. Unlike fully cpu bound tasks and the maximum
-+latencies possible described in the modelling deadline behaviour section
-+above, tasks that sleep will wake up with quota available usually at the
-+current runqueue's priority_level or better. This means that the most latency
-+they are likely to see is one RR_INTERVAL, and often they will preempt the
-+current task if it is not of a sleeping nature. This then guarantees very
-+low latency for interactive tasks, and the lowest latencies for the least
-+cpu bound tasks.
-+
-+
-+Fri, 4 May 2007
-+Con Kolivas <kernel@kolivas.org>
-Index: linux-2.6.22-ck1/Documentation/sysctl/kernel.txt
-===================================================================
---- linux-2.6.22-ck1.orig/Documentation/sysctl/kernel.txt	2007-07-10 14:55:00.000000000 +1000
-+++ linux-2.6.22-ck1/Documentation/sysctl/kernel.txt	2007-07-10 14:55:20.000000000 +1000
-@@ -25,6 +25,9 @@
- - domainname
- - hostname
- - hotplug
-+- interactive
-+- iso_cpu
-+- iso_period
- - java-appletviewer           [ binfmt_java, obsolete ]
- - java-interpreter            [ binfmt_java, obsolete ]
- - kstack_depth_to_print       [ X86 only ]
-@@ -43,6 +46,7 @@
- - printk
- - real-root-dev               ==> Documentation/initrd.txt
- - reboot-cmd                  [ SPARC only ]
-+- rr_interval
- - rtsig-max
- - rtsig-nr
- - sem
-@@ -164,6 +168,40 @@
- 
- ==============================================================
- 
-+interactive:
-+
-+The staircase-deadline cpu scheduler can be set in either purely
-+forward-looking mode for absolutely rigid fairness and cpu distribution
-+according to nice level, or it can allow a small per-process history
-+to smooth out cpu usage perturbations common in interactive tasks by
-+enabling this sysctl. While small fairness issues can arise with this
-+enabled, overall fairness is usually still strongly maintained and
-+starvation is never possible. Enabling this can significantly smooth
-+out 3d graphics and games.
-+
-+Default value is 1 (enabled).
-+
-+==============================================================
-+
-+iso_cpu:
-+
-+This sets the percentage cpu that the unprivileged SCHED_ISO tasks can
-+run effectively at realtime priority, averaged over a rolling iso_period
-+seconds.
-+
-+Set to 80 (percent) by default.
-+
-+==============================================================
-+
-+iso_period:
-+
-+This sets the number of seconds over which SCHED_ISO cpu usage is averaged
-+to see if it exceeds its allocated cpu bandwidth.
-+
-+Set to 5 (seconds) by default.
-+
-+==============================================================
-+
- l2cr: (PPC only)
- 
- This flag controls the L2 cache of G3 processor boards. If
-@@ -288,6 +326,19 @@
- 
- ==============================================================
- 
-+rr_interval:
-+
-+This is the smallest duration that any cpu process scheduling unit
-+will run for. Increasing this value can increase throughput of cpu
-+bound tasks substantially but at the expense of increased latencies
-+overall. This value is in milliseconds and the default value chosen
-+depends on the number of cpus available at scheduler initialisation
-+with a minimum of 8.
-+
-+Valid values are from 1-5000.
-+
-+==============================================================
-+
- rtsig-max & rtsig-nr:
- 
- The file rtsig-max can be used to tune the maximum number
-Index: linux-2.6.22-ck1/fs/pipe.c
-===================================================================
---- linux-2.6.22-ck1.orig/fs/pipe.c	2007-07-10 14:55:00.000000000 +1000
-+++ linux-2.6.22-ck1/fs/pipe.c	2007-07-10 14:55:02.000000000 +1000
-@@ -41,12 +41,7 @@
- {
- 	DEFINE_WAIT(wait);
- 
--	/*
--	 * Pipes are system-local resources, so sleeping on them
--	 * is considered a noninteractive wait:
--	 */
--	prepare_to_wait(&pipe->wait, &wait,
--			TASK_INTERRUPTIBLE | TASK_NONINTERACTIVE);
-+	prepare_to_wait(&pipe->wait, &wait, TASK_INTERRUPTIBLE);
- 	if (pipe->inode)
- 		mutex_unlock(&pipe->inode->i_mutex);
- 	schedule();
-Index: linux-2.6.22-ck1/fs/proc/array.c
-===================================================================
---- linux-2.6.22-ck1.orig/fs/proc/array.c	2007-07-10 14:55:00.000000000 +1000
-+++ linux-2.6.22-ck1/fs/proc/array.c	2007-07-10 14:55:02.000000000 +1000
-@@ -165,7 +165,6 @@
- 	rcu_read_lock();
- 	buffer += sprintf(buffer,
- 		"State:\t%s\n"
--		"SleepAVG:\t%lu%%\n"
- 		"Tgid:\t%d\n"
- 		"Pid:\t%d\n"
- 		"PPid:\t%d\n"
-@@ -173,7 +172,6 @@
- 		"Uid:\t%d\t%d\t%d\t%d\n"
- 		"Gid:\t%d\t%d\t%d\t%d\n",
- 		get_task_state(p),
--		(p->sleep_avg/1024)*100/(1020000000/1024),
- 	       	p->tgid, p->pid,
- 	       	pid_alive(p) ? rcu_dereference(p->real_parent)->tgid : 0,
- 		pid_alive(p) && p->ptrace ? rcu_dereference(p->parent)->pid : 0,
-Index: linux-2.6.22-ck1/include/linux/init_task.h
-===================================================================
---- linux-2.6.22-ck1.orig/include/linux/init_task.h	2007-07-10 14:55:00.000000000 +1000
-+++ linux-2.6.22-ck1/include/linux/init_task.h	2007-07-10 14:55:20.000000000 +1000
-@@ -125,13 +125,15 @@
- 	.prio		= MAX_PRIO-20,					\
- 	.static_prio	= MAX_PRIO-20,					\
- 	.normal_prio	= MAX_PRIO-20,					\
-+	.rotation	= 0,						\
- 	.policy		= SCHED_NORMAL,					\
- 	.cpus_allowed	= CPU_MASK_ALL,					\
- 	.mm		= NULL,						\
- 	.active_mm	= &init_mm,					\
- 	.run_list	= LIST_HEAD_INIT(tsk.run_list),			\
- 	.ioprio		= 0,						\
--	.time_slice	= HZ,						\
-+	.time_slice	= 1000000000,						\
-+	.quota		= 1000000000,						\
- 	.tasks		= LIST_HEAD_INIT(tsk.tasks),			\
- 	.ptrace_children= LIST_HEAD_INIT(tsk.ptrace_children),		\
- 	.ptrace_list	= LIST_HEAD_INIT(tsk.ptrace_list),		\
-@@ -158,6 +160,7 @@
- 		.signal = {{0}}},					\
- 	.blocked	= {{0}},					\
- 	.alloc_lock	= __SPIN_LOCK_UNLOCKED(tsk.alloc_lock),		\
-+	.mutexes_held	= 0,						\
- 	.journal_info	= NULL,						\
- 	.cpu_timers	= INIT_CPU_TIMERS(tsk.cpu_timers),		\
- 	.fs_excl	= ATOMIC_INIT(0),				\
-Index: linux-2.6.22-ck1/kernel/softirq.c
-===================================================================
---- linux-2.6.22-ck1.orig/kernel/softirq.c	2007-07-10 14:55:00.000000000 +1000
-+++ linux-2.6.22-ck1/kernel/softirq.c	2007-07-10 14:55:02.000000000 +1000
-@@ -488,7 +488,7 @@
- 
- static int ksoftirqd(void * __bind_cpu)
- {
--	set_user_nice(current, 19);
-+	set_user_nice(current, 15);
- 	current->flags |= PF_NOFREEZE;
- 
- 	set_current_state(TASK_INTERRUPTIBLE);
-Index: linux-2.6.22-ck1/kernel/workqueue.c
-===================================================================
---- linux-2.6.22-ck1.orig/kernel/workqueue.c	2007-07-10 14:55:00.000000000 +1000
-+++ linux-2.6.22-ck1/kernel/workqueue.c	2007-07-10 14:55:02.000000000 +1000
-@@ -285,8 +285,6 @@
- 	if (!cwq->wq->freezeable)
- 		current->flags |= PF_NOFREEZE;
- 
--	set_user_nice(current, -5);
--
- 	for (;;) {
- 		prepare_to_wait(&cwq->more_work, &wait, TASK_INTERRUPTIBLE);
- 		if (!freezing(current) &&
-Index: linux-2.6.22-ck1/kernel/kthread.c
-===================================================================
---- linux-2.6.22-ck1.orig/kernel/kthread.c	2007-07-10 14:55:00.000000000 +1000
-+++ linux-2.6.22-ck1/kernel/kthread.c	2007-07-10 14:55:02.000000000 +1000
-@@ -223,7 +223,6 @@
- 
- 	ignore_signals(tsk);
- 
--	set_user_nice(tsk, -5);
- 	set_cpus_allowed(tsk, CPU_MASK_ALL);
- }
- 
-Index: linux-2.6.22-ck1/kernel/fork.c
-===================================================================
---- linux-2.6.22-ck1.orig/kernel/fork.c	2007-07-10 14:55:00.000000000 +1000
-+++ linux-2.6.22-ck1/kernel/fork.c	2007-07-10 14:55:20.000000000 +1000
-@@ -1063,6 +1063,7 @@
- 	p->io_context = NULL;
- 	p->io_wait = NULL;
- 	p->audit_context = NULL;
-+	p->mutexes_held = 0;
- 	cpuset_fork(p);
- #ifdef CONFIG_NUMA
-  	p->mempolicy = mpol_copy(p->mempolicy);
-Index: linux-2.6.22-ck1/kernel/mutex.c
-===================================================================
---- linux-2.6.22-ck1.orig/kernel/mutex.c	2007-07-10 14:55:00.000000000 +1000
-+++ linux-2.6.22-ck1/kernel/mutex.c	2007-07-10 14:55:20.000000000 +1000
-@@ -60,6 +60,16 @@
- static void fastcall noinline __sched
- __mutex_lock_slowpath(atomic_t *lock_count);
- 
-+static inline void inc_mutex_count(void)
-+{
-+	current->mutexes_held++;
-+}
-+
-+static inline void dec_mutex_count(void)
-+{
-+	current->mutexes_held--;
-+}
-+
- /***
-  * mutex_lock - acquire the mutex
-  * @lock: the mutex to be acquired
-@@ -89,6 +99,7 @@
- 	 * 'unlocked' into 'locked' state.
- 	 */
- 	__mutex_fastpath_lock(&lock->count, __mutex_lock_slowpath);
-+	inc_mutex_count();
- }
- 
- EXPORT_SYMBOL(mutex_lock);
-@@ -114,6 +125,7 @@
- 	 * into 'unlocked' state:
- 	 */
- 	__mutex_fastpath_unlock(&lock->count, __mutex_unlock_slowpath);
-+	dec_mutex_count();
- }
- 
- EXPORT_SYMBOL(mutex_unlock);
-@@ -283,9 +295,14 @@
-  */
- int fastcall __sched mutex_lock_interruptible(struct mutex *lock)
- {
-+	int ret;
-+
- 	might_sleep();
--	return __mutex_fastpath_lock_retval
-+	ret = __mutex_fastpath_lock_retval
- 			(&lock->count, __mutex_lock_interruptible_slowpath);
-+	if (likely(!ret))
-+		inc_mutex_count();
-+	return ret;
- }
- 
- EXPORT_SYMBOL(mutex_lock_interruptible);
-@@ -340,8 +357,12 @@
-  */
- int fastcall __sched mutex_trylock(struct mutex *lock)
- {
--	return __mutex_fastpath_trylock(&lock->count,
-+	int ret = __mutex_fastpath_trylock(&lock->count,
- 					__mutex_trylock_slowpath);
-+
-+	if (likely(ret))
-+		inc_mutex_count();
-+	return ret;
- }
- 
- EXPORT_SYMBOL(mutex_trylock);
-Index: linux-2.6.22-ck1/block/cfq-iosched.c
-===================================================================
---- linux-2.6.22-ck1.orig/block/cfq-iosched.c	2007-07-10 14:55:00.000000000 +1000
-+++ linux-2.6.22-ck1/block/cfq-iosched.c	2007-07-10 14:55:21.000000000 +1000
-@@ -1276,10 +1276,12 @@
- 			printk(KERN_ERR "cfq: bad prio %x\n", ioprio_class);
- 		case IOPRIO_CLASS_NONE:
- 			/*
--			 * no prio set, place us in the middle of the BE classes
-+			 * Select class and ioprio according to policy and nice
- 			 */
-+			cfqq->ioprio_class = task_policy_ioprio_class(tsk);
- 			cfqq->ioprio = task_nice_ioprio(tsk);
--			cfqq->ioprio_class = IOPRIO_CLASS_BE;
-+			if (cfqq->ioprio_class == IOPRIO_CLASS_IDLE)
-+				cfq_clear_cfqq_idle_window(cfqq);
- 			break;
- 		case IOPRIO_CLASS_RT:
- 			cfqq->ioprio = task_ioprio(tsk);
-Index: linux-2.6.22-ck1/include/linux/ioprio.h
-===================================================================
---- linux-2.6.22-ck1.orig/include/linux/ioprio.h	2007-07-10 14:55:00.000000000 +1000
-+++ linux-2.6.22-ck1/include/linux/ioprio.h	2007-07-10 14:55:21.000000000 +1000
-@@ -22,7 +22,7 @@
-  * class, the default for any process. IDLE is the idle scheduling class, it
-  * is only served when no one else is using the disk.
-  */
--enum {
-+enum ioprio_class {
- 	IOPRIO_CLASS_NONE,
- 	IOPRIO_CLASS_RT,
- 	IOPRIO_CLASS_BE,
-@@ -51,8 +51,25 @@
- 	return IOPRIO_PRIO_DATA(task->ioprio);
- }
- 
-+static inline enum ioprio_class
-+	task_policy_ioprio_class(struct task_struct *task)
-+{
-+	if (rt_task(task))
-+		return IOPRIO_CLASS_RT;
-+	if (idleprio_task(task))
-+		return IOPRIO_CLASS_IDLE;
-+	return IOPRIO_CLASS_BE;
-+}
-+
- static inline int task_nice_ioprio(struct task_struct *task)
- {
-+	if (rt_task(task))
-+		return (MAX_RT_PRIO - task->rt_priority) * IOPRIO_BE_NR /
-+			(MAX_RT_PRIO + 1);
-+	if (iso_task(task))
-+		return 0;
-+	if (idleprio_task(task))
-+		return IOPRIO_BE_NR - 1;
- 	return (task_nice(task) + 20) / 5;
- }
- 
-Index: linux-2.6.22-ck1/Documentation/sysctl/vm.txt
-===================================================================
---- linux-2.6.22-ck1.orig/Documentation/sysctl/vm.txt	2007-07-10 14:55:00.000000000 +1000
-+++ linux-2.6.22-ck1/Documentation/sysctl/vm.txt	2007-07-10 14:55:23.000000000 +1000
-@@ -22,6 +22,8 @@
- - dirty_background_ratio
- - dirty_expire_centisecs
- - dirty_writeback_centisecs
-+- hardmaplimit
-+- mapped
- - max_map_count
- - min_free_kbytes
- - laptop_mode
-@@ -31,12 +33,15 @@
- - min_unmapped_ratio
- - min_slab_ratio
- - panic_on_oom
-+- swap_prefetch
-+- swap_prefetch_delay
-+- swap_prefetch_sleep
- 
- ==============================================================
- 
- dirty_ratio, dirty_background_ratio, dirty_expire_centisecs,
- dirty_writeback_centisecs, vfs_cache_pressure, laptop_mode,
--block_dump, swap_token_timeout, drop-caches:
-+block_dump, swap_token_timeout, drop-caches, tail_largefiles:
- 
- See Documentation/filesystems/proc.txt
- 
-@@ -86,6 +91,27 @@
- 
- ==============================================================
- 
-+hardmaplimit:
-+
-+This flag makes the vm adhere to the mapped value as closely as possible
-+except in the most extreme vm stress where doing so would provoke an out
-+of memory condition (see mapped below).
-+
-+Enabled by default.
-+
-+==============================================================
-+
-+mapped:
-+
-+This is the percentage ram that is filled with mapped pages (applications)
-+before the vm will start reclaiming mapped pages by moving them to swap.
-+It is altered by the relative stress of the vm at the time so is not
-+strictly adhered to to prevent provoking out of memory kills.
-+
-+Set to 66 by default.
-+
-+==============================================================
-+
- max_map_count:
- 
- This file contains the maximum number of memory map areas a process
-@@ -216,3 +242,37 @@
- The default value is 0.
- 1 and 2 are for failover of clustering. Please select either
- according to your policy of failover.
-+
-+==============================================================
-+
-+swap_prefetch
-+
-+This enables or disables the swap prefetching feature. When the virtual
-+memory subsystem has been extremely idle for at least swap_prefetch_sleep
-+seconds it will start copying back pages from swap into the swapcache and keep
-+a copy in swap. Valid values are 0 - 3. A value of 0 disables swap
-+prefetching, 1 enables it unless laptop_mode is enabled, 2 enables it in the
-+presence of laptop_mode, and 3 enables it unconditionally, ignoring whether
-+the system is idle or not. If set to 0, swap prefetch wil not even try to keep
-+record of ram swapped out to have the most minimal impact on performance.
-+
-+The default value is 1.
-+
-+==============================================================
-+
-+swap_prefetch_delay
-+
-+This is the time in seconds that swap prefetching is delayed upon finding
-+the system is not idle (ie the vm is busy or non-niced cpu load is present).
-+
-+The default value is 1.
-+
-+==============================================================
-+
-+swap_prefetch_sleep
-+
-+This is the time in seconds that the swap prefetch kernel thread is put to
-+sleep for when the ram is found to be full and it is unable to prefetch
-+further.
-+
-+The default value is 5.
-Index: linux-2.6.22-ck1/include/linux/swap.h
-===================================================================
---- linux-2.6.22-ck1.orig/include/linux/swap.h	2007-07-10 14:55:00.000000000 +1000
-+++ linux-2.6.22-ck1/include/linux/swap.h	2007-07-10 14:55:22.000000000 +1000
-@@ -180,6 +180,7 @@
- /* linux/mm/swap.c */
- extern void FASTCALL(lru_cache_add(struct page *));
- extern void FASTCALL(lru_cache_add_active(struct page *));
-+extern void FASTCALL(lru_cache_add_tail(struct page *));
- extern void FASTCALL(activate_page(struct page *));
- extern void FASTCALL(mark_page_accessed(struct page *));
- extern void lru_add_drain(void);
-@@ -188,9 +189,11 @@
- extern void swap_setup(void);
- 
- /* linux/mm/vmscan.c */
--extern unsigned long try_to_free_pages(struct zone **, gfp_t);
-+extern unsigned long try_to_free_pages(struct zone **, gfp_t,
-+				       struct task_struct *p);
- extern unsigned long shrink_all_memory(unsigned long nr_pages);
--extern int vm_swappiness;
-+extern int vm_mapped;
-+extern int vm_hardmaplimit;
- extern int remove_mapping(struct address_space *mapping, struct page *page);
- extern long vm_total_pages;
- 
-@@ -237,6 +240,7 @@
- extern struct page * lookup_swap_cache(swp_entry_t);
- extern struct page * read_swap_cache_async(swp_entry_t, struct vm_area_struct *vma,
- 					   unsigned long addr);
-+extern int add_to_swap_cache(struct page *page, swp_entry_t entry);
- /* linux/mm/swapfile.c */
- extern long total_swap_pages;
- extern unsigned int nr_swapfiles;
-Index: linux-2.6.22-ck1/init/Kconfig
-===================================================================
---- linux-2.6.22-ck1.orig/init/Kconfig	2007-07-10 14:55:00.000000000 +1000
-+++ linux-2.6.22-ck1/init/Kconfig	2007-07-10 14:55:22.000000000 +1000
-@@ -105,6 +105,28 @@
- 	  used to provide more virtual memory than the actual RAM present
- 	  in your computer.  If unsure say Y.
- 
-+config SWAP_PREFETCH
-+	bool "Support for prefetching swapped memory"
-+	depends on SWAP
-+	default y
-+	---help---
-+	  This option will allow the kernel to prefetch swapped memory pages
-+	  when idle. The pages will be kept on both swap and in swap_cache
-+	  thus avoiding the need for further I/O if either ram or swap space
-+	  is required.
-+
-+	  What this will do on workstations is slowly bring back applications
-+	  that have swapped out after memory intensive workloads back into
-+	  physical ram if you have free ram at a later stage and the machine
-+	  is relatively idle. This means that when you come back to your
-+	  computer after leaving it idle for a while, applications will come
-+	  to life faster. Note that your swap usage will appear to increase
-+	  but these are cached pages, can be dropped freely by the vm, and it
-+	  should stabilise around 50% swap usage maximum.
-+
-+	  Workstations and multiuser workstation servers will most likely want
-+	  to say Y.
-+
- config SYSVIPC
- 	bool "System V IPC"
- 	---help---
-Index: linux-2.6.22-ck1/mm/Makefile
-===================================================================
---- linux-2.6.22-ck1.orig/mm/Makefile	2007-07-10 14:55:00.000000000 +1000
-+++ linux-2.6.22-ck1/mm/Makefile	2007-07-10 14:55:22.000000000 +1000
-@@ -17,6 +17,7 @@
- obj-y			+= bounce.o
- endif
- obj-$(CONFIG_SWAP)	+= page_io.o swap_state.o swapfile.o thrash.o
-+obj-$(CONFIG_SWAP_PREFETCH) += swap_prefetch.o
- obj-$(CONFIG_HUGETLBFS)	+= hugetlb.o
- obj-$(CONFIG_NUMA) 	+= mempolicy.o
- obj-$(CONFIG_SPARSEMEM)	+= sparse.o
-Index: linux-2.6.22-ck1/mm/swap.c
-===================================================================
---- linux-2.6.22-ck1.orig/mm/swap.c	2007-07-10 14:55:00.000000000 +1000
-+++ linux-2.6.22-ck1/mm/swap.c	2007-07-10 14:55:23.000000000 +1000
-@@ -17,6 +17,7 @@
- #include <linux/sched.h>
- #include <linux/kernel_stat.h>
- #include <linux/swap.h>
-+#include <linux/swap-prefetch.h>
- #include <linux/mman.h>
- #include <linux/pagemap.h>
- #include <linux/pagevec.h>
-@@ -176,6 +177,7 @@
-  */
- static DEFINE_PER_CPU(struct pagevec, lru_add_pvecs) = { 0, };
- static DEFINE_PER_CPU(struct pagevec, lru_add_active_pvecs) = { 0, };
-+static DEFINE_PER_CPU(struct pagevec, lru_add_tail_pvecs) = { 0, };
- 
- void fastcall lru_cache_add(struct page *page)
- {
-@@ -197,6 +199,31 @@
- 	put_cpu_var(lru_add_active_pvecs);
- }
- 
-+static void __pagevec_lru_add_tail(struct pagevec *pvec)
-+{
-+	int i;
-+	struct zone *zone = NULL;
-+
-+	for (i = 0; i < pagevec_count(pvec); i++) {
-+		struct page *page = pvec->pages[i];
-+		struct zone *pagezone = page_zone(page);
-+
-+		if (pagezone != zone) {
-+			if (zone)
-+				spin_unlock_irq(&zone->lru_lock);
-+			zone = pagezone;
-+			spin_lock_irq(&zone->lru_lock);
-+		}
-+		BUG_ON(PageLRU(page));
-+		SetPageLRU(page);
-+		add_page_to_inactive_list_tail(zone, page);
-+	}
-+	if (zone)
-+		spin_unlock_irq(&zone->lru_lock);
-+	release_pages(pvec->pages, pvec->nr, pvec->cold);
-+	pagevec_reinit(pvec);
-+}
-+
- static void __lru_add_drain(int cpu)
- {
- 	struct pagevec *pvec = &per_cpu(lru_add_pvecs, cpu);
-@@ -207,6 +234,9 @@
- 	pvec = &per_cpu(lru_add_active_pvecs, cpu);
- 	if (pagevec_count(pvec))
- 		__pagevec_lru_add_active(pvec);
-+	pvec = &per_cpu(lru_add_tail_pvecs, cpu);
-+	if (pagevec_count(pvec))
-+		__pagevec_lru_add_tail(pvec);
- }
- 
- void lru_add_drain(void)
-@@ -403,6 +433,20 @@
- }
- 
- /*
-+ * Function used uniquely to put pages back to the lru at the end of the
-+ * inactive list to preserve the lru order.
-+ */
-+void fastcall lru_cache_add_tail(struct page *page)
-+{
-+	struct pagevec *pvec = &get_cpu_var(lru_add_tail_pvecs);
-+
-+	page_cache_get(page);
-+	if (!pagevec_add(pvec, page))
-+		__pagevec_lru_add_tail(pvec);
-+	put_cpu_var(lru_add_pvecs);
-+}
-+
-+/*
-  * Try to drop buffers from the pages in a pagevec
-  */
- void pagevec_strip(struct pagevec *pvec)
-@@ -514,6 +558,9 @@
- 	 * Right now other parts of the system means that we
- 	 * _really_ don't want to cluster much more
- 	 */
-+
-+	prepare_swap_prefetch();
-+
- #ifdef CONFIG_HOTPLUG_CPU
- 	hotcpu_notifier(cpu_swap_callback, 0);
- #endif
-Index: linux-2.6.22-ck1/mm/swap_prefetch.c
-===================================================================
---- /dev/null	1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.22-ck1/mm/swap_prefetch.c	2007-07-10 14:55:22.000000000 +1000
-@@ -0,0 +1,542 @@
-+/*
-+ * linux/mm/swap_prefetch.c
-+ *
-+ * Copyright (C) 2005-2007 Con Kolivas
-+ *
-+ * Written by Con Kolivas <kernel@kolivas.org>
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#include <linux/fs.h>
-+#include <linux/mm.h>
-+#include <linux/swap.h>
-+#include <linux/swap-prefetch.h>
-+#include <linux/ioprio.h>
-+#include <linux/kthread.h>
-+#include <linux/pagemap.h>
-+#include <linux/syscalls.h>
-+#include <linux/writeback.h>
-+#include <linux/vmstat.h>
-+#include <linux/freezer.h>
-+
-+/*
-+ * sysctls:
-+ * swap_prefetch:	0. Disable swap prefetching
-+ *			1. Prefetch only when idle and not with laptop_mode
-+ *			2. Prefetch when idle and with laptop_mode
-+ *			3. Prefetch at all times.
-+ * swap_prefetch_delay:	Number of seconds to delay prefetching when system
-+ *			is not idle.
-+ * swap_prefetch_sleep:	Number of seconds to put kprefetchd to sleep when
-+ *			unable to prefetch.
-+ */
-+int swap_prefetch __read_mostly = 1;
-+int swap_prefetch_delay __read_mostly = 1;
-+int swap_prefetch_sleep __read_mostly = 5;
-+
-+#define PREFETCH_DELAY		(HZ * swap_prefetch_delay)
-+#define PREFETCH_SLEEP		((HZ * swap_prefetch_sleep) ? : 1)
-+
-+struct swapped_root {
-+	unsigned long		busy;		/* vm busy */
-+	spinlock_t		lock;		/* protects all data */
-+	struct list_head	list;		/* MRU list of swapped pages */
-+	struct radix_tree_root	swap_tree;	/* Lookup tree of pages */
-+	unsigned int		count;		/* Number of entries */
-+	unsigned int		maxcount;	/* Maximum entries allowed */
-+	struct kmem_cache	*cache;		/* Of struct swapped_entry */
-+};
-+
-+static struct swapped_root swapped = {
-+	.lock		= SPIN_LOCK_UNLOCKED,
-+	.list  		= LIST_HEAD_INIT(swapped.list),
-+	.swap_tree	= RADIX_TREE_INIT(GFP_ATOMIC),
-+};
-+
-+static struct task_struct *kprefetchd_task;
-+
-+/*
-+ * We check to see no part of the vm is busy. If it is this will interrupt
-+ * trickle_swap and wait another PREFETCH_DELAY. Purposefully racy.
-+ */
-+inline void delay_swap_prefetch(void)
-+{
-+	if (!test_bit(0, &swapped.busy))
-+		__set_bit(0, &swapped.busy);
-+}
-+
-+/*
-+ * If laptop_mode is enabled don't prefetch to avoid hard drives
-+ * doing unnecessary spin-ups unless swap_prefetch is explicitly
-+ * set to a higher value.
-+ */
-+static inline int prefetch_enabled(void)
-+{
-+	if (swap_prefetch <= laptop_mode)
-+		return 0;
-+	return 1;
-+}
-+
-+static int kprefetchd_awake;
-+
-+/*
-+ * Drop behind accounting which keeps a list of the most recently used swap
-+ * entries. Entries are removed lazily by kprefetchd.
-+ */
-+void add_to_swapped_list(struct page *page)
-+{
-+	struct swapped_entry *entry;
-+	unsigned long index, flags;
-+
-+	if (!prefetch_enabled())
-+		goto out;
-+
-+	spin_lock_irqsave(&swapped.lock, flags);
-+	if (swapped.count >= swapped.maxcount) {
-+		/*
-+		 * Once the number of entries exceeds maxcount we start
-+		 * removing the least recently used entries.
-+		 */
-+		entry = list_entry(swapped.list.next,
-+			struct swapped_entry, swapped_list);
-+		radix_tree_delete(&swapped.swap_tree, entry->swp_entry.val);
-+		list_del(&entry->swapped_list);
-+		swapped.count--;
-+	} else {
-+		entry = kmem_cache_alloc(swapped.cache, GFP_ATOMIC);
-+		if (unlikely(!entry))
-+			/* bad, can't allocate more mem */
-+			goto out_locked;
-+	}
-+
-+	index = page_private(page);
-+	entry->swp_entry.val = index;
-+	/*
-+	 * On numa we need to store the node id to ensure that we prefetch to
-+	 * the same node it came from.
-+	 */
-+	store_swap_entry_node(entry, page);
-+
-+	if (likely(!radix_tree_insert(&swapped.swap_tree, index, entry))) {
-+		list_add(&entry->swapped_list, &swapped.list);
-+		swapped.count++;
-+	} else
-+		kmem_cache_free(swapped.cache, entry);
-+
-+out_locked:
-+	spin_unlock_irqrestore(&swapped.lock, flags);
-+out:
-+	if (!kprefetchd_awake)
-+		wake_up_process(kprefetchd_task);
-+	return;
-+}
-+
-+/*
-+ * Removes entries from the swapped_list. The radix tree allows us to quickly
-+ * look up the entry from the index without having to iterate over the whole
-+ * list.
-+ */
-+static void remove_from_swapped_list(const unsigned long index)
-+{
-+	struct swapped_entry *entry;
-+	unsigned long flags;
-+
-+	spin_lock_irqsave(&swapped.lock, flags);
-+	entry = radix_tree_delete(&swapped.swap_tree, index);
-+	if (likely(entry)) {
-+		list_del(&entry->swapped_list);
-+		swapped.count--;
-+		kmem_cache_free(swapped.cache, entry);
-+	}
-+	spin_unlock_irqrestore(&swapped.lock, flags);
-+}
-+
-+enum trickle_return {
-+	TRICKLE_SUCCESS,
-+	TRICKLE_FAILED,
-+	TRICKLE_DELAY,
-+};
-+
-+struct node_stats {
-+	/* Free ram after a cycle of prefetching */
-+	unsigned long	last_free;
-+	/* Free ram on this cycle of checking prefetch_suitable */
-+	unsigned long	current_free;
-+	/* The amount of free ram before we start prefetching */
-+	unsigned long	highfree[MAX_NR_ZONES];
-+	/* The amount of free ram where we will stop prefetching */
-+	unsigned long	lowfree[MAX_NR_ZONES];
-+	/* highfree or lowfree depending on whether we've hit a watermark */
-+	unsigned long	*pointfree[MAX_NR_ZONES];
-+};
-+
-+/*
-+ * prefetch_stats stores the free ram data of each node and this is used to
-+ * determine if a node is suitable for prefetching into.
-+ */
-+struct prefetch_stats {
-+	/* Which nodes are currently suited to prefetching */
-+	nodemask_t	prefetch_nodes;
-+	/* Total pages we've prefetched on this wakeup of kprefetchd */
-+	unsigned long	prefetched_pages;
-+	struct node_stats node[MAX_NUMNODES];
-+};
-+
-+static struct prefetch_stats sp_stat;
-+
-+/*
-+ * This tries to read a swp_entry_t into swap cache for swap prefetching.
-+ * If it returns TRICKLE_DELAY we should delay further prefetching.
-+ */
-+static enum trickle_return trickle_swap_cache_async(const swp_entry_t entry,
-+	const int node)
-+{
-+	enum trickle_return ret = TRICKLE_FAILED;
-+	unsigned long flags;
-+	struct page *page;
-+
-+	read_lock_irqsave(&swapper_space.tree_lock, flags);
-+	/* Entry may already exist */
-+	page = radix_tree_lookup(&swapper_space.page_tree, entry.val);
-+	read_unlock_irqrestore(&swapper_space.tree_lock, flags);
-+	if (page)
-+		goto out;
-+
-+	/*
-+	 * Get a new page to read from swap. We have already checked the
-+	 * watermarks so __alloc_pages will not call on reclaim.
-+	 */
-+	page = alloc_pages_node(node, GFP_HIGHUSER & ~__GFP_WAIT, 0);
-+	if (unlikely(!page)) {
-+		ret = TRICKLE_DELAY;
-+		goto out;
-+	}
-+
-+	if (add_to_swap_cache(page, entry)) {
-+		/* Failed to add to swap cache */
-+		goto out_release;
-+	}
-+
-+	/* Add them to the tail of the inactive list to preserve LRU order */
-+	lru_cache_add_tail(page);
-+	if (unlikely(swap_readpage(NULL, page)))
-+		goto out_release;
-+
-+	sp_stat.prefetched_pages++;
-+	sp_stat.node[node].last_free--;
-+
-+	ret = TRICKLE_SUCCESS;
-+out_release:
-+	page_cache_release(page);
-+out:
-+	/*
-+	 * All entries are removed here lazily. This avoids the cost of
-+	 * remove_from_swapped_list during normal swapin. Thus there are
-+	 * usually many stale entries.
-+	 */
-+	remove_from_swapped_list(entry.val);
-+	return ret;
-+}
-+
-+static void clear_last_prefetch_free(void)
-+{
-+	int node;
-+
-+	/*
-+	 * Reset the nodes suitable for prefetching to all nodes. We could
-+	 * update the data to take into account memory hotplug if desired..
-+	 */
-+	sp_stat.prefetch_nodes = node_online_map;
-+	for_each_node_mask(node, sp_stat.prefetch_nodes) {
-+		struct node_stats *ns = &sp_stat.node[node];
-+
-+		ns->last_free = 0;
-+	}
-+}
-+
-+static void clear_current_prefetch_free(void)
-+{
-+	int node;
-+
-+	sp_stat.prefetch_nodes = node_online_map;
-+	for_each_node_mask(node, sp_stat.prefetch_nodes) {
-+		struct node_stats *ns = &sp_stat.node[node];
-+
-+		ns->current_free = 0;
-+	}
-+}
-+
-+/*
-+ * This updates the high and low watermarks of amount of free ram in each
-+ * node used to start and stop prefetching. We prefetch from pages_high * 4
-+ * down to pages_high * 3.
-+ */
-+static void examine_free_limits(void)
-+{
-+	struct zone *z;
-+
-+	for_each_zone(z) {
-+		struct node_stats *ns;
-+		int idx;
-+
-+		if (!populated_zone(z))
-+			continue;
-+
-+		ns = &sp_stat.node[zone_to_nid(z)];
-+		idx = zone_idx(z);
-+		ns->lowfree[idx] = z->pages_high * 3;
-+		ns->highfree[idx] = ns->lowfree[idx] + z->pages_high;
-+
-+		if (zone_page_state(z, NR_FREE_PAGES) > ns->highfree[idx]) {
-+			/*
-+			 * We've gotten above the high watermark of free pages
-+			 * so we can start prefetching till we get to the low
-+			 * watermark.
-+			 */
-+			ns->pointfree[idx] = &ns->lowfree[idx];
-+		}
-+	}
-+}
-+
-+/*
-+ * We want to be absolutely certain it's ok to start prefetching.
-+ */
-+static enum trickle_return prefetch_suitable(void)
-+{
-+	enum trickle_return ret = TRICKLE_DELAY;
-+	struct zone *z;
-+	int node;
-+
-+	/*
-+	 * If swap_prefetch is set to a high value we can ignore load
-+	 * and prefetch whenever we can. Otherwise we test for vm and
-+	 * cpu activity.
-+	 */
-+	if (swap_prefetch < 3) {
-+		/* Purposefully racy, may return false positive */
-+		if (test_bit(0, &swapped.busy)) {
-+			__clear_bit(0, &swapped.busy);
-+			goto out;
-+		}
-+
-+		/*
-+		 * above_background_load is expensive so we only perform it
-+		 * every SWAP_CLUSTER_MAX prefetched_pages.
-+		 * We test to see if we're above_background_load as disk
-+		 * activity even at low priority can cause interrupt induced
-+		 * scheduling latencies.
-+		 */
-+		if (!(sp_stat.prefetched_pages % SWAP_CLUSTER_MAX) &&
-+		    above_background_load())
-+			goto out;
-+	}
-+	clear_current_prefetch_free();
-+
-+	/*
-+	 * Have some hysteresis between where page reclaiming and prefetching
-+	 * will occur to prevent ping-ponging between them.
-+	 */
-+	for_each_zone(z) {
-+		struct node_stats *ns;
-+		unsigned long free;
-+		int idx;
-+
-+		if (!populated_zone(z))
-+			continue;
-+
-+		node = zone_to_nid(z);
-+		ns = &sp_stat.node[node];
-+		idx = zone_idx(z);
-+
-+		free = zone_page_state(z, NR_FREE_PAGES);
-+		if (free < *ns->pointfree[idx]) {
-+			/*
-+			 * Free pages have dropped below the low watermark so
-+			 * we won't start prefetching again till we hit the
-+			 * high watermark of free pages.
-+			 */
-+			ns->pointfree[idx] = &ns->highfree[idx];
-+			node_clear(node, sp_stat.prefetch_nodes);
-+			continue;
-+		}
-+		ns->current_free += free;
-+	}
-+
-+	/*
-+	 * We iterate over each node testing to see if it is suitable for
-+	 * prefetching and clear the nodemask if it is not.
-+	 */
-+	for_each_node_mask(node, sp_stat.prefetch_nodes) {
-+		struct node_stats *ns = &sp_stat.node[node];
-+
-+		/*
-+		 * We check to see that pages are not being allocated
-+		 * elsewhere at any significant rate implying any
-+		 * degree of memory pressure (eg during file reads)
-+		 */
-+		if (ns->last_free) {
-+			if (ns->current_free + SWAP_CLUSTER_MAX <
-+			    ns->last_free) {
-+				ns->last_free = ns->current_free;
-+				node_clear(node,
-+					sp_stat.prefetch_nodes);
-+				continue;
-+			}
-+		} else
-+			ns->last_free = ns->current_free;
-+
-+		/* We shouldn't prefetch when we are doing writeback */
-+		if (node_page_state(node, NR_WRITEBACK))
-+			node_clear(node, sp_stat.prefetch_nodes);
-+	}
-+
-+	/* Nothing suitable, put kprefetchd back to sleep */
-+	if (nodes_empty(sp_stat.prefetch_nodes))
-+		return TRICKLE_FAILED;
-+
-+	/* Survived all that? Hooray we can prefetch! */
-+	ret = TRICKLE_SUCCESS;
-+out:
-+	return ret;
-+}
-+
-+/*
-+ * trickle_swap is the main function that initiates the swap prefetching. It
-+ * first checks to see if the busy flag is set, and does not prefetch if it
-+ * is, as the flag implied we are low on memory or swapping in currently.
-+ * Otherwise it runs until prefetch_suitable fails which occurs when the
-+ * vm is busy, we prefetch to the watermark, the list is empty or we have
-+ * iterated over all entries once.
-+ */
-+static enum trickle_return trickle_swap(void)
-+{
-+	enum trickle_return suitable, ret = TRICKLE_DELAY;
-+	struct swapped_entry *pos, *n;
-+	unsigned long flags;
-+
-+	if (!prefetch_enabled())
-+		return ret;
-+
-+	examine_free_limits();
-+	suitable = prefetch_suitable();
-+	if (suitable != TRICKLE_SUCCESS)
-+		return suitable;
-+	if (list_empty(&swapped.list)) {
-+		kprefetchd_awake = 0;
-+		return TRICKLE_FAILED;
-+	}
-+
-+	spin_lock_irqsave(&swapped.lock, flags);
-+	list_for_each_entry_safe_reverse(pos, n, &swapped.list, swapped_list) {
-+		swp_entry_t swp_entry;
-+		int node;
-+
-+		spin_unlock_irqrestore(&swapped.lock, flags);
-+		cond_resched();
-+		suitable = prefetch_suitable();
-+		if (suitable != TRICKLE_SUCCESS) {
-+			ret = suitable;
-+			goto out_unlocked;
-+		}
-+
-+		spin_lock_irqsave(&swapped.lock, flags);
-+		if (unlikely(!pos))
-+			continue;
-+		node = get_swap_entry_node(pos);
-+		if (!node_isset(node, sp_stat.prefetch_nodes)) {
-+			/*
-+			 * We found an entry that belongs to a node that is
-+			 * not suitable for prefetching so skip it.
-+			 */
-+			continue;
-+		}
-+		swp_entry = pos->swp_entry;
-+		spin_unlock_irqrestore(&swapped.lock, flags);
-+
-+		if (trickle_swap_cache_async(swp_entry, node) == TRICKLE_DELAY)
-+			goto out_unlocked;
-+		spin_lock_irqsave(&swapped.lock, flags);
-+	}
-+	spin_unlock_irqrestore(&swapped.lock, flags);
-+
-+out_unlocked:
-+	if (sp_stat.prefetched_pages) {
-+		lru_add_drain();
-+		sp_stat.prefetched_pages = 0;
-+	}
-+	return ret;
-+}
-+
-+static int kprefetchd(void *__unused)
-+{
-+	struct sched_param param = { .sched_priority = 0 };
-+
-+	sched_setscheduler(current, SCHED_BATCH, &param);
-+	set_user_nice(current, 19);
-+	/* Set ioprio to lowest if supported by i/o scheduler */
-+	sys_ioprio_set(IOPRIO_WHO_PROCESS, IOPRIO_BE_NR - 1, IOPRIO_CLASS_BE);
-+
-+	while (!kthread_should_stop()) {
-+		try_to_freeze();
-+
-+		if (!kprefetchd_awake) {
-+			set_current_state(TASK_INTERRUPTIBLE);
-+			schedule();
-+			kprefetchd_awake = 1;
-+		}
-+
-+		if (trickle_swap() == TRICKLE_FAILED)
-+			schedule_timeout_interruptible(PREFETCH_SLEEP);
-+		else
-+			schedule_timeout_interruptible(PREFETCH_DELAY);
-+		clear_last_prefetch_free();
-+	}
-+	return 0;
-+}
-+
-+/*
-+ * Create kmem cache for swapped entries
-+ */
-+void __init prepare_swap_prefetch(void)
-+{
-+	struct zone *zone;
-+
-+	swapped.cache = kmem_cache_create("swapped_entry",
-+		sizeof(struct swapped_entry), 0, SLAB_PANIC, NULL, NULL);
-+
-+	/*
-+	 * We set the limit to more entries than the physical ram.
-+	 * We remove entries lazily so we need some headroom.
-+	 */
-+	swapped.maxcount = nr_free_pagecache_pages() * 2;
-+
-+	for_each_zone(zone) {
-+		struct node_stats *ns;
-+		int idx;
-+
-+		if (!populated_zone(zone))
-+			continue;
-+
-+		ns = &sp_stat.node[zone_to_nid(zone)];
-+		idx = zone_idx(zone);
-+		ns->pointfree[idx] = &ns->highfree[idx];
-+	}
-+}
-+
-+static int __init kprefetchd_init(void)
-+{
-+	kprefetchd_task = kthread_run(kprefetchd, NULL, "kprefetchd");
-+
-+	return 0;
-+}
-+
-+static void __exit kprefetchd_exit(void)
-+{
-+	kthread_stop(kprefetchd_task);
-+}
-+
-+module_init(kprefetchd_init);
-+module_exit(kprefetchd_exit);
-Index: linux-2.6.22-ck1/mm/swap_state.c
-===================================================================
---- linux-2.6.22-ck1.orig/mm/swap_state.c	2007-07-10 14:55:00.000000000 +1000
-+++ linux-2.6.22-ck1/mm/swap_state.c	2007-07-10 14:55:22.000000000 +1000
-@@ -10,6 +10,7 @@
- #include <linux/mm.h>
- #include <linux/kernel_stat.h>
- #include <linux/swap.h>
-+#include <linux/swap-prefetch.h>
- #include <linux/init.h>
- #include <linux/pagemap.h>
- #include <linux/buffer_head.h>
-@@ -95,7 +96,7 @@
- 	return error;
- }
- 
--static int add_to_swap_cache(struct page *page, swp_entry_t entry)
-+int add_to_swap_cache(struct page *page, swp_entry_t entry)
- {
- 	int error;
- 
-@@ -148,6 +149,9 @@
- 	swp_entry_t entry;
- 	int err;
- 
-+	/* Swap prefetching is delayed if we're swapping pages */
-+	delay_swap_prefetch();
-+
- 	BUG_ON(!PageLocked(page));
- 
- 	for (;;) {
-@@ -320,6 +324,9 @@
- 	struct page *found_page, *new_page = NULL;
- 	int err;
- 
-+	/* Swap prefetching is delayed if we're already reading from swap */
-+	delay_swap_prefetch();
-+
- 	do {
- 		/*
- 		 * First check the swap cache.  Since this is normally
-Index: linux-2.6.22-ck1/mm/vmscan.c
-===================================================================
---- linux-2.6.22-ck1.orig/mm/vmscan.c	2007-07-10 14:55:00.000000000 +1000
-+++ linux-2.6.22-ck1/mm/vmscan.c	2007-07-10 14:55:23.000000000 +1000
-@@ -16,6 +16,7 @@
- #include <linux/slab.h>
- #include <linux/kernel_stat.h>
- #include <linux/swap.h>
-+#include <linux/swap-prefetch.h>
- #include <linux/pagemap.h>
- #include <linux/init.h>
- #include <linux/highmem.h>
-@@ -36,6 +37,7 @@
- #include <linux/rwsem.h>
- #include <linux/delay.h>
- #include <linux/kthread.h>
-+#include <linux/timer.h>
- #include <linux/freezer.h>
- 
- #include <asm/tlbflush.h>
-@@ -63,7 +65,7 @@
- 	 * whole list at once. */
- 	int swap_cluster_max;
- 
--	int swappiness;
-+	int mapped;
- 
- 	int all_unreclaimable;
- };
-@@ -110,9 +112,10 @@
- #endif
- 
- /*
-- * From 0 .. 100.  Higher means more swappy.
-+ * From 0 .. 100.  Lower means more swappy.
-  */
--int vm_swappiness = 60;
-+int vm_mapped __read_mostly = 66;
-+int vm_hardmaplimit __read_mostly = 1;
- long vm_total_pages;	/* The total number of pages which the VM controls */
- 
- static LIST_HEAD(shrinker_list);
-@@ -803,10 +806,14 @@
- 		 * The distress ratio is important - we don't want to start
- 		 * going oom.
- 		 *
--		 * A 100% value of vm_swappiness overrides this algorithm
--		 * altogether.
-+		 * This distress value is ignored if we apply a hardmaplimit except
-+		 * in extreme distress.
-+		 *
-+		 * A 0% value of vm_mapped overrides this algorithm altogether.
- 		 */
--		swap_tendency = mapped_ratio / 2 + distress + sc->swappiness;
-+		swap_tendency = mapped_ratio * 100 / (sc->mapped + 1);
-+		if (!vm_hardmaplimit || distress == 100)
-+			swap_tendency += distress;
- 
- 		/*
- 		 * Now use this metric to decide whether to start moving mapped
-@@ -955,6 +962,41 @@
- }
- 
- /*
-+ * Helper functions to adjust nice level of kswapd, based on the priority of
-+ * the task (p) that called it. If it is already higher priority we do not
-+ * demote its nice level since it is still working on behalf of a higher
-+ * priority task. With kernel threads we leave it at nice 0.
-+ *
-+ * We don't ever run kswapd real time, so if a real time task calls kswapd we
-+ * set it to highest SCHED_NORMAL priority.
-+ */
-+static int effective_sc_prio(struct task_struct *p)
-+{
-+	if (likely(p->mm)) {
-+		if (rt_task(p))
-+			return -20;
-+		if (idleprio_task(p))
-+			return 19;
-+		return task_nice(p);
-+	}
-+	return 0;
-+}
-+
-+static void set_kswapd_nice(struct task_struct *kswapd, struct task_struct *p,
-+			    int active)
-+{
-+	long nice = effective_sc_prio(p);
-+
-+	if (task_nice(kswapd) > nice || !active)
-+		set_user_nice(kswapd, nice);
-+}
-+
-+static int sc_priority(struct task_struct *p)
-+{
-+	return (DEF_PRIORITY + (DEF_PRIORITY * effective_sc_prio(p) / 40));
-+}
-+
-+/*
-  * This is the direct reclaim path, for page-allocating processes.  We only
-  * try to reclaim pages from zones which will satisfy the caller's allocation
-  * request.
-@@ -1011,7 +1053,8 @@
-  * holds filesystem locks which prevent writeout this might not work, and the
-  * allocation attempt will fail.
-  */
--unsigned long try_to_free_pages(struct zone **zones, gfp_t gfp_mask)
-+unsigned long try_to_free_pages(struct zone **zones, gfp_t gfp_mask,
-+				struct task_struct *p)
- {
- 	int priority;
- 	int ret = 0;
-@@ -1019,15 +1062,20 @@
- 	unsigned long nr_reclaimed = 0;
- 	struct reclaim_state *reclaim_state = current->reclaim_state;
- 	unsigned long lru_pages = 0;
--	int i;
-+	int i, scan_priority = DEF_PRIORITY;
- 	struct scan_control sc = {
- 		.gfp_mask = gfp_mask,
- 		.may_writepage = !laptop_mode,
- 		.swap_cluster_max = SWAP_CLUSTER_MAX,
- 		.may_swap = 1,
--		.swappiness = vm_swappiness,
-+		.mapped = vm_mapped,
- 	};
- 
-+	if (p)
-+		scan_priority = sc_priority(p);
-+
-+	delay_swap_prefetch();
-+
- 	count_vm_event(ALLOCSTALL);
- 
- 	for (i = 0; zones[i] != NULL; i++) {
-@@ -1040,7 +1088,7 @@
- 				+ zone_page_state(zone, NR_INACTIVE);
- 	}
- 
--	for (priority = DEF_PRIORITY; priority >= 0; priority--) {
-+	for (priority = scan_priority; priority >= 0; priority--) {
- 		sc.nr_scanned = 0;
- 		if (!priority)
- 			disable_swap_token();
-@@ -1070,7 +1118,7 @@
- 		}
- 
- 		/* Take a nap, wait for some writeback to complete */
--		if (sc.nr_scanned && priority < DEF_PRIORITY - 2)
-+		if (sc.nr_scanned && priority < scan_priority - 2)
- 			congestion_wait(WRITE, HZ/10);
- 	}
- 	/* top priority shrink_caches still had more to do? don't OOM, then */
-@@ -1120,9 +1168,9 @@
-  */
- static unsigned long balance_pgdat(pg_data_t *pgdat, int order)
- {
--	int all_zones_ok;
-+	int all_zones_ok = 0;
- 	int priority;
--	int i;
-+	int i, scan_priority;
- 	unsigned long total_scanned;
- 	unsigned long nr_reclaimed;
- 	struct reclaim_state *reclaim_state = current->reclaim_state;
-@@ -1130,7 +1178,7 @@
- 		.gfp_mask = GFP_KERNEL,
- 		.may_swap = 1,
- 		.swap_cluster_max = SWAP_CLUSTER_MAX,
--		.swappiness = vm_swappiness,
-+		.mapped = vm_mapped,
- 	};
- 	/*
- 	 * temp_priority is used to remember the scanning priority at which
-@@ -1138,6 +1186,8 @@
- 	 */
- 	int temp_priority[MAX_NR_ZONES];
- 
-+	scan_priority = sc_priority(pgdat->kswapd);
-+
- loop_again:
- 	total_scanned = 0;
- 	nr_reclaimed = 0;
-@@ -1145,9 +1195,9 @@
- 	count_vm_event(PAGEOUTRUN);
- 
- 	for (i = 0; i < pgdat->nr_zones; i++)
--		temp_priority[i] = DEF_PRIORITY;
-+		temp_priority[i] = scan_priority;
- 
--	for (priority = DEF_PRIORITY; priority >= 0; priority--) {
-+	for (priority = scan_priority; priority >= 0; priority--) {
- 		int end_zone = 0;	/* Inclusive.  0 = ZONE_DMA */
- 		unsigned long lru_pages = 0;
- 
-@@ -1163,15 +1213,22 @@
- 		 */
- 		for (i = pgdat->nr_zones - 1; i >= 0; i--) {
- 			struct zone *zone = pgdat->node_zones + i;
-+			unsigned long watermark;
- 
- 			if (!populated_zone(zone))
- 				continue;
- 
--			if (zone->all_unreclaimable && priority != DEF_PRIORITY)
-+			if (zone->all_unreclaimable && priority != scan_priority)
- 				continue;
- 
--			if (!zone_watermark_ok(zone, order, zone->pages_high,
--					       0, 0)) {
-+			/*
-+			 * The watermark is relaxed depending on the
-+			 * level of "priority" till it drops to
-+			 * pages_high.
-+			 */
-+			watermark = zone->pages_high + (zone->pages_high *
-+				    priority / scan_priority);
-+			if (!zone_watermark_ok(zone, order, watermark, 0, 0)) {
- 				end_zone = i;
- 				break;
- 			}
-@@ -1198,14 +1255,18 @@
- 		for (i = 0; i <= end_zone; i++) {
- 			struct zone *zone = pgdat->node_zones + i;
- 			int nr_slab;
-+			unsigned long watermark;
- 
- 			if (!populated_zone(zone))
- 				continue;
- 
--			if (zone->all_unreclaimable && priority != DEF_PRIORITY)
-+			if (zone->all_unreclaimable && priority != scan_priority)
- 				continue;
- 
--			if (!zone_watermark_ok(zone, order, zone->pages_high,
-+			watermark = zone->pages_high + (zone->pages_high *
-+				    priority / scan_priority);
-+
-+			if (!zone_watermark_ok(zone, order, watermark,
- 					       end_zone, 0))
- 				all_zones_ok = 0;
- 			temp_priority[i] = priority;
-@@ -1238,7 +1299,7 @@
- 		 * OK, kswapd is getting into trouble.  Take a nap, then take
- 		 * another pass across the zones.
- 		 */
--		if (total_scanned && priority < DEF_PRIORITY - 2)
-+		if (total_scanned && priority < scan_priority - 2)
- 			congestion_wait(WRITE, HZ/10);
- 
- 		/*
-@@ -1272,6 +1333,8 @@
- 	return nr_reclaimed;
- }
- 
-+#define WT_EXPIRY	(HZ * 5)	/* Time to wakeup watermark_timer */
-+
- /*
-  * The background pageout daemon, started as a kernel thread
-  * from the init process. 
-@@ -1319,6 +1382,8 @@
- 	for ( ; ; ) {
- 		unsigned long new_order;
- 
-+		/* kswapd has been busy so delay watermark_timer */
-+		mod_timer(&pgdat->watermark_timer, jiffies + WT_EXPIRY);
- 		prepare_to_wait(&pgdat->kswapd_wait, &wait, TASK_INTERRUPTIBLE);
- 		new_order = pgdat->kswapd_max_order;
- 		pgdat->kswapd_max_order = 0;
-@@ -1332,6 +1397,7 @@
- 			if (!freezing(current))
- 				schedule();
- 
-+			set_user_nice(tsk, 0);
- 			order = pgdat->kswapd_max_order;
- 		}
- 		finish_wait(&pgdat->kswapd_wait, &wait);
-@@ -1349,9 +1415,10 @@
- /*
-  * A zone is low on free memory, so wake its kswapd task to service it.
-  */
--void wakeup_kswapd(struct zone *zone, int order)
-+void wakeup_kswapd(struct zone *zone, int order, struct task_struct *p)
- {
- 	pg_data_t *pgdat;
-+	int active;
- 
- 	if (!populated_zone(zone))
- 		return;
-@@ -1363,7 +1430,9 @@
- 		pgdat->kswapd_max_order = order;
- 	if (!cpuset_zone_allowed_hardwall(zone, GFP_KERNEL))
- 		return;
--	if (!waitqueue_active(&pgdat->kswapd_wait))
-+	active = waitqueue_active(&pgdat->kswapd_wait);
-+	set_kswapd_nice(pgdat->kswapd, p, active);
-+	if (!active)
- 		return;
- 	wake_up_interruptible(&pgdat->kswapd_wait);
- }
-@@ -1382,6 +1451,8 @@
- 	struct zone *zone;
- 	unsigned long nr_to_scan, ret = 0;
- 
-+	delay_swap_prefetch();
-+
- 	for_each_zone(zone) {
- 
- 		if (!populated_zone(zone))
-@@ -1441,7 +1512,7 @@
- 		.may_swap = 0,
- 		.swap_cluster_max = nr_pages,
- 		.may_writepage = 1,
--		.swappiness = vm_swappiness,
-+		.mapped = vm_mapped,
- 	};
- 
- 	current->reclaim_state = &reclaim_state;
-@@ -1476,7 +1547,7 @@
- 		/* Force reclaiming mapped pages in the passes #3 and #4 */
- 		if (pass > 2) {
- 			sc.may_swap = 1;
--			sc.swappiness = 100;
-+			sc.mapped = 0;
- 		}
- 
- 		for (prio = DEF_PRIORITY; prio >= 0; prio--) {
-@@ -1540,20 +1611,57 @@
- }
- 
- /*
-+ * We wake up kswapd every WT_EXPIRY till free ram is above pages_lots
-+ */
-+static void watermark_wakeup(unsigned long data)
-+{
-+	pg_data_t *pgdat = (pg_data_t *)data;
-+	struct timer_list *wt = &pgdat->watermark_timer;
-+	int i;
-+
-+	if (!waitqueue_active(&pgdat->kswapd_wait) || above_background_load())
-+		goto out;
-+	for (i = pgdat->nr_zones - 1; i >= 0; i--) {
-+		struct zone *z = pgdat->node_zones + i;
-+
-+		if (!populated_zone(z) || is_highmem(z)) {
-+			/* We are better off leaving highmem full */
-+			continue;
-+		}
-+		if (!zone_watermark_ok(z, 0, z->pages_lots, 0, 0)) {
-+			wake_up_interruptible(&pgdat->kswapd_wait);
-+			goto out;
-+		}
-+	}
-+out:
-+	mod_timer(wt, jiffies + WT_EXPIRY);
-+	return;
-+}
-+
-+/*
-  * This kswapd start function will be called by init and node-hot-add.
-  * On node-hot-add, kswapd will moved to proper cpus if cpus are hot-added.
-  */
- int kswapd_run(int nid)
- {
- 	pg_data_t *pgdat = NODE_DATA(nid);
-+	struct timer_list *wt;
- 	int ret = 0;
- 
- 	if (pgdat->kswapd)
- 		return 0;
- 
-+	wt = &pgdat->watermark_timer;
-+	init_timer(wt);
-+	wt->data = (unsigned long)pgdat;
-+	wt->function = watermark_wakeup;
-+	wt->expires = jiffies + WT_EXPIRY;
-+	add_timer(wt);
-+
- 	pgdat->kswapd = kthread_run(kswapd, pgdat, "kswapd%d", nid);
- 	if (IS_ERR(pgdat->kswapd)) {
- 		/* failure at boot is fatal */
-+		del_timer(wt);
- 		BUG_ON(system_state == SYSTEM_BOOTING);
- 		printk("Failed to start kswapd on node %d\n",nid);
- 		ret = -1;
-@@ -1624,7 +1732,7 @@
- 		.swap_cluster_max = max_t(unsigned long, nr_pages,
- 					SWAP_CLUSTER_MAX),
- 		.gfp_mask = gfp_mask,
--		.swappiness = vm_swappiness,
-+		.mapped = vm_mapped,
- 	};
- 	unsigned long slab_reclaimable;
- 
-Index: linux-2.6.22-ck1/include/linux/mm_inline.h
-===================================================================
---- linux-2.6.22-ck1.orig/include/linux/mm_inline.h	2007-07-10 14:54:59.000000000 +1000
-+++ linux-2.6.22-ck1/include/linux/mm_inline.h	2007-07-10 14:55:22.000000000 +1000
-@@ -13,6 +13,13 @@
- }
- 
- static inline void
-+add_page_to_inactive_list_tail(struct zone *zone, struct page *page)
-+{
-+	list_add_tail(&page->lru, &zone->inactive_list);
-+	__inc_zone_state(zone, NR_INACTIVE);
-+}
-+
-+static inline void
- del_page_from_active_list(struct zone *zone, struct page *page)
- {
- 	list_del(&page->lru);
-Index: linux-2.6.22-ck1/include/linux/swap-prefetch.h
-===================================================================
---- /dev/null	1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.22-ck1/include/linux/swap-prefetch.h	2007-07-10 14:55:22.000000000 +1000
-@@ -0,0 +1,53 @@
-+#ifndef SWAP_PREFETCH_H_INCLUDED
-+#define SWAP_PREFETCH_H_INCLUDED
-+
-+#ifdef CONFIG_SWAP_PREFETCH
-+/* mm/swap_prefetch.c */
-+extern int swap_prefetch;
-+extern int swap_prefetch_delay;
-+extern int swap_prefetch_sleep;
-+
-+struct swapped_entry {
-+	swp_entry_t		swp_entry;	/* The actual swap entry */
-+	struct list_head	swapped_list;	/* Linked list of entries */
-+#if MAX_NUMNODES > 1
-+	int			node;		/* Node id */
-+#endif
-+} __attribute__((packed));
-+
-+static inline void store_swap_entry_node(struct swapped_entry *entry,
-+	struct page *page)
-+{
-+#if MAX_NUMNODES > 1
-+	entry->node = page_to_nid(page);
-+#endif
-+}
-+
-+static inline int get_swap_entry_node(struct swapped_entry *entry)
-+{
-+#if MAX_NUMNODES > 1
-+	return entry->node;
-+#else
-+	return 0;
-+#endif
-+}
-+
-+extern void add_to_swapped_list(struct page *page);
-+extern void delay_swap_prefetch(void);
-+extern void prepare_swap_prefetch(void);
-+
-+#else	/* CONFIG_SWAP_PREFETCH */
-+static inline void add_to_swapped_list(struct page *__unused)
-+{
-+}
-+
-+static inline void prepare_swap_prefetch(void)
-+{
-+}
-+
-+static inline void delay_swap_prefetch(void)
-+{
-+}
-+#endif	/* CONFIG_SWAP_PREFETCH */
-+
-+#endif		/* SWAP_PREFETCH_H_INCLUDED */
-Index: linux-2.6.22-ck1/mm/page_io.c
-===================================================================
---- linux-2.6.22-ck1.orig/mm/page_io.c	2007-07-10 14:55:00.000000000 +1000
-+++ linux-2.6.22-ck1/mm/page_io.c	2007-07-10 14:55:22.000000000 +1000
-@@ -17,6 +17,7 @@
- #include <linux/bio.h>
- #include <linux/swapops.h>
- #include <linux/writeback.h>
-+#include <linux/swap-prefetch.h>
- #include <asm/pgtable.h>
- 
- static struct bio *get_swap_bio(gfp_t gfp_flags, pgoff_t index,
-@@ -118,6 +119,7 @@
- 		ret = -ENOMEM;
- 		goto out;
- 	}
-+	add_to_swapped_list(page);
- 	if (wbc->sync_mode == WB_SYNC_ALL)
- 		rw |= (1 << BIO_RW_SYNC);
- 	count_vm_event(PSWPOUT);
-Index: linux-2.6.22-ck1/include/linux/sysctl.h
-===================================================================
---- linux-2.6.22-ck1.orig/include/linux/sysctl.h	2007-07-10 14:54:59.000000000 +1000
-+++ linux-2.6.22-ck1/include/linux/sysctl.h	2007-07-10 14:55:22.000000000 +1000
-@@ -190,7 +190,7 @@
- 	VM_OVERCOMMIT_RATIO=16, /* percent of RAM to allow overcommit in */
- 	VM_PAGEBUF=17,		/* struct: Control pagebuf parameters */
- 	VM_HUGETLB_PAGES=18,	/* int: Number of available Huge Pages */
--	VM_SWAPPINESS=19,	/* Tendency to steal mapped memory */
-+	VM_UNUSED19=19,		/* was: Tendency to steal mapped memory */
- 	VM_LOWMEM_RESERVE_RATIO=20,/* reservation ratio for lower memory zones */
- 	VM_MIN_FREE_KBYTES=21,	/* Minimum free kilobytes to maintain */
- 	VM_MAX_MAP_COUNT=22,	/* int: Maximum number of mmaps/address-space */
-Index: linux-2.6.22-ck1/include/linux/mmzone.h
-===================================================================
---- linux-2.6.22-ck1.orig/include/linux/mmzone.h	2007-07-10 14:54:59.000000000 +1000
-+++ linux-2.6.22-ck1/include/linux/mmzone.h	2007-07-10 14:55:23.000000000 +1000
-@@ -13,6 +13,7 @@
- #include <linux/init.h>
- #include <linux/seqlock.h>
- #include <linux/nodemask.h>
-+#include <linux/timer.h>
- #include <asm/atomic.h>
- #include <asm/page.h>
- 
-@@ -181,7 +182,7 @@
- 
- struct zone {
- 	/* Fields commonly accessed by the page allocator */
--	unsigned long		pages_min, pages_low, pages_high;
-+	unsigned long		pages_min, pages_low, pages_high, pages_lots;
- 	/*
- 	 * We don't know if the memory that we're going to allocate will be freeable
- 	 * or/and it will be released eventually, so to avoid totally wasting several
-@@ -452,6 +453,7 @@
- 	wait_queue_head_t kswapd_wait;
- 	struct task_struct *kswapd;
- 	int kswapd_max_order;
-+	struct timer_list watermark_timer;
- } pg_data_t;
- 
- #define node_present_pages(nid)	(NODE_DATA(nid)->node_present_pages)
-@@ -468,7 +470,7 @@
- void get_zone_counts(unsigned long *active, unsigned long *inactive,
- 			unsigned long *free);
- void build_all_zonelists(void);
--void wakeup_kswapd(struct zone *zone, int order);
-+void wakeup_kswapd(struct zone *zone, int order, struct task_struct *p);
- int zone_watermark_ok(struct zone *z, int order, unsigned long mark,
- 		int classzone_idx, int alloc_flags);
- enum memmap_context {
-Index: linux-2.6.22-ck1/mm/page_alloc.c
-===================================================================
---- linux-2.6.22-ck1.orig/mm/page_alloc.c	2007-07-10 14:54:59.000000000 +1000
-+++ linux-2.6.22-ck1/mm/page_alloc.c	2007-07-10 14:55:22.000000000 +1000
-@@ -1250,7 +1250,7 @@
- 		goto nopage;
- 
- 	for (z = zonelist->zones; *z; z++)
--		wakeup_kswapd(*z, order);
-+		wakeup_kswapd(*z, order, p);
- 
- 	/*
- 	 * OK, we're below the kswapd watermark and have kicked background
-@@ -1314,7 +1314,7 @@
- 	reclaim_state.reclaimed_slab = 0;
- 	p->reclaim_state = &reclaim_state;
- 
--	did_some_progress = try_to_free_pages(zonelist->zones, gfp_mask);
-+	did_some_progress = try_to_free_pages(zonelist->zones, gfp_mask, p);
- 
- 	p->reclaim_state = NULL;
- 	p->flags &= ~PF_MEMALLOC;
-@@ -1570,6 +1570,7 @@
- 			" min:%lukB"
- 			" low:%lukB"
- 			" high:%lukB"
-+			" lots:%lukB"
- 			" active:%lukB"
- 			" inactive:%lukB"
- 			" present:%lukB"
-@@ -1581,6 +1582,7 @@
- 			K(zone->pages_min),
- 			K(zone->pages_low),
- 			K(zone->pages_high),
-+			K(zone->pages_lots),
- 			K(zone_page_state(zone, NR_ACTIVE)),
- 			K(zone_page_state(zone, NR_INACTIVE)),
- 			K(zone->present_pages),
-@@ -3142,6 +3144,7 @@
- 
- 		zone->pages_low   = zone->pages_min + (tmp >> 2);
- 		zone->pages_high  = zone->pages_min + (tmp >> 1);
-+		zone->pages_lots  = zone->pages_min + tmp;
- 		spin_unlock_irqrestore(&zone->lru_lock, flags);
- 	}
- 
-Index: linux-2.6.22-ck1/fs/buffer.c
-===================================================================
---- linux-2.6.22-ck1.orig/fs/buffer.c	2007-07-10 14:54:59.000000000 +1000
-+++ linux-2.6.22-ck1/fs/buffer.c	2007-07-10 14:55:22.000000000 +1000
-@@ -356,7 +356,7 @@
- 	for_each_online_pgdat(pgdat) {
- 		zones = pgdat->node_zonelists[gfp_zone(GFP_NOFS)].zones;
- 		if (*zones)
--			try_to_free_pages(zones, GFP_NOFS);
-+			try_to_free_pages(zones, GFP_NOFS, NULL);
- 	}
- }
- 
-Index: linux-2.6.22-ck1/mm/filemap.c
-===================================================================
---- linux-2.6.22-ck1.orig/mm/filemap.c	2007-07-10 14:54:59.000000000 +1000
-+++ linux-2.6.22-ck1/mm/filemap.c	2007-07-10 14:55:23.000000000 +1000
-@@ -466,6 +466,16 @@
- 	return ret;
- }
- 
-+int add_to_page_cache_lru_tail(struct page *page,
-+	struct address_space *mapping, pgoff_t offset, gfp_t gfp_mask)
-+{
-+	int ret = add_to_page_cache(page, mapping, offset, gfp_mask);
-+
-+	if (ret == 0)
-+		lru_cache_add_tail(page);
-+	return ret;
-+}
-+
- #ifdef CONFIG_NUMA
- struct page *__page_cache_alloc(gfp_t gfp)
- {
-@@ -839,6 +849,34 @@
- 	ra->ra_pages /= 4;
- }
- 
-+/*
-+ * Sysctl which determines whether we should read from large files to the
-+ * tail of the inactive lru list.
-+ */
-+int vm_tail_largefiles __read_mostly = 1;
-+
-+static inline int nr_mapped(void)
-+{
-+	return global_page_state(NR_FILE_MAPPED) +
-+		global_page_state(NR_ANON_PAGES);
-+}
-+
-+/*
-+ * This examines how large in pages a file size is and returns 1 if it is
-+ * more than half the unmapped ram. Avoid doing read_page_state which is
-+ * expensive unless we already know it is likely to be large enough.
-+ */
-+static int large_isize(unsigned long nr_pages)
-+{
-+	if (nr_pages * 6 > vm_total_pages) {
-+		 unsigned long unmapped_ram = vm_total_pages - nr_mapped();
-+
-+		if (nr_pages * 2 > unmapped_ram)
-+			return 1;
-+	}
-+	return 0;
-+}
-+
- /**
-  * do_generic_mapping_read - generic file read routine
-  * @mapping:	address_space to be read
-@@ -1051,8 +1089,19 @@
- 				goto out;
- 			}
- 		}
--		error = add_to_page_cache_lru(cached_page, mapping,
--						index, GFP_KERNEL);
-+
-+		/*
-+		 * If we know the file is large we add the pages read to the
-+		 * end of the lru as we're unlikely to be able to cache the
-+		 * whole file in ram so make those pages the first to be
-+		 * dropped if not referenced soon.
-+		 */
-+		if (vm_tail_largefiles && large_isize(end_index))
-+			error = add_to_page_cache_lru_tail(cached_page,
-+						mapping, index, GFP_KERNEL);
-+		else
-+			error = add_to_page_cache_lru(cached_page, mapping,
-+							index, GFP_KERNEL);
- 		if (error) {
- 			if (error == -EEXIST)
- 				goto find_page;
-Index: linux-2.6.22-ck1/Documentation/filesystems/proc.txt
-===================================================================
---- linux-2.6.22-ck1.orig/Documentation/filesystems/proc.txt	2007-07-10 14:54:59.000000000 +1000
-+++ linux-2.6.22-ck1/Documentation/filesystems/proc.txt	2007-07-10 14:55:23.000000000 +1000
-@@ -1333,6 +1333,14 @@
- As this is a non-destructive operation and dirty objects are not freeable, the
- user should run `sync' first.
- 
-+tail_largefiles
-+---------------
-+
-+When enabled reads from large files to the tail end of the inactive lru list.
-+This means that any cache from reading large files is dropped very quickly,
-+preventing loss of mapped ram and useful pagecache when large files are read.
-+This does, however, make caching less effective when working with large files.
-+
- 
- 2.5 /proc/sys/dev - Device specific parameters
- ----------------------------------------------
-Index: linux-2.6.22-ck1/arch/i386/Kconfig
-===================================================================
---- linux-2.6.22-ck1.orig/arch/i386/Kconfig	2007-07-10 14:54:59.000000000 +1000
-+++ linux-2.6.22-ck1/arch/i386/Kconfig	2007-07-10 14:55:23.000000000 +1000
-@@ -550,7 +550,7 @@
- 
- choice
- 	depends on EXPERIMENTAL
--	prompt "Memory split" if EMBEDDED
-+	prompt "Memory split"
- 	default VMSPLIT_3G
- 	help
- 	  Select the desired split between kernel and user memory.
-@@ -569,17 +569,17 @@
- 	  option alone!
- 
- 	config VMSPLIT_3G
--		bool "3G/1G user/kernel split"
-+		bool "Default 896MB lowmem (3G/1G user/kernel split)"
- 	config VMSPLIT_3G_OPT
- 		depends on !HIGHMEM
--		bool "3G/1G user/kernel split (for full 1G low memory)"
-+		bool "1GB lowmem (3G/1G user/kernel split)"
- 	config VMSPLIT_2G
--		bool "2G/2G user/kernel split"
-+		bool "2GB lowmem (2G/2G user/kernel split)"
- 	config VMSPLIT_2G_OPT
- 		depends on !HIGHMEM
--		bool "2G/2G user/kernel split (for full 2G low memory)"
-+		bool "2GB lowmem (2G/2G user/kernel split)"
- 	config VMSPLIT_1G
--		bool "1G/3G user/kernel split"
-+		bool "3GB lowmem (1G/3G user/kernel split)"
- endchoice
- 
- config PAGE_OFFSET
-Index: linux-2.6.22-ck1/kernel/Kconfig.hz
-===================================================================
---- linux-2.6.22-ck1.orig/kernel/Kconfig.hz	2007-07-10 14:54:59.000000000 +1000
-+++ linux-2.6.22-ck1/kernel/Kconfig.hz	2007-07-10 14:55:24.000000000 +1000
-@@ -4,7 +4,7 @@
- 
- choice
- 	prompt "Timer frequency"
--	default HZ_250
-+	default HZ_1000
- 	help
- 	 Allows the configuration of the timer frequency. It is customary
- 	 to have the timer interrupt run at 1000 Hz but 100 Hz may be more
-@@ -13,8 +13,7 @@
- 	 contention and cacheline bounces as a result of timer interrupts.
- 	 Note that the timer interrupt occurs on each processor in an SMP
- 	 environment leading to NR_CPUS * HZ number of timer interrupts
--	 per second.
--
-+	 per second.Laptops may also show improved battery life.
- 
- 	config HZ_100
- 		bool "100 HZ"
-@@ -23,13 +22,14 @@
- 	  with lots of processors that may show reduced performance if
- 	  too many timer interrupts are occurring.
- 
--	config HZ_250
-+	config HZ_250_NODEFAULT
- 		bool "250 HZ"
- 	help
--	 250 Hz is a good compromise choice allowing server performance
--	 while also showing good interactive responsiveness even
--	 on SMP and NUMA systems. If you are going to be using NTSC video
--	 or multimedia, selected 300Hz instead.
-+	 250 HZ is a lousy compromise choice allowing server interactivity
-+	 while also showing desktop throughput and no extra power saving on
-+	 laptops. Good for when you can't make up your mind.
-+
-+	 Recommend 100 or 1000 instead.
- 
- 	config HZ_300
- 		bool "300 HZ"
-@@ -45,12 +45,76 @@
- 	 1000 Hz is the preferred choice for desktop systems and other
- 	 systems requiring fast interactive responses to events.
- 
-+	config HZ_1500
-+		bool "1500 HZ"
-+	help
-+	 1500 Hz is an insane value to use to run broken software that is Hz
-+	 limited.
-+
-+	 Being over 1000, driver breakage is likely.
-+
-+	config HZ_2000
-+		bool "2000 HZ"
-+	help
-+	 2000 Hz is an insane value to use to run broken software that is Hz
-+	 limited.
-+
-+	 Being over 1000, driver breakage is likely.
-+
-+	config HZ_3000
-+		bool "3000 HZ"
-+	help
-+	 3000 Hz is an insane value to use to run broken software that is Hz
-+	 limited.
-+
-+	 Being over 1000, driver breakage is likely.
-+
-+	config HZ_4000
-+		bool "4000 HZ"
-+	help
-+	 4000 Hz is an insane value to use to run broken software that is Hz
-+	 limited.
-+
-+	 Being over 1000, driver breakage is likely.
-+
-+	config HZ_5000
-+		bool "5000 HZ"
-+	help
-+	 5000 Hz is an obscene value to use to run broken software that is Hz
-+	 limited.
-+
-+	 Being over 1000, driver breakage is likely.
-+
-+	config HZ_7500
-+		bool "7500 HZ"
-+	help
-+	 7500 Hz is an obscene value to use to run broken software that is Hz
-+	 limited.
-+
-+	 Being over 1000, driver breakage is likely.
-+
-+	config HZ_10000
-+		bool "10000 HZ"
-+	help
-+	 10000 Hz is an obscene value to use to run broken software that is Hz
-+	 limited.
-+
-+	 Being over 1000, driver breakage is likely.
-+
-+
- endchoice
- 
- config HZ
- 	int
- 	default 100 if HZ_100
--	default 250 if HZ_250
-+	default 250 if HZ_250_NODEFAULT
- 	default 300 if HZ_300
- 	default 1000 if HZ_1000
-+	default 1500 if HZ_1500
-+	default 2000 if HZ_2000
-+	default 3000 if HZ_3000
-+	default 4000 if HZ_4000
-+	default 5000 if HZ_5000
-+	default 7500 if HZ_7500
-+	default 10000 if HZ_10000
- 
-Index: linux-2.6.22-ck1/arch/i386/defconfig
-===================================================================
---- linux-2.6.22-ck1.orig/arch/i386/defconfig	2007-07-10 14:54:59.000000000 +1000
-+++ linux-2.6.22-ck1/arch/i386/defconfig	2007-07-10 14:55:23.000000000 +1000
-@@ -226,10 +226,10 @@
- # CONFIG_IRQBALANCE is not set
- CONFIG_SECCOMP=y
- # CONFIG_HZ_100 is not set
--CONFIG_HZ_250=y
-+# CONFIG_HZ_250 is not set
- # CONFIG_HZ_300 is not set
--# CONFIG_HZ_1000 is not set
--CONFIG_HZ=250
-+CONFIG_HZ_1000=y
-+CONFIG_HZ=1000
- # CONFIG_KEXEC is not set
- # CONFIG_CRASH_DUMP is not set
- CONFIG_PHYSICAL_START=0x100000
-Index: linux-2.6.22-ck1/arch/x86_64/defconfig
-===================================================================
---- linux-2.6.22-ck1.orig/arch/x86_64/defconfig	2007-07-10 14:54:59.000000000 +1000
-+++ linux-2.6.22-ck1/arch/x86_64/defconfig	2007-07-10 14:55:23.000000000 +1000
-@@ -185,10 +185,10 @@
- CONFIG_SECCOMP=y
- # CONFIG_CC_STACKPROTECTOR is not set
- # CONFIG_HZ_100 is not set
--CONFIG_HZ_250=y
-+# CONFIG_HZ_250 is not set
- # CONFIG_HZ_300 is not set
--# CONFIG_HZ_1000 is not set
--CONFIG_HZ=250
-+CONFIG_HZ_1000=y
-+CONFIG_HZ=1000
- CONFIG_K8_NB=y
- CONFIG_GENERIC_HARDIRQS=y
- CONFIG_GENERIC_IRQ_PROBE=y
-Index: linux-2.6.22-ck1/include/linux/jiffies.h
-===================================================================
---- linux-2.6.22-ck1.orig/include/linux/jiffies.h	2007-07-10 14:54:59.000000000 +1000
-+++ linux-2.6.22-ck1/include/linux/jiffies.h	2007-07-10 14:55:24.000000000 +1000
-@@ -29,6 +29,12 @@
- # define SHIFT_HZ	9
- #elif HZ >= 768 && HZ < 1536
- # define SHIFT_HZ	10
-+#elif HZ >= 1536 && HZ < 3072
-+# define SHIFT_HZ	11
-+#elif HZ >= 3072 && HZ < 6144
-+# define SHIFT_HZ	12
-+#elif HZ >= 6144 && HZ < 12288
-+# define SHIFT_HZ	13
- #else
- # error You lose.
- #endif
-Index: linux-2.6.22-ck1/include/net/inet_timewait_sock.h
-===================================================================
---- linux-2.6.22-ck1.orig/include/net/inet_timewait_sock.h	2007-07-10 14:54:59.000000000 +1000
-+++ linux-2.6.22-ck1/include/net/inet_timewait_sock.h	2007-07-10 14:55:24.000000000 +1000
-@@ -38,8 +38,8 @@
-  * If time > 4sec, it is "slow" path, no recycling is required,
-  * so that we select tick to get range about 4 seconds.
-  */
--#if HZ <= 16 || HZ > 4096
--# error Unsupported: HZ <= 16 or HZ > 4096
-+#if HZ <= 16 || HZ > 16384
-+# error Unsupported: HZ <= 16 or HZ > 16384
- #elif HZ <= 32
- # define INET_TWDR_RECYCLE_TICK (5 + 2 - INET_TWDR_RECYCLE_SLOTS_LOG)
- #elif HZ <= 64
-@@ -54,8 +54,12 @@
- # define INET_TWDR_RECYCLE_TICK (10 + 2 - INET_TWDR_RECYCLE_SLOTS_LOG)
- #elif HZ <= 2048
- # define INET_TWDR_RECYCLE_TICK (11 + 2 - INET_TWDR_RECYCLE_SLOTS_LOG)
--#else
-+#elif HZ <= 4096
- # define INET_TWDR_RECYCLE_TICK (12 + 2 - INET_TWDR_RECYCLE_SLOTS_LOG)
-+#elif HZ <= 8192
-+# define INET_TWDR_RECYCLE_TICK (13 + 2 - INET_TWDR_RECYCLE_SLOTS_LOG)
-+#else
-+# define INET_TWDR_RECYCLE_TICK (14 + 2 - INET_TWDR_RECYCLE_SLOTS_LOG)
- #endif
- 
- /* TIME_WAIT reaping mechanism. */
-Index: linux-2.6.22-ck1/init/calibrate.c
-===================================================================
---- linux-2.6.22-ck1.orig/init/calibrate.c	2007-07-10 14:54:59.000000000 +1000
-+++ linux-2.6.22-ck1/init/calibrate.c	2007-07-10 14:55:24.000000000 +1000
-@@ -122,12 +122,12 @@
- 		printk("Calibrating delay loop (skipped)... "
- 			"%lu.%02lu BogoMIPS preset\n",
- 			loops_per_jiffy/(500000/HZ),
--			(loops_per_jiffy/(5000/HZ)) % 100);
-+			(loops_per_jiffy * 10/(50000/HZ)) % 100);
- 	} else if ((loops_per_jiffy = calibrate_delay_direct()) != 0) {
- 		printk("Calibrating delay using timer specific routine.. ");
- 		printk("%lu.%02lu BogoMIPS (lpj=%lu)\n",
- 			loops_per_jiffy/(500000/HZ),
--			(loops_per_jiffy/(5000/HZ)) % 100,
-+			(loops_per_jiffy * 10/(50000/HZ)) % 100,
- 			loops_per_jiffy);
- 	} else {
- 		loops_per_jiffy = (1<<12);
-@@ -166,7 +166,7 @@
- 		/* Round the value and print it */
- 		printk("%lu.%02lu BogoMIPS (lpj=%lu)\n",
- 			loops_per_jiffy/(500000/HZ),
--			(loops_per_jiffy/(5000/HZ)) % 100,
-+			(loops_per_jiffy * 10/(50000/HZ)) % 100,
- 			loops_per_jiffy);
- 	}
- 
-Index: linux-2.6.22-ck1/arch/i386/kernel/cpu/proc.c
-===================================================================
---- linux-2.6.22-ck1.orig/arch/i386/kernel/cpu/proc.c	2007-07-10 14:54:59.000000000 +1000
-+++ linux-2.6.22-ck1/arch/i386/kernel/cpu/proc.c	2007-07-10 14:55:24.000000000 +1000
-@@ -157,7 +157,7 @@
- 
- 	seq_printf(m, "\nbogomips\t: %lu.%02lu\n",
- 		     c->loops_per_jiffy/(500000/HZ),
--		     (c->loops_per_jiffy/(5000/HZ)) % 100);
-+		     (c->loops_per_jiffy * 10/(50000/HZ)) % 100);
- 	seq_printf(m, "clflush size\t: %u\n\n", c->x86_clflush_size);
- 
- 	return 0;
-Index: linux-2.6.22-ck1/arch/i386/kernel/smpboot.c
-===================================================================
---- linux-2.6.22-ck1.orig/arch/i386/kernel/smpboot.c	2007-07-10 14:54:59.000000000 +1000
-+++ linux-2.6.22-ck1/arch/i386/kernel/smpboot.c	2007-07-10 14:55:24.000000000 +1000
-@@ -1094,7 +1094,7 @@
- 		"Total of %d processors activated (%lu.%02lu BogoMIPS).\n",
- 		cpucount+1,
- 		bogosum/(500000/HZ),
--		(bogosum/(5000/HZ))%100);
-+		(bogosum * 10/(50000/HZ))%100);
- 	
- 	Dprintk("Before bogocount - setting activated=1.\n");
- 
-Index: linux-2.6.22-ck1/include/linux/nfsd/stats.h
-===================================================================
---- linux-2.6.22-ck1.orig/include/linux/nfsd/stats.h	2007-07-10 14:54:59.000000000 +1000
-+++ linux-2.6.22-ck1/include/linux/nfsd/stats.h	2007-07-10 14:55:24.000000000 +1000
-@@ -35,8 +35,8 @@
- 
- };
- 
--/* thread usage wraps very million seconds (approx one fortnight) */
--#define	NFSD_USAGE_WRAP	(HZ*1000000)
-+/* thread usage wraps every one hundred thousand seconds (approx one day) */
-+#define	NFSD_USAGE_WRAP	(HZ*100000)
- 
- #ifdef __KERNEL__
- 
-Index: linux-2.6.22-ck1/arch/x86_64/kernel/setup.c
-===================================================================
---- linux-2.6.22-ck1.orig/arch/x86_64/kernel/setup.c	2007-07-10 14:54:59.000000000 +1000
-+++ linux-2.6.22-ck1/arch/x86_64/kernel/setup.c	2007-07-10 14:55:24.000000000 +1000
-@@ -1047,7 +1047,7 @@
- 		
- 	seq_printf(m, "\nbogomips\t: %lu.%02lu\n",
- 		   c->loops_per_jiffy/(500000/HZ),
--		   (c->loops_per_jiffy/(5000/HZ)) % 100);
-+		   (c->loops_per_jiffy * 10/(50000/HZ)) % 100);
- 
- 	if (c->x86_tlbsize > 0) 
- 		seq_printf(m, "TLB size\t: %d 4K pages\n", c->x86_tlbsize);
-Index: linux-2.6.22-ck1/Makefile
-===================================================================
---- linux-2.6.22-ck1.orig/Makefile	2007-07-10 14:54:59.000000000 +1000
-+++ linux-2.6.22-ck1/Makefile	2007-07-10 14:55:24.000000000 +1000
-@@ -1,8 +1,9 @@
- VERSION = 2
- PATCHLEVEL = 6
- SUBLEVEL = 22
--EXTRAVERSION =
--NAME = Holy Dancing Manatees, Batman!
-+EXTRAVERSION = -ck1
-+NAME = So long, and thanks for all the fish
-+JANAME = さようなら、いままで魚をありがとう
- 
- # *DOCUMENTATION*
- # To see a list of typical targets execute "make help"
diff --git a/pkgs/os-specific/linux/kvm/82.nix b/pkgs/os-specific/linux/kvm/82.nix
new file mode 100644
index 0000000000000..eb5db5c542473
--- /dev/null
+++ b/pkgs/os-specific/linux/kvm/82.nix
@@ -0,0 +1,38 @@
+{stdenv, fetchurl, kernelHeaders, zlib, e2fsprogs, SDL, alsaLib, pkgconfig, rsync}:
+   
+assert stdenv.isLinux;
+   
+stdenv.mkDerivation {
+  name = "kvm-82";
+   
+  src = fetchurl {
+    url = mirror://sourceforge/kvm/kvm-82.tar.gz;
+    sha256 = "1fk58g8z9v7z42vy76zq0sq28slqf8zszzmh73vyxm07vfbc96zs";
+  };
+
+  patches = [
+    # Allow setting the path to Samba through $QEMU_SMBD_COMMAND.
+    ./smbd-path-r2.patch
+    # The makefile copies stuff from the kernel directory and then
+    # tries to modify the copy, but it must be made writable first.
+    ./readonly-kernel-r3.patch
+  ];
+
+  configureFlags = "--with-patched-kernel --kerneldir=${kernelHeaders}";
+
+  # e2fsprogs is needed for libuuid.
+  # rsync is a weird dependency used for copying kernel header files.
+  buildInputs = [zlib e2fsprogs SDL alsaLib pkgconfig rsync];
+
+  preConfigure = ''
+    for i in configure user/configure; do
+      substituteInPlace $i --replace /bin/bash $shell
+    done
+    substituteInPlace libkvm/Makefile --replace kvm_para.h kvm.h # !!! quick hack
+  '';
+
+  meta = {
+    homepage = http://kvm.qumranet.com/;
+    description = "A full virtualization solution for Linux on x86 hardware containing virtualization extensions";
+  };
+}
diff --git a/pkgs/os-specific/linux/kvm/readonly-kernel-r3.patch b/pkgs/os-specific/linux/kvm/readonly-kernel-r3.patch
new file mode 100644
index 0000000000000..016ed12dc2406
--- /dev/null
+++ b/pkgs/os-specific/linux/kvm/readonly-kernel-r3.patch
@@ -0,0 +1,14 @@
+diff -rc kvm-78-orig/kernel/Makefile kvm-78/kernel/Makefile
+*** kvm-78-orig/kernel/Makefile	2008-10-30 11:58:12.000000000 +0100
+--- kvm-78/kernel/Makefile	2008-11-07 15:59:34.000000000 +0100
+***************
+*** 66,71 ****
+--- 66,72 ----
+  	     "$(LINUX)"/./include/linux/kvm*.h \
+  	     $(if $(wildcard $(headers-old)), $(headers-old)) \
+               $T/
++ 	chmod -R u+w $T
+  	$(if $(wildcard $(headers-new)), \
+  	rsync -R \
+  	     $(headers-new) \
+Only in kvm-78/kernel: Makefile~
diff --git a/pkgs/os-specific/linux/kvm/smbd-path-r2.patch b/pkgs/os-specific/linux/kvm/smbd-path-r2.patch
new file mode 100644
index 0000000000000..191d456656996
--- /dev/null
+++ b/pkgs/os-specific/linux/kvm/smbd-path-r2.patch
@@ -0,0 +1,50 @@
+diff -rc kvm-82-orig/qemu/net.c kvm-82/qemu/net.c
+*** kvm-82-orig/qemu/net.c	2008-12-24 15:24:58.000000000 +0100
+--- kvm-82/qemu/net.c	2009-01-13 12:59:15.000000000 +0100
+***************
+*** 560,570 ****
+          slirp_init();
+      }
+  
+!     /* XXX: better tmp dir construction */
+!     snprintf(smb_dir, sizeof(smb_dir), "/tmp/qemu-smb.%d", getpid());
+!     if (mkdir(smb_dir, 0700) < 0) {
+!         fprintf(stderr, "qemu: could not create samba server dir '%s'\n", smb_dir);
+!         exit(1);
+      }
+      snprintf(smb_conf, sizeof(smb_conf), "%s/%s", smb_dir, "smb.conf");
+  
+--- 560,572 ----
+          slirp_init();
+      }
+  
+!     while (1) {
+!         snprintf(smb_dir, sizeof(smb_dir), "/tmp/qemu-smb.%d.%d", getpid(), random());
+!         if (mkdir(smb_dir, 0700) == 0) break;
+!         if (errno != EEXIST) {
+!             fprintf(stderr, "qemu: could not create samba server dir '%s'\n", smb_dir);
+!             exit(1);
+!         }
+      }
+      snprintf(smb_conf, sizeof(smb_conf), "%s/%s", smb_dir, "smb.conf");
+  
+diff -rc kvm-82-orig/qemu/net.h kvm-82/qemu/net.h
+*** kvm-82-orig/qemu/net.h	2008-12-24 15:24:58.000000000 +0100
+--- kvm-82/qemu/net.h	2009-01-13 12:58:28.000000000 +0100
+***************
+*** 99,105 ****
+  #ifdef __sun__
+  #define SMBD_COMMAND "/usr/sfw/sbin/smbd"
+  #else
+! #define SMBD_COMMAND "/usr/sbin/smbd"
+  #endif
+  
+  #endif
+--- 99,105 ----
+  #ifdef __sun__
+  #define SMBD_COMMAND "/usr/sfw/sbin/smbd"
+  #else
+! #define SMBD_COMMAND "smbd"
+  #endif
+  
+  #endif
diff --git a/pkgs/os-specific/linux/mkinitrd/builder.sh b/pkgs/os-specific/linux/mkinitrd/builder.sh
deleted file mode 100644
index 951c0cdc478e5..0000000000000
--- a/pkgs/os-specific/linux/mkinitrd/builder.sh
+++ /dev/null
@@ -1,5 +0,0 @@
-source $stdenv/setup
-
-export BUILDROOT=$out
-
-genericBuild
diff --git a/pkgs/os-specific/linux/mkinitrd/default.nix b/pkgs/os-specific/linux/mkinitrd/default.nix
deleted file mode 100644
index 2849155af4df1..0000000000000
--- a/pkgs/os-specific/linux/mkinitrd/default.nix
+++ /dev/null
@@ -1,14 +0,0 @@
-{stdenv, fetchurl, popt}:
-
-# Red Hat mkinitrd
-
-stdenv.mkDerivation {
-  builder = ./builder.sh;
-  name = "mkinitrd-4.2.15";
-  src = fetchurl {
-    url = http://losser.st-lab.cs.uu.nl/~armijn/.nix/mkinitrd-4.2.15.tar.bz2;
-    md5 = "2f707784c460613357343ab5ce8b3aad";
-  };
-
-  buildInputs = [popt];
-}
diff --git a/pkgs/os-specific/linux/nvidia/builder.sh b/pkgs/os-specific/linux/nvidia/builder.sh
index eaec6d56ed0a9..16bc0628b9b6c 100755
--- a/pkgs/os-specific/linux/nvidia/builder.sh
+++ b/pkgs/os-specific/linux/nvidia/builder.sh
@@ -22,6 +22,8 @@ buildPhase() {
     kernelVersion=$(cd $kernel/lib/modules && ls)
     sysSrc=$(echo $kernel/lib/modules/$kernelVersion/build/)
     unset src # used by the nv makefile
+    # Hack necessary to compile on 2.6.28.
+    export NIX_CFLAGS_COMPILE="$NIX_CFLAGS_COMPILE -I$sysSrc/include/asm/mach-default"
     make SYSSRC=$sysSrc module
     cd ../../..
 }
diff --git a/pkgs/os-specific/linux/nvidia/default.nix b/pkgs/os-specific/linux/nvidia/default.nix
index 6e7b50dffa526..abb7eef04438f 100644
--- a/pkgs/os-specific/linux/nvidia/default.nix
+++ b/pkgs/os-specific/linux/nvidia/default.nix
@@ -2,7 +2,7 @@
 
 let 
 
-  versionNumber = "177.80";
+  versionNumber = "180.22";
 
 in
 
@@ -15,12 +15,12 @@ stdenv.mkDerivation {
     if stdenv.system == "i686-linux" then
       fetchurl {
         url = "http://us.download.nvidia.com/XFree86/Linux-x86/${versionNumber}/NVIDIA-Linux-x86-${versionNumber}-pkg1.run";
-        sha256 = "1z6z4dzhl2zmnwywaxbn2nf7lf72whjn7ffasdkb9217d5099wh7";
+        sha256 = "0cp6ii14pm8kzy1fy1qx2id2fp0lmb02akddid8wwdca7xpczqg7";
       }
     else if stdenv.system == "x86_64-linux" then
       fetchurl {
         url = "http://us.download.nvidia.com/XFree86/Linux-x86_64/${versionNumber}/NVIDIA-Linux-x86_64-${versionNumber}-pkg2.run";
-        sha256 = "1kx1kpc5flbsy9h1ii8al8cwzmvlfg4ymr6hvqsanxcdarq1sz47";
+        sha256 = "0yycsr8i5cc8bnqwvfrk0v9d7gxxv42zqdpz9ki8vxil7lvjfdxv";
       }
     else throw "nvidia-x11 does not support platform ${stdenv.system}";
 
diff --git a/pkgs/os-specific/linux/splashutils/1.5.nix b/pkgs/os-specific/linux/splashutils/1.5.nix
index 7bd190e81f98b..2544b3f056545 100644
--- a/pkgs/os-specific/linux/splashutils/1.5.nix
+++ b/pkgs/os-specific/linux/splashutils/1.5.nix
@@ -1,11 +1,11 @@
 {stdenv, fetchurl, klibc, zlib, libjpeg}:
 
 stdenv.mkDerivation {
-  name = "splashutils-1.5.4.2";
+  name = "splashutils-1.5.4.3";
 
   src = fetchurl {
-    url = http://download.berlios.de/fbsplash/splashutils-1.5.4.2.tar.bz2;
-    sha256 = "1d28p2wlmgm2cf2dbsxzmgma8gq9nwza43binp2hsscajjy5s9h5";
+    url = http://download.berlios.de/fbsplash/splashutils-1.5.4.3.tar.bz2;
+    sha256 = "0vn0ifqp9a3bmprzx2yr82hgq8m2y5xv8qcifs2plz6p3lidagpg";
   };
 
   buildInputs = [klibc zlib libjpeg];
diff --git a/pkgs/os-specific/linux/upstart/default.nix b/pkgs/os-specific/linux/upstart/default.nix
index 03a18f9c96109..b35f9c0364213 100644
--- a/pkgs/os-specific/linux/upstart/default.nix
+++ b/pkgs/os-specific/linux/upstart/default.nix
@@ -2,11 +2,20 @@
 
 stdenv.mkDerivation {
   name = "upstart-0.3.0";
+  
   src = fetchurl {
-    url = http://losser.st-lab.cs.uu.nl/~eelco/dist/upstart-0.3.0.tar.bz2;
+    url = http://nixos.org/tarballs/upstart-0.3.0.tar.bz2;
     md5 = "269046f41c6418225306280044a799eb";
   };
+  
   configureFlags = "--enable-compat";
+  
   patches = [./cfgdir.patch];
+  
   preBuild = "export NIX_CFLAGS_COMPILE=\"$NIX_CFLAGS_COMPILE -DSHELL=\\\"$SHELL\\\"\"";
+
+  meta = {
+    homepage = "http://upstart.ubuntu.com/";
+    description = "An event-based replacement for the /sbin/init daemon";
+  };
 }
diff --git a/pkgs/os-specific/linux/util-linux-ng/default.nix b/pkgs/os-specific/linux/util-linux-ng/default.nix
new file mode 100644
index 0000000000000..8c77cf297af33
--- /dev/null
+++ b/pkgs/os-specific/linux/util-linux-ng/default.nix
@@ -0,0 +1,54 @@
+{ stdenv, fetchurl, ncurses ? null
+
+, # Util-linux-ng requires libuuid and libblkid.
+  e2fsprogs
+
+, # Build mount/umount only.
+  buildMountOnly ? false
+  
+, # A directory containing mount helpers programs
+  # (i.e. `mount.<fstype>') to be used instead of /sbin.
+  mountHelpers ? null
+}:
+
+stdenv.mkDerivation {
+  name = (if buildMountOnly then "mount-" else "") + "util-linux-ng-2.14.1";
+
+  src = fetchurl {
+    url = mirror://kernel/linux/utils/util-linux-ng/v2.14/util-linux-ng-2.14.1.tar.bz2;
+    sha256 = "0b40xwdqpp16fcy1vfzqigl41d9slq32kzv2jr6nfy5bk59rqa5z";
+  };
+
+  configureFlags = ''
+    --disable-use-tty-group
+    ${if ncurses == null then "--without-ncurses" else ""}
+  '';
+
+  buildInputs = [e2fsprogs]
+    ++ stdenv.lib.optional (ncurses != null) ncurses;
+
+  inherit mountHelpers;
+
+  preConfigure = ''
+    makeFlagsArray=(usrbinexecdir=$out/bin usrsbinexecdir=$out/sbin datadir=$out/share exampledir=$out/share/getopt)
+    if test -n "$mountHelpers"; then
+      substituteInPlace mount/mount.c --replace /sbin/mount. $mountHelpers/mount.
+      substituteInPlace mount/umount.c --replace /sbin/umount. $mountHelpers/umount.
+    fi
+  '';
+
+  buildPhase =
+    if buildMountOnly then ''
+      make "''${makeFlagsArray[@]}" -C lib
+      make "''${makeFlagsArray[@]}" -C mount
+    '' else "";
+
+  installPhase =
+    if buildMountOnly then ''
+      make "''${makeFlagsArray[@]}" -C lib install
+      make "''${makeFlagsArray[@]}" -C mount install
+    '' else "";
+
+  # Hack to get static builds to work.
+  NIX_CFLAGS_COMPILE = "-DHAVE___PROGNAME=1"; 
+}
diff --git a/pkgs/servers/http/apache-httpd/default.nix b/pkgs/servers/http/apache-httpd/default.nix
index 853ed3b301a2f..7a0f074dcf1c7 100644
--- a/pkgs/servers/http/apache-httpd/default.nix
+++ b/pkgs/servers/http/apache-httpd/default.nix
@@ -6,11 +6,11 @@
 assert sslSupport -> openssl != null;
 
 stdenv.mkDerivation {
-  name = "apache-httpd-2.2.9";
+  name = "apache-httpd-2.2.11";
 
   src = fetchurl {
-    url = mirror://apache/httpd/httpd-2.2.9.tar.bz2;
-    md5 = "3afa8137dc1999be695a20b62fdf032b";
+    url = mirror://apache/httpd/httpd-2.2.11.tar.bz2;
+    md5 = "3e98bcb14a7122c274d62419566431bb";
   };
 
   #inherit sslSupport;
diff --git a/pkgs/servers/http/tomcat/6.0.nix b/pkgs/servers/http/tomcat/6.0.nix
index 7ab5ebcb3b3a7..00907844ba894 100644
--- a/pkgs/servers/http/tomcat/6.0.nix
+++ b/pkgs/servers/http/tomcat/6.0.nix
@@ -2,13 +2,13 @@
 
 stdenv.mkDerivation {
 
-  name = "apache-tomcat-6.0.16";
+  name = "apache-tomcat-6.0.18";
 
   builder = ./builder-6.0.sh;
 
   src = fetchurl {
-    url = http://apache.mirrors.webazilla.nl/tomcat/tomcat-6/v6.0.16/bin/apache-tomcat-6.0.16.tar.gz;
-    md5 = "4985fed02341a9e04ea43e91e6444ace";
+    url = http://apache.mirrors.webazilla.nl/tomcat/tomcat-6/v6.0.18/bin/apache-tomcat-6.0.18.tar.gz;
+    md5 = "8354e156f097158f8d7b699078fd39c1";
   };
 
   inherit jdk;
diff --git a/pkgs/servers/pulseaudio/default.nix b/pkgs/servers/pulseaudio/default.nix
new file mode 100644
index 0000000000000..7244eac463182
--- /dev/null
+++ b/pkgs/servers/pulseaudio/default.nix
@@ -0,0 +1,42 @@
+{ stdenv, fetchurl, pkgconfig, gnum4, gdbm, libtool, glib, dbus, hal, avahi
+, gconf, liboil, intltool, gettext
+, libsamplerate, libsndfile, speex }:
+
+stdenv.mkDerivation rec {
+  name = "pulseaudio-0.9.13";
+
+  src = fetchurl {
+    url = "http://0pointer.de/lennart/projects/pulseaudio/${name}.tar.gz";
+    sha256 = "0lwd5rcppyvcvy9n2j074k5mydgqszfvw6fnsjlz46gkda9vgydq";
+  };
+
+  buildInputs = [
+    pkgconfig gnum4 gdbm libtool glib dbus hal avahi gconf liboil
+    libsamplerate libsndfile speex
+    intltool gettext
+  ];
+
+  configureFlags = ''
+    --disable-solaris --disable-jack --disable-bluez --disable-polkit
+  '';
+
+  meta = {
+    description = "PulseAudio, a sound server for POSIX and Win32 systems";
+
+    longDescription = ''
+      PulseAudio is a sound server for POSIX and Win32 systems.  A
+      sound server is basically a proxy for your sound applications.
+      It allows you to do advanced operations on your sound data as it
+      passes between your application and your hardware.  Things like
+      transferring the audio to a different machine, changing the
+      sample format or channel count and mixing several sounds into
+      one are easily achieved using a sound server.
+    '';
+
+    homepage = http://www.pulseaudio.org/;
+
+    # Note: Practically, the server is under the GPL due to the
+    # dependency on `libsamplerate'.  See `LICENSE' for details.
+    licenses = "LGPLv2+";
+  };
+}
diff --git a/pkgs/servers/squid/3.head.nix b/pkgs/servers/squid/3.head.nix
deleted file mode 100644
index 26f459525a864..0000000000000
--- a/pkgs/servers/squid/3.head.nix
+++ /dev/null
@@ -1,24 +0,0 @@
-args:
-( args.mkDerivationByConfiguration {
-    flagConfig = {
-      mandatory = { buildInputs = [ "perl" ]; };
-      # many options I don't know wether they should be default .. 
-    }; 
-
-    extraAttrs = co : {
-      name = "squid-3.0-stable5";
-
-      src = args.fetchurl {
-	url = http://www.squid-cache.org/Versions/v3/HEAD/squid-3.HEAD-20080706.tar.bz2;
-        sha256 = "20f5994dd2189faa07edaef2c529f385e4590266d283745027b35d140eefe1ab";
-      };
-
-      configureFlags = ["--enable-ipv6"];
-
-      meta = { 
-        description = "http-proxy";
-        homepage = "http://www.squid-cache.org";
-        license = "GPL2";
-      };
-  };
-} ) args
diff --git a/pkgs/servers/squid/default.nix b/pkgs/servers/squid/default.nix
deleted file mode 100644
index 3ae7053f92949..0000000000000
--- a/pkgs/servers/squid/default.nix
+++ /dev/null
@@ -1,24 +0,0 @@
-args:
-( args.mkDerivationByConfiguration {
-    flagConfig = {
-      mandatory = { buildInputs = [ "perl" ]; };
-      # many options I don't know wether they should be default .. 
-    }; 
-
-    extraAttrs = co : {
-      name = "squid-3.0-stable5";
-
-      src = args.fetchurl {
-        url = http://www.squid-cache.org/Versions/v3/3.0/squid-3.0.STABLE5.tar.bz2;
-        sha256 = "1m4ccpjw30q9vwsycmgg9dmhly0mpznvxrch6f7dxgfzpjp26l7w";
-      };
-
-      configureFlags = ["--enable-ipv6"];
-
-      meta = { 
-        description = "http-proxy";
-        homepage = "http://www.squid-cache.org";
-        license = "GPL2";
-      };
-  };
-} ) args
diff --git a/pkgs/servers/squid/squids.nix b/pkgs/servers/squid/squids.nix
new file mode 100644
index 0000000000000..beffef1733662
--- /dev/null
+++ b/pkgs/servers/squid/squids.nix
@@ -0,0 +1,44 @@
+args: with args;
+let edf = composableDerivation.edf; in
+rec {
+  squid30 = composableDerivation.composableDerivation {
+    initial = {
+      name = "squid-3.0-stable5";
+
+      buildInputs = [perl];
+
+      src = args.fetchurl {
+        url = http://www.squid-cache.org/Versions/v3/3.0/squid-3.0.STABLE5.tar.bz2;
+        sha256 = "1m4ccpjw30q9vwsycmgg9dmhly0mpznvxrch6f7dxgfzpjp26l7w";
+      };
+
+      configureFlags = ["--enable-ipv6"];
+
+      meta = {
+        description = "http-proxy";
+        homepage = "http://www.squid-cache.org";
+        license = "GPL2";
+      };
+
+    };
+  };
+
+  squid3Beta = squid30.passthru.funMerge {
+    name = "squid-3.1-beta";
+    src = args.fetchurl {
+      url = http://www.squid-cache.org/Versions/v3/3.1/squid-3.1.0.3.tar.bz2;
+      sha256 = "0khc4w9sbdwzxw8285z60ymz15q5qjy7b8yvvfnzfkihdacs735x";
+    };
+    configureFlags = ["--enable-ipv6"];
+  };
+
+  squid3Head = squid3Beta.passthru.funMerge {
+    name = "squid-3.1-HEAD";
+    src = args.fetchurl {
+      url = http://www.squid-cache.org/Versions/v3/3.1/squid-3.1.0.3-20081221.tar.bz2;
+      md5 = "345b50251dcc369e1be992d0a4a4c801";
+    };
+  };
+
+  latest = squid3Beta;
+}
diff --git a/pkgs/servers/x11/xorg/default.nix b/pkgs/servers/x11/xorg/default.nix
index e1cccdff87261..350b711847800 100644
--- a/pkgs/servers/x11/xorg/default.nix
+++ b/pkgs/servers/x11/xorg/default.nix
@@ -1877,6 +1877,26 @@ rec {
     buildInputs = [pkgconfig fontsproto libpciaccess randrproto renderproto xextproto xorgserver xproto ];
   }) // {inherit fontsproto libpciaccess randrproto renderproto xextproto xorgserver xproto ;};
     
+  xf86videovga = (stdenv.mkDerivation {
+    name = "xf86-video-vga-4.1.0";
+    builder = ./builder.sh;
+    src = fetchurl {
+      url = http://mirror.switch.ch/ftp/mirror/X11/pub/X11R7.3/src/everything/xf86-video-vga-4.1.0.tar.bz2;
+      sha256 = "0havz5hv46qz3g6g0mq2568758apdapzy0yd5ny8qs06yz0g89fa";
+    };
+    buildInputs = [pkgconfig fontsproto randrproto renderproto xextproto xorgserver xproto ];
+  }) // {inherit fontsproto randrproto renderproto xextproto xorgserver xproto ;};
+    
+  xf86videovia = (stdenv.mkDerivation {
+    name = "xf86-video-via-0.2.2";
+    builder = ./builder.sh;
+    src = fetchurl {
+      url = http://mirror.switch.ch/ftp/mirror/X11/pub/X11R7.3/src/everything/xf86-video-via-0.2.2.tar.bz2;
+      sha256 = "0qn89m1s50m4jajw95wcidarknyxn19h8696dbkgwy21cjpvs9jh";
+    };
+    buildInputs = [pkgconfig fontsproto libdrm randrproto renderproto libX11 xextproto xf86driproto xorgserver xproto libXvMC mesaHeaders glproto ];
+  }) // {inherit fontsproto libdrm randrproto renderproto libX11 xextproto xf86driproto xorgserver xproto libXvMC ;};
+    
   xf86videovmware = (stdenv.mkDerivation {
     name = "xf86-video-vmware-10.16.5";
     builder = ./builder.sh;
diff --git a/pkgs/shells/zsh/cvs.nix b/pkgs/shells/zsh/cvs.nix
new file mode 100644
index 0000000000000..db34f0666d50b
--- /dev/null
+++ b/pkgs/shells/zsh/cvs.nix
@@ -0,0 +1,19 @@
+args: with args;
+# cvs does include docs
+# the cvs snapshot is updated occasionally. see bleedingEdgeRepos
+
+stdenv.mkDerivation {
+  name = "zsh-${version}";
+
+  src = sourceByName "zsh";
+  configureFlags = "--with-tcsetpgrp --enable-maildir-support --enable-multibyte";
+
+  preConfigure = "autoconf; autoheader";
+
+  postInstall = ''
+    ensureDir $out/share/
+    cp -R Doc $out/share
+  '';
+
+  buildInputs = [ncurses coreutils autoconf yodl ];
+}
diff --git a/pkgs/tools/archivers/cromfs/default.nix b/pkgs/tools/archivers/cromfs/default.nix
new file mode 100644
index 0000000000000..97293176c6baa
--- /dev/null
+++ b/pkgs/tools/archivers/cromfs/default.nix
@@ -0,0 +1,28 @@
+{stdenv, fetchurl, pkgconfig, fuse, perl}:
+
+stdenv.mkDerivation {
+  name = "cromfs-1.5.6.2";
+  src = fetchurl {
+    url = http://bisqwit.iki.fi/src/arch/cromfs-1.5.6.2.tar.bz2;
+    sha256 = "bbe5db623d3c0d2b92fe877d8c8e22a8f8d84210739313bf691d42c05406464d";
+  };
+
+  patchPhase = ''sed -i 's@/bin/bash@/bin/sh@g' configure; set -x'';
+
+
+  meta = {
+    description = "FUSE Compressed ROM filesystem with lzma"  ;
+	  homepage = http://bisqwit.iki.fi/source/cromfs.html;
+  };
+  
+  installPhase = ''
+    install -d $out/bin
+    install cromfs-driver $out/bin
+    install cromfs-driver-static $out/bin
+    install util/cvcromfs $out/bin
+    install util/mkcromfs $out/bin
+    install util/unmkcromfs $out/bin
+  '';
+
+  buildInputs = [pkgconfig fuse perl];
+}
diff --git a/pkgs/tools/archivers/dar/default.nix b/pkgs/tools/archivers/dar/default.nix
new file mode 100644
index 0000000000000..8febdb18d15b3
--- /dev/null
+++ b/pkgs/tools/archivers/dar/default.nix
@@ -0,0 +1,16 @@
+{stdenv, fetchurl, zlib, bzip2, openssl}:
+
+stdenv.mkDerivation {
+  name = "dar-2.3.8";
+  src = fetchurl {
+    url = mirror://sourceforge/dar/dar-2.3.8.tar.gz;
+    md5 = "6c0d383c22df0e1816e860153f60d746";
+  };
+
+  meta = {
+	  homepage = http://dar.linux.free.fr/;
+	  description = "Disk ARchiver, allows backing up files into indexed archives";
+  };
+
+  buildInputs = [zlib bzip2 openssl];
+}
diff --git a/pkgs/tools/cd-dvd/cdrkit/default.nix b/pkgs/tools/cd-dvd/cdrkit/default.nix
index 03ef0c0cad5c7..7e5bb44764cd4 100644
--- a/pkgs/tools/cd-dvd/cdrkit/default.nix
+++ b/pkgs/tools/cd-dvd/cdrkit/default.nix
@@ -1,11 +1,11 @@
 {stdenv, fetchurl, cmake, libcap, zlib, bzip2}:
 
-stdenv.mkDerivation {
-  name = "cdrkit-1.1.8";
+stdenv.mkDerivation rec {
+  name = "cdrkit-1.1.9";
 
   src = fetchurl {
-    url = http://cdrkit.org/releases/cdrkit-1.1.8.tar.gz;
-    sha256 = "0dzj89swc5h9jr6rr9y6cq6742gc1sdfaivz8r26yfmv5ajx104x";
+    url = "http://cdrkit.org/releases/${name}.tar.gz";
+    sha256 = "18pgak1qh2xsb3sjikfh1hqn27v2ax72nx7r7sjkdw5yqys8mmfm";
   };
 
   buildInputs = [cmake libcap zlib bzip2];
@@ -14,7 +14,19 @@ stdenv.mkDerivation {
 
   meta = {
     description = "Portable command-line CD/DVD recorder software, mostly compatible with cdrtools";
+
+    longDescription = ''
+      Cdrkit is a suite of programs for recording CDs and DVDs,
+      blanking CD-RW media, creating ISO-9660 filesystem images,
+      extracting audio CD data, and more.  The programs included in
+      the cdrkit package were originally derived from several sources,
+      most notably mkisofs by Eric Youngdale and others, cdda2wav by
+      Heiko Eissfeldt, and cdrecord by Jörg Schilling.  However,
+      cdrkit is not affiliated with any of these authors; it is now an
+      independent project.
+    '';
+    
     homepage = http://cdrkit.org/;
-    license = "GPL2";
+    license = "GPLv2";
   };
 }
diff --git a/pkgs/tools/misc/grub/default.nix b/pkgs/tools/misc/grub/default.nix
index 31ee5e70e8bfb..e0c35d63f7276 100644
--- a/pkgs/tools/misc/grub/default.nix
+++ b/pkgs/tools/misc/grub/default.nix
@@ -1,7 +1,7 @@
 {stdenv, fetchurl, autoconf, automake}:
 
 stdenv.mkDerivation {
-  name = "grub-0.97-patch-1.7";
+  name = "grub-0.97-patch-1.9";
   
   src = fetchurl {
     url = ftp://alpha.gnu.org/gnu/grub/grub-0.97.tar.gz;
@@ -11,10 +11,10 @@ stdenv.mkDerivation {
   # Lots of patches from Gentoo, in particular splash screen support
   # (not the fancy SUSE gfxmenu stuff though).  Also a fix for boot
   # failures on systems with more than 2 GiB RAM, and for booting from
-  # ext3 filesystems with 256-byte inodes. 
+  # ext3 filesystems with 256-byte inodes as well as ext4 filesystems.
   gentooPatches = fetchurl {
-    url = mirror://gentoo/distfiles/grub-0.97-patches-1.7.tar.bz2;
-    sha256 = "12akcbp1a31pxzsxm01scgir0fqkk8qqqwhs44vzgs2chzzigyvd";
+    url = mirror://gentoo/distfiles/grub-0.97-patches-1.9.tar.bz2;
+    sha256 = "0a20bi2njqdgi0993g9dzjcn9vjzlisp9ghw0dcz00q84v4lb13b";
   };
 
   patches = [
diff --git a/pkgs/tools/networking/proxychains/default.nix b/pkgs/tools/networking/proxychains/default.nix
new file mode 100644
index 0000000000000..6ea12f262b4d2
--- /dev/null
+++ b/pkgs/tools/networking/proxychains/default.nix
@@ -0,0 +1,16 @@
+{ stdenv, fetchurl } :
+stdenv.mkDerivation {
+  name = "proxychains-3.1";
+  src = fetchurl {
+    url = mirror://sourceforge/proxychains/proxychains-3.1.tar.gz;
+    sha256 = "9a27657fe9f6e17de9e402ba5c60f9954e7e79fb270c1ef242770f3c01d8515a";
+  };
+
+  patchPhase = "sed -e s@libproxychains.so@$out/lib/libproxychains.so@ -i proxychains/proxychains";
+
+  meta = {
+    description = "Proxifier for SOCKS proxies.";
+    homepage = http://proxychains.sourceforge.net;
+    license = "GPLv2+";
+  };
+}
diff --git a/pkgs/tools/package-management/checkinstall/default.nix b/pkgs/tools/package-management/checkinstall/default.nix
index 80f774e8e5d94..f7a8321fe317f 100644
--- a/pkgs/tools/package-management/checkinstall/default.nix
+++ b/pkgs/tools/package-management/checkinstall/default.nix
@@ -17,6 +17,22 @@ stdenv.mkDerivation {
     substituteInPlace checkinstallrc-dist --replace /usr/local $out
   '';
 
+  postInstall =
+    if stdenv.isLinux then
+      # Clear the RPATH, otherwise installwatch.so won't work properly
+      # as an LD_PRELOADed library on applications that load against a
+      # different Glibc.
+      ''
+         patchelf --set-rpath "" $out/lib/installwatch.so
+      ''
+    else "";
+
+  patches = [
+    # Necessary for building on x86_64, see
+    # http://checkinstall.izto.org/cklist/msg00256.html
+    ./readlink.patch
+  ];
+
   meta = {
     homepage = http://checkinstall.izto.org/;
     description = "A tool for automatically generating Slackware, RPM or Debian packages when doing `make install'";
diff --git a/pkgs/tools/package-management/checkinstall/readlink.patch b/pkgs/tools/package-management/checkinstall/readlink.patch
new file mode 100644
index 0000000000000..f276c057d8f95
--- /dev/null
+++ b/pkgs/tools/package-management/checkinstall/readlink.patch
@@ -0,0 +1,40 @@
+--- a/installwatch-0.7.0beta5/installwatch.c	2007-04-07 14:27:23.000000000 -0400
++++ b/installwatch-0.7.0beta5/installwatch.c	2007-04-07 14:25:06.000000000 -0400
+@@ -84,7 +84,7 @@
+ static int (*true_open)(const char *, int, ...);
+ static DIR *(*true_opendir)(const char *);
+ static struct dirent *(*true_readdir)(DIR *dir);
+-static int (*true_readlink)(const char*,char *,size_t);
++static ssize_t (*true_readlink)(const char*,char *,size_t);
+ static char *(*true_realpath)(const char *,char *);
+ static int (*true_rename)(const char *, const char *);
+ static int (*true_rmdir)(const char *);
+@@ -546,7 +546,7 @@
+ 	struct utimbuf timbuf;
+ 	size_t truesz;
+ 	char linkpath[PATH_MAX+1];
+-	size_t linksz;
++	ssize_t linksz;
+ 
+ #if DEBUG
+ 	debug(2,"copy_path(%s,%s)\n",truepath,translroot);
+@@ -1582,7 +1582,7 @@
+ 	struct stat reslvinfo;
+ 	instw_t iw;
+ 	char wpath[PATH_MAX+1];
+-	size_t wsz=0;
++	ssize_t wsz=0;
+ 	char linkpath[PATH_MAX+1];
+ 
+ 
+@@ -2698,8 +2698,8 @@
+ 	return result;
+ }
+ 
+-int readlink(const char *path,char *buf,size_t bufsiz) {
+-	int result;
++ssize_t readlink(const char *path,char *buf,size_t bufsiz) {
++	ssize_t result;
+ 	instw_t instw;
+ 	int status;
+ 
diff --git a/pkgs/tools/package-management/nix/unstable.nix b/pkgs/tools/package-management/nix/unstable.nix
index ad180c7906f52..a55c052b32cd6 100644
--- a/pkgs/tools/package-management/nix/unstable.nix
+++ b/pkgs/tools/package-management/nix/unstable.nix
@@ -4,14 +4,12 @@
 , supportOldDBs ? true
 }:
 
-let version = "0.13pre13403"; in
-
 stdenv.mkDerivation {
-  name = "nix-${version}";
+  name = "nix-0.13pre13641";
   
   src = fetchurl {
-    url = "http://nixos.org/releases/nix/nix-${version}-a84h5996/nix-${version}.tar.bz2";
-    sha256 = "81169cc6448fff2e1f72464fb537d6db0d386d303869346fea2433b04181cc7b";
+    url = http://hydra.nixos.org/download/546/1/nix-0.13pre13641.tar.bz2;
+    sha256 = "83936327ed7cfa6e6a103764c3f43c780b2727ed804721200811ba999c31c7e1";
   };
 
   buildInputs = [perl curl openssl];
diff --git a/pkgs/tools/security/aefs/default.nix b/pkgs/tools/security/aefs/default.nix
index 972d997e2429b..8bf52795be2d7 100644
--- a/pkgs/tools/security/aefs/default.nix
+++ b/pkgs/tools/security/aefs/default.nix
@@ -4,9 +4,14 @@ stdenv.mkDerivation {
   name = "aefs-0.3pre285";
   
   src = fetchurl {
-    url = http://losser.st-lab.cs.uu.nl/~eelco/dist/aefs-0.3pre285.tar.bz2;
+    url = http://nixos.org/tarballs/aefs-0.3pre285.tar.bz2;
     sha256 = "1psciqllzm08c21h6k2zxmvmi0grkvaiq177giv1avzzzfhq0z3c";
   };
 
   buildInputs = [fuse];
+
+  meta = {
+    homepage = http://www.st.ewi.tudelft.nl/~dolstra/aefs/;
+    description = "A cryptographic filesystem implemented in userspace using FUSE";
+  };
 }
diff --git a/pkgs/tools/security/ccrypt/default.nix b/pkgs/tools/security/ccrypt/default.nix
new file mode 100644
index 0000000000000..9898d6080ff6f
--- /dev/null
+++ b/pkgs/tools/security/ccrypt/default.nix
@@ -0,0 +1,13 @@
+{stdenv, fetchurl}:
+stdenv.mkDerivation {
+  name = "ccrypt-1.7";
+
+  src = fetchurl {
+    url = mirror://sourceforge/ccrypt/ccrypt-1.7.tar.gz;
+    sha256 = "1bf974c9ee5f20332f0117c5b80784825f505f1a24eb57a10c8195c3ad16540e";
+  };
+  meta = {
+    description = "Utility for encrypting and decrypting files and streams with AES-256";
+    license = "GPLv2+";
+  };
+}
diff --git a/pkgs/tools/security/gnupg2/default.nix b/pkgs/tools/security/gnupg2/default.nix
index 2ac2608ea3c21..19fa84ae65003 100644
--- a/pkgs/tools/security/gnupg2/default.nix
+++ b/pkgs/tools/security/gnupg2/default.nix
@@ -1,22 +1,37 @@
-# remmeber to
-# echo "pinentry-program `which pinentry-gtk-2`" >> ~/.gnupg/gpg-agent.conf
-# and install pinentry as well
+# Remember to install Pinentry and
+# 'echo "pinentry-program `which pinentry-gtk-2`" >> ~/.gnupg/gpg-agent.conf'.
+
+{ fetchurl, stdenv, readline, openldap, bzip2, zlib, libgpgerror
+, pth, libgcrypt, libassuan, libksba, libusb, curl }:
 
-args: with args;
 stdenv.mkDerivation rec {
-  name = "gnupg-2.0.8";
+  name = "gnupg-2.0.10";
 
   src = fetchurl {
     url = "mirror://gnupg/gnupg/${name}.tar.bz2";
-    sha256 = "04v9s92xph1hrhac49yyrgzdwjqshs2zawvjbi3jc2klwjpi1wqn";
+    sha256 = "08yz2kgcnphjml5mhq4bm4dg64jrz79p97nlrlb88ym6p6ybg26l";
   };
 
   buildInputs = [ readline openldap bzip2 zlib libgpgerror pth libgcrypt
     libassuan libksba libusb curl ];
 
+  doCheck = true;
+
   meta = {
-    description = "A free implementation of the OpenPGP standard for encrypting
-	and signing data, v2";
-    homepage = http://www.gnupg.org/;
+    description = "GNU Privacy Guard (GnuPG), GNU Project's implementation of the OpenPGP standard";
+
+    longDescription = ''
+      GnuPG is the GNU project's complete and free implementation of
+      the OpenPGP standard as defined by RFC4880.  GnuPG allows to
+      encrypt and sign your data and communication, features a
+      versatile key managment system as well as access modules for all
+      kind of public key directories.  GnuPG, also known as GPG, is a
+      command line tool with features for easy integration with other
+      applications.  A wealth of frontend applications and libraries
+      are available.  Version 2 of GnuPG also provides support for
+      S/MIME.
+    '';
+
+    homepage = http://gnupg.org/;
   };
 }
diff --git a/pkgs/tools/system/ts/default.nix b/pkgs/tools/system/ts/default.nix
index 0981446a58e42..2a09167b9ce0e 100644
--- a/pkgs/tools/system/ts/default.nix
+++ b/pkgs/tools/system/ts/default.nix
@@ -2,15 +2,13 @@
 
 stdenv.mkDerivation {
 
-  name = "ts-0.6";
+  name = "ts-0.6.2";
 
   installPhase=''make install "PREFIX=$out"'';
 
-  patchPhase = ''sed -i 's@/usr/bin/install@install@g' Makefile; set -x'';
-
   src = fetchurl {
-    url = http://vicerveza.homeunix.net/~viric/soft/ts/ts-0.6.tar.gz;
-    sha256 = "663df09f9a6e6491f7924b1cdf8a5d00546c736ec3f5f1135ccccb83bf4f2ce8";
+    url = http://vicerveza.homeunix.net/~viric/soft/ts/ts-0.6.2.tar.gz;
+    sha256 = "6a99b48800658fb7424a76c5756a638a6b6abb2a8a8c129e196bc24a9aeeb5cc";
   };
 
   meta = { homepage = "http://vicerveza.homeunix.net/~viric/soft/ts";
diff --git a/pkgs/tools/text/groff/default.nix b/pkgs/tools/text/groff/default.nix
index fde60a4e5f6a2..060e5d5e2c70b 100644
--- a/pkgs/tools/text/groff/default.nix
+++ b/pkgs/tools/text/groff/default.nix
@@ -1,9 +1,34 @@
-{stdenv, fetchurl}:
+{ stdenv, fetchurl, ghostscript, perl }:
+
+stdenv.mkDerivation rec {
+  name = "groff-1.20.1";
 
-stdenv.mkDerivation {
-  name = "groff-1.19.2";
   src = fetchurl {
-    url = ftp://ftp.gnu.org/gnu/groff/groff-1.19.2.tar.gz;
-    md5 = "f7c9cf2e4b9967d3af167d7c9fadaae4";
+    url = "mirror://gnu/groff/${name}.tar.gz";
+    sha256 = "01fq5i68p4s4fc6m8i90y5d28wk1x6zh2mkw85n0qqnb6n0qfidn";
+  };
+
+  buildInputs = [ ghostscript perl ];
+
+  doCheck = true;
+
+  meta = {
+    description = "GNU Troff, a typesetting package that reads plain text and produces formatted output";
+
+    longDescription = ''
+      groff is the GNU implementation of troff, a document formatting
+      system.  Included in this release are implementations of troff,
+      pic, eqn, tbl, grn, refer, -man, -mdoc, -mom, and -ms macros,
+      and drivers for PostScript, TeX dvi format, HP LaserJet 4
+      printers, Canon CAPSL printers, HTML and XHTML format (beta
+      status), and typewriter-like devices.  Also included is a
+      modified version of the Berkeley -me macros, the enhanced
+      version gxditview of the X11 xditview previewer, and an
+      implementation of the -mm macros.
+    '';
+
+    homepage = http://www.gnu.org/software/groff/;
+
+    license = "GPLv3+";
   };
 }
diff --git a/pkgs/tools/text/namazu/default.nix b/pkgs/tools/text/namazu/default.nix
new file mode 100644
index 0000000000000..a57b5cc594a8c
--- /dev/null
+++ b/pkgs/tools/text/namazu/default.nix
@@ -0,0 +1,37 @@
+{ fetchurl, stdenv, perl }:
+
+stdenv.mkDerivation rec {
+  name = "namazu-2.0.18";
+
+  src = fetchurl {
+    url = "http://namazu.org/stable/${name}.tar.gz";
+    sha256 = "12i5z830yh5sw3087gmna44742gcw2q7lpj6b94k8fj0h45cm26j";
+  };
+
+  buildInputs = [ perl ];
+
+  # First install the `File::MMagic' Perl module.
+  preConfigure = ''
+    ( cd File-MMagic &&				\
+      perl Makefile.PL				\
+        LIB="$out/lib/site_perl/5.10.0"		\
+        INSTALLSITEMAN3DIR="$out/man" &&	\
+      make && make install )
+    export PERL5LIB="$out/lib/site_perl/5.10.0:$PERL5LIB"
+  '';
+
+  doCheck = true;
+
+  meta = {
+    description = "Namazu, a full-text search engine";
+
+    longDescription = ''
+      Namazu is a full-text search engine intended for easy use.  Not
+      only does it work as a small or medium scale Web search engine,
+      but also as a personal search system for email or other files.
+    '';
+
+    license = "GPLv2+";
+    homepage = http://namazu.org/;
+  };
+}
diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix
index 99c2a5095c948..750236f44d48b 100644
--- a/pkgs/top-level/all-packages.nix
+++ b/pkgs/top-level/all-packages.nix
@@ -249,25 +249,6 @@ let
     meta = (if drv ? meta then drv.meta else {}) // {priority = "10";};
   };
 
-  # documentation see examples in lib at end of file or read some use cases
-  # within this file
-  # Before spending much time on investigating how this works just ask me
-  # - Marc Weber (#irc or marco-oweber@gmx.de)
-  mkDerivationByConfiguration =
-    assert builtins ? isAttrs;
-    { flagConfig ? {}, optionals ? [], defaults ? []
-    , extraAttrs, collectExtraPhaseActions ? []
-    }:
-    args: with args.lib; with args;
-    if ( builtins.isAttrs extraAttrs ) then builtins.throw "the argument extraAttrs needs to be a function beeing passed co, but attribute set passed "
-    else
-    let co = lib.chooseOptionsByFlags { inherit args flagConfig optionals defaults collectExtraPhaseActions; }; in
-      args.stdenv.mkDerivation (
-      {
-        inherit (co) configureFlags buildInputs propagatedBuildInputs /*flags*/;
-      } // extraAttrs co  // co.pass // co.flags_prefixed );
-
-
   # Check absence of non-used options
   checker = x: flag: opts: config:
     (if flag then let result=(
@@ -472,21 +453,26 @@ let
     inherit pkgs;
   };
 
-  # see new python derivations for example..
-  # You should be able to override anything you like easily
-  composableDerivation = {
-          # modify args before applying stdenv.mkDerivation, this should remove at least attrs removeAttrsBy
-        f ? lib.prepareDerivationArgs,
-        stdenv ? pkgs.stdenv,
-          # initial set of arguments to be passed to stdenv.mkDerivation passing prepareDerivationArgs by default
-        initial ? {},
-          # example func :  (x: x // { x.buildInputs ++ ["foo"] }), but see mergeAttrByFunc which does this for you
-        merge ? (lib.mergeOrApply lib.mergeAttrByFunc)
-      }: lib.applyAndFun
-            (args: stdenv.mkDerivation (f args))
-            merge
-            (merge { inherit (lib) mergeAttrBy; } initial);
+  composableDerivation = (import ../lib/composable-derivation.nix) {
+    inherit pkgs lib;
+  };
+
+  # Write the references (i.e. the runtime dependencies in the Nix store) of `path' to a file.
+  writeReferencesToFile = path: runCommand "runtime-deps"
+    {
+      exportReferencesGraph = ["graph" path];
+    }
+    ''
+      touch $out
+      while read path; do
+        echo $path >> $out
+        read dummy
+        read nrRefs
+        for ((i = 0; i < nrRefs; i++)); do read ref; done
+      done < graph
+    '';
 
+            
   ### TOOLS
 
 
@@ -507,14 +493,11 @@ let
   };
 
   avahi =
-    # XXX: Versions prior to 0.6.22 did not support Qt4, so enabling
-    # Qt4 should not be permitted when using a version of Avahi older
-    # than 0.6.22, hence the default to `false'.
     let qt4Support = getConfig [ "avahi" "qt4Support" ] false;
     in
-      selectVersion ../development/libraries/avahi "0.6.22" {
+      import ../development/libraries/avahi {
         inherit stdenv fetchurl pkgconfig libdaemon dbus perl perlXMLParser
-          expat lib;
+          expat gettext intltool lib;
         inherit (gtkLibs) glib gtk;
         inherit qt4Support;
         qt4 = if qt4Support then qt4 else null;
@@ -576,6 +559,10 @@ let
     inherit fetchurl stdenv;
   };
 
+  ccrypt = import ../tools/security/ccrypt {
+    inherit fetchurl stdenv;
+  };
+
   cdrdao = import ../tools/cd-dvd/cdrdao {
     inherit fetchurl stdenv;
   };
@@ -621,6 +608,10 @@ let
     inherit fetchurl stdenv;
   };
 
+  cromfs = import ../tools/archivers/cromfs {
+    inherit fetchurl stdenv pkgconfig fuse perl;
+  };
+
   cron = import ../tools/system/cron { # see also fcron
     inherit fetchurl stdenv;
   };
@@ -637,6 +628,10 @@ let
     inherit (gtkLibs) glib;
   };
 
+  dar = import ../tools/archivers/dar {
+    inherit fetchurl stdenv zlib bzip2 openssl;
+  };
+
   ddrescue = builderDefsPackage (selectVersion ../tools/system/ddrescue "1.8") {};
 
   dnsmasq = import ../tools/networking/dnsmasq {
@@ -824,7 +819,7 @@ let
   };
 
   groff = import ../tools/text/groff {
-    inherit fetchurl stdenv;
+    inherit fetchurl stdenv ghostscript perl;
   };
 
   grub = import ../tools/misc/grub {
@@ -978,6 +973,11 @@ let
     inherit (xlibs) libX11;
   };
 
+  mcabber = import ../applications/networking/instant-messengers/mcabber {
+    inherit fetchurl stdenv openssl ncurses pkgconfig;
+    inherit (gtkLibs) glib;
+  };
+
   mdbtools = builderDefsPackage (selectVersion ../tools/misc/mdbtools "0.6-pre1") {
     inherit readline pkgconfig bison;
     inherit (gtkLibs) glib;
@@ -993,6 +993,10 @@ let
     inherit fetchurl stdenv;
   };
 
+  mldonkey = import ../applications/networking/p2p/mldonkey {
+    inherit fetchurl stdenv ocaml zlib ncurses;
+  };
+
   mpage = import ../tools/text/mpage {
     inherit fetchurl stdenv;
   };
@@ -1009,6 +1013,10 @@ let
     inherit fetchurl stdenv perl shebangfix;
   };
 
+  namazu = import ../tools/text/namazu {
+    inherit fetchurl stdenv perl;
+  };
+
   nc6 = composedArgsAndFun (selectVersion ../tools/networking/nc6 "1.0") {
     inherit builderDefs;
   };
@@ -1089,6 +1097,10 @@ let
     inherit (xlibs) libX11;
   };
 
+  proxychains = import ../tools/networking/proxychains {
+    inherit fetchurl stdenv;
+  };
+
   proxytunnel = import ../tools/misc/proxytunnel {
     inherit fetchurl stdenv openssl;
   };
@@ -1271,10 +1283,8 @@ let
   };
 
   truecrypt = import ../applications/misc/truecrypt {
-    inherit fetchurl stdenv pkgconfig fuse;
-    inherit (gtkLibs) gtk;
-    inherit (xorg) libSM;
-    glibc = stdenv.gcc.libc;
+    inherit fetchurl stdenv pkgconfig fuse devicemapper;
+    wxGTK = wxGTK28;
   };
 
   ttmkfdir = import ../tools/misc/ttmkfdir {
@@ -1387,6 +1397,9 @@ let
 
   zsh = composedArgsAndFun (selectVersion ../shells/zsh "4.3.9") {
     inherit fetchurl stdenv ncurses coreutils;
+    # for CVS:
+    inherit (bleedingEdgeRepos) sourceByName;
+    inherit autoconf yodl;
   };
 
 
@@ -1780,9 +1793,9 @@ let
 
   #TODO add packages http://cvs.haskell.org/Hugs/downloads/2006-09/packages/ and test
   # commented out because it's using the new configuration style proposal which is unstable
-  #hugs = import ../development/compilers/hugs {
-    #inherit lib fetchurl stdenv;
-  #};
+  hugs = import ../development/compilers/hugs {
+    inherit lib fetchurl stdenv composableDerivation;
+  };
 
   j2sdk14x =
     assert system == "i686-linux";
@@ -1895,7 +1908,7 @@ let
   };
 
   roadsend = import ../development/compilers/roadsend {
-    inherit fetchurl stdenv flex bison mkDerivationByConfiguration bigloo lib curl;
+    inherit fetchurl stdenv flex bison bigloo lib curl composableDerivation;
     # optional features
     # all features pcre, fcgi xml mysql, sqlite3, (not implemented: odbc gtk gtk2)
     flags = ["pcre" "xml" "mysql"];
@@ -2064,13 +2077,9 @@ let
 
   php = import ../development/interpreters/php_configurable {
     inherit
-      stdenv fetchurl lib mkDerivationByConfiguration autoconf automake
+      stdenv fetchurl lib composableDerivation autoconf automake
       flex bison apacheHttpd mysql libxml2 # gettext
       zlib curl gd postgresql openssl pkgconfig;
-    flags = [
-      "xdebug" "mysql" "mysqli" "pdo_mysql" "libxml2" "apxs2" "curl"
-      "postgresql" "bcmath" "gd" "sockets" "curl"
-    ];
   };
 
   pltScheme = builderDefsPackage (import ../development/interpreters/plt-scheme) {
@@ -2244,6 +2253,10 @@ let
     inherit fetchurl stdenv perl m4 lzma;
   };
 
+  autoconf213 = import ../development/tools/misc/autoconf/2.13.nix {
+    inherit fetchurl stdenv perl m4 lzma;
+  };
+
   automake = automake19x;
 
   automake17x = import ../development/tools/misc/automake/automake-1.7.x.nix {
@@ -2258,10 +2271,9 @@ let
     inherit fetchurl stdenv perl autoconf;
   };
 
-  # commented out because it's using the new configuration style proposal which is unstable
-  #avrdude = import ../development/tools/misc/avrdude {
-  #  inherit lib fetchurl stdenv flex yacc;
-  #};
+  avrdude = import ../development/tools/misc/avrdude {
+    inherit lib fetchurl stdenv flex yacc composableDerivation texLive;
+  };
 
   binutils = useFromStdenv "binutils"
     (import ../development/tools/misc/binutils {
@@ -2299,7 +2311,7 @@ let
   };
 
   cmake = import ../development/tools/build-managers/cmake {
-    inherit fetchurl stdenv replace;
+    inherit fetchurl stdenv replace ncurses;
   };
 
   cproto = import ../development/tools/misc/cproto {
@@ -2583,7 +2595,7 @@ let
   };
 
   gdb = import ../development/tools/misc/gdb {
-    inherit fetchurl stdenv ncurses gmp mpfr texinfo;
+    inherit fetchurl stdenv ncurses readline gmp mpfr texinfo;
   };
 
   valgrind = import ../development/tools/analysis/valgrind {
@@ -2599,6 +2611,10 @@ let
 
   yacc = bison;
 
+  yodl = import ../development/tools/misc/yodl {
+    inherit stdenv fetchurl perl;
+  };
+
 
   ### DEVELOPMENT / LIBRARIES
 
@@ -2786,8 +2802,6 @@ let
     inherit fetchurl stdenv pkgconfig expat;
     inherit (xlibs) libX11 libICE libSM;
     useX11 = true; # !!! `false' doesn't build
-    #useX11 = getConfig ["dbus" "tools" "useX11"]
-    #  (getConfig ["services" "xserver" "enable"] false);
   };
 
   dbus_glib = import ../development/libraries/dbus-glib {
@@ -2856,12 +2870,16 @@ let
   };
 
   fltk20 = (import ../development/libraries/fltk) {
-    inherit mkDerivationByConfiguration x11 lib;
+    inherit composableDerivation x11 lib pkgconfig freeglut;
     inherit fetchurl stdenv mesa mesaHeaders libpng libjpeg zlib ;
-    inherit (xlibs) inputproto libXi;
+    inherit (xlibs) inputproto libXi libXinerama libXft;
     flags = [ "useNixLibs" "threads" "shared" "gl" ];
   };
 
+  freeimage = import ../development/libraries/freeimage {
+    inherit fetchurl stdenv unzip;
+  };
+
   cfitsio = import ../development/libraries/cfitsio {
     inherit fetchurl stdenv;
   };
@@ -2911,11 +2929,9 @@ let
   };
 
   geos = import ../development/libraries/geos {
-    inherit fetchurl fetchsvn stdenv mkDerivationByConfiguration autoconf automake libtool swig which lib;
+    inherit fetchurl fetchsvn stdenv autoconf
+      automake libtool swig which lib composableDerivation python ruby;
     use_svn = stdenv.system == "x86_64-linux";
-    python = python;
-    # optional features:
-    # python / ruby support
   };
 
   gettext = composedArgsAndFun (selectVersion ../development/libraries/gettext "0.17") {
@@ -3226,7 +3242,7 @@ let
   };
 
   libdv = import ../development/libraries/libdv {
-    inherit fetchurl stdenv lib mkDerivationByConfiguration;
+    inherit fetchurl stdenv lib composableDerivation;
   };
 
   libdrm = import ../development/libraries/libdrm {
@@ -3280,7 +3296,7 @@ let
   };
 
   libsamplerate = import ../development/libraries/libsamplerate {
-    inherit fetchurl stdenv mkDerivationByConfiguration pkgconfig lib;
+    inherit fetchurl stdenv pkgconfig lib;
   };
 
   libspectre = import ../development/libraries/libspectre {
@@ -3641,10 +3657,6 @@ let
     inherit fetchurl stdenv gettext;
   };
 
-  popt110 = import ../development/libraries/popt/popt-1.10.6.nix {
-    inherit fetchurl stdenv gettext libtool autoconf automake;
-  };
-
   proj = import ../development/libraries/proj.4 {
     inherit fetchurl stdenv;
   };
@@ -3653,6 +3665,10 @@ let
     inherit fetchurl stdenv;
   };
 
+  pthread_stubs = import ../development/libraries/pthread-stubs {
+    inherit fetchurl stdenv;
+  };
+
   qt3 = import ../development/libraries/qt-3 {
     inherit fetchurl stdenv x11 zlib libjpeg libpng which mysql mesa;
     inherit (xlibs) xextproto libXft libXrender libXrandr randrproto
@@ -3794,6 +3810,10 @@ let
     inherit postgresql mysql sqlite;
   });
 
+  vxl = import ../development/libraries/vxl {
+   inherit fetchurl stdenv cmake unzip libtiff expat zlib libpng libjpeg;
+  };
+
   webkit = builderDefsPackage (import ../development/libraries/webkit) {
     inherit (gtkLibs) gtk atk pango;
     inherit freetype fontconfig gettext gperf curl
@@ -4452,6 +4472,15 @@ let
     };
   };
 
+  perlClassUnload = buildPerlPackage {
+    name = "Class-Unload-0.05";
+    src = fetchurl {
+      url = mirror://cpan/authors/id/I/IL/ILMARI/Class-Unload-0.05.tar.gz;
+      sha256 = "01b0j10nxbz37xnnzw3hgmpfgq09mc489kq2d8f5nswsrlk75001";
+    };
+    propagatedBuildInputs = [perlClassInspector];
+  };
+
   perlCompressZlib = buildPerlPackage {
     name = "Compress-Zlib-1.41";
     src = fetchurl {
@@ -4564,17 +4593,17 @@ let
   };
 
   perlDBIxClass = buildPerlPackage {
-    name = "DBIx-Class-0.08099_04";
+    name = "DBIx-Class-0.08099_05";
     src = fetchurl {
-      url = mirror://cpan/authors/id/L/LS/LSAUNDERS/DBIx-Class-0.08099_04.tar.gz;
-      sha256 = "0ik5bjsrlpz0sbwrrwiyjiga17rh9jb09gflqif5h59gq9y7kcyf";
+      url = mirror://cpan/authors/id/R/RI/RIBASUSHI/DBIx-Class-0.08099_05.tar.gz;
+      sha256 = "143sp6walr9gmnk0caxidhnzciixawihkiwm7vf9clbdhhrn39zj";
     };
     propagatedBuildInputs = [
       perlTestNoWarnings perlTestException perlDBI perlScopeGuard
       perlPathClass perlClassInspector perlClassAccessorGrouped
       perlCarpClan perlTestWarn perlDataPage perlSQLAbstract
       perlSQLAbstractLimit perlClassC3 perlClassC3Componentised
-      perlModuleFind perlDBDSQLite perlJSONAny
+      perlModuleFind perlDBDSQLite perlJSONAny perlSubName
     ];
   };
 
@@ -4590,13 +4619,14 @@ let
   perlDBIxClassSchemaLoader = buildPerlPackage {
     name = "DBIx-Class-Schema-Loader-0.04005";
     src = fetchurl {
-      url = mirror://cpan/authors/id/I/IL/ILMARI/DBIx-Class-Schema-Loader-0.04005.tar.gz;
-      sha256 = "1adymxsh1q7y1d3x25mar1rz6nshag16h6bfzhwy0w50qd2vvx9l";
+      url = mirror://cpan/authors/id/I/IL/ILMARI/DBIx-Class-Schema-Loader-0.04999_06.tar.gz;
+      sha256 = "169ydwjarq6qk48jdxcn5ks8rx9aksk9fnx07gl5mz7banw5cs6y";
     };
     propagatedBuildInputs = [
       perlDBI perlDBDSQLite perlDataDump perlUNIVERSALrequire
       perlClassAccessor perlClassDataAccessor perlClassC3 perlCarpClan
       perlClassInspector perlDBIxClass perlLinguaENInflectNumber
+      perlClassUnload
     ];
   };
 
@@ -5147,6 +5177,14 @@ let
     };
   };
 
+  perlSubName = buildPerlPackage {
+    name = "Sub-Name-0.04";
+    src = fetchurl {
+      url = mirror://cpan/authors/id/X/XM/XMATH/Sub-Name-0.04.tar.gz;
+      sha256 = "1nlin0ag2krpmiyapp3lzb6qw2yfqvqmx57iz5zwbhr4pyi46bhb";
+    };
+  };
+
   perlSubUplevel = buildPerlPackage {
     name = "Sub-Uplevel-0.2002";
     src = fetchurl {
@@ -5738,6 +5776,14 @@ let
     glibc = stdenv.glibc;
   };
 
+  pulseaudio = import ../servers/pulseaudio {
+    inherit fetchurl stdenv pkgconfig gnum4 libtool gdbm
+      dbus hal avahi liboil libsamplerate libsndfile speex
+      intltool gettext;
+    inherit (gtkLibs) glib;
+    gconf = gnome.GConf;
+  };
+
   tomcat_connectors = import ../servers/http/apache-modules/tomcat-connectors {
     inherit fetchurl stdenv apacheHttpd jdk;
   };
@@ -5794,13 +5840,10 @@ let
   libunwind acl fam;
   };
 
-  squid = import ../servers/squid {
-    inherit fetchurl stdenv mkDerivationByConfiguration perl lib;
-  };
-
-  squidHead = import ../servers/squid/3.head.nix {
-    inherit fetchurl stdenv mkDerivationByConfiguration perl lib;
-  };
+  squids = recurseIntoAttrs( import ../servers/squid/squids.nix {
+    inherit fetchurl stdenv perl lib composableDerivation;
+  });
+  squid = squids.squid3Beta; # has ipv6 support
 
   tomcat5 = import ../servers/http/tomcat {
     inherit fetchurl stdenv jdk;
@@ -5888,6 +5931,12 @@ let
     inherit fetchurl stdenv autoconf automake;
   };
 
+  cpufrequtils = import ../os-specific/linux/cpufrequtils {
+    inherit fetchurl stdenv libtool gettext;
+    glibc = stdenv.gcc.libc;
+    kernelHeaders = stdenv.gcc.libc.kernelHeaders;
+  };
+
   cryopid = import ../os-specific/linux/cryopid {
     inherit fetchurl stdenv zlibStatic;
   };
@@ -6035,6 +6084,10 @@ let
     inherit fetchurl stdenv;
   };
 
+  kernelHeaders_2_6_28 = import ../os-specific/linux/kernel-headers/2.6.28.nix {
+    inherit fetchurl stdenv perl;
+  };
+
   kernelHeadersArm = import ../os-specific/linux/kernel-headers-cross {
     inherit fetchurl stdenv;
     cross = "arm-linux";
@@ -6085,14 +6138,6 @@ let
   kernel_2_6_21 = import ../os-specific/linux/kernel/linux-2.6.21.nix {
     inherit fetchurl stdenv perl mktemp module_init_tools;
     kernelPatches = [
-      { name = "ext3cow";
-        patch = ../os-specific/linux/kernel/linux-2.6.20.3-ext3cow.patch;
-        extraConfig =
-          "CONFIG_EXT3COW_FS=m\n" +
-          "CONFIG_EXT3COW_FS_XATTR=y\n" +
-          "CONFIG_EXT3COW_FS_POSIX_ACL=y\n" +
-          "CONFIG_EXT3COW_FS_SECURITY=y\n";
-      }
       /* Commented out because only acer users have need for it..
          It takes quite a while to create the patch when unpacking the kernel sources only for that task
       { name = "acerhk";
@@ -6126,27 +6171,6 @@ let
   kernel_2_6_22 = import ../os-specific/linux/kernel/linux-2.6.22.nix {
     inherit fetchurl stdenv perl mktemp module_init_tools;
     kernelPatches = [
-      /*
-      { name = "ext3cow";
-        patch = ../os-specific/linux/kernel/linux-2.6.20.3-ext3cow.patch;
-        extraConfig =
-        "CONFIG_EXT3COW_FS=m\n" +
-        "CONFIG_EXT3COW_FS_XATTR=y\n" +
-        "CONFIG_EXT3COW_FS_POSIX_ACL=y\n" +
-        "CONFIG_EXT3COW_FS_SECURITY=y\n";
-      }
-      */
-      /*
-      { name = "skas-2.6.20-v9-pre9";
-        patch = fetchurl {
-          url = http://www.user-mode-linux.org/~blaisorblade/patches/skas3-2.6/skas-2.6.20-v9-pre9/skas-2.6.20-v9-pre9.patch.bz2;
-          md5 = "02e619e5b3aaf0f9768f03ac42753e74";
-        };
-        extraConfig =
-          "CONFIG_PROC_MM=y\n" +
-          "# CONFIG_PROC_MM_DUMPABLE is not set\n";
-      }
-      */
       { name = "fbsplash-0.9.2-r5-2.6.21";
         patch = fetchurl {
           url = http://dev.gentoo.org/~dsd/genpatches/trunk/2.6.22/4200_fbsplash-0.9.2-r5.patch;
@@ -6163,64 +6187,6 @@ let
       [(getConfig ["kernel" "addConfig"] "")];
   };
 
-  kernel_2_6_21_ck = import ../os-specific/linux/kernel/linux-2.6.21_ck.nix {
-    inherit fetchurl stdenv perl mktemp module_init_tools;
-    kernelPatches = [
-      { name = "ext3cow";
-        patch = ../os-specific/linux/kernel/linux-2.6.20.3-ext3cow.patch;
-        extraConfig =
-        "CONFIG_EXT3COW_FS=m\n" +
-        "CONFIG_EXT3COW_FS_XATTR=y\n" +
-        "CONFIG_EXT3COW_FS_POSIX_ACL=y\n" +
-        "CONFIG_EXT3COW_FS_SECURITY=y\n";
-      }
-      { name = "Con Kolivas Patch";
-        patch = ../os-specific/linux/kernel/patch-2.6.21-ck1;
-      }
-      { name = "paravirt-nvidia";
-        patch = ../os-specific/linux/kernel/2.6.20-paravirt-nvidia.patch;
-      }
-      { name = "skas-2.6.20-v9-pre9";
-        patch = fetchurl {
-          url = http://www.user-mode-linux.org/~blaisorblade/patches/skas3-2.6/skas-2.6.20-v9-pre9/skas-2.6.20-v9-pre9.patch.bz2;
-          md5 = "02e619e5b3aaf0f9768f03ac42753e74";
-        };
-        extraConfig =
-          "CONFIG_PROC_MM=y\n" +
-          "# CONFIG_PROC_MM_DUMPABLE is not set\n";
-      }
-      { name = "fbsplash-0.9.2-r5-2.6.21";
-        patch = fetchurl {
-          url = http://dev.gentoo.org/~dsd/genpatches/trunk/2.6.21/4200_fbsplash-0.9.2-r5.patch;
-          sha256 = "00s8074fzsly2zpir885zqkvq267qyzg6vhsn7n1z2v1z78avxd8";
-        };
-        extraConfig = "CONFIG_FB_SPLASH=y";
-      }
-    ];
-  };
-
-  kernel_2_6_25 = import ../os-specific/linux/kernel/linux-2.6.25.nix {
-    inherit fetchurl stdenv perl mktemp module_init_tools;
-    kernelPatches = [
-      { name = "fbcondecor-0.9.4-2.6.25-rc6";
-        patch = fetchurl {
-          url = http://dev.gentoo.org/~spock/projects/fbcondecor/archive/fbcondecor-0.9.4-2.6.25-rc6.patch;
-          sha256 = "1wm94n7f0qyb8xvafip15r158z5pzw7zb7q8hrgddb092c6ibmq8";
-        };
-        extraConfig = "CONFIG_FB_CON_DECOR=y";
-        features = { fbConDecor = true; };
-      }
-      { name = "sec_perm-2.6.24";
-        patch = ../os-specific/linux/kernel/sec_perm-2.6.24.patch;
-        features = { secPermPatch = true; };
-      }
-    ];
-    extraConfig =
-      lib.optional (getConfig ["kernel" "timer_stats"] false) "CONFIG_TIMER_STATS=y" ++
-      lib.optional (getConfig ["kernel" "no_irqbalance"] false) "# CONFIG_IRQBALANCE is not set" ++
-      [(getConfig ["kernel" "addConfig"] "")];
-  };
-
   kernel_2_6_23 = import ../os-specific/linux/kernel/linux-2.6.23.nix {
     inherit fetchurl stdenv perl mktemp module_init_tools;
     kernelPatches = [
@@ -6265,6 +6231,28 @@ let
       [(getConfig ["kernel" "addConfig"] "")];
   };
 
+  kernel_2_6_25 = import ../os-specific/linux/kernel/linux-2.6.25.nix {
+    inherit fetchurl stdenv perl mktemp module_init_tools;
+    kernelPatches = [
+      { name = "fbcondecor-0.9.4-2.6.25-rc6";
+        patch = fetchurl {
+          url = http://dev.gentoo.org/~spock/projects/fbcondecor/archive/fbcondecor-0.9.4-2.6.25-rc6.patch;
+          sha256 = "1wm94n7f0qyb8xvafip15r158z5pzw7zb7q8hrgddb092c6ibmq8";
+        };
+        extraConfig = "CONFIG_FB_CON_DECOR=y";
+        features = { fbConDecor = true; };
+      }
+      { name = "sec_perm-2.6.24";
+        patch = ../os-specific/linux/kernel/sec_perm-2.6.24.patch;
+        features = { secPermPatch = true; };
+      }
+    ];
+    extraConfig =
+      lib.optional (getConfig ["kernel" "timer_stats"] false) "CONFIG_TIMER_STATS=y" ++
+      lib.optional (getConfig ["kernel" "no_irqbalance"] false) "# CONFIG_IRQBALANCE is not set" ++
+      [(getConfig ["kernel" "addConfig"] "")];
+  };
+
   kernel_2_6_26 = import ../os-specific/linux/kernel/linux-2.6.26.nix {
     inherit fetchurl stdenv perl mktemp module_init_tools;
     kernelPatches = [
@@ -6307,6 +6295,27 @@ let
       [(getConfig ["kernel" "addConfig"] "")];
   };
 
+  kernel_2_6_28 = import ../os-specific/linux/kernel/linux-2.6.28.nix {
+    inherit fetchurl stdenv perl mktemp module_init_tools;
+    kernelPatches = [
+      { name = "fbcondecor-0.9.5-2.6.28";
+        patch = fetchurl {
+          url = http://dev.gentoo.org/~spock/projects/fbcondecor/archive/fbcondecor-0.9.5-2.6.28.patch;
+          sha256 = "105q2dwrwi863r7nhlrvljim37aqv67mjc3lgg529jzqgny3fjds";
+        };
+        extraConfig = "CONFIG_FB_CON_DECOR=y";
+        features = { fbConDecor = true; };
+      }
+      { name = "sec_perm-2.6.24";
+        patch = ../os-specific/linux/kernel/sec_perm-2.6.24.patch;
+        features = { secPermPatch = true; };
+      }
+    ];
+    extraConfig =
+      lib.optional (getConfig ["kernel" "no_irqbalance"] false) "# CONFIG_IRQBALANCE is not set" ++
+      [(getConfig ["kernel" "addConfig"] "")];
+  };
+
   /* Kernel modules are inherently tied to a specific kernel.  So
      rather than provide specific instances of those packages for a
      specific kernel, we have a function that builds those packages
@@ -6422,12 +6431,12 @@ let
   kernelPackages_2_6_25 = recurseIntoAttrs (kernelPackagesFor kernel_2_6_25);
   kernelPackages_2_6_26 = recurseIntoAttrs (kernelPackagesFor kernel_2_6_26);
   kernelPackages_2_6_27 = recurseIntoAttrs (kernelPackagesFor kernel_2_6_27);
+  kernelPackages_2_6_28 = recurseIntoAttrs (kernelPackagesFor kernel_2_6_28);
 
   # The current default kernel / kernel modules.
   kernelPackages = kernelPackages_2_6_25;
-  #kernel = kernelPackages.kernel;
 
-  customKernel = composedArgsAndFun (lib.sumTwoArgs (import ../os-specific/linux/kernel/linux.nix) {
+  customKernel = composedArgsAndFun (lib.sumTwoArgs (import ../os-specific/linux/kernel/generic.nix) {
     inherit fetchurl stdenv perl mktemp module_init_tools lib;
   });
 
@@ -6471,6 +6480,11 @@ let
     kernelHeaders = kernelHeaders_2_6_26;
   };
 
+  kvm82 = import ../os-specific/linux/kvm/82.nix {
+    inherit fetchurl stdenv zlib e2fsprogs SDL alsaLib pkgconfig rsync;
+    kernelHeaders = kernelHeaders_2_6_28;
+  };
+
   libcap = import ../os-specific/linux/libcap {
     inherit fetchurl stdenv attr;
   };
@@ -6500,11 +6514,6 @@ let
     inherit fetchurl stdenv;
   };
 
-  mkinitrd = import ../os-specific/linux/mkinitrd {
-    inherit fetchurl stdenv;
-    popt = popt110;
-  };
-
   module_init_tools = import ../os-specific/linux/module-init-tools {
     inherit fetchurl stdenv;
   };
@@ -6684,6 +6693,14 @@ let
     stdenv = makeStaticBinaries stdenv;
   }));
 
+  utillinuxng = composedArgsAndFun (import ../os-specific/linux/util-linux-ng) {
+    inherit fetchurl stdenv e2fsprogs;
+  };
+
+  utillinuxngCurses = composedArgsAndFun (import ../os-specific/linux/util-linux-ng) {
+    inherit fetchurl stdenv e2fsprogs ncurses;
+  };
+
   wesnoth = import ../games/wesnoth {
     inherit fetchurl stdenv SDL SDL_image SDL_mixer SDL_net gettext zlib boost freetype;
   };
@@ -6795,7 +6812,7 @@ let
   };
 
   manpages = import ../data/documentation/man-pages {
-     inherit fetchurl stdenv;
+    inherit fetchurl stdenv;
   };
 
   mph_2b_damase = import ../data/fonts/mph-2b-damase {
@@ -6827,6 +6844,10 @@ let
     inherit fetchurl stdenv texinfo;
   };
 
+  themes = name: import (../data/misc/themes + ("/" + name + ".nix")) {
+    inherit fetchurl;
+  };
+
   ttf_bitstream_vera = import ../data/fonts/ttf-bitstream-vera {
     inherit fetchurl stdenv;
   };
@@ -7174,6 +7195,10 @@ let
     inherit libpng libtiff;
   };
 
+  dvdauthor = import ../applications/video/dvdauthor {
+    inherit fetchurl stdenv freetype libpng fribidi libxml2 libdvdread imagemagick;
+  };
+
   dwm = import ../applications/window-managers/dwm {
     inherit fetchurl stdenv;
     inherit (xlibs) libX11 libXinerama;
@@ -7320,6 +7345,27 @@ let
     #enableOfficialBranding = true;
   });
 
+  firefox3_1 = lowPrio (import ../applications/networking/browsers/firefox-3/3.1.nix {
+    inherit fetchurl stdenv pkgconfig perl zip libjpeg zlib cairo
+      python dbus dbus_glib freetype fontconfig bzip2;
+    inherit (gtkLibs) gtk pango;
+    inherit (gnome) libIDL;
+    inherit (alsa) alsaLib;
+    #enableOfficialBranding = true;
+    xulrunner = xulrunner3_1;
+    autoconf = autoconf213;
+  });
+
+  xulrunner3_1 = lowPrio (import ../applications/networking/browsers/firefox-3/xulrunner-3.1.nix {
+    inherit fetchurl stdenv pkgconfig perl zip libjpeg libpng zlib cairo
+      python dbus dbus_glib freetype fontconfig bzip2 xlibs file;
+    inherit (gtkLibs) gtk pango;
+    inherit (gnome) libIDL;
+    inherit (alsa) alsaLib;
+    autoconf = autoconf213;
+    #enableOfficialBranding = true;
+  });
+
   firefox3b1Bin = lowPrio (import ../applications/networking/browsers/firefox-3/binary.nix {
     inherit fetchurl stdenv pkgconfig perl zip libjpeg libpng zlib cairo
       python curl coreutils freetype fontconfig;
@@ -7478,7 +7524,7 @@ let
 
   icecat3Xul =
     (symlinkJoin "icecat-3-with-xulrunner" [ icecat3 icecatXulrunner3 ])
-    // { inherit (icecat3) gtk meta; };
+    // { inherit (icecat3) gtk isFirefox3Like meta; };
 
   icecatWrapper = wrapFirefox icecat3Xul "icecat" "";
 
@@ -7668,21 +7714,6 @@ let
     cddaSupport = true;
   };
 
-  # commented out because it's using the new configuration style proposal which is unstable
-  # should be the same as the nix expression above except support for esound :)
-  /*
-  MPlayer_new_config = import ../applications/video/MPlayer/newconfig.nix {
-    inherit fetchurl stdenv freetype x11 zlib freefont_ttf lib;
-    inherit (xlibs) libX11 xextproto;
-
-    # optional features
-    inherit alsaLib libtheora libcaca;
-    inherit (gnome) esound;
-    inherit (xlibs) libXv libXinerama;
-    inherit (xlibs) libXrandr; # FIXME does this option exist? I couldn't find it as configure option
-  };
-  */
-
   MPlayerPlugin = browser:
     import ../applications/networking/browsers/mozilla-plugins/mplayerplug-in {
       inherit browser;
@@ -7691,13 +7722,10 @@ let
       # !!! should depend on MPlayer
     };
 
-  # commented out because it's using the new configuration style proposal which is unstable
-  /*
   mrxvt = import ../applications/misc/mrxvt {
     inherit lib fetchurl stdenv;
     inherit (xlibs) libXaw xproto libXt libX11 libSM libICE;
   };
-  */
 
   multisync = import ../applications/misc/multisync {
     inherit fetchurl stdenv autoconf automake libtool pkgconfig;
@@ -7755,7 +7783,7 @@ let
     inherit (xlibs) libX11 libSM libICE libXt libXext;
     qt = qt3;
     #33motif = lesstif;
-    libstdcpp5 = (if (stdenv.system == "i686-linux") then gcc33 /* stdc++ 3.8 is used */ else gcc).gcc;
+    libstdcpp5 = (if (stdenv.system == "i686-linux") then gcc33 /* stdc++ 3.8 is used */ else gcc42).gcc;
   };
 
   pan = import ../applications/networking/newsreaders/pan {
@@ -7877,7 +7905,7 @@ let
     inherit fetchurl stdenv;
     inherit glibc alsaLib freetype fontconfig libsigcxx gcc;
     inherit (xlibs) libSM libICE libXi libXrender libXrandr libXfixes libXcursor
-                    libXinerama libXext libX11;
+                    libXinerama libXext libX11 libXv libXScrnSaver;
   };
 
   slim = import ../applications/display-managers/slim {
@@ -7897,9 +7925,9 @@ let
   };
 
   sox = import ../applications/misc/audio/sox {
-    inherit fetchurl stdenv lib mkDerivationByConfiguration;
+    inherit fetchurl stdenv lib composableDerivation;
     # optional features
-    inherit alsaLib; # libao
+    inherit alsaLib libao;
     inherit libsndfile libogg flac libmad lame libsamplerate;
     # Using the default nix ffmpeg I get this error when linking
     # .libs/libsox_la-ffmpeg.o: In function `audio_decode_frame':
@@ -8065,7 +8093,7 @@ let
   };
 
   vim_configurable = import ../applications/editors/vim/configurable.nix {
-    inherit fetchurl stdenv ncurses pkgconfig mkDerivationByConfiguration lib;
+    inherit fetchurl stdenv ncurses pkgconfig composableDerivation lib;
     inherit (xlibs) libX11 libXext libSM libXpm
         libXt libXaw libXau libXmu;
     inherit (gtkLibs) glib gtk;
@@ -8216,9 +8244,16 @@ let
   };
 
   xneur = import ../applications/misc/xneur {
-    inherit fetchurl stdenv pkgconfig pcre libxml2 aspell;
+    inherit fetchurl stdenv pkgconfig pcre libxml2 aspell imlib2 xosd;
+    GStreamer=gst_all.gstreamer;
+    inherit (xlibs) libX11 libXpm libXt libXext;
+    inherit (gtkLibs) glib;
+  };
+
+  xneur_0_8 = import ../applications/misc/xneur/0.8.nix {
+    inherit fetchurl stdenv pkgconfig pcre libxml2 aspell imlib2 xosd;
     GStreamer=gst_all.gstreamer;
-    inherit (xlibs) libX11 libXpm;
+    inherit (xlibs) libX11 libXpm libXt libXext;
     inherit (gtkLibs) glib;
   };
 
@@ -8283,12 +8318,11 @@ let
   };
 
   # doesn't compile yet - in case someone else want's to continue ..
-  /*
-  qgis_svn = import ../applications/misc/qgis_svn {
-    inherit mkDerivationByConfiguration fetchsvn stdenv flex lib
+  qgis =  composedArgsAndFun (selectVersion ../applications/misc/qgis "0.11.0") {
+    inherit composableDerivation fetchsvn stdenv flex lib
             ncurses fetchurl perl cmake gdal geos proj x11
             gsl libpng zlib bison
-            sqlite glibc fontconfig freetype / * use libc from stdenv ? - to lazy now - Marc * /;
+            sqlite glibc fontconfig freetype /* use libc from stdenv ? - to lazy now - Marc */;
     inherit (xlibs) libSM libXcursor libXinerama libXrandr libXrender;
     inherit (xorg) libICE;
     qt = qt4;
@@ -8296,7 +8330,6 @@ let
     # optional features
     # grass = "not yet supported" # cmake -D WITH_GRASS=TRUE  and GRASS_PREFX=..
   };
-  */
 
   zapping = import ../applications/video/zapping {
     inherit fetchurl stdenv pkgconfig perl python
@@ -8400,6 +8433,12 @@ let
     inherit fetchurl stdenv SDL zlib mpeg2dec;
   };
 
+  sgtpuzzles = builderDefsPackage (import ../games/sgt-puzzles) {
+    inherit (gtkLibs) gtk glib;
+    inherit pkgconfig;
+    inherit (xlibs) libX11;
+  };
+
   # You still can override by passing more arguments.
   spaceOrbit =  composedArgsAndFun (selectVersion ../games/orbit "1.01") {
     inherit fetchurl stdenv builderDefs mesa freeglut;
@@ -8412,6 +8451,11 @@ let
       libvorbis libogg gettext;
   };
 
+  teeworlds = import ../games/teeworlds {
+    inherit fetchurl stdenv python alsaLib mesa SDL;
+    inherit (xlibs) libX11;
+  };
+
   /*tpm = import ../games/thePenguinMachine {
     inherit stdenv fetchurl pil pygame SDL;
     python24 = python;
@@ -8421,6 +8465,10 @@ let
     inherit fetchurl stdenv xlibs mesa;
   };
 
+  xsokoban = builderDefsPackage (import ../games/xsokoban) {
+    inherit (xlibs) libX11 xproto libXpm libXt;
+  };
+
   zoom = import ../games/zoom {
     inherit fetchurl stdenv perl expat freetype;
     inherit (xlibs) xlibs;
@@ -8625,17 +8673,14 @@ let
     x11Support = true;
   }));
 
-  # commented out because it's using the new configuration style proposal which is unstable
-  /*
   gxemul = (import ../misc/gxemul) {
-    inherit lib stdenv fetchurl;
+    inherit lib stdenv fetchurl composableDerivation;
     inherit (xlibs) libX11;
   };
-  */
 
   # using the new configuration style proposal which is unstable
   jackaudio = import ../misc/jackaudio {
-    inherit mkDerivationByConfiguration
+    inherit composableDerivation
            ncurses lib stdenv fetchurl alsaLib pkgconfig;
     flags = [ "posix_shm" "timestamps" "alsa"];
   };
@@ -8733,7 +8778,7 @@ let
   };
 
   psi = builderDefsPackage
-    (selectVersion ../applications/networking/instant-messengers/psi "0.11")
+    (selectVersion ../applications/networking/instant-messengers/psi "0.12")
     {
       inherit builderDefs zlib aspell sox openssl;
       inherit (xlibs) xproto libX11 libSM libICE;
diff --git a/pkgs/top-level/build-for-release.nix b/pkgs/top-level/build-for-release.nix
index 7d99450e6b992..2ab5d421708f2 100644
--- a/pkgs/top-level/build-for-release.nix
+++ b/pkgs/top-level/build-for-release.nix
@@ -73,10 +73,12 @@ let
       gnum4
       gnumake
       gnupatch
+      gnupg2
       gnused
       gnutar
       gnutls
       gphoto2
+      gsl
       guile
       gqview
       graphviz
@@ -148,9 +150,10 @@ let
       qt4
       #quake3demo
       readline
-      reiserfsprogs
       rLang
+      reiserfsprogs
       rogue
+      rpm
       rsync
       ruby
       screen
@@ -170,6 +173,7 @@ let
       sysvinit
       sysvtools
       tcpdump
+      teeworlds
       #tetex
       texLive
       texLiveBeamer
@@ -263,6 +267,13 @@ let
 #        splashutils
         ;
     };
+    kernelPackages_2_6_28 = pkgs.recurseIntoAttrs {
+      inherit (pkgs.kernelPackages_2_6_28)
+        kernel
+        klibc
+#        splashutils
+        ;
+    };
   };
 
   i686LinuxPkgs = commonLinuxPkgs "i686-linux" // {
@@ -285,6 +296,7 @@ let
       jrePlugin
       keen4
       mono
+      namazu  # FIXME: The test suite fails on x86-64.
       openoffice
       pidgin
       postgresql_jdbc
diff --git a/pkgs/top-level/builder-defs.nix b/pkgs/top-level/builder-defs.nix
index 367f018a1949f..4efed47f6d0b9 100644
--- a/pkgs/top-level/builder-defs.nix
+++ b/pkgs/top-level/builder-defs.nix
@@ -9,7 +9,7 @@ args: with args; with stringsWithDeps; with lib;
 
         forceShare = if args ? forceShare then args.forceShare else ["man" "doc" "info"];
         forceCopy = ["COPYING" "LICENSE" "DISTRIBUTION" "LEGAL" 
-          "README" "AUTHORS" "ChangeLog" "CHANGES"] ++ 
+          "README" "AUTHORS" "ChangeLog" "CHANGES" "LICENCE" "COPYRIGHT"] ++ 
           (optional (getAttr ["forceCopyDoc"] true args) "doc"); 
 
         archiveType = s: 
@@ -278,8 +278,8 @@ args: with args; with stringsWithDeps; with lib;
         ") ["minInit" "defEnsureDir"];
 
         doForceCopy = FullDepEntry (''
-                name=$(basename $out)
-                name=''${name#*-}
+                name="$(basename $out)"
+                name="''${name#*-}"
                 ensureDir "$prefix/share/$name"
                 for f in ${toString forceCopy}; do
                         cp -r "$f" "$prefix/share/$name/$f" || true
@@ -381,8 +381,27 @@ args: with args; with stringsWithDeps; with lib;
         surroundWithCommands = x : before : after : {deps=x.deps; text = before + "\n" +
                 x.text + "\n" + after ;};
 
-        realPhaseNames = args.phaseNames ++ 
+	createDirs = FullDepEntry (concatStringsSep ";"
+		(map (x: "ensureDir ${x}") (getAttr ["neededDirs"] [] args))
+	) ["minInit" "defEnsureDir"];
+
+	copyExtraDoc = FullDepEntry (''
+          name="$(basename $out)"
+          name="''${name#*-}"
+          ensureDir "$out/share/doc/$name"
+	'' + (concatStringsSep ";"
+               (map 
+	         (x: ''cp "${x}" "$out/share/doc/$name" || true;'') 
+		 (getAttr ["extraDoc"] [] args)))) ["minInit" "defEnsureDir" "doUnpack"];
+
+        realPhaseNames = 
+	  (optional ([] != getAttr ["neededDirs"] [] args) "createDirs")
+	  ++
+	  args.phaseNames 
+	  ++ 
           ["doForceShare" "doPropagate" "doForceCopy"]
+	  ++
+	  (optional ([] != getAttr ["extraDoc"] [] args) "copyExtraDoc")
           ++
           (optional (getAttr ["doCheck"] false args) "doMakeCheck")
           ++
@@ -410,7 +429,8 @@ args: with args; with stringsWithDeps; with lib;
           inherit (localDefs) name;
           builder = writeScript (name + "-builder")
             (textClosure localDefs localDefs.realPhaseNames);
-          meta = localDefs.meta // {inherit src;};
+          meta = localDefs.meta;
+	  passthru = localDefs.passthru // {inherit (localDefs) src; };
         }) // (if localDefs ? propagatedBuildInputs then {
           inherit (localDefs) propagatedBuildInputs;
         } else {}) // extraDerivationAttrs)