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

Re: [Nbd] nbd-server working easily in cygwin in XP



On Sun, Jul 20, 2008 at 11:56:46AM -0700, ulmo@...205... wrote:
> I conveniently made a version that works for cygwin in XP and put it in
> <ftp://ftp.sonic.net/pub/users/qm/nbd/nbd-2.9.11-cygwin.tar.gz>.
> Everything I did is in the README.cygwin, which I append to this message,
> so if you have this message, you won't need the tarball (but it makes
> it simpler).
> 
> I believe the fix is a simple bug, either in cygwin, or in nbd.  Someone
> with knowledge in the area of my bug/hack fix should certainly fix it.
> My fix is not generalized, and I haven't yet tested the changes to
> nbd-server in Linux/unix yet to see if it actually breaks that
> (although of course my nbd-client was in Linux/unix).

That's okay, I can do that :-)

> Brad Allen <Ulmo@...206...>
> 
> These are the changes I made to make nbd-server work under Cygwin in
> XP.  It was quite easy.  It took very little to make nbd-server work
> in Cygwin in XP.  All it needed was nbd.h and fcntl(...&~O_NONBLOCK).
> 
> The steps below are separated with the following line:
> 
> ======================================================
> 
> 0.  Obviously, every time ./configure says something is missing, go get it!
>     I have a healthy cygwin installation (that means a lot of stuff is
>     present).  If you don't know enough to select the right cygwin
>     packages, then you are brave indeed!  To such a brave soul, go and
>     install EVERY cygwin package that might be used, and you'll be
>     just fine.  (I don't; no room, and no time for all the insane
>     conflicts, which I've never seen so maybe there aren't any.)
> 
>     Be sure to include glib2-devel.  I have no idea what it is, but
>     they say nbd needs it, and indeed it does (I tried without it,
>     since I have a no-Gnome policy).
> 
> ======================================================
> 
> 1.  "./configure --prefix=/usr/local"  failed with the following:
> 
>     checking where to find a working nbd.h... configure: error: Could not find an nbd.h from 2.6 or above.
> 
>     So, I got nbd.h from a recent kernel and put it in this directory,
>     and commented out all the #include statements (which caused it to
>     fail to compile correctly).  I put an example at nbd.h-cygwin
>     (which I got from linux-2.6.26/include/linux/nbd.h); rename or
>     symlink it to nbd.h.
> 
>     Here's a patch for commenting out the includes if you get a fresh copy.
> 
> --- /usr/src/linux/include/linux/nbd.h  2008-07-13 14:51:29.000000000 -0700
> +++ nbd.h       2008-07-18 12:21:42.187500000 -0700
> @@ -15,7 +15,7 @@
>  #ifndef LINUX_NBD_H
>  #define LINUX_NBD_H
> 
> -#include <linux/types.h>
> +/*#include <linux/types.h>*/

Perhaps I should just stop pretending and ship nbd.h as part of the
source. That will kill off a *lot* of issues. Anyway.

>  #define NBD_SET_SOCK   _IO( 0xab, 0 )
>  #define NBD_SET_BLKSIZE        _IO( 0xab, 1 )
> @@ -39,8 +39,8 @@
>  /* userspace doesn't need the nbd_device structure */
>  #ifdef __KERNEL__
> 
> -#include <linux/wait.h>
> -#include <linux/mutex.h>
> +/*#include <linux/wait.h>*/
> +/*#include <linux/mutex.h>*/

Note that these are inside an #ifdef __KERNEL__, so they won't hurt even
if they're left in there.

>  /* values for flags field */
>  #define NBD_READ_ONLY 0x0001
> 
> ======================================================
> 
> 2.  I commented out the junk in "configure" that didn't work without the
>     above nbd.h, or with it with the #includes still in it.
>     I don't know how to program "configure.in", so as you can guess,
>     my programming abilities to fix and enhance programs has been on a
>     hiatus for the last 15 years as a result.

Heh.

It's actually configure.ac, rather than configure.in; and after editing
configure.ac, just run 'autoreconf' to get everything working. Of
course, that does require you to have autoconf and automake installed.

>     But, once I got nbd.h in the local directory to work anyway, I
>     didn't need to fix configure any more.  So, you get to skip this
>     step as long as your nbd.h works right as above.

Exactly.

> 3.  I found out nbd-server disconnected whenever nbd-client connected to it.

On cygwin, too? We hit that on Solaris as well...

[...]
> As you can see, now it is working better.  The client also worked.
> 
> Note that with NOFORK turned on, it wouldn't work with multiple
> clients (I tried, not thinking about it much; not sure DODBG is much
> use without NOFORK, though; would require some hacking to make that
> useful).

NOFORK indeed makes more than one client impossible, since the server
currently uses the fork-per-child paradigm. The idea of NOFORK is for me
to have an easier gdb session, not for anyone to use that in production.
This is also why nbd-server currently doesn't have a "-d" option to
switch debugging output on at runtime rather than at compiletime.

> 4.  This is the main patch to fix the bug.  It's amazingly simple, and
>     meant that my nap to figure it out was very worthwhile.  What a nap!
>     Many, many dreams.  Took me a while, though (couple of hours).
> 
>     So, why is this?  Does Cygwin keep the NONBLOCK from when the
>     socket was just listening and unconnected vs. Linux which resets
>     it to BLOCKING IO?  Anyway, this was necessary with Cygwin, and
>     not with Linux.
> 
> diff -Nrup nbd-2.9.11/nbd-server.c nbd-2.9.11.ulmo/nbd-server.c
> --- nbd-2.9.11/nbd-server.c     2008-05-01 12:04:44.000000000 -0700
> +++ nbd-2.9.11.ulmo/nbd-server.c        2008-07-18 15:04:39.687500000 -0700
> @@ -1059,6 +1071,16 @@ void negotiate(CLIENT *client) {
>         char zeros[128];
>         u64 size_host;
>         u32 flags = NBD_FLAG_HAS_FLAGS;
> +       int sock_flags;
> +
> +       /* make the socket blocking */
> +       if ((sock_flags = fcntl(client->net, F_GETFL, 0)) == -1) {
> +               err("fcntl F_GETFL");
> +       }
> +       if (fcntl(client->net, F_SETFL, sock_flags &~O_NONBLOCK) == -1) {
> +               err("fcntl F_SETFL ~O_NONBLOCK");
> +       }
> +

Ah, darn. Yeah, that explains a lot of things.

On Linux, apparently the default is to make sockets blocking, even if
they're coming from an accept() call from a socket that is blocking.
Apparently this is not POSIX, which I presumed it to be. Of course
making incorrect assumptions is never a good idea :-)

I've incorporated this patch now (though I've added it right after the
accept() call, instead of at the beginning of the negotiate() function),
so it should now work on systems which inherit socket flags through
accept(). This should also fix the issues on Solaris that I promised
ages ago to debug; Daniel (CC), could you check?

[...]
> 5.  In cygwin in XP, a big file I had of 7.5G worked fine, but when I had
>     DODBG defined to 1 (in config.h) and it printed the size, the size
>     was minus 2^32, so I assume it just wraps at 2^32.  So to isolate
>     that that wasn't the problem, besides testing smaller pieces and
>     stuff, I put in a simple test to check if the variable was at
>     least correct.  Then I improved it a bit, to actually print right.
>     You'll note my beautifully written new function that prints any
>     decimal number into a static string.  Now when debugging, it prints
>     the right size (in my case, 7641252864).  It also works right with
>     another one of size 35082608640.  The first one of 7641252864 was
>     originally a 7.5GB file on an NTFS filesystem, but I shrunk it and
>     moved it to its own partition.  They all worked fine.
> 
> --- nbd-2.9.11/nbd-server.c.~1~ 2008-05-01 12:04:44.000000000 -0700
> +++ nbd-2.9.11/nbd-server.c     2008-07-20 09:17:27.093750000 -0700
> @@ -239,6 +239,12 @@
>                                   is PARAM_BOOL. */
>  } PARAM;
> 
> +typedef unsigned long long big_t; /* any int type works (e.g., signed) */
> +#define MXSTRNMSZ (21) /* max signed long long is -9223372036854775808\0 */
> +char *strnm(big_t x){static char s[MXSTRNMSZ],*c;register big_t y,z;c=s;for(
> +  z=1,y=x;y/=10;)z*=10;y=x/z;x-=y*z;if(y<0){*c++='-';x*=-1;y*=-1;}*c++='0'+y;
> +  z/=10;while(z){*c++='0'+(y=x/z);x-=y*z;z/=10;}*c='\0';return s;}
> +

Oh my; 'beautifully', indeed. If you want me to incorporate that, you'll
have to clean it up some.

-- 
<Lo-lan-do> Home is where you have to wash the dishes.
  -- #debian-devel, Freenode, 2004-09-22



Reply to: