Hello community,
here is the log from the commit of package nbd
checked in at Fri Nov 9 00:37:08 CET 2007.
--------
--- nbd/nbd.changes 2007-07-30 17:35:31.000000000 +0200
+++ /mounts/work_src_done/STABLE/nbd/nbd.changes 2007-11-07 22:33:37.450963000 +0100
@@ -1,0 +2,12 @@
+Wed Nov 7 22:12:26 CET 2007 - garloff@suse.de
+
+- Split nbd into nbd and nbd-doc packages.
+- Update to 2.9.8:
+ * nbd-server can now setuid to specified user and group
+ * prerun and postrun scripts can be specified
+ * IP address to bind to (listenaddress) can be configured
+ * Socket Direct Protocol (sdp) -- not enabled
+ * server exits now after connection has gone (oops!)
+ * nbd-client: timeout parameter
+
+-------------------------------------------------------------------
Old:
----
nbd-2.9.5.tar.bz2
nbd-server-daemonize-0.diff
New:
----
nbd-2.9.8.tar.bz2
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ nbd.spec ++++++
--- /var/tmp/diff_new_pack.xz1562/_old 2007-11-09 00:36:30.000000000 +0100
+++ /var/tmp/diff_new_pack.xz1562/_new 2007-11-09 00:36:30.000000000 +0100
@@ -1,5 +1,5 @@
#
-# spec file for package nbd (Version 2.9.5)
+# spec file for package nbd (Version 2.9.8)
#
# Copyright (c) 2007 SUSE LINUX Products GmbH, Nuernberg, Germany.
# This file and all modifications and additions to the pristine
@@ -12,21 +12,21 @@
Name: nbd
BuildRequires: doxygen glib2-devel
-PreReq: %insserv_prereq
-Version: 2.9.5
+PreReq: %insserv_prereq coreutils
+Version: 2.9.8
Release: 1
License: GPL v2 or later
Group: Productivity/Networking/Other
-Autoreqprov: on
+AutoReqProv: on
Source: %{name}-%{version}.tar.bz2
Source2: init.nbd-server
-Patch1: nbd-server-daemonize-0.diff
Patch2: nbd-2.9.5-warn.diff
Patch3: nbd-2.9.5-doc.diff
Summary: Network Block Device Server and Client Utilities
-URL: http://nbd.sourceforge.net/
+Url: http://nbd.sourceforge.net/
Prefix: /usr
BuildRoot: %{_tmppath}/%{name}-%{version}-build
+Suggests: nbd-doc
%description
This package contains nbd-server. It is the server backend for the nbd
@@ -55,9 +55,37 @@
Pavel Machek
Paul Clements
+%package doc
+Summary: Network Block Device Server and Client Utilities
+Group: Productivity/Networking/Other
+Requires: nbd = %{version}
+
+%description doc
+This package contains the HTML documentation for the network block
+device (nbd) utilities.
+
+nbd can be used to have a filesystem stored on another machine. It does
+provide a block device, not a file system; so unless you put a
+clustering filesystem on top of it, you can't access it simultaneously
+from more than one client. Use NFS or a real cluster FS (such as
+ocfs2) if you want to do this. nbd-server can export a file (which may
+contain a filesystem image) or a partition. Swapping over nbd is
+possible as well, though it's said not to be safe against OOM and
+should not be used for that case. nbd-server also has a copy-on-write
+mode where changes are saved to a separate file and thrown away when
+the connection closes.
+
+
+
+Authors:
+--------
+ Wouter Verhelst
+ Anton Altaparmakov
+ Pavel Machek
+ Paul Clements
+
%prep
%setup
-%patch1 -p1
%patch2 -p1
%patch3 -p1
touch nbd-client.8
@@ -93,13 +121,16 @@
%{_mandir}/man1/nbd-server.1.gz
%{_mandir}/man8/nbd-client.8.gz
%doc README
-%doc doc/html
#%config(noreplace) /etc/nbd-server.conf
%dir /etc/nbd-server
%ghost %config(noreplace) /etc/nbd-server/config
%ghost %config(noreplace) /etc/nbd-server/allow
/etc/nbd-server/config.example
+%files doc
+%defattr(-,root,root)
+%doc doc/html
+
%post
%{fillup_and_insserv -f nbd-server}
if test -e /etc/nbd-server.conf; then
@@ -124,7 +155,18 @@
%postun
%{insserv_cleanup}
+%preun
+%{stop_on_removal nbd-server}
%changelog
+* Wed Nov 07 2007 - garloff@suse.de
+- Split nbd into nbd and nbd-doc packages.
+- Update to 2.9.8:
+ * nbd-server can now setuid to specified user and group
+ * prerun and postrun scripts can be specified
+ * IP address to bind to (listenaddress) can be configured
+ * Socket Direct Protocol (sdp) -- not enabled
+ * server exits now after connection has gone (oops!)
+ * nbd-client: timeout parameter
* Mon Jul 30 2007 - garloff@suse.de
- Convert options from old nbd-server.conf to new nbd-server/config
on update and drop support for old config file syntax.
++++++ nbd-2.9.5-doc.diff ++++++
--- /var/tmp/diff_new_pack.xz1562/_old 2007-11-09 00:36:30.000000000 +0100
+++ /var/tmp/diff_new_pack.xz1562/_new 2007-11-09 00:36:30.000000000 +0100
@@ -1,7 +1,9 @@
-diff -uNrp nbd-2.9.5.nowarn/README nbd-2.9.5.doc/README
---- nbd-2.9.5.nowarn/README 2007-01-30 14:00:59.000000000 +0100
-+++ nbd-2.9.5.doc/README 2007-07-30 17:08:31.328692000 +0200
-@@ -12,14 +12,16 @@ deadlock issues if you do that[1].
+Index: nbd-2.9.8/README
+===================================================================
+--- nbd-2.9.8.orig/README
++++ nbd-2.9.8/README
+@@ -11,16 +11,18 @@ deadlock issues if you do that[1].
+
To install the package, please see the INSTALL file. You'll need to
install it on both the client and the server.
@@ -21,9 +23,11 @@
+(if you need more than one NBD device, repeat the above command for nbd1,
+nbd2, ...)
- Next, start the server. You can use a file or a block device for that:
+ Since there's a problem with nbd and the (default) cfq I/O scheduler,
+ you may want to set it to deadline:
-@@ -39,7 +41,7 @@ nbd-client <hostname> <port> 0 && (ret=rawexpwrite(a, buf, len, client)) > 0 ) {
- a += ret;
-@@ -907,7 +907,7 @@ ssize_t rawexpread(off_t a, char *buf, s
- * @return 0 on success, nonzero on failure
- **/
- int rawexpread_fully(off_t a, char *buf, size_t len, CLIENT *client) {
-- ssize_t ret;
-+ ssize_t ret = 0;
-
- while(len > 0 && (ret=rawexpread(a, buf, len, client)) > 0 ) {
- a += ret;
-@@ -1266,7 +1266,7 @@ void serveconnection(CLIENT *client) {
void set_peername(int net, CLIENT *client) {
struct sockaddr_in addrin;
struct sockaddr_in netaddr;
@@ -37,12 +12,4 @@
char *peername;
char *netname;
char *tmp;
-@@ -1486,7 +1486,7 @@ int serveloop(GArray* servers) {
- }
- /* child */
- g_hash_table_destroy(children);
-- for(i=0;i<servers->len,serve=(g_array_index(servers, SERVER*, i));i++) {
-+ for(i=0; (i<servers->len && (serve=(g_array_index(servers, SERVER*, i)))); i++) {
- close(serve->socket);
- }
- /* FALSE does not free the
+ int i;
++++++ nbd-2.9.5.tar.bz2 -> nbd-2.9.8.tar.bz2 ++++++
++++ 1724 lines of diff (skipped)
++++ retrying with extended exclude list
diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/nbd-2.9.5/cliserv.h new/nbd-2.9.8/cliserv.h
--- old/nbd-2.9.5/cliserv.h 2007-01-30 14:00:59.000000000 +0100
+++ new/nbd-2.9.8/cliserv.h 2007-10-26 21:45:29.000000000 +0200
@@ -74,6 +74,16 @@
#endif
}
+#ifndef G_GNUC_NORETURN
+#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 4)
+#define G_GNUC_NORETURN __attribute__((__noreturn__))
+#else
+#define G_GNUC_NORETURN
+#endif
+#endif
+
+void err(const char *s) G_GNUC_NORETURN;
+
void err(const char *s) {
const int maxlen = 150;
char s1[maxlen], *s2;
@@ -96,9 +106,8 @@
s1[maxlen-1] = '\0';
#ifdef ISSERVER
syslog(LOG_ERR, "%s", s1);
-#else
- fprintf(stderr, "Error: %s\n", s1);
#endif
+ fprintf(stderr, "Error: %s\n", s1);
exit(1);
}
@@ -124,3 +133,7 @@
}
#endif
#define htonll ntohll
+
+/* Flags used between the client and server */
+#define NBD_FLAG_HAS_FLAGS (1 << 0) /* Flags are there */
+#define NBD_FLAG_READ_ONLY (1 << 1) /* Device is read-only */
diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/nbd-2.9.5/config.h.in new/nbd-2.9.8/config.h.in
--- old/nbd-2.9.5/config.h.in 2007-07-08 12:03:29.000000000 +0200
+++ new/nbd-2.9.8/config.h.in 2007-10-26 22:33:05.000000000 +0200
@@ -157,6 +157,9 @@
/* Version number of package */
#undef VERSION
+/* Define to 1 if you have and want support for the Socket Direct Protocol */
+#undef WITH_SDP
+
/* Define to 1 if your processor stores words with the most significant byte
first (like Motorola and SPARC, unlike Intel and VAX). */
#undef WORDS_BIGENDIAN
diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/nbd-2.9.5/configure.ac new/nbd-2.9.8/configure.ac
--- old/nbd-2.9.5/configure.ac 2007-07-08 12:01:51.000000000 +0200
+++ new/nbd-2.9.8/configure.ac 2007-10-26 22:32:26.000000000 +0200
@@ -1,7 +1,7 @@
dnl Configure script for NBD system
dnl (c) 1998 Martin Mares , (c) 2000 Pavel Machek ,
dnl (c) 2003-2006 Wouter Verhelst
-AC_INIT([nbd],[2.9.5],[wouter@debian.org])
+AC_INIT([nbd],[2.9.8],[wouter@debian.org])
AM_INIT_AUTOMAKE(foreign dist-bzip2)
AM_MAINTAINER_MODE
@@ -59,6 +59,7 @@
],
[DODBG=0]
)
+
AC_MSG_CHECKING([whether a debugging version is requested])
if test $DODBG -eq 1; then
AC_MSG_RESULT([yes])
@@ -71,6 +72,16 @@
AC_MSG_RESULT([no])
fi
+AC_ARG_ENABLE(
+ sdp,
+ AC_HELP_STRING(--enable-sdp,Build a version of nbd-server with support for the Socket Direct Protocol (SDP). Requires you to build and install a kernel with the InfiniBand patches (default disabled)),
+ [
+ if test "x$enableval" = "xyes"; then
+ AC_DEFINE(WITH_SDP, 1, [Define to 1 if you have and want support for the Socket Direct Protocol])
+ fi
+ ]
+)
+
AC_PROG_CC
AC_PROG_CPP
AC_PROG_INSTALL
@@ -98,8 +109,13 @@
#define __be32 int
#define __be64 int
#include "nbd.h"
+#ifdef __GNUC__
+#define UNUSED __attribute__((__unused__))
+#else
+#define UNUSED
+#endif
],
-[int foo=NBD_CMD_DISC],
+[int UNUSED foo=NBD_CMD_DISC],
[AC_DEFINE(NBD_H_LOCAL, 1, Set to 1 if a (2.6) nbd.h can be found in the current directory)
NBD_H='"nbd.h"'],
AC_TRY_COMPILE([#define u32 int
@@ -107,13 +123,23 @@
#define __be32 int
#define __be64 int
#include
+#ifdef __GNUC__
+#define UNUSED __attribute__((__unused__))
+#else
+#define UNUSED
+#endif
],
-[int foo=NBD_CMD_DISC],
+[int UNUSED foo=NBD_CMD_DISC],
[AC_DEFINE(NBD_H_LINUX, 1, Set to 1 if a (2.6) nbd.h can be found in the linux directory in the search path)
NBD_H=''],
AC_TRY_COMPILE([#include
+#ifdef __GNUC__
+#define UNUSED __attribute__((__unused__))
+#else
+#define UNUSED
+#endif
],
- [int foo=NBD_CMD_DISC],
+ [int UNUSED foo=NBD_CMD_DISC],
[AC_DEFINE(NBD_H_LINUX, 1, Set to 1 if a (2.6) nbd.h can be found in the linux directory in the search path)
NBD_H=''],
AC_MSG_ERROR(Could not find an nbd.h from 2.6 or above.)
diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/nbd-2.9.5/nbd-client.8 new/nbd-2.9.8/nbd-client.8
--- old/nbd-2.9.5/nbd-client.8 2007-01-30 14:02:52.000000000 +0100
+++ new/nbd-2.9.8/nbd-client.8 2007-10-22 02:45:47.000000000 +0200
@@ -3,13 +3,13 @@
.\" http://shell.ipoline.com/~elmert/comp/docbook2X/
.\" Please send any bug reports, improvements, comments, patches,
.\" etc. to Steve Cheng .
-.TH "NBD-CLIENT" "8" "30 januari 2007" "" ""
+.TH "NBD-CLIENT" "8" "22 oktober 2007" "" ""
.SH NAME
nbd-client \- connect to a server running nbd-server(1), to use its exported block device
.SH SYNOPSIS
-\fBnbd-client\fR [ \fBbs=\fIblocksize\fB\fR ] \fB\fIhost\fB\fR \fB\fIport\fB\fR \fB\fInbd-device\fB\fR [ \fB-swap\fR ]
+\fBnbd-client\fR [ \fBbs=\fIblocksize\fB\fR ] [ \fBtimeout=\fIseconds\fB\fR ] \fB\fIhost\fB\fR \fB\fIport\fB\fR \fB\fInbd-device\fB\fR [ \fB-sdp\fR ] [ \fB-swap\fR ] [ \fB-persist\fR ]
\fBnbd-client\fR \fB-d \fInbd-device\fB\fR
@@ -46,6 +46,10 @@
The block special file this nbd-client should connect
to.
.TP
+\fB-sdp\fR
+Connect to the server using the Socket Direct Protocol
+(SDP), rather than IP. See nbd-server(1) for details.
+.TP
\fB-swap\fR
Specifies that this NBD device will be used as
swapspace. If you intend to do that, please use this
diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/nbd-2.9.5/nbd-client.8.sgml new/nbd-2.9.8/nbd-client.8.sgml
--- old/nbd-2.9.5/nbd-client.8.sgml 2007-01-30 14:02:48.000000000 +0100
+++ new/nbd-2.9.8/nbd-client.8.sgml 2007-10-17 11:52:51.000000000 +0200
@@ -13,7 +13,7 @@
<!ENTITY dhfirstname "<firstname>Wouter</firstname>">
<!ENTITY dhsurname "<surname>Verhelst</surname>">
<!-- Please adjust the date whenever revising the manpage. -->
- <!ENTITY dhdate "<date>$Date: 2006-10-18 15:01:57 +0200 (wo, 18 okt 2006) $</date>">
+ <!ENTITY dhdate "<date>$Date: 2007-10-17 11:52:50 +0200 (wo, 17 okt 2007) $</date>">
<!-- SECTION should be 1-8, maybe w/ subsection other parameters are
allowed: see man(7), man(1). -->
<!ENTITY dhsection "<manvolnum>8</manvolnum>">
@@ -56,10 +56,13 @@
<cmdsynopsis>
<command>&dhpackage;</command>
<arg><option>bs=<replaceable>blocksize</replaceable></option></arg>
+ <arg><option>timeout=<replaceable>seconds</replaceable></option></arg>
<arg choice=plain><option><replaceable>host</replaceable></option></arg>
<arg choice=plain><option><replaceable>port</replaceable></option></arg>
<arg choice=plain><option><replaceable>nbd-device</replaceable></option></arg>
+ <arg><optoin>-sdp</option></arg>
<arg><option>-swap</option></arg>
+ <arg><option>-persist</option></arg>
</cmdsynopsis>
<cmdsynopsis>
<command>&dhpackage;</command>
@@ -116,6 +119,13 @@
</listitem>
</varlistentry>
<varlistentry>
+ <term><option>-sdp</option></term>
+ <listitem>
+ <para>Connect to the server using the Socket Direct Protocol
+ (SDP), rather than IP. See nbd-server(1) for details.
+ </para>
+ </listitem>
+ <varlistentry>
<term><option>-swap</option></term>
<listitem>
<para>Specifies that this NBD device will be used as
diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/nbd-2.9.5/nbd-client.c new/nbd-2.9.8/nbd-client.c
--- old/nbd-2.9.5/nbd-client.c 2007-06-08 14:21:14.000000000 +0200
+++ new/nbd-2.9.8/nbd-client.c 2007-10-22 02:45:39.000000000 +0200
@@ -27,6 +27,7 @@
#include
#include
#include
+#include
#ifndef __GNUC__
#error I need GCC to work
@@ -36,20 +37,29 @@
#define MY_NAME "nbd_client"
#include "cliserv.h"
-int opennet(char *name, int port) {
+int opennet(char *name, int port, int sdp) {
int sock;
struct sockaddr_in xaddrin;
int xaddrinlen = sizeof(xaddrin);
struct hostent *hostn;
+ int af;
hostn = gethostbyname(name);
if (!hostn)
err("Gethostname failed: %h\n");
- if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
+ af = AF_INET;
+ if(sdp) {
+#ifdef WITH_SDP
+ af = AF_INET_SDP;
+#else
+ err("Can't do SDP: I was not compiled with SDP support!");
+#endif
+ }
+ if ((sock = socket(af, SOCK_STREAM, IPPROTO_TCP)) < 0)
err("Socket failed: %m");
- xaddrin.sin_family = AF_INET;
+ xaddrin.sin_family = af;
xaddrin.sin_port = htons(port);
xaddrin.sin_addr.s_addr = *((int *) hostn->h_addr);
if ((connect(sock, (struct sockaddr *) &xaddrin, xaddrinlen) < 0))
@@ -59,7 +69,7 @@
return sock;
}
-u64 negotiate(int sock, int blocksize) {
+void negotiate(int sock, u64 *rsize64, u32 *flags) {
u64 magic, size64;
char buf[256] = "\0\0\0\0\0\0\0\0\0";
@@ -96,15 +106,20 @@
printf("size = %lu", (unsigned long)(size64));
#endif
- if (read(sock, &buf, 128) < 0)
+ if (read(sock, flags, sizeof(*flags)) < 0)
err("Failed/4: %m\n");
+ *flags = ntohl(*flags);
+
+ if (read(sock, &buf, 124) < 0)
+ err("Failed/5: %m\n");
printf("\n");
- return size64;
+ *rsize64 = size64;
}
-void setsizes(int nbd, u64 size64, int blocksize) {
+void setsizes(int nbd, u64 size64, int blocksize, u32 flags) {
unsigned long size;
+ int read_only = (flags & NBD_FLAG_READ_ONLY) ? 1 : 0;
#ifdef NBD_SET_SIZE_BLOCKS
if (size64/blocksize > (~0UL >> 1))
@@ -129,6 +144,19 @@
#endif
ioctl(nbd, NBD_CLEAR_SOCK);
+
+ if (ioctl(nbd, BLKROSET, (unsigned long) &read_only) < 0)
+ 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, (unsigned long)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) {
@@ -151,14 +179,17 @@
char *hostname, *nbddev;
int swap=0;
int cont=0;
+ int timeout=0;
+ int sdp=0;
u64 size64;
+ u32 flags;
logging();
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 :) */
@@ -196,6 +227,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 */
@@ -205,30 +241,38 @@
++argv; --argc; /* skip port */
if (argc==0) goto errmsg;
- sock = opennet(hostname, port);
nbddev = argv[0];
nbd = open(nbddev, O_RDWR);
if (nbd < 0)
err("Can not open NBD: %m");
++argv; --argc; /* skip device */
- if (argc>2) goto errmsg;
- if (argc!=0) {
+ if (argc>3) goto errmsg;
+ if (argc) {
if(strncmp(argv[0], "-swap", 5)==0) {
swap=1;
++argv;--argc;
}
}
- if (argc!=0) {
+ if (argc) {
if(strncmp(argv[0], "-persist", 8)==0) {
cont=1;
++argv;--argc;
}
}
+ if (argc) {
+ if(strncmp(argv[0], "-sdp", 4)==0) {
+ sdp=1;
+ ++argv;--argc;
+ }
+ }
+ if(argc) goto errmsg;
+ sock = opennet(hostname, port, sdp);
argv=NULL; argc=0; /* don't use it later suddenly */
- size64 = negotiate(sock, blocksize);
- setsizes(nbd, size64, blocksize);
+ negotiate(sock, &size64, &flags);
+ setsizes(nbd, size64, blocksize, flags);
+ set_timeout(nbd, timeout);
finish_sock(sock, nbd, swap);
/* Go daemon */
@@ -248,14 +292,21 @@
cont=0;
} else {
if(cont) {
+ u64 new_size;
+ u32 new_flags;
+
fprintf(stderr, " Reconnecting\n");
close(sock); close(nbd);
- sock = opennet(hostname, port);
+ sock = opennet(hostname, port, sdp);
nbd = open(nbddev, O_RDWR);
- if(size64!=negotiate(sock,blocksize)) {
+ negotiate(sock, &new_size, &new_flags);
+ if (size64 != new_size) {
err("Size of the device changed. Bye");
}
- setsizes(nbd, size64, blocksize);
+ setsizes(nbd, size64, blocksize,
+ new_flags);
+
+ set_timeout(nbd, timeout);
finish_sock(sock,nbd,swap);
}
}
diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/nbd-2.9.5/nbd-server.1.in new/nbd-2.9.8/nbd-server.1.in
--- old/nbd-2.9.5/nbd-server.1.in 2007-06-15 11:28:13.000000000 +0200
+++ new/nbd-2.9.8/nbd-server.1.in 2007-10-26 20:02:00.000000000 +0200
@@ -3,13 +3,13 @@
.\" http://shell.ipoline.com/~elmert/comp/docbook2X/
.\" Please send any bug reports, improvements, comments, patches,
.\" etc. to Steve Cheng .
-.TH "NBD-SERVER" "1" "15 juni 2007" "" ""
+.TH "NBD-SERVER" "1" "26 oktober 2007" "" ""
.SH NAME
nbd-server \- serve a file as a block device to other computers running the GNU/Linux(tm) or GNU/Hurd Operating System
.SH SYNOPSIS
-\fBnbd-server \fR \fB\fIport\fB\fR \fB\fIfilename\fB\fR [ \fB\fIsize\fB\fR ] [ \fB-r\fR ] [ \fB-m\fR ] [ \fB-c\fR ] [ \fB-a \fItimeout\fB\fR ] [ \fB-l \fIhost list\fB\fR ] [ \fB-o \fIsection name\fB\fR ]
+\fBnbd-server \fR \fB\fI[ip:]port\fB\fR \fB\fIfilename\fB\fR [ \fB\fIsize\fB\fR ] [ \fB-r\fR ] [ \fB-m\fR ] [ \fB-c\fR ] [ \fB-a \fItimeout\fB\fR ] [ \fB-l \fIhost list\fB\fR ] [ \fB-o \fIsection name\fB\fR ]
.SH "DESCRIPTION"
.PP
@@ -30,6 +30,10 @@
If the file is empty, no clients can connect.
.SH "OPTIONS"
.TP
+\fBip\fR
+The ip address the server should listen on. If
+omitted, 0.0.0.0 (aka "any address") is used.
+.TP
\fBport \fR
The port the server should listen to. A valid port is
any number between 1 and 65536; if 0 is used, nbd-server
diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/nbd-2.9.5/nbd-server.1.sgml new/nbd-2.9.8/nbd-server.1.sgml
--- old/nbd-2.9.5/nbd-server.1.sgml 2007-06-13 13:07:24.000000000 +0200
+++ new/nbd-2.9.8/nbd-server.1.sgml 2007-10-26 20:01:54.000000000 +0200
@@ -13,7 +13,7 @@
<!ENTITY dhfirstname "<firstname>Wouter</firstname>">
<!ENTITY dhsurname "<surname>Verhelst</surname>">
<!-- Please adjust the date whenever revising the manpage. -->
- <!ENTITY dhdate "<date>$Date: 2007-06-13 12:07:26 +0100 (wo, 13 jun 2007) $</date>">
+ <!ENTITY dhdate "<date>$Date: 2007-10-26 20:01:51 +0200 (vr, 26 okt 2007) $</date>">
<!-- SECTION should be 1-8, maybe w/ subsection other parameters are
allowed: see man(7), man(1). -->
<!ENTITY dhsection "<manvolnum>1</manvolnum>">
@@ -57,7 +57,7 @@
<cmdsynopsis>
<command>&dhpackage; </command>
- <arg choice=plain><replaceable>porthttp://shell.ipoline.com/~elmert/comp/docbook2X/
.\" Please send any bug reports, improvements, comments, patches,
.\" etc. to Steve Cheng .
-.TH "NBD-SERVER" "5" "30 januari 2007" "" ""
+.TH "NBD-SERVER" "5" "26 oktober 2007" "" ""
.SH NAME
/etc/nbd-server/config \- configuration file for nbd-server
@@ -16,10 +16,10 @@
\fB/etc/nbd-server/config\fR allows to configure the
nbd-server.
.PP
-The default configuration file is
-\fI@sysconfdir@/nbd-server/config\fR, but this
-can be varied with the \fB-C\fR option to
-\fBnbd-server\fR(1).
+While
+\fI@sysconfdir@/nbd-server/config\fR is the default
+configuration file, this can be varied with the \fB-C\fR
+option to \fBnbd-server\fR(1).
.PP
The configuration file consists of section header lines, comment
lines, and option lines.
@@ -153,6 +153,15 @@
When specified on the command line, this should be the
third argument.
.TP
+\fBlistenaddr\fR
+Optional; string
+
+If this option is set, it should contain the local IP
+address (in "dotted-quad" notation) on which we should
+listen to \fBnbd-client\fR(8) connections. If
+it is not set, 0.0.0.0 is used (i.e., "listen on all local
+IP addresses")
+.TP
\fBmultifile\fR
Optional; boolean.
@@ -200,6 +209,24 @@
Corresponds to the \fB-r\fR option on the
command line.
.TP
+\fBsdp\fR
+.PP
+Optional; boolean.
+.PP
+When this option is enabled, \fBnbd-server\fR
+will use the Socket Direct Protocol (SDP) to serve the
+export, rather than just IP. This is faster, but requires
+special hardware (usually something like InfiniBand) and
+support in the kernel.
+.PP
+Additionally, support for this option must be enabled at
+compile time, using the \fB--enable-sdp\fR option
+to the \fBconfigure\fR script. If this option
+is found in a configuration file and
+\fBnbd-server\fR does not have support for SDP,
+then \fBnbd-server\fR will exit with an error
+message.
+.TP
\fBsparse_cow\fR
Optional; boolean.
@@ -207,7 +234,8 @@
will use sparse files to implement the copy-on-write
option; such files take up less space then they appear to,
which allows \fBnbd-server\fR to handle the
-file as if it was just as large as the block device it's for.
+file as if it was just as large as the block device it's
+for.
If this option is disabled, \fBnbd-server\fR
will map every newly written block to the end of the
@@ -272,15 +300,50 @@
after it. \fBnbd-server\fR will use the
number as a network mask in CIDR style, and use that
as a hash cutoff point. In the above example, if
-\fBvirtstyle\fR has been specified
-as cidrhash 16, then
+\fBvirtstyle\fR has been specified as
+cidrhash 16, then
\fBnbd-server\fR will try to open
-\fI/export/192.168.0.0/192.168.1.100\fR; if
-\fBvirtstyle\fR were specified as
+\fI/export/192.168.0.0/192.168.1.100\fR;
+if \fBvirtstyle\fR were specified as
cidrhash 26, then
\fBnbd-server\fR will try to open
\fI/export/192.168.1.64/192.168.1.100\fR\&.
.RE
+.TP
+\fBprerun\fR
+Optional; string
+
+If specified, then this command will be ran after a
+client has connected to the server (and has been
+accepted), but before the server starts serving. If
+the command contains the literal string '%s', then
+this string will be replaced by the filename of the
+file which nbd-server wants to export.
+
+This is useful to create export files on the fly, or
+to verify that a file can be used for export, to
+write something to a log file, or similar.
+
+If the command runs with a non-zero exit status,
+then nbd-server will assume the export will fail,
+and refuse to serve it.
+.TP
+\fBpostrun\fR
+Optional; string
+
+If specified, then it is assumed to be a command
+that will be ran when a client has
+disconnected. This can be useful to clean up
+whatever \fBprerun\fR has set up, to log
+something, or similar.
+
+If the literal string '%s' is present in the
+command, it will be replaced by the file name that
+has just been closed.
+
+In contrast to the \fBprerun\fR option,
+the exit state of \fBpostrun\fR is
+\fBignored\fR\&.
.SH "SEE ALSO"
.PP
nbd-server (1), nbd-client (8),
diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/nbd-2.9.5/nbd-server.5.sgml new/nbd-2.9.8/nbd-server.5.sgml
--- old/nbd-2.9.5/nbd-server.5.sgml 2007-01-30 14:02:48.000000000 +0100
+++ new/nbd-2.9.8/nbd-server.5.sgml 2007-10-26 19:53:42.000000000 +0200
@@ -63,10 +63,10 @@
<para><command>&dhpackage;</command> allows to configure the
nbd-server.</para>
- <para>The default configuration file is
- <filename>@sysconfdir@/nbd-server/config</filename>, but this
- can be varied with the <option>-C</option> option to
- <command>nbd-server</command>(1).
+ <para>While
+ <filename>@sysconfdir@/nbd-server/config</filename> is the default
+ configuration file, this can be varied with the <option>-C</option>
+ option to <command>nbd-server</command>(1).
</para>
<para>
The configuration file consists of section header lines, comment
@@ -250,6 +250,17 @@
</listitem>
</varlistentry>
<varlistentry>
+ <term>listenaddr</term>
+ <listitem>
+ <para>Optional; string</para>
+ <para>If this option is set, it should contain the local IP
+ address (in "dotted-quad" notation) on which we should
+ listen to <command>nbd-client</command>(8) connections. If
+ it is not set, 0.0.0.0 is used (i.e., "listen on all local
+ IP addresses")</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
<term><option>multifile</option></term>
<listitem>
<para>Optional; boolean.</para>
@@ -312,6 +323,27 @@
</listitem>
</varlistentry>
<varlistentry>
+ <term><option>sdp</option></term>
+ <lisitem>
+ <para>Optional; boolean.</para>
+ <para>
+ When this option is enabled, <command>nbd-server</command>
+ will use the Socket Direct Protocol (SDP) to serve the
+ export, rather than just IP. This is faster, but requires
+ special hardware (usually something like InfiniBand) and
+ support in the kernel.
+ </para>
+ <para>
+ Additionally, support for this option must be enabled at
+ compile time, using the <option>--enable-sdp</option> option
+ to the <command>configure</command> script. If this option
+ is found in a configuration file and
+ <command>nbd-server</command> does not have support for SDP,
+ then <command>nbd-server</command> will exit with an error
+ message.
+ </para>
+ /* For BLKGETSIZE */
#endif
#include /* sigaction */
+#include
#include
#include /* sockaddr_in, htons, in_addr */
#include /* hostent, gethostby*, getservby* */
@@ -138,7 +139,7 @@
**/
#define OFFT_MAX ~((off_t)1<<(sizeof(off_t)*8-1))
#define LINELEN 256 /**< Size of static buffer used to read the
- authorization file (yuck) */
+ authorization file (yuck) */
#define BUFSIZE (1024*1024) /**< Size of buffer that can hold requests */
#define DIFFPAGESIZE 4096 /**< diff file uses those chunks */
#define F_READONLY 1 /**< flag to tell us a file is readonly */
@@ -146,7 +147,8 @@
#define F_COPYONWRITE 4 /**< flag to tell us a file is exported using
copyonwrite */
#define F_AUTOREADONLY 8 /**< flag to tell us a file is set to autoreadonly */
-#define F_SPARSE 16
+#define F_SPARSE 16 /**< flag to tell us copyronwrite should use a sparse file */
+#define F_SDP 32 /**< flag to tell us the export should be done using the Socket Direct Protocol for RDMA */
GHashTable *children;
char pidfname[256]; /**< name of our PID file */
char pidftemplate[256]; /**< template to be used for the filename of the PID file */
@@ -170,6 +172,7 @@
gchar* exportname; /**< (unprocessed) filename of the file we're exporting */
off_t expected_size; /**< size of the exported file as it was told to
us through configuration */
+ gchar* listenaddr; /**< The IP address we're listening on */
unsigned int port; /**< port we're exporting this file at */
char* authname; /**< filename of the authorization file */
int flags; /**< flags associated with this exported file */
@@ -179,6 +182,10 @@
VIRT_STYLE virtstyle;/**< The style of virtualization, if any */
uint8_t cidrlen; /**< The length of the mask when we use
CIDR-style virtualization */
+ gchar* prerun; /**< command to be ran after connecting a client,
+ but before starting to serve */
+ gchar* postrun; /**< command that will be ran after the client
+ disconnects */
} SERVER;
/**
@@ -328,7 +335,7 @@
*/
void usage() {
printf("This is nbd-server version " VERSION "\n");
- printf("Usage: port file_to_export [size][kKmM] [-l authorize_file] [-r] [-m] [-c] [-a timeout_sec] [-C configuration file] [-p PID file name] [-o section name]\n"
+ printf("Usage: [ip:]port file_to_export [size][kKmM] [-l authorize_file] [-r] [-m] [-c] [-a timeout_sec] [-C configuration file] [-p PID file name] [-o section name]\n"
"\t-r|--read-only\t\tread only\n"
"\t-m|--multi-file\t\tmultiple file\n"
"\t-c|--copy-on-write\tcopy on write\n"
@@ -339,7 +346,8 @@
"\t-o|--output-config\toutput a config file section for what you\n\t\t\t\tspecified on the command line, with the\n\t\t\t\tspecified section name\n\n"
"\tif port is set to 0, stdin is used (for running from inetd)\n"
"\tif file_to_export contains '%%s', it is substituted with the IP\n"
- "\t\taddress of the machine trying to connect\n" );
+ "\t\taddress of the machine trying to connect\n"
+ "\tif ip is set, it contains the local IP address on which we're listening.\n\tif not, the server will listen on all local IP addresses\n");
printf("Using configuration file %s\n", CFILE);
}
@@ -347,6 +355,7 @@
void dump_section(SERVER* serve, gchar* section_header) {
printf("[%s]\n", section_header);
printf("\texportname = %s\n", serve->exportname);
+ printf("\tlistenaddr = %s\n", serve->listenaddr);
printf("\tport = %d\n", serve->port);
if(serve->flags & F_READONLY) {
printf("\treadonly = true\n");
@@ -395,20 +404,30 @@
size_t last;
char suffix;
gboolean do_output=FALSE;
- gchar* section_header;
+ gchar* section_header="";
+ gchar** addr_port;
if(argc==1) {
return NULL;
}
serve=g_new0(SERVER, 1);
serve->authname = g_strdup(default_authname);
+ serve->virtstyle=VIRT_IPLIT;
while((c=getopt_long(argc, argv, "-a:C:cl:mo:rp:", long_options, &i))>=0) {
switch (c) {
case 1:
/* non-option argument */
switch(nonspecial++) {
case 0:
- serve->port=strtol(optarg, NULL, 0);
+ addr_port=g_strsplit(optarg, ":", 2);
+ if(addr_port[1]) {
+ serve->port=strtol(addr_port[1], NULL, 0);
+ serve->listenaddr=g_strdup(addr_port[0]);
+ } else {
+ serve->listenaddr=g_strdup("0.0.0.0");
+ serve->port=strtol(addr_port[0], NULL, 0);
+ }
+ g_strfreev(addr_port);
break;
case 1:
serve->exportname = g_strdup(optarg);
@@ -492,6 +511,7 @@
CFILE_MISSING_GENERIC, /**< The (required) group "generic" is missing */
CFILE_KEY_MISSING, /**< A (required) key is missing */
CFILE_VALUE_INVALID, /**< A value is syntactically invalid */
+ CFILE_VALUE_UNSUPPORTED,/**< A value is not supported in this build */
CFILE_PROGERR /**< Programmer error */
} CFILE_ERRORS;
@@ -530,13 +550,17 @@
{ "timeout", FALSE, PARAM_INT, NULL, 0 },
{ "filesize", FALSE, PARAM_INT, NULL, 0 },
{ "virtstyle", FALSE, PARAM_STRING, NULL, 0 },
+ { "prerun", FALSE, PARAM_STRING, NULL, 0 },
+ { "postrun", FALSE, PARAM_STRING, NULL, 0 },
{ "readonly", FALSE, PARAM_BOOL, NULL, F_READONLY },
{ "multifile", FALSE, PARAM_BOOL, NULL, F_MULTIFILE },
{ "copyonwrite", FALSE, PARAM_BOOL, NULL, F_COPYONWRITE },
{ "autoreadonly", FALSE, PARAM_BOOL, NULL, F_AUTOREADONLY },
{ "sparse_cow", FALSE, PARAM_BOOL, NULL, F_SPARSE },
+ { "sdp", FALSE, PARAM_BOOL, NULL, F_SDP },
+ { "listenaddr", FALSE, PARAM_STRING, NULL, 0 },
};
- const int lp_size=11;
+ const int lp_size=15;
PARAM gp[] = {
{ "user", FALSE, PARAM_STRING, &runuser, 0 },
{ "group", FALSE, PARAM_STRING, &rungroup, 0 },
@@ -576,8 +600,13 @@
lp[3].target=&(s.timeout);
lp[4].target=&(s.expected_size);
lp[5].target=&(virtstyle);
- lp[6].target=lp[7].target=lp[8].target=
- lp[9].target=lp[10].target=&(s.flags);
+ lp[6].target=&(s.prerun);
+ lp[7].target=&(s.postrun);
+ lp[8].target=lp[9].target=lp[10].target=
+ lp[11].target=lp[12].target=
+ lp[13].target=&(s.flags);
+ lp[14].target=&(s.listenaddr);
+
/* After the [generic] group, start parsing exports */
if(i==1) {
p=lp;
@@ -662,8 +691,19 @@
virtstyle=NULL;
/* Don't append values for the [generic] group */
if(i>0) {
+ if(!s.listenaddr) {
+ s.listenaddr = g_strdup("0.0.0.0");
+ }
g_array_append_val(retval, s);
}
+#ifndef WITH_SDP
+ if(s.flags & F_SDP) {
+ g_set_error(e, errdomain, CFILE_VALUE_UNSUPPORTED, "This nbd-server was built without support for SDP, yet group %s uses it", groups[i]);
+ g_array_free(retval, TRUE);
+ g_key_file_free(cfile);
+ return NULL;
+ }
+#endif
}
return retval;
}
@@ -865,7 +905,7 @@
* @return 0 on success, nonzero on failure
**/
int rawexpwrite_fully(off_t a, char *buf, size_t len, CLIENT *client) {
- ssize_t ret;
+ ssize_t ret=0;
while(len > 0 && (ret=rawexpwrite(a, buf, len, client)) > 0 ) {
a += ret;
@@ -907,7 +947,7 @@
* @return 0 on success, nonzero on failure
**/
int rawexpread_fully(off_t a, char *buf, size_t len, CLIENT *client) {
- ssize_t ret;
+ ssize_t ret=0;
while(len > 0 && (ret=rawexpread(a, buf, len, client)) > 0 ) {
a += ret;
@@ -1018,10 +1058,11 @@
* @param client The client we're negotiating with.
**/
void negotiate(CLIENT *client) {
- char zeros[300];
+ char zeros[128];
u64 size_host;
+ u32 flags = NBD_FLAG_HAS_FLAGS;
- memset(zeros, '\0', 290);
+ memset(zeros, '\0', sizeof(zeros));
if (write(client->net, INIT_PASSWD, 8) < 0)
err("Negotiation failed: %m");
cliserv_magic = htonll(cliserv_magic);
@@ -1030,14 +1071,19 @@
size_host = htonll((u64)(client->exportsize));
if (write(client->net, &size_host, 8) < 0)
err("Negotiation failed: %m");
- if (write(client->net, zeros, 128) < 0)
+ if (client->server->flags & F_READONLY)
+ flags |= NBD_FLAG_READ_ONLY;
+ flags = htonl(flags);
+ if (write(client->net, &flags, 4) < 0)
+ err("Negotiation failed: %m");
+ if (write(client->net, zeros, 124) < 0)
err("Negotiation failed: %m");
}
/** sending macro. */
#define SEND(net,reply) writeit( net, &reply, sizeof( reply ));
/** error macro. */
-#define ERROR(client,reply) { reply.error = htonl(-1); SEND(client->net,reply); reply.error = 0; }
+#define ERROR(client,reply,errcode) { reply.error = htonl(errcode); SEND(client->net,reply); reply.error = 0; }
/**
* Serve a file to a single client.
*
@@ -1045,7 +1091,7 @@
* pieces. Preferably with a chainsaw.
*
* @param client The client we're going to serve to.
- * @return never
+ * @return when the client disconnects
**/
int mainloop(CLIENT *client) {
struct nbd_request request;
@@ -1097,13 +1143,13 @@
memcpy(reply.handle, request.handle, sizeof(reply.handle));
if ((request.from + len) > (OFFT_MAX)) {
DEBUG("[Number too large!]");
- ERROR(client, reply);
+ ERROR(client, reply, EINVAL);
continue;
}
if (((ssize_t)((off_t)request.from + len) > client->exportsize)) {
DEBUG("[RANGE!]");
- ERROR(client, reply);
+ ERROR(client, reply, EINVAL);
continue;
}
@@ -1114,12 +1160,12 @@
if ((client->server->flags & F_READONLY) ||
(client->server->flags & F_AUTOREADONLY)) {
DEBUG("[WRITE to READONLY!]");
- ERROR(client, reply);
+ ERROR(client, reply, EPERM);
continue;
}
if (expwrite(request.from, buf, len, client)) {
DEBUG("Write failed: %m" );
- ERROR(client, reply);
+ ERROR(client, reply, errno);
continue;
}
SEND(client->net, reply);
@@ -1131,7 +1177,7 @@
DEBUG("exp->buf, ");
if (expread(request.from, buf + sizeof(struct nbd_reply), len, client)) {
DEBUG("Read failed: %m");
- ERROR(client, reply);
+ ERROR(client, reply, errno);
continue;
}
@@ -1233,6 +1279,25 @@
}
/**
+ * Run a command. This is used for the ``prerun'' and ``postrun'' config file
+ * options
+ *
+ * @param command the command to be ran. Read from the config file
+ * @param file the file name we're about to export
+ **/
+int do_run(gchar* command, gchar* file) {
+ gchar* cmd;
+ int retval=0;
+
+ if(command && *command) {
+ cmd = g_strdup_printf(command, file);
+ retval=system(cmd);
+ g_free(cmd);
+ }
+ return retval;
+}
+
+/**
* Serve a connection.
*
* @todo allow for multithreading, perhaps use libevent. Not just yet, though;
@@ -1241,6 +1306,9 @@
* @param client a connected client
**/
void serveconnection(CLIENT *client) {
+ if(do_run(client->server->prerun, client->exportname)) {
+ exit(EXIT_FAILURE);
+ }
setupexport(client);
if (client->server->flags & F_COPYONWRITE) {
@@ -1250,6 +1318,7 @@
setmysockopt(client->net);
mainloop(client);
+ do_run(client->server->postrun, client->exportname);
}
/**
@@ -1313,112 +1382,7 @@
}
/**
- * Go daemon (unless we specified at compile time that we didn't want this)
- * @param serve the first server of our configuration. If its port is zero,
- * then do not daemonize, because we're doing inetd then. This parameter
- * is only used to create a PID file of the form
- * /var/run/nbd-server.<port>.pid; it's not modified in any way.
- **/
-#if !defined(NODAEMON) && !defined(NOFORK)
-void daemonize(SERVER* serve) {
- FILE*pidf;
-
- if(!(serve->port)) {
- return;
- }
- if(daemon(0,0)<0) {
- err("daemon");
- }
- if(!*pidftemplate) {
- if(serve) {
- strncpy(pidftemplate, "/var/run/server.%d.pid", 255);
- } else {
- strncpy(pidftemplate, "/var/run/server.pid", 255);
- }
- }
- snprintf(pidfname, 255, pidftemplate, serve ? serve->port : 0);
- pidf=fopen(pidfname, "w");
- if(pidf) {
- fprintf(pidf,"%d\n", (int)getpid());
- fclose(pidf);
- } else {
- perror("fopen");
- fprintf(stderr, "Not fatal; continuing");
- }
-}
-#else
-#define daemonize(serve)
-#endif /* !defined(NODAEMON) && !defined(NOFORK) */
-
-/**
- * Connect a server's socket.
- *
- * @param serve the server we want to connect.
- **/
-void setup_serve(SERVER *serve) {
- struct sockaddr_in addrin;
- struct sigaction sa;
- int addrinlen = sizeof(addrin);
- int sock_flags;
-#ifndef sun
- int yes=1;
-#else
- char yes='1';
-#endif /* sun */
- if ((serve->socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
- err("socket: %m");
-
- /* lose the pesky "Address already in use" error message */
- if (setsockopt(serve->socket,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(int)) == -1) {
- err("setsockopt SO_REUSEADDR");
- }
- if (setsockopt(serve->socket,SOL_SOCKET,SO_KEEPALIVE,&yes,sizeof(int)) == -1) {
- err("setsockopt SO_KEEPALIVE");
- }
-
- /* make the listening socket non-blocking */
- if ((sock_flags = fcntl(serve->socket, F_GETFL, 0)) == -1) {
- err("fcntl F_GETFL");
- }
- if (fcntl(serve->socket, F_SETFL, sock_flags | O_NONBLOCK) == -1) {
- err("fcntl F_SETFL O_NONBLOCK");
- }
-
- DEBUG("Waiting for connections... bind, ");
- addrin.sin_family = AF_INET;
- addrin.sin_port = htons(serve->port);
- addrin.sin_addr.s_addr = 0;
- if (bind(serve->socket, (struct sockaddr *) &addrin, addrinlen) < 0)
- err("bind: %m");
- DEBUG("listen, ");
- if (listen(serve->socket, 1) < 0)
- err("listen: %m");
- sa.sa_handler = sigchld_handler;
- sigemptyset(&sa.sa_mask);
- sa.sa_flags = SA_RESTART;
- if(sigaction(SIGCHLD, &sa, NULL) == -1)
- err("sigaction: %m");
- sa.sa_handler = sigterm_handler;
- sigemptyset(&sa.sa_mask);
- sa.sa_flags = SA_RESTART;
- if(sigaction(SIGTERM, &sa, NULL) == -1)
- err("sigaction: %m");
-}
-
-/**
- * Connect our servers.
- **/
-void setup_servers(GArray* servers) {
- int i;
-
- for(i=0;i<servers->len;i++) {
- setup_serve(&(g_array_index(servers, SERVER, i)));
- }
- children=g_hash_table_new_full(g_int_hash, g_int_equal, NULL, destroy_pid_t);
-}
-
-/**
- * Loop through the available servers, and serve them.
+ * Loop through the available servers, and serve them. Never returns.
**/
int serveloop(GArray* servers) {
struct sockaddr_in addrin;
@@ -1486,7 +1450,8 @@
}
/* child */
g_hash_table_destroy(children);
- for(i=0;i<servers->len,serve=(g_array_index(servers, SERVER*, i));i++) {
+ for(i=0;i<servers->len;i++) {
+ serve=g_array_index(servers, SERVER*, i);
close(serve->socket);
}
/* FALSE does not free the
@@ -1499,6 +1464,7 @@
#endif // NOFORK
msg2(LOG_INFO,"Starting to serve");
serveconnection(client);
+ exit(EXIT_SUCCESS);
}
}
}
@@ -1506,20 +1472,164 @@
}
/**
+ * Connect a server's socket.
+ *
+ * @param serve the server we want to connect.
+ **/
+void setup_serve(SERVER *serve) {
+ struct sockaddr_in addrin;
+ struct sigaction sa;
+ int addrinlen = sizeof(addrin);
+ int sock_flags;
+ int af;
+#ifndef sun
+ int yes=1;
+#else
+ char yes='1';
+#endif /* sun */
+
+ af = AF_INET;
+#ifdef WITH_SDP
+ if ((serve->flags) && F_SDP) {
+ af = AF_INET_SDP;
+ }
+#endif
+ if ((serve->socket = socket(af, SOCK_STREAM, IPPROTO_TCP)) < 0)
+ err("socket: %m");
+
+ /* lose the pesky "Address already in use" error message */
+ if (setsockopt(serve->socket,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(int)) == -1) {
+ err("setsockopt SO_REUSEADDR");
+ }
+ if (setsockopt(serve->socket,SOL_SOCKET,SO_KEEPALIVE,&yes,sizeof(int)) == -1) {
+ err("setsockopt SO_KEEPALIVE");
+ }
+
+ /* make the listening socket non-blocking */
+ if ((sock_flags = fcntl(serve->socket, F_GETFL, 0)) == -1) {
+ err("fcntl F_GETFL");
+ }
+ if (fcntl(serve->socket, F_SETFL, sock_flags | O_NONBLOCK) == -1) {
+ err("fcntl F_SETFL O_NONBLOCK");
+ }
+
+ DEBUG("Waiting for connections... bind, ");
+ addrin.sin_family = AF_INET;
+#ifdef WITH_SDP
+ if(serve->flags & F_SDP) {
+ addrin.sin_family = AF_INET_SDP;
+ }
+#endif
+ addrin.sin_port = htons(serve->port);
+ if(!inet_aton(serve->listenaddr, &(addrin.sin_addr)))
+ err("could not parse listen address");
+ if (bind(serve->socket, (struct sockaddr *) &addrin, addrinlen) < 0)
+ err("bind: %m");
+ DEBUG("listen, ");
+ if (listen(serve->socket, 1) < 0)
+ err("listen: %m");
+ sa.sa_handler = sigchld_handler;
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = SA_RESTART;
+ if(sigaction(SIGCHLD, &sa, NULL) == -1)
+ err("sigaction: %m");
+ sa.sa_handler = sigterm_handler;
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = SA_RESTART;
+ if(sigaction(SIGTERM, &sa, NULL) == -1)
+ err("sigaction: %m");
+}
+
+/**
+ * Connect our servers.
+ **/
+void setup_servers(GArray* servers) {
+ int i;
+
+ for(i=0;i<servers->len;i++) {
+ setup_serve(&(g_array_index(servers, SERVER, i)));
+ }
+ children=g_hash_table_new_full(g_int_hash, g_int_equal, NULL, destroy_pid_t);
+}
+
+/**
+ * Go daemon (unless we specified at compile time that we didn't want this)
+ * @param serve the first server of our configuration. If its port is zero,
+ * then do not daemonize, because we're doing inetd then. This parameter
+ * is only used to create a PID file of the form
+ * /var/run/nbd-server.<port>.pid; it's not modified in any way.
+ **/
+#if !defined(NODAEMON) && !defined(NOFORK)
+void daemonize(SERVER* serve) {
+ FILE*pidf;
+
+ if(serve && !(serve->port)) {
+ return;
+ }
+ if(daemon(0,0)<0) {
+ err("daemon");
+ }
+ if(!*pidftemplate) {
+ if(serve) {
+ strncpy(pidftemplate, "/var/run/server.%d.pid", 255);
+ } else {
+ strncpy(pidftemplate, "/var/run/server.pid", 255);
+ }
+ }
+ snprintf(pidfname, 255, pidftemplate, serve ? serve->port : 0);
+ pidf=fopen(pidfname, "w");
+ if(pidf) {
+ fprintf(pidf,"%d\n", (int)getpid());
+ fclose(pidf);
+ } else {
+ perror("fopen");
+ fprintf(stderr, "Not fatal; continuing");
+ }
+}
+#else
+#define daemonize(serve)
+#endif /* !defined(NODAEMON) && !defined(NOFORK) */
+
+/*
+ * Everything beyond this point (in the file) is run in non-daemon mode.
+ * The stuff above daemonize() isn't.
+ */
+
+void serve_err(SERVER* serve, const char* msg) G_GNUC_NORETURN;
+
+void serve_err(SERVER* serve, const char* msg) {
+ g_message("Export of %s on port %d failed:", serve->exportname,
+ serve->port);
+ err(msg);
+}
+
+/**
* Set up user-ID and/or group-ID
**/
void dousers(void) {
struct passwd *pw;
struct group *gr;
- if(runuser) {
- pw=getpwnam(runuser);
- if(setuid(pw->pw_uid)<0)
- msg3(LOG_DEBUG, "Could not set UID: %s", strerror(errno));
- }
if(rungroup) {
gr=getgrnam(rungroup);
- if(setgid(gr->gr_gid)<0)
- msg3(LOG_DEBUG, "Could not set GID: %s", strerror(errno));
+ if(!gr) {
+ g_message("Invalid group name: %s", rungroup);
+ exit(EXIT_FAILURE);
+ }
+ if(setgid(gr->gr_gid)<0) {
+ g_message("Could not set GID: %s", strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+ }
+ if(runuser) {
+ pw=getpwnam(runuser);
+ if(!pw) {
+ g_message("Invalid user name: %s", runuser);
+ exit(EXIT_FAILURE);
+ }
+ if(setuid(pw->pw_uid)<0) {
+ g_message("Could not set UID: %s", strerror(errno));
+ exit(EXIT_FAILURE);
+ }
}
}
@@ -1543,7 +1653,8 @@
serve=cmdline(argc, argv);
servers = parse_cfile(config_file_pos, &err);
if(!servers || !servers->len) {
- g_warning("Could not parse config file: %s", err->message);
+ g_warning("Could not parse config file: %s",
+ err ? err->message : "Unknown error");
}
if(serve) {
g_array_append_val(servers, *serve);
diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/nbd-2.9.5/nbd-tester-client.c new/nbd-2.9.8/nbd-tester-client.c
--- old/nbd-2.9.5/nbd-tester-client.c 2007-01-30 14:00:59.000000000 +0100
+++ new/nbd-2.9.8/nbd-tester-client.c 2007-10-26 22:31:34.000000000 +0200
@@ -178,12 +178,12 @@
rep.magic=ntohl(rep.magic);
rep.error=ntohl(rep.error);
if(rep.magic!=NBD_REPLY_MAGIC) {
- snprintf(errstr, errstr_len, "Received package with incorrect reply_magic. Index of sent packages is %lld (0x%llX), received handle is %lld (0x%llX). Received magic 0x%lX, expected 0x%lX", curhandle, curhandle, *((u64*)rep.handle), *((u64*)rep.handle), rep.magic, NBD_REPLY_MAGIC);
+ snprintf(errstr, errstr_len, "Received package with incorrect reply_magic. Index of sent packages is %lld (0x%llX), received handle is %lld (0x%llX). Received magic 0x%lX, expected 0x%lX", curhandle, curhandle, *((u64*)rep.handle), *((u64*)rep.handle), (long unsigned int)rep.magic, (long unsigned int)NBD_REPLY_MAGIC);
retval=-1;
goto end;
}
if(rep.error) {
- snprintf(errstr, errstr_len, "Received error from server: %ld (0x%lX). Handle is %lld (0x%llX).", rep.error, *((u64*)rep.handle), *((u64*)rep.handle));
+ snprintf(errstr, errstr_len, "Received error from server: %ld (0x%lX). Handle is %lld (0x%llX).", (long int)rep.error, (long unsigned int)rep.error, (long long int)(*((u64*)rep.handle)), *((u64*)rep.handle));
retval=-1;
goto end;
}
@@ -326,7 +326,7 @@
gchar *hostname;
long int p;
int port;
- int sock;
+ int sock=0;
if(argc<3) {
g_message("Not enough arguments");
diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/nbd-2.9.5/README new/nbd-2.9.8/README
--- old/nbd-2.9.5/README 2007-01-30 14:00:59.000000000 +0100
+++ new/nbd-2.9.8/README 2007-10-23 12:54:01.000000000 +0200
@@ -21,6 +21,14 @@
(if you need more than one NBD device, repeat the above command for nb1,
nb2, ...)
+Since there's a problem with nbd and the (default) cfq I/O scheduler,
+you may want to set it to deadline:
+
+echo 'deadline' > /sys/block/nbd0/queue/scheduler
+
+(again, repeat the above for nbd1, nbd2, etc, if you need more than one
+device)
+
Next, start the server. You can use a file or a block device for that:
nbd-server <port> <filename>
@@ -52,9 +60,13 @@
# This is a comment
[generic]
- # The [generic] section is required, but can not currently
- # contain any options. This section name is reserved for future
- # use.
+ # The [generic] section is required, even if nothing is specified
+ # there.
+ # When either of these options are specified, nbd-server drops
+ # privileges to the given user and group after opening ports, but
+ # _before_ opening files.
+ user = nbd
+ group = nbd
[export1]
exportname = /export/nbd/export1-file
port = 12345
@@ -64,6 +76,8 @@
readonly = false
multifile = false
copyonwrite = false
+ prerun = dd if=/dev/zero of=%s bs=1k count=500
+ postrun = rm -f %s
[otherexport]
exportname = /export/nbd/experiment
port = 12346
diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/nbd-2.9.5/simple_test new/nbd-2.9.8/simple_test
--- old/nbd-2.9.5/simple_test 2007-01-30 14:00:59.000000000 +0100
+++ new/nbd-2.9.8/simple_test 2007-10-17 11:00:39.000000000 +0200
@@ -20,5 +20,29 @@
kill $PID
fi
rm -f nbd-server.pid
+if [ $retval -ne 0 ]
+then
+ rm -f $tmpnam
+ exit $retval
+fi
+cat > nbd-server.conf <