Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package nbd for openSUSE:Factory checked in 
at 2022-04-11 23:48:52
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/nbd (Old)
 and      /work/SRC/openSUSE:Factory/.nbd.new.1900 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "nbd"

Mon Apr 11 23:48:52 2022 rev:58 rq:968361 version:3.24

Changes:
--------
--- /work/SRC/openSUSE:Factory/nbd/nbd.changes  2021-12-13 20:51:06.096661990 
+0100
+++ /work/SRC/openSUSE:Factory/.nbd.new.1900/nbd.changes        2022-04-11 
23:50:19.594329112 +0200
@@ -1,0 +2,6 @@
+Sun Apr 10 14:45:08 UTC 2022 - Dirk M??ller <dmuel...@suse.com>
+
+- update to 3.24 (bsc#1196827, CVE-2022-26495):
+  * https://github.com/advisories/GHSA-q9rw-8758-hccj
+
+-------------------------------------------------------------------

Old:
----
  nbd-3.23.tar.xz

New:
----
  nbd-3.24.tar.xz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ nbd.spec ++++++
--- /var/tmp/diff_new_pack.JnjF2Y/_old  2022-04-11 23:50:20.130322997 +0200
+++ /var/tmp/diff_new_pack.JnjF2Y/_new  2022-04-11 23:50:20.134322952 +0200
@@ -1,7 +1,7 @@
 #
 # spec file for package nbd
 #
-# Copyright (c) 2021 SUSE LLC
+# Copyright (c) 2022 SUSE LLC
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -20,7 +20,7 @@
   %define _fillupdir %{_localstatedir}/adm/fillup-templates
 %endif
 Name:           nbd
-Version:        3.23
+Version:        3.24
 Release:        0
 Summary:        Network Block Device Server and Client Utilities
 License:        GPL-2.0-or-later
@@ -128,12 +128,14 @@
 %{_sbindir}/nbd-client
 %{_bindir}/nbd-server
 %{_bindir}/nbd-trdump
+%{_bindir}/nbd-trplay
 %{_sbindir}/min-nbd-client
 %{_sbindir}/rcnbd-server
 %{_unitdir}/%{name}@.service
 %{_unitdir}/%{name}-server.service
 %{_mandir}/man1/nbd-server.1%{?ext_man}
 %{_mandir}/man1/nbd-trdump.1%{?ext_man}
+%{_mandir}/man1/nbd-trplay.1%{?ext_man}
 %{_mandir}/man5/nbd-server.5%{?ext_man}
 %{_mandir}/man8/nbd-client.8%{?ext_man}
 %{_mandir}/man5/nbdtab.5%{?ext_man}

++++++ nbd-3.23.tar.xz -> nbd-3.24.tar.xz ++++++
++++ 7828 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-3.23/Makefile.am new/nbd-3.24/Makefile.am
--- old/nbd-3.23/Makefile.am    2021-10-04 14:32:32.000000000 +0200
+++ new/nbd-3.24/Makefile.am    2022-03-07 10:16:05.000000000 +0100
@@ -1,22 +1,25 @@
 ACLOCAL_AMFLAGS = -I support
 SUBDIRS = . man doc tests systemd gznbd
-bin_PROGRAMS = nbd-server nbd-trdump
+bin_PROGRAMS = nbd-server nbd-trdump nbd-trplay
 EXTRA_PROGRAMS = nbd-client make-integrityhuge
 noinst_LTLIBRARIES = libnbdsrv.la libcliserv.la libnbdclt.la
 libcliserv_la_SOURCES = cliserv.h cliserv.c
 libcliserv_la_CFLAGS = @CFLAGS@
 client_srcs = nbd-client.c cliserv.h nbd-netlink.h
 nbd_server_SOURCES = nbd-server.c cliserv.h lfs.h nbd.h nbdsrv.h backend.h \
-       netdb-compat.h
+       netdb-compat.h nbd-helper.h
 nbd_trdump_SOURCES = nbd-trdump.c cliserv.h nbd.h
+nbd_trplay_SOURCES = nbd-trplay.c cliserv.h nbd.h
 client_flags = @CFLAGS@
 nbd_server_CFLAGS = @CFLAGS@ @GLIB_CFLAGS@
 nbd_trdump_CFLAGS = @CFLAGS@ @GLIB_CFLAGS@
+nbd_trplay_CFLAGS = @CFLAGS@ @GLIB_CFLAGS@
 libnbdsrv_la_SOURCES = nbdsrv.c nbdsrv.h treefiles.c treefiles.h
 libnbdsrv_la_CFLAGS = @CFLAGS@ @GLIB_CFLAGS@
 client_libs = libcliserv.la libnbdclt.la
 nbd_server_LDADD = @GLIB_LIBS@ libnbdsrv.la libcliserv.la
 nbd_trdump_LDADD = libcliserv.la
+nbd_trplay_LDADD = libcliserv.la
 make_integrityhuge_SOURCES = make-integrityhuge.c cliserv.h nbd.h nbd-debug.h
 EXTRA_DIST = maketr CodingStyle autogen.sh README.md support/genver.sh
 if GNUTLS
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-3.23/autogen.sh new/nbd-3.24/autogen.sh
--- old/nbd-3.23/autogen.sh     2019-02-14 15:50:57.000000000 +0100
+++ new/nbd-3.24/autogen.sh     2022-03-03 10:53:02.000000000 +0100
@@ -1,5 +1,5 @@
 #!/bin/sh
 set -ex
-make -C man -f mans.mk nbd-server.1.sh.in nbd-server.5.sh.in 
nbd-client.8.sh.in nbd-trdump.1.sh.in nbdtab.5.sh.in
+make -C man -f mans.mk nbd-server.1.sh.in nbd-server.5.sh.in 
nbd-client.8.sh.in nbd-trdump.1.sh.in nbd-trplay.1.sh.in nbdtab.5.sh.in
 make -C systemd -f Makefile.am n...@.service.sh.in
 exec autoreconf -f -i
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-3.23/configure.ac new/nbd-3.24/configure.ac
--- old/nbd-3.23/configure.ac   2021-11-16 10:55:32.000000000 +0100
+++ new/nbd-3.24/configure.ac   2022-03-07 13:53:06.000000000 +0100
@@ -107,7 +107,7 @@
   [ENABLE_GZNBD=no]
 )
 
-AC_PROG_CC_C99
+AC_PROG_CC
 AC_PROG_CPP
 AC_PROG_INSTALL
 AM_PROG_LEX(noyywrap)
@@ -267,7 +267,6 @@
        [AC_DEFINE([HAVE_SYNC_FILE_RANGE], [sync_file_range(2) is not 
supported], [sync_file_range(2) is supported])],
         [])
 AC_FUNC_FORK
-AC_FUNC_SETVBUF_REVERSED
 AC_MSG_CHECKING(whether client should be built)
 AS_CASE([$host_os],
   [linux*], [NBD_CLIENT_NAME="nbd-client"; AC_MSG_RESULT(yes)],
@@ -354,6 +353,7 @@
                man/nbd-server.5.sh \
                man/nbd-server.1.sh \
                man/nbd-trdump.1.sh \
+               man/nbd-trplay.1.sh \
                man/nbdtab.5.sh \
                "])
        ])
@@ -381,6 +381,7 @@
                  man/nbd-server.5.sh
                  man/nbd-server.1.sh
                  man/nbd-trdump.1.sh
+                 man/nbd-trplay.1.sh
                  man/nbdtab.5.sh
                 systemd/Makefile
                 systemd/n...@.service.sh
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-3.23/doc/proto.md new/nbd-3.24/doc/proto.md
--- old/nbd-3.23/doc/proto.md   2021-10-04 14:32:32.000000000 +0200
+++ new/nbd-3.24/doc/proto.md   2022-03-03 10:53:01.000000000 +0100
@@ -458,6 +458,18 @@
 The client and the server MUST NOT initiate any form
 of disconnect other than in one of the above circumstances.
 
+#### Reserved Magic values
+
+The following magic values are reserved and must not be used
+for future protocol extentions:
+
+0x12560953 - Historic value for NBD_REQUEST_MAGIC, used
+            until Linux 2.1.116pre2.
+0x96744668 - Historic value for NBD_REPLY_MAGIC, used
+            until Linux 2.1.116pre2.
+0x25609514 - Used by nbd-server to store data log flags in the
+            transaction log. Never sent from/to a client.
+
 ## TLS support
 
 The NBD protocol supports Transport Layer Security (TLS) (see
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-3.23/man/Makefile.am new/nbd-3.24/man/Makefile.am
--- old/nbd-3.23/man/Makefile.am        2019-02-14 15:50:57.000000000 +0100
+++ new/nbd-3.24/man/Makefile.am        2022-03-03 10:53:02.000000000 +0100
@@ -1,9 +1,9 @@
 if MANPAGES
-man_MANS = nbd-server.1 nbd-server.5 nbd-client.8 nbd-trdump.1 nbdtab.5
+man_MANS = nbd-server.1 nbd-server.5 nbd-client.8 nbd-trdump.1 nbd-trplay.1 
nbdtab.5
 CLEANFILES = manpage.links manpage.refs
-DISTCLEANFILES = nbd-server.1 nbd-client.8 nbd-server.5 nbd-trdump.1 nbdtab.5
-MAINTAINERCLEANFILES = nbd-server.1.sh.in nbd-client.8.sh.in 
nbd-server.5.sh.in nbd-trdump.1.sh.in nbdtab.5.sh.in
-EXTRA_DIST = nbd-server.1.in.sgml nbd-client.8.in.sgml nbd-server.5.in.sgml 
nbd-trdump.1.in.sgml nbdtab.5.in.sgml nbd-server.1.sh.in nbd-server.5.sh.in 
nbd-client.8.sh.in nbd-trdump.1.sh.in nbdtab.5.sh.in sh.tmpl
+DISTCLEANFILES = nbd-server.1 nbd-client.8 nbd-server.5 nbd-trdump.1 
nbd-trplay.1 nbdtab.5
+MAINTAINERCLEANFILES = nbd-server.1.sh.in nbd-client.8.sh.in 
nbd-server.5.sh.in nbd-trdump.1.sh.in nbd-trplay.1.sh.in nbdtab.5.sh.in
+EXTRA_DIST = nbd-server.1.in.sgml nbd-client.8.in.sgml nbd-server.5.in.sgml 
nbd-trdump.1.in.sgml nbd-trplay.1.in.sgml nbdtab.5.in.sgml nbd-server.1.sh.in 
nbd-server.5.sh.in nbd-client.8.sh.in nbd-trdump.1.sh.in nbd-trdump.1.sh.in 
nbdtab.5.sh.in sh.tmpl
 
 include $(srcdir)/mans.mk
 endif
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-3.23/man/mans.mk new/nbd-3.24/man/mans.mk
--- old/nbd-3.23/man/mans.mk    2019-02-14 15:50:57.000000000 +0100
+++ new/nbd-3.24/man/mans.mk    2022-03-03 10:53:02.000000000 +0100
@@ -6,6 +6,8 @@
        sh nbd-client.8.sh > nbd-client.8
 nbd-trdump.1: nbd-trdump.1.sh
        sh nbd-trdump.1.sh > nbd-trdump.1
+nbd-trplay.1: nbd-trplay.1.sh
+       sh nbd-trplay.1.sh > nbd-trplay.1
 nbdtab.5: nbdtab.5.sh
        sh nbdtab.5.sh > nbdtab.5
 nbd-server.1.sh.in: nbd-server.1.in.sgml sh.tmpl
@@ -32,6 +34,12 @@
        cat NBD-TRDUMP.1 >> nbd-trdump.1.sh.in
        echo "EOF" >> nbd-trdump.1.sh.in
        rm NBD-TRDUMP.1
+nbd-trplay.1.sh.in: nbd-trplay.1.in.sgml sh.tmpl
+       LC_ALL=C docbook2man nbd-trplay.1.in.sgml
+       cat sh.tmpl > nbd-trplay.1.sh.in
+       cat NBD-TRPLAY.1 >> nbd-trplay.1.sh.in
+       echo "EOF" >> nbd-trplay.1.sh.in
+       rm NBD-TRPLAY.1
 nbdtab.5.sh.in: nbdtab.5.in.sgml sh.tmpl
        LC_ALL=C docbook2man nbdtab.5.in.sgml
        cat sh.tmpl > nbdtab.5.sh.in
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-3.23/man/nbd-trplay.1.in.sgml new/nbd-3.24/man/nbd-trplay.1.in.sgml
--- old/nbd-3.23/man/nbd-trplay.1.in.sgml       1970-01-01 01:00:00.000000000 
+0100
+++ new/nbd-3.24/man/nbd-trplay.1.in.sgml       2022-03-03 10:53:02.000000000 
+0100
@@ -0,0 +1,99 @@
+<!doctype refentry PUBLIC "-//OASIS//DTD DocBook V4.5//EN" [
+
+<!-- Process this file with docbook-to-man to generate an nroff manual
+     page: `docbook-to-man manpage.sgml > manpage.1'.  You may view
+     the manual page with: `docbook-to-man manpage.sgml | nroff -man |
+     less'.  A typical entry in a Makefile or Makefile.am is:
+
+manpage.1: manpage.sgml
+       docbook-to-man $< > $@
+  -->
+
+  <!-- Fill in your name for FIRSTNAME and SURNAME. -->
+  <!ENTITY dhfirstname "<firstname>Manfred</firstname>">
+  <!ENTITY dhsurname   "<surname>Spraul</surname>">
+  <!-- Please adjust the date whenever revising the manpage. -->
+  <!ENTITY dhdate      "<date>$Date$</date>">
+  <!-- SECTION should be 1-8, maybe w/ subsection other parameters are
+       allowed: see man(7), man(1). -->
+  <!ENTITY dhsection   "<manvolnum>1</manvolnum>">
+  <!ENTITY dhemail     "<email>manf...@de.bosch.com</email>">
+  <!ENTITY dhusername  "Manfred Spraul">
+  <!ENTITY dhucpackage "<refentrytitle>NBD-TRPLAY</refentrytitle>">
+  <!ENTITY dhpackage   "nbd-trplay">
+
+  <!ENTITY debian      "<productname>Debian GNU/Linux</productname>">
+  <!ENTITY gnu         "<acronym>GNU</acronym>">
+]>
+
+<refentry>
+  <refentryinfo>
+    <address>
+      &dhemail;
+    </address>
+    <author>
+      &dhfirstname;
+      &dhsurname;
+    </author>
+    <copyright>
+      <year>2001</year>
+      <holder>&dhusername;</holder>
+    </copyright>
+    &dhdate;
+  </refentryinfo>
+  <refmeta>
+    &dhucpackage;
+
+    &dhsection;
+  </refmeta>
+  <refnamediv>
+    <refname>&dhpackage;</refname>
+
+    <refpurpose>replay all or parts of an nbd transaction log</refpurpose>
+  </refnamediv>
+  <refsynopsisdiv>
+    <cmdsynopsis>
+      <command>&dhpackage;</command>
+    </cmdsynopsis>
+  </refsynopsisdiv>
+  <refsect1>
+    <title>DESCRIPTION</title>
+
+    <para><command>&dhpackage;</command> replays all or parts of
+    a transaction log produced by <command>nbd-server</command>
+    (specifically by the <command>transactionlog</command>
+    configuration directive with the option <command>datalog
+    </command>).</para>
+
+    <para>See nbd-trplay --help for the command line parameters.
+    </para>
+  </refsect1>
+  <refsect1>
+    <title>OUTPUT</title>
+
+    <para>The file updates the image provided via -i.</para>
+
+  </refsect1>
+  <refsect1>
+    <title>SEE ALSO</title>
+
+    <para>nbd-server (1).</para>
+
+  </refsect1>
+  <refsect1>
+    <title>AUTHOR</title>
+    <para>The NBD kernel module and the NBD tools have been written by
+    Pavel Macheck (pa...@ucw.cz).</para>
+
+    <para>The kernel module is now maintained by Paul Clements
+    (paul.cleme...@steeleye.com), while the userland tools are maintained by
+    Wouter Verhelst (wou...@debian.org)</para>
+
+    <para>This manual page was written by &dhusername; (&dhemail;) for
+    the &debian; system (but may be used by others).  Permission is
+    granted to copy, distribute and/or modify this document under the
+    terms of the <acronym>GNU</acronym> General Public License,
+    version 2, as published by the Free Software Foundation.</para>
+
+  </refsect1>
+</refentry>
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-3.23/man/nbd-trplay.1.sh.in new/nbd-3.24/man/nbd-trplay.1.sh.in
--- old/nbd-3.23/man/nbd-trplay.1.sh.in 1970-01-01 01:00:00.000000000 +0100
+++ new/nbd-3.24/man/nbd-trplay.1.sh.in 2022-03-07 13:48:42.000000000 +0100
@@ -0,0 +1,50 @@
+#!/bin/sh
+
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+sysconfdir=@sysconfdir@
+
+cat <<EOF
+.\" This manpage has been automatically generated by docbook2man 
+.\" from a DocBook document.  This tool can be found at:
+.\" <http://shell.ipoline.com/~elmert/comp/docbook2X/> 
+.\" Please send any bug reports, improvements, comments, patches, 
+.\" etc. to Steve Cheng <st...@ggi-project.org>.
+.TH "NBD-TRPLAY" "1" "$Date$" "" ""
+
+.SH NAME
+nbd-trplay \- replay all or parts of an nbd transaction log
+.SH SYNOPSIS
+
+\fBnbd-trplay\fR
+
+.SH "DESCRIPTION"
+.PP
+\fBnbd-trplay\fR replays all or parts of
+a transaction log produced by \fBnbd-server\fR
+(specifically by the \fBtransactionlog\fR
+configuration directive with the option \fBdatalog
+\fR).
+.PP
+See nbd-trplay --help for the command line parameters.
+.SH "OUTPUT"
+.PP
+The file updates the image provided via -i.
+.SH "SEE ALSO"
+.PP
+nbd-server (1).
+.SH "AUTHOR"
+.PP
+The NBD kernel module and the NBD tools have been written by
+Pavel Macheck (pa...@ucw.cz).
+.PP
+The kernel module is now maintained by Paul Clements
+(paul.cleme...@steeleye.com), while the userland tools are maintained by
+Wouter Verhelst (wou...@debian.org)
+.PP
+This manual page was written by Manfred Spraul (<manf...@de.bosch.com>) for
+the Debian GNU/Linux system (but may be used by others).  Permission is
+granted to copy, distribute and/or modify this document under the
+terms of the GNU General Public License,
+version 2, as published by the Free Software Foundation.
+EOF
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-3.23/nbd-helper.h new/nbd-3.24/nbd-helper.h
--- old/nbd-3.23/nbd-helper.h   1970-01-01 01:00:00.000000000 +0100
+++ new/nbd-3.24/nbd-helper.h   2022-03-03 10:53:01.000000000 +0100
@@ -0,0 +1,63 @@
+#ifndef NBD_HELPER_H
+#define NBD_HELPER_H
+
+#include "nbd.h"
+
+/* Constants and macros */
+
+/*
+ * Constants for nbd_request.magic == NBD_TRACELOG_MAGIC
+ */
+/* 1) stored in nbd_req.type */
+enum {
+       /* enable/disable logging actual data.
+        * nbd_request.len is the new value (true/false)
+        */
+       NBD_TRACELOG_SET_DATALOG = 1
+};
+
+/* 2) Must be in nbd_req.from */
+#define NBD_TRACELOG_FROM_MAGIC        0x4A93BA39A54F31B6ULL
+
+/* Functions */
+
+/**
+ * Translate a command name into human readable form
+ *
+ * @param command The command number (after applying NBD_CMD_MASK_COMMAND)
+ * @return pointer to the command name
+ **/
+#define ENUM2STR(x)    case x: return #x
+static inline const char * getcommandname(uint32_t command) {
+       switch (command) {
+       ENUM2STR(NBD_CMD_READ);
+       ENUM2STR(NBD_CMD_WRITE);
+       ENUM2STR(NBD_CMD_DISC);
+       ENUM2STR(NBD_CMD_FLUSH);
+       ENUM2STR(NBD_CMD_TRIM);
+       ENUM2STR(NBD_CMD_CACHE);
+       ENUM2STR(NBD_CMD_WRITE_ZEROES);
+       ENUM2STR(NBD_CMD_BLOCK_STATUS);
+       ENUM2STR(NBD_CMD_RESIZE);
+       default:
+               return "UNKNOWN";
+       }
+}
+
+/**
+ * Translate a tracelog parameter name into human readable form
+ *
+ * @type tracelog parameter number from struct nbd_req.type
+ * @return pointer to the name
+ **/
+static inline const char * gettracelogname(uint32_t type) {
+       switch (type) {
+       ENUM2STR(NBD_TRACELOG_SET_DATALOG);
+       default:
+               return "UNKNOWN";
+       }
+}
+
+#undef ENUM2STR
+
+#endif //NBD_HELPER_H
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-3.23/nbd-server.c new/nbd-3.24/nbd-server.c
--- old/nbd-3.23/nbd-server.c   2021-10-04 14:32:32.000000000 +0200
+++ new/nbd-3.24/nbd-server.c   2022-03-07 09:37:11.000000000 +0100
@@ -120,8 +120,6 @@
 #include <pthread.h>
 #endif
 
-#include <semaphore.h>
-
 /* used in cliserv.h, so must come first */
 #define MY_NAME "nbd_server"
 #include "cliserv.h"
@@ -129,6 +127,7 @@
 #include "netdb-compat.h"
 #include "backend.h"
 #include "treefiles.h"
+#include "nbd-helper.h"
 
 #ifdef WITH_SDP
 #include <sdp_inet.h>
@@ -208,7 +207,7 @@
        CLIENT* client;
        struct nbd_request* req;
        int pipefd[2];
-       void* data; /**< for read requests */
+       void* data; /**< for write requests */
 };
 
 static volatile sig_atomic_t is_sigchld_caught; /**< Flag set by
@@ -285,31 +284,6 @@
        gint threads;           /**< maximum number of parallel threads we want 
to run */
 };
 
-/**
- * Translate a command name into human readable form
- *
- * @param command The command number (after applying NBD_CMD_MASK_COMMAND)
- * @return pointer to the command name
- **/
-static inline const char * getcommandname(uint64_t command) {
-       switch (command) {
-       case NBD_CMD_READ:
-               return "NBD_CMD_READ";
-       case NBD_CMD_WRITE:
-               return "NBD_CMD_WRITE";
-       case NBD_CMD_DISC:
-               return "NBD_CMD_DISC";
-       case NBD_CMD_FLUSH:
-               return "NBD_CMD_FLUSH";
-       case NBD_CMD_TRIM:
-               return "NBD_CMD_TRIM";
-       case NBD_CMD_WRITE_ZEROES:
-               return "NBD_CMD_WRITE_ZEROES";
-       default:
-               return "UNKNOWN";
-       }
-}
-
 #if HAVE_GNUTLS
 static int writeit_tls(gnutls_session_t s, void *buf, size_t len) {
        ssize_t res;
@@ -423,6 +397,26 @@
        err("Negotiation failed: %m");
 }
 
+static void cleanup_transactionlog(CLIENT *client) {
+
+       if (client->transactionlogfd != -1) {
+               close(client->transactionlogfd);
+               client->transactionlogfd = -1;
+       }
+       if (client->logsem != SEM_FAILED) {
+               sem_close(client->logsem);
+               client->logsem = SEM_FAILED;
+               sem_unlink(client->semname);
+       }
+}
+
+static void lock_logsem(CLIENT *client) {
+       sem_wait(client->logsem);
+}
+static void unlock_logsem(CLIENT *client) {
+       sem_post(client->logsem);
+}
+
 /**
  * Run a command. This is used for the ``prerun'' and ``postrun'' config file
  * options
@@ -445,10 +439,9 @@
 static inline void finalize_client(CLIENT* client) {
        g_thread_pool_free(tpool, FALSE, TRUE);
        do_run(client->server->postrun, client->exportname);
-       if(client->transactionlogfd != -1) {
-               close(client->transactionlogfd);
-               client->transactionlogfd = -1;
-       }
+       if(client->transactionlogfd != -1)
+               cleanup_transactionlog(client);
+
        if(client->server->flags & F_COPYONWRITE) {
                unlink(client->difffilename);
        }
@@ -810,6 +803,7 @@
                { "rotational", FALSE,  PARAM_BOOL,     &(s.flags),             
F_ROTATIONAL },
                { "temporary",  FALSE,  PARAM_BOOL,     &(s.flags),             
F_TEMPORARY },
                { "trim",       FALSE,  PARAM_BOOL,     &(s.flags),             
F_TRIM },
+               { "datalog",    FALSE,  PARAM_BOOL,     &(s.flags),             
F_DATALOG },
                { "listenaddr", FALSE,  PARAM_STRING,   &(s.listenaddr),        
0 },
                { "maxconnections", FALSE, PARAM_INT,   &(s.max_connections),   
0 },
                { "force_tls",  FALSE,  PARAM_BOOL,     &(s.flags),             
F_FORCEDTLS },
@@ -1006,6 +1000,15 @@
                        g_key_file_free(cfile);
                        return NULL;
                }
+               /* We can't mix datalog and splice. */
+               if ((s.flags & F_DATALOG) && (s.flags & F_SPLICE)) {
+                       g_set_error(e, NBDS_ERR, NBDS_ERR_CFILE_INVALID_SPLICE,
+                                   "Cannot mix datalog with splice for an 
export in group %s",
+                                   groups[i]);
+                       g_array_free(retval, TRUE);
+                       g_key_file_free(cfile);
+                       return NULL;
+               }
                /* Don't need to free this, it's not our string */
                virtstyle=NULL;
                /* Don't append values for the [generic] group */
@@ -2005,6 +2008,75 @@
 }
 
 /**
+  * Setup the transaction log
+  *
+  * The function does all things required for the transaction log:
+  * - Create a new log file.
+  * - allocate the posix semaphore for synchronization.
+  * - Report if a log file already exists.
+  * - If needed add a header to the log.
+  *
+  * If something goes wrong, logging is disabled.
+  *
+  * @param client the CLIENT structure with .server and .net members set
+  * up correctly
+  */
+static void setup_transactionlog(CLIENT *client) {
+       struct stat fdinfo;
+       int ret;
+
+       /* 1) create the file */
+       if((client->transactionlogfd =
+                               open(client->server->transactionlog,
+                                       O_WRONLY | O_CREAT,
+                                       S_IRUSR | S_IWUSR)) ==
+                       -1) {
+               msg(LOG_INFO, "Could not open transactionlog %s, moving on 
without it",
+                               client->server->transactionlog);
+       }
+
+       /* 2) If needed, write flags */
+       if (client->server->flags & F_DATALOG) {
+               struct nbd_request req;
+               int ret;
+
+               req.magic = htonl(NBD_TRACELOG_MAGIC);
+               req.type = htonl(NBD_TRACELOG_SET_DATALOG);
+               memset(req.handle, 0, sizeof(req.handle));
+               req.from = htonll(NBD_TRACELOG_FROM_MAGIC);
+               req.len = htonl(TRUE);
+
+               ret = writeit(client->transactionlogfd, &req, sizeof(struct 
nbd_request));
+               if (ret < 0) {
+                       msg(LOG_INFO, "Could not write to transactionlog %s, 
moving on without it",
+                               client->server->transactionlog);
+                       close(client->transactionlogfd);
+                       client->transactionlogfd = -1;
+               }
+       }
+
+       /* 3) Allocate the semaphore used for locking */
+       ret = fstat(client->transactionlogfd, &fdinfo);
+       if (ret == -1) {
+               msg(LOG_INFO, "Could not stat transactionlog %s, moving on 
without it",
+                       client->server->transactionlog);
+               close(client->transactionlogfd);
+               client->transactionlogfd = -1;
+               return;
+       }
+       snprintf(client->semname, sizeof(client->semname), 
"/nbd-server-%llx-%llx",
+                               (unsigned long long)fdinfo.st_dev,
+                               (unsigned long long)fdinfo.st_ino);
+       client->logsem = sem_open(client->semname, O_CREAT, 0600, 1);
+       if (client->logsem == SEM_FAILED) {
+               msg(LOG_INFO, "Could not allocate semaphore for transactionlog 
%s, moving on without it",
+                       client->server->transactionlog);
+               close(client->transactionlogfd);
+               client->transactionlogfd = -1;
+       }
+}
+
+/**
   * Commit to exporting the chosen export
   *
   * When a client sends NBD_OPT_EXPORT_NAME or NBD_OPT_GO, we need to do
@@ -2067,16 +2139,8 @@
         }
 
        /* Set up the transactionlog, if we need one */
-       if (client->server->transactionlog && (client->transactionlogfd == -1)) 
{
-               if((client->transactionlogfd =
-                                       open(client->server->transactionlog,
-                                               O_WRONLY | O_CREAT,
-                                               S_IRUSR | S_IWUSR)) ==
-                               -1) {
-                       msg(LOG_INFO, "Could not open transactionlog %s, moving 
on without it",
-                                       client->server->transactionlog);
-               }
-       }
+       if (client->server->transactionlog && (client->transactionlogfd == -1))
+               setup_transactionlog(client);
 
        /* Run any pre scripts that we may need */
        if (do_run(client->server->prerun, client->exportname)) {
@@ -2113,6 +2177,9 @@
 
        socket_read(client, &namelen, sizeof(namelen));
        namelen = ntohl(namelen);
+       if(namelen > 4096) {
+               return NULL;
+       }
        if(namelen > 0) {
                name = malloc(namelen+1);
                name[namelen]=0;
@@ -2296,7 +2363,11 @@
        namelen = htonl(namelen);
        if(namelen > (len - 6)) {
                send_reply(client, opt, NBD_REP_ERR_INVALID, -1, "An OPT_INFO 
request cannot be smaller than the length of the name + 6");
-               socket_read(client, buf, len - sizeof(namelen));
+               consume(client, len - sizeof(namelen), buf, sizeof(buf));
+       }
+       if(namelen > 4096) {
+               send_reply(client, opt, NBD_REP_ERR_INVALID, -1, "The name for 
this OPT_INFO request is too long");
+               consume(client, namelen, buf, sizeof(buf));
        }
        if(namelen > 0) {
                name = malloc(namelen + 1);
@@ -2374,6 +2445,8 @@
        client->socket_read = socket_read_notls;
        client->socket_write = socket_write_notls;
        client->socket_closed = socket_closed_negotiate;
+       client->transactionlogfd = -1;
+       client->logsem = SEM_FAILED;
 
        assert(servers != NULL);
        socket_write(client, INIT_PASSWD, 8);
@@ -2550,6 +2623,15 @@
        memcpy(&(rep->handle), &(req->handle), sizeof(req->handle));
 }
 
+static void log_reply(CLIENT *client, struct nbd_reply *prply)
+{
+       if (client->transactionlogfd != -1) {
+               lock_logsem(client);
+               writeit(client->transactionlogfd, prply, sizeof(*prply));
+               unlock_logsem(client);
+       }
+}
+
 #ifdef HAVE_SPLICE
 static int handle_splice_read(CLIENT *client, struct nbd_request *req)
 {
@@ -2571,6 +2653,7 @@
 
        DEBUG("handling read request (splice)\n");
        setup_reply(&rep, req);
+       log_reply(client, &rep);
        pthread_mutex_lock(&(client->lock));
        writeit(client->net, &rep, sizeof(rep));
        spliceit(pipefd[0], NULL, client->net, NULL, req->len);
@@ -2594,6 +2677,7 @@
                DEBUG("Read failed: %m");
                rep.error = nbd_errno(errno);
        }
+       log_reply(client, &rep);
        pthread_mutex_lock(&(client->lock));
        socket_write(client, &rep, sizeof rep);
        if(!rep.error) {
@@ -2642,6 +2726,7 @@
                        rep.error = nbd_errno(errno);
                }
        }
+       log_reply(client, &rep);
        pthread_mutex_lock(&(client->lock));
        socket_write(client, &rep, sizeof rep);
        pthread_mutex_unlock(&(client->lock));
@@ -2655,6 +2740,7 @@
                DEBUG("Flush failed: %m");
                rep.error = nbd_errno(errno);
        }
+       log_reply(client, &rep);
        pthread_mutex_lock(&(client->lock));
        socket_write(client, &rep, sizeof rep);
        pthread_mutex_unlock(&(client->lock));
@@ -2668,6 +2754,7 @@
                DEBUG("Trim failed: %m");
                rep.error = nbd_errno(errno);
        }
+       log_reply(client, &rep);
        pthread_mutex_lock(&(client->lock));
        socket_write(client, &rep, sizeof rep);
        pthread_mutex_unlock(&(client->lock));
@@ -2685,6 +2772,7 @@
        // For now, don't trim
        // TODO: handle this far more efficiently with reference to the
        // actual backing driver
+       log_reply(client, &rep);
        pthread_mutex_lock(&(client->lock));
        socket_write(client, &rep, sizeof rep);
        pthread_mutex_unlock(&(client->lock));
@@ -2771,6 +2859,7 @@
 error:
        setup_reply(&rep, package->req);
        rep.error = nbd_errno(err);
+       log_reply(package->client, &rep);
        pthread_mutex_lock(&(package->client->lock));
        socket_write(package->client, &rep, sizeof rep);
        pthread_mutex_unlock(&(package->client->lock));
@@ -2781,20 +2870,32 @@
 static int mainloop_threaded(CLIENT* client) {
        struct nbd_request* req;
        struct work_package* pkg;
+       int write_data = false;
 
        DEBUG("Entering request loop\n");
        while(1) {
                req = calloc(sizeof (struct nbd_request), 1);
 
                socket_read(client, req, sizeof(struct nbd_request));
+
                if(client->transactionlogfd != -1) {
+                       lock_logsem(client);
                        writeit(client->transactionlogfd, req, sizeof(struct 
nbd_request));
+                       if(((ntohl(req->type) & NBD_CMD_MASK_COMMAND) == 
NBD_CMD_WRITE) &&
+                                       (client->server->flags & F_DATALOG) &&
+                                       !(client->server->flags & F_SPLICE)) {
+                               write_data = true;
+                       } else {
+                               write_data = false;
+                               unlock_logsem(client);
+                       }
                }
 
                req->from = ntohll(req->from);
                req->type = ntohl(req->type);
                req->len = ntohl(req->len);
 
+
                if(req->magic != htonl(NBD_REQUEST_MAGIC))
                        err("Protocol error: not enough magic.");
 
@@ -2810,6 +2911,12 @@
                        else
 #endif
                                socket_read(client, pkg->data, req->len);
+
+                       if (write_data) {
+                               writeit(client->transactionlogfd, pkg->data, 
req->len);
+                               unlock_logsem(client);
+                               write_data = false;
+                       }
                }
                if(req->type == NBD_CMD_DISC) {
                        finalize_client(client);
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-3.23/nbd-trdump.c new/nbd-3.24/nbd-trdump.c
--- old/nbd-3.23/nbd-trdump.c   2021-09-10 11:12:01.000000000 +0200
+++ new/nbd-3.24/nbd-trdump.c   2022-03-03 10:53:01.000000000 +0100
@@ -11,12 +11,19 @@
 #include <sys/time.h>
 #include <sys/types.h>
 #include <stdint.h>
+#include <stdbool.h>
 #include <unistd.h>
 #include "config.h"
 /* We don't want to do syslog output in this program */
 #undef ISSERVER
 #include "cliserv.h"
 #include "nbd.h"
+#include "nbd-helper.h"
+
+#define BUFSIZE        131072
+static char tmpbuf[BUFSIZE];
+
+static bool g_with_datalog = false;
 
 static inline void doread(int f, void *buf, size_t len) {
         ssize_t res;
@@ -42,7 +49,7 @@
        uint32_t command;
        uint32_t len;
        uint64_t offset;
-       char * ctext;
+       const char * ctext;
        int readfd = 0; /* stdin */
 
        if(argc > 1) {
@@ -68,30 +75,26 @@
                        len = ntohl(req.len);
                        command = ntohl(req.type);
                        
-                       switch (command & NBD_CMD_MASK_COMMAND) {
-                       case NBD_CMD_READ:
-                               ctext="NBD_CMD_READ";
-                               break;
-                       case NBD_CMD_WRITE:
-                               ctext="NBD_CMD_WRITE";
-                               break;
-                       case NBD_CMD_DISC:
-                               ctext="NBD_CMD_DISC";
-                               break;
-                       case NBD_CMD_FLUSH:
-                               ctext="NBD_CMD_FLUSH";
-                               break;
-                       default:
-                               ctext="UNKNOWN";
-                               break;
-                       }
-                       printf("> H=%016llx C=0x%08x (%13s+%4s) O=%016llx 
L=%08x\n",
+                       ctext = getcommandname(command & NBD_CMD_MASK_COMMAND);
+
+                       printf("> H=%016llx C=0x%08x (%20s+%4s) O=%016llx 
L=%08x\n",
                               (long long unsigned int) handle,
                               command,
                               ctext,
                               (command & NBD_CMD_FLAG_FUA)?"FUA":"NONE",
                               (long long unsigned int) offset,
                               len);
+                       if (((command & NBD_CMD_MASK_COMMAND) == NBD_CMD_WRITE) 
&&
+                                       g_with_datalog) {
+                               while (len > 0) {
+                                       uint32_t tmplen = len;
+
+                                       if (tmplen > BUFSIZE)
+                                               tmplen = BUFSIZE;
+                                       doread(readfd, tmpbuf, tmplen);
+                                       len -= tmplen;
+                               }
+                       }
                        
                        break;
                case NBD_REPLY_MAGIC:
@@ -104,6 +107,35 @@
                               error);
                        break;
                        
+               case NBD_TRACELOG_MAGIC:
+                       doread(readfd, sizeof(magic)+(char *)(&req), 
sizeof(struct nbd_request)-sizeof(magic));
+                       handle = ntohll(*((long long int *)(req.handle)));
+                       offset = ntohll(req.from);
+                       len = ntohl(req.len);
+                       command = ntohl(req.type);
+
+                       ctext = gettracelogname(command);
+
+                       printf("TRACE_OPTION C=0x%08x (%23s) O=%016llx 
L=%08x\n",
+                              command,
+                              ctext,
+                              (long long unsigned int) offset,
+                              len);
+                       if (offset == NBD_TRACELOG_FROM_MAGIC) {
+
+                               switch (command) {
+                               case NBD_TRACELOG_SET_DATALOG:
+                                       g_with_datalog = !!len;
+                                       printf("TRACE_OPTION DATALOG set to 
%d.\n", (int)g_with_datalog);
+                                       break;
+                               default:
+                                       printf("TRACE_OPTION ? Unknown type\n");
+                               }
+                       } else {
+                               printf("TRACE_OPTION ? Unknown FROM_MAGIC\n");
+                       }
+                       break;
+
                default:
                        printf("? Unknown transaction type %08x\n",magic);
                        break;
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-3.23/nbd-trplay.c new/nbd-3.24/nbd-trplay.c
--- old/nbd-3.23/nbd-trplay.c   1970-01-01 01:00:00.000000000 +0100
+++ new/nbd-3.24/nbd-trplay.c   2022-03-03 10:53:02.000000000 +0100
@@ -0,0 +1,327 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * nbd-trplay.c
+ *
+ * Takes an nbd transaction log file and replays some/all of the write 
commands.
+ *
+ * Based on nbd-trdump
+ * (C) Robert Bosch GmbH, 2021
+ */
+
+#include <stdlib.h>
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <unistd.h>
+#include "config.h"
+/* We don't want to do syslog output in this program */
+#undef ISSERVER
+#include "cliserv.h"
+#include "nbd.h"
+#include "nbd-helper.h"
+
+#define BUFSIZE        131072
+static char g_tmpbuf[BUFSIZE];
+
+static bool g_with_datalog = false;
+
+#define        VERBOSE_DEBUG   3
+#define        VERBOSE_DETAILS 2
+#define        VERBOSE_NORMAL  1
+#define        VERBOSE_OFF     0
+
+int g_verbose = 0;
+
+unsigned long g_blocksize = 512;
+unsigned long long g_cur_blocks = 0;
+unsigned long long g_max_blocks = ULLONG_MAX;
+
+static inline void doread(int f, char *buf, size_t len) {
+        ssize_t res;
+
+        while(len>0) {
+                if((res=read(f, buf, len)) <=0) {
+                        if (!res) {
+                               /* normal exit, end of transaction log. */
+                               printf("End of transaction log, total %llu 
blocks written.\n",
+                                       (unsigned long long) g_cur_blocks);
+                               exit(0);
+                       }
+                       perror ("Error reading transactions");
+                       exit(1);
+                }
+                len-=res;
+                buf+=res;
+        }
+}
+
+static inline void dowriteimage(int imagefd, const char *buf, size_t len, 
off_t offset) {
+       ssize_t res;
+
+       if (g_verbose >= VERBOSE_DETAILS) {
+               printf("block %llu (0x%llx): writing to offset %lld (0x%llx), 
len %lld (0x%llx).\n",
+                       g_cur_blocks, g_cur_blocks,
+                       (long long)offset, (long long) offset,
+                       (long long) len, (long long) len);
+       }
+
+       while(len>0) {
+               if((res=pwrite(imagefd, buf, len, offset)) <=0) {
+                       if (!res)
+                               exit(0);
+                       perror ("Error writing to image file");
+                       exit(1);
+               }
+               len-=res;
+               buf+=res;
+               offset+=res;
+       }
+}
+
+
+void process_command(uint32_t command, uint64_t offset, uint32_t len, int 
logfd, int imagefd)
+{
+       if (offset % g_blocksize != 0) {
+               printf("  Got offset %llu (0x%llx), not a multiple of the block 
size %ld (0x%lx).\n",
+                               (unsigned long long)offset, (unsigned long 
long)offset, g_blocksize, g_blocksize);
+               exit(1);
+       }
+       if (len % g_blocksize != 0) {
+               printf("  Got len %lu (0x%lx), not a multiple of the block size 
%ld (0x%lx).\n",
+                               (unsigned long) len, (unsigned long) len, 
g_blocksize, g_blocksize);
+               exit(1);
+       }
+
+       switch (command & NBD_CMD_MASK_COMMAND) {
+       case NBD_CMD_READ:
+       case NBD_CMD_DISC:
+       case NBD_CMD_FLUSH:
+               /* READ, DISCONNECT, FLUSH: nothing to do */
+               break;
+       case NBD_CMD_WRITE:
+               if (!g_with_datalog) {
+                       printf("  NBD_CMD_WRITE without data log, replay 
impossible.\n");
+                       exit(1);
+               }
+               while (len > 0) {
+                       doread(logfd, g_tmpbuf, g_blocksize);
+                       dowriteimage(imagefd, g_tmpbuf, g_blocksize, offset);
+
+                       offset+=g_blocksize;
+                       len-=g_blocksize;
+                       g_cur_blocks++;
+
+                       if (g_cur_blocks == g_max_blocks) {
+                               printf("g_max_blocks (%llu, 0x%llx) 
reached!.\n", g_max_blocks, g_max_blocks);
+                               exit(0);
+                       }
+               }
+               break;
+       case NBD_CMD_TRIM:
+       case NBD_CMD_WRITE_ZEROES:
+               while (len > 0) {
+                       memset(g_tmpbuf, 0, g_blocksize);
+                       dowriteimage(imagefd, g_tmpbuf, g_blocksize, offset);
+
+                       offset+=g_blocksize;
+                       len-=g_blocksize;
+                       g_cur_blocks++;
+
+                       if (g_cur_blocks == g_max_blocks) {
+                               printf("g_max_blocks (%llu, 0x%llx) 
reached!.\n", g_max_blocks, g_max_blocks);
+                               exit(0);
+                       }
+               }
+               break;
+       default:
+               printf("  Unexpected command %d (0x%x), replay impossible.\n",
+                       (unsigned int) command, (unsigned int) command);
+               exit(1);
+       }
+}
+
+int main_loop(int logfd, int imagefd) {
+       struct nbd_request req;
+       struct nbd_reply rep;
+       uint32_t magic;
+       uint64_t handle;
+       uint32_t error;
+       uint32_t command;
+       uint32_t len;
+       uint64_t offset;
+       const char * ctext;
+
+       while (1) {
+               /* Read a request or reply from the transaction file */
+               doread(logfd, (char*) &magic, sizeof(magic));
+               magic = ntohl(magic);
+               switch (magic) {
+               case NBD_REQUEST_MAGIC:
+                       doread(logfd, sizeof(magic)+(char *)(&req), 
sizeof(struct nbd_request)-sizeof(magic));
+                       handle = ntohll(*((long long int *)(req.handle)));
+                       offset = ntohll(req.from);
+                       len = ntohl(req.len);
+                       command = ntohl(req.type);
+
+                       ctext = getcommandname(command & NBD_CMD_MASK_COMMAND);
+
+                       if (g_verbose >= VERBOSE_NORMAL) {
+                               printf("> H=%016llx C=0x%08x (%13s+%4s) 
O=%016llx L=%08x\n",
+                                      (long long unsigned int) handle,
+                                      command,
+                                      ctext,
+                                      (command & 
NBD_CMD_FLAG_FUA)?"FUA":"NONE",
+                                      (long long unsigned int) offset,
+                                      len);
+                       }
+                       process_command(command, offset, len, logfd, imagefd);
+
+                       break;
+
+               case NBD_REPLY_MAGIC:
+                       doread(logfd, sizeof(magic)+(char *)(&rep), 
sizeof(struct nbd_reply)-sizeof(magic));
+                       handle = ntohll(*((long long int *)(rep.handle)));
+                       error = ntohl(rep.error);
+
+                       if (g_verbose >= VERBOSE_NORMAL) {
+                               printf("< H=%016llx E=0x%08x\n",
+                                      (long long unsigned int) handle,
+                                      error);
+                       }
+                       break;
+
+               case NBD_TRACELOG_MAGIC:
+                       doread(logfd, sizeof(magic)+(char *)(&req), 
sizeof(struct nbd_request)-sizeof(magic));
+                       handle = ntohll(*((long long int *)(req.handle)));
+                       offset = ntohll(req.from);
+                       len = ntohl(req.len);
+                       command = ntohl(req.type);
+
+                       ctext = gettracelogname(command);
+
+                       if (g_verbose >= VERBOSE_NORMAL) {
+                               printf("TRACE_OPTION C=0x%08x (%23s) O=%016llx 
L=%08x\n",
+                                      command,
+                                      ctext,
+                                      (long long unsigned int) offset,
+                                      len);
+                       }
+                       if (offset == NBD_TRACELOG_FROM_MAGIC) {
+
+                               switch (command) {
+                               case NBD_TRACELOG_SET_DATALOG:
+                                       g_with_datalog = !!len;
+                                       if (g_verbose >= VERBOSE_NORMAL)
+                                               printf("TRACE_OPTION DATALOG 
set to %d.\n", (int)g_with_datalog);
+                                       break;
+                               default:
+                                       printf("TRACE_OPTION ? Unknown type\n");
+                               }
+                       } else {
+                               printf("TRACE_OPTION ? Unknown FROM_MAGIC\n");
+                       }
+                       break;
+
+
+               default:
+                       printf("? Unknown transaction type %08x, replay 
impossible.\n", magic);
+                       exit(1);
+               }
+
+       }
+       /* never reached */
+       return 0;
+}
+
+static void show_help(const char *progname) {
+       printf("\n");
+       printf("This is nbd-trplay, part of nbd %s.\n", PACKAGE_VERSION);
+       printf("Use: %s -i <image> -l <log> [-m <max blocks>] [-b <block 
size]\n", progname);
+       printf(" Applies up to <max blocks> elements from file <log> to disk 
image <image>.\n");
+       printf(" Command line parameters:\n");
+       printf(" <image>: name of the initial image file.\n");
+       printf(" <log>: nbd trace log. Must contain actual data 
(datalog=true).\n");
+       printf(" <block size>: device block size. Default 512.\n");
+       printf(" <max blocks>: where to stop the replay. Default all.\n");
+       printf("  -v: Increase verbose level. Specify multiple times to 
increase further.\n");
+
+}
+
+
+int main(int argc, char **argv) {
+       int opt;
+       int imagefd = -1;
+       int logfd = -1;
+
+       printf("%s -i <image> -l <log> [-m <max blocks>] [-b <block size]\n", 
argv[0]);
+
+       while ((opt = getopt(argc, argv, "i:l:m:b:hv")) != -1) {
+               if (g_verbose >= VERBOSE_DEBUG) {
+                       printf("getopt: opt %c, optarg %s.\n", (char)opt, 
optarg);
+               }
+               switch(opt) {
+               case 'v':
+                       g_verbose++;
+                       break;
+               default:
+               case '?':
+               case 'h':
+                       show_help(argv[0]);
+                       return 0;
+               case 'm':
+                       g_max_blocks = strtoull(optarg, NULL, 0);
+                       if (g_max_blocks == 0) {
+                               printf("  Invalid block count.\n");
+                               return 1;
+                       }
+                       break;
+               case 'b':
+                       g_blocksize = strtoul(optarg, NULL, 0);
+                       if (g_blocksize == 0) {
+                               printf("  Invalid block size.\n");
+                               return 1;
+                       }
+                       if (g_blocksize > BUFSIZE) {
+                               printf(" block size is larger than %d, not 
supported.\n", (int)BUFSIZE);
+                               return 1;
+                       }
+                       break;
+               case 'i':
+                       imagefd = open(optarg, O_RDWR, 0);
+                       if (imagefd == -1) {
+                               printf("  Opening disk image failed, errno 
%d.", errno);
+                               return 1;
+                       }
+                       break;
+               case 'l':
+                       logfd = open(optarg, O_RDONLY, 0);
+                       if (logfd == -1) {
+                               printf("  Opening disk image failed, errno 
%d.", errno);
+                               return 1;
+                       }
+                       break;
+               }
+       }
+
+       if (logfd == -1) {
+               printf("  Log file not specified, this is mandatory.\n");
+               return 1;
+       }
+       if (imagefd == -1) {
+               printf("  Disk image not specified, this is mandatory.\n");
+               return 1;
+       }
+
+       if (g_verbose >= VERBOSE_NORMAL) {
+               printf(" block size: %ld bytes (0x%lx bytes).\n", g_blocksize, 
g_blocksize);
+               printf(" max blocks to apply: %llu (0x%llx).\n", g_max_blocks, 
g_max_blocks);
+       }
+       main_loop(logfd, imagefd);
+
+       return 0;
+}
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-3.23/nbd.h new/nbd-3.24/nbd.h
--- old/nbd-3.23/nbd.h  2021-09-10 11:12:01.000000000 +0200
+++ new/nbd-3.24/nbd.h  2022-03-07 09:37:11.000000000 +0100
@@ -35,7 +35,10 @@
        NBD_CMD_DISC = 2,
        NBD_CMD_FLUSH = 3,
        NBD_CMD_TRIM = 4,
-       NBD_CMD_WRITE_ZEROES = 6
+       NBD_CMD_CACHE = 5,
+       NBD_CMD_WRITE_ZEROES = 6,
+       NBD_CMD_BLOCK_STATUS = 7,
+       NBD_CMD_RESIZE = 8
 };
 
 #define NBD_CMD_MASK_COMMAND 0x0000ffff
@@ -61,7 +64,10 @@
 
 #define NBD_REQUEST_MAGIC 0x25609513
 #define NBD_REPLY_MAGIC 0x67446698
-/* Do *not* use magics: 0x12560953 0x96744668. */
+#define NBD_STRUCTURED_REPLY_MAGIC 0x668e33ef
+
+/* for the trace log, not part of the protocol, not sent over the wire */
+#define NBD_TRACELOG_MAGIC 0x25609514
 
 #define NBD_OPT_REPLY_MAGIC 0x3e889045565a9LL
 
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-3.23/nbdsrv.h new/nbd-3.24/nbdsrv.h
--- old/nbd-3.23/nbdsrv.h       2021-09-10 11:12:01.000000000 +0200
+++ new/nbd-3.24/nbdsrv.h       2022-03-07 09:37:11.000000000 +0100
@@ -9,6 +9,7 @@
 
 #include <sys/socket.h>
 #include <sys/types.h>
+#include <semaphore.h>
 #include "nbd.h"
 
 /* Structures */
@@ -70,6 +71,8 @@
        uint32_t difffilelen;     /**< number of pages in difffile */
        uint32_t *difmap;            /**< see comment on the global difmap for 
this one */
        int transactionlogfd;/**< fd for transaction log */
+       char semname[100]; /**< name of the posix sem that protects access to 
the transaction log */
+       sem_t *logsem;   /**< posix sem that protects access to the transaction 
log */
        int clientfeats;     /**< Features supported by this client */
        pthread_mutex_t lock; /**< socket lock */
        void *tls_session; /**< TLS session context. Is NULL unless STARTTLS
@@ -155,6 +158,7 @@
 #define F_FORCEDTLS 16384 /**< TLS is required, either for the server as a 
whole or for a given export */
 #define F_SPLICE 32768   /**< flag to tell us to use splice for read/write 
operations */
 #define F_WAIT 65536      /**< flag to tell us to wait for file creation */
+#define F_DATALOG 131072  /**< flag to tell us that the transaction log shall 
contain the written data */
 
 /* Functions */
 
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-3.23/nbdtab_lexer.c new/nbd-3.24/nbdtab_lexer.c
--- old/nbd-3.23/nbdtab_lexer.c 2021-10-04 14:35:28.000000000 +0200
+++ new/nbd-3.24/nbdtab_lexer.c 2022-03-07 13:49:21.000000000 +0100
@@ -373,7 +373,7 @@
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    2,    1,    1,    4,    1,    1,    1,    1,    1,
-        1,    1,    1,    5,    1,    5,    1,    1,    1,    1,
+        1,    1,    1,    5,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         5,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
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-3.23/nbdtab_lexer.l new/nbd-3.24/nbdtab_lexer.l
--- old/nbd-3.23/nbdtab_lexer.l 2021-10-04 14:32:32.000000000 +0200
+++ new/nbd-3.24/nbdtab_lexer.l 2022-01-13 11:58:17.000000000 +0100
@@ -8,6 +8,6 @@
 
 #[^\n]*\n      { /* ignoring comments */ }
 [ \t]+         { yylval = strdup(yytext); return SPACE; }
-[^ \t\n,=.]+   { yylval = strdup(yytext); return STRING; }
+[^ \t\n,=]+    { yylval = strdup(yytext); return STRING; }
 .              { yylval = strdup(yytext); return *yytext; }
 \n             { yylval = strdup(yytext); return *yytext; }
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-3.23/nbdtab_parser.c new/nbd-3.24/nbdtab_parser.c
--- old/nbd-3.23/nbdtab_parser.c        2021-10-04 14:35:28.000000000 +0200
+++ new/nbd-3.24/nbdtab_parser.c        2022-03-07 13:49:22.000000000 +0100
@@ -1,4 +1,4 @@
-/* A Bison parser, made by GNU Bison 3.8.1.  */
+/* A Bison parser, made by GNU Bison 3.8.2.  */
 
 /* Bison implementation for Yacc-like parsers in C
 
@@ -46,10 +46,10 @@
    USER NAME SPACE" below.  */
 
 /* Identify Bison output, and Bison version.  */
-#define YYBISON 30801
+#define YYBISON 30802
 
 /* Bison version string.  */
-#define YYBISON_VERSION "3.8.1"
+#define YYBISON_VERSION "3.8.2"
 
 /* Skeleton name.  */
 #define YYSKELETON_NAME "yacc.c"
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-3.23/nbdtab_parser.tab.h new/nbd-3.24/nbdtab_parser.tab.h
--- old/nbd-3.23/nbdtab_parser.tab.h    2021-10-04 14:35:28.000000000 +0200
+++ new/nbd-3.24/nbdtab_parser.tab.h    2022-03-07 13:49:21.000000000 +0100
@@ -1,4 +1,4 @@
-/* A Bison parser, made by GNU Bison 3.8.1.  */
+/* A Bison parser, made by GNU Bison 3.8.2.  */
 
 /* Bison interface for Yacc-like parsers in C
 
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-3.23/tests/parse/Makefile.am new/nbd-3.24/tests/parse/Makefile.am
--- old/nbd-3.23/tests/parse/Makefile.am        2021-10-18 16:22:41.000000000 
+0200
+++ new/nbd-3.24/tests/parse/Makefile.am        2022-01-13 11:58:17.000000000 
+0100
@@ -3,5 +3,5 @@
 TESTS_ENVIRONMENT = $(builddir)/parser
 parser_SOURCES = parser.c
 parser_LDADD = $(top_builddir)/libnbdclt.la $(top_builddir)/libcliserv.la
-TESTS = empty noopts singleopt multiopt ipv6
+TESTS = empty noopts singleopt multiopt ipv6 ipv4
 EXTRA_DIST=$(TESTS)
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-3.23/tests/parse/ipv4 new/nbd-3.24/tests/parse/ipv4
--- old/nbd-3.23/tests/parse/ipv4       1970-01-01 01:00:00.000000000 +0100
+++ new/nbd-3.24/tests/parse/ipv4       2022-01-13 11:58:17.000000000 +0100
@@ -0,0 +1 @@
+nbd0 192.168.1.1 test
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-3.23/tests/parse/parser.c new/nbd-3.24/tests/parse/parser.c
--- old/nbd-3.23/tests/parse/parser.c   2021-10-18 16:23:20.000000000 +0200
+++ new/nbd-3.24/tests/parse/parser.c   2022-01-13 11:58:17.000000000 +0100
@@ -35,7 +35,14 @@
        .hostn = "2a01:4f8:200:91e8::2",
 };
 
+CLIENT client_ipv4 = {
+       .name = "test",
+       .dev = "nbd0",
+       .hostn = "192.168.1.1",
+};
+
 CLIENT *cur_client;
+bool seen_commit = false;
 
 void nbdtab_set_property(char *property, char *val) {
        printf("property %s set to %s\n", property, val);
@@ -54,6 +61,7 @@
        assert(strcmp(cur_client->dev, devn) == 0);
        assert(strcmp(cur_client->hostn, hostn) == 0);
        assert(strcmp(cur_client->name, exportname) == 0);
+       seen_commit = true;
 }
 
 void yyerror(char *s) {
@@ -80,10 +88,13 @@
        KNOW_CONF(singleopt);
        KNOW_CONF(multiopt);
        KNOW_CONF(ipv6);
+       KNOW_CONF(ipv4);
 
 #undef KNOW_CONF
 
        assert(cur_client != NULL);
 
        yyparse();
+
+       assert(cur_client == &client_empty || seen_commit == true);
 }

Reply via email to