From cb5bcfa04a6fdf3756cf760af6238d928c060ceb Mon Sep 17 00:00:00 2001
From: Eelco Dolstra <eelco.dolstra@logicblox.com>
Date: Sun, 20 Jun 2010 20:52:08 +0000
Subject: [PATCH] * In the VM tests, apply a patch to increase the 15s timeout
 on CIFS   operations to 120s.  This is necessary if the host is heavily  
 loaded.  For instance, in the Hydra build farm, if there are many  
 concurrent jobs, VM builds often fail because they hit the timeout.

svn path=/nixpkgs/trunk/; revision=22347
---
 pkgs/build-support/vm/default.nix             | 16 ++++---
 .../linux/kernel/cifs-timeout.patch           | 47 +++++++++++++++++++
 pkgs/os-specific/linux/kernel/patches.nix     |  7 +++
 3 files changed, 63 insertions(+), 7 deletions(-)
 create mode 100644 pkgs/os-specific/linux/kernel/cifs-timeout.patch

diff --git a/pkgs/build-support/vm/default.nix b/pkgs/build-support/vm/default.nix
index e4eb993fbf1c..50083ca688ff 100644
--- a/pkgs/build-support/vm/default.nix
+++ b/pkgs/build-support/vm/default.nix
@@ -4,7 +4,12 @@ with pkgs;
 
 rec {
 
-  inherit (linuxPackages_2_6_32) kernel;
+  # The 15 second CIFS timeout is too short if the host if heavily
+  # loaded (e.g., in the Hydra build farm when it's running many jobs
+  # in parallel).  So apply a patch to increase the timeout to 120s.
+  kernel = pkgs.linux.override (orig: {
+    kernelPatches = orig.kernelPatches ++ [ kernelPatches.cifs_timeout ];
+  });
 
   kvm = pkgs.qemu_kvm;
 
@@ -135,10 +140,8 @@ rec {
     mkdir -p /fs/dev
     mount -o bind /dev /fs/dev
 
-    for ((n = 0; n < 10; n++)); do
-      echo "mounting host filesystem, attempt $n..."
-      mount -t cifs //10.0.2.4/qemu /fs/hostfs -o guest,username=nobody && break
-    done
+    echo "mounting host filesystem..."
+    mount -t cifs //10.0.2.4/qemu /fs/hostfs -o guest,username=nobody
 
     mkdir -p /fs/nix/store
     mount -o bind /fs/hostfs/nix/store /fs/nix/store
@@ -225,7 +228,6 @@ rec {
 
 
   startSamba =
-    let sambaScript = writeScript "run-smbd" "while ${samba}/sbin/smbd -s $TMPDIR/smb.conf; do true; done"; in
     ''
       cat > $TMPDIR/smb.conf <<SMB
       [global]
@@ -244,7 +246,7 @@ rec {
       SMB
 
       rm -f ./samba
-      ${socat}/bin/socat unix-listen:./samba exec:'/bin/sh -c ${sambaScript}',nofork > /dev/null 2>&1 &
+      ${socat}/bin/socat unix-listen:./samba exec:'${samba}/sbin/smbd -s $TMPDIR/smb.conf',nofork > /dev/null 2>&1 &
       while [ ! -e ./samba ]; do sleep 0.1; done # ugly
     '';
 
diff --git a/pkgs/os-specific/linux/kernel/cifs-timeout.patch b/pkgs/os-specific/linux/kernel/cifs-timeout.patch
new file mode 100644
index 000000000000..b2dac3f016c4
--- /dev/null
+++ b/pkgs/os-specific/linux/kernel/cifs-timeout.patch
@@ -0,0 +1,47 @@
+diff -ru -x '*~' /tmp/linux-2.6.32.14/fs/cifs/transport.c linux-2.6.32.14/fs/cifs/transport.c
+--- /tmp/linux-2.6.32.14/fs/cifs/transport.c	2010-05-26 23:29:57.000000000 +0200
++++ linux-2.6.32.14/fs/cifs/transport.c	2010-06-20 22:03:13.000000000 +0200
+@@ -166,9 +166,9 @@
+ 			   after the retries we will kill the socket and
+ 			   reconnect which may clear the network problem.
+ 			*/
+-			if ((i >= 14) || (!server->noblocksnd && (i > 2))) {
++			if ((i >= 119) || (!server->noblocksnd && (i > 2))) {
+ 				cERROR(1,
+-				   ("sends on sock %p stuck for 15 seconds",
++				   ("sends on sock %p stuck for 120 seconds",
+ 				    ssocket));
+ 				rc = -EAGAIN;
+ 				break;
+@@ -459,11 +459,11 @@
+ 		goto out;
+ 
+ 	if (long_op == CIFS_STD_OP)
+-		timeout = 15 * HZ;
++		timeout = 120 * HZ;
+ 	else if (long_op == CIFS_VLONG_OP) /* e.g. slow writes past EOF */
+ 		timeout = 180 * HZ;
+ 	else if (long_op == CIFS_LONG_OP)
+-		timeout = 45 * HZ; /* should be greater than
++		timeout = 120 * HZ; /* should be greater than
+ 			servers oplock break timeout (about 43 seconds) */
+ 	else if (long_op == CIFS_ASYNC_OP)
+ 		goto out;
+@@ -651,7 +651,7 @@
+ 		goto out;
+ 
+ 	if (long_op == CIFS_STD_OP)
+-		timeout = 15 * HZ;
++		timeout = 120 * HZ;
+ 	/* wait for 15 seconds or until woken up due to response arriving or
+ 	   due to last connection to this server being unmounted */
+ 	else if (long_op == CIFS_ASYNC_OP)
+@@ -659,7 +659,7 @@
+ 	else if (long_op == CIFS_VLONG_OP) /* writes past EOF can be slow */
+ 		timeout = 180 * HZ;
+ 	else if (long_op == CIFS_LONG_OP)
+-		timeout = 45 * HZ; /* should be greater than
++		timeout = 120 * HZ; /* should be greater than
+ 			servers oplock break timeout (about 43 seconds) */
+ 	else if (long_op == CIFS_BLOCKING_OP)
+ 		timeout = 0x7FFFFFFF; /* large but no so large as to wrap */
diff --git a/pkgs/os-specific/linux/kernel/patches.nix b/pkgs/os-specific/linux/kernel/patches.nix
index 2e5232025dd9..45e3174dc804 100644
--- a/pkgs/os-specific/linux/kernel/patches.nix
+++ b/pkgs/os-specific/linux/kernel/patches.nix
@@ -155,4 +155,11 @@ in
       features.aufsBase = true;
     };
 
+  # Increase the timeout on CIFS requests from 15 to 120 seconds to
+  # make CIFS more resilient to high load on the CIFS server.
+  cifs_timeout =
+    { name = "cifs-timeout";
+      patch = ./cifs-timeout.patch;
+    };
+  
 }