[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: [Nbd] [PATCH 2/2] NBD: allow hung network I/O to be cancelled



On 8/24/07, Paul Clements <paul.clements@...124...> wrote:
> Mike Snitzer wrote:
> > On 8/24/07, Paul Clements <paul.clements@...124...> wrote:
> >> This patch allows NBD I/O to be cancelled when a network outage occurs.
> >> Previously, I/O would just hang, and if enough I/O was hung in nbd, the
> >> system (at least user-level) would completely hang until a TCP timeout
> >> (default, 15 minutes) occurred.
> >>
> >> The patch introduces a new ioctl NBD_SET_TIMEOUT that allows a transmit
> >> timeout value (in seconds) to be specified. Any network send that
> >> exceeds the timeout will be cancelled and the nbd connection will be
> >> shut down. I've tested with various timeout values and 6 seconds seems
> >> to be a good choice for the timeout. If the NBD_SET_TIMEOUT ioctl is not
> >> called, you get the old (I/O hang) behavior.
> >
> > Hi Paul,
> >
> > Thanks for implementing this!  Do you happen to have an associated
> > nbd-client patch for userspace?  If not I'd be happy to coordinate
> > with you and Wouter on a patch.
>
> No, I don't. I just basically hardcoded my nbd-client to do a 6 second
> timeout by default, but Wouter will probably want to do something a
> little less hackish for the official nbd-client.

I trimmed LKML to avoid spamming so many others with userspace changes...

Wouter,

The attached patch adds nbd-client timeout support; this applies to
the tip of the svn trunk.
Please feel free to change as you see fit.  I'm not sure if it would
be wise to default to a timeout (e.g. Paul's suggestion of 6) rather
than my current default of not specifying a timeout (to maintain
compatibility).

thanks,
Mike
Index: nbd-client.c
===================================================================
--- ./nbd-client.c	(revision 278)
+++ ./nbd-client.c	(working copy)
@@ -140,6 +140,16 @@
 		err("Unable to set read-only attribute for device");
 }
 
+void set_timeout(int nbd, int timeout) {
+#ifdef NBD_SET_TIMEOUT
+	if (timeout) {
+		if (ioctl(nbd, NBD_SET_TIMEOUT, timeout) < 0)
+			err("Ioctl NBD_SET_TIMEOUT failed: %m\n");
+		fprintf(stderr, "timeout=%d\n", timeout);
+	}
+#endif
+}
+
 void finish_sock(int sock, int nbd, int swap) {
 	if (ioctl(nbd, NBD_SET_SOCK, sock) < 0)
 		err("Ioctl NBD_SET_SOCK failed: %m\n");
@@ -160,6 +170,7 @@
 	char *hostname, *nbddev;
 	int swap=0;
 	int cont=0;
+	int timeout=0;
 	u64 size64;
 	u32 flags;
 
@@ -168,7 +179,7 @@
 	if (argc < 3) {
 	errmsg:
 		fprintf(stderr, "nbd-client version %s\n", PACKAGE_VERSION);
-		fprintf(stderr, "Usage: nbd-client [bs=blocksize] host port nbd_device [-swap] [-persist]\n");
+		fprintf(stderr, "Usage: nbd-client [bs=blocksize] [timeout=sec] host port nbd_device [-swap] [-persist]\n");
 		fprintf(stderr, "Or   : nbd-client -d nbd_device\n");
 		fprintf(stderr, "Default value for blocksize is 1024 (recommended for ethernet)\n");
 		fprintf(stderr, "Allowed values for blocksize are 512,1024,2048,4096\n"); /* will be checked in kernel :) */
@@ -206,6 +217,11 @@
 		++argv; --argc; /* skip blocksize */
 	}
 
+	if (strncmp(argv[0], "timeout=", 8)==0) {
+		timeout=atoi(argv[0]+8);
+		++argv; --argc; /* skip timeout */
+	}
+	
 	if (argc==0) goto errmsg;
 	hostname=argv[0];
 	++argv; --argc; /* skip hostname */
@@ -239,6 +255,7 @@
 
 	negotiate(sock, &size64, &flags);
 	setsizes(nbd, size64, blocksize, flags);
+	set_timeout(nbd, timeout);
 	finish_sock(sock, nbd, swap);
 
 	/* Go daemon */
@@ -272,6 +289,7 @@
 					setsizes(nbd, size64, blocksize,
 								new_flags);
 
+					set_timeout(nbd, timeout);
 					finish_sock(sock,nbd,swap);
 				}
 			}

Reply to: