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

[PATCH 5/7] Add a new utility: nbd-trplay



Initial commit for nbd-trplay, a command to replay parts of an nbd
trace file.

Changes:
- Just copy nbd-trdump.
- Changes:
   * nbd-trdump replaced with nbd-trplay.
   * Whitespace in empty lines removed.

Signed-off-by: Manfred Spraul <manfred.spraul@de.bosch.com>
---
 Makefile.am  |   5 ++-
 nbd-trplay.c | 113 +++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 117 insertions(+), 1 deletion(-)
 create mode 100644 nbd-trplay.c

diff --git a/Makefile.am b/Makefile.am
index fde6ad7..14d264e 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,6 +1,6 @@
 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
@@ -9,14 +9,17 @@ 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
 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 --git a/nbd-trplay.c b/nbd-trplay.c
new file mode 100644
index 0000000..e31bb3b
--- /dev/null
+++ b/nbd-trplay.c
@@ -0,0 +1,113 @@
+/*
+ * nbd-trplay.c
+ *
+ * Takes an nbd transaction log file and replays some/all of the write commands.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <stdint.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 inline void doread(int f, void *buf, size_t len) {
+        ssize_t res;
+
+        while(len>0) {
+                if((res=read(f, buf, len)) <=0) {
+                        if (!res)
+				exit(0);
+			perror ("Error reading transactions");
+			exit(1);
+                }
+                len-=res;
+                buf+=res;
+        }
+}
+
+int main(int argc, char**argv) {
+	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;
+	int readfd = 0; /* stdin */
+
+	if(argc > 1) {
+		int retval=0;
+		if(strcmp(argv[1], "--help") && strcmp(argv[1], "-h")) {
+			printf("E: unknown option %s.\n", argv[1]);
+			retval=1;
+		}
+		printf("This is nbd-trplay, part of nbd %s.\n", PACKAGE_VERSION);
+		printf("Use: %s < transactionlog\n", argv[0]);
+		return retval;
+	}
+
+	while (1) {
+		/* Read a request or reply from the transaction file */
+		doread(readfd, &magic, sizeof(magic));
+		magic = ntohl(magic);
+		switch (magic) {
+		case NBD_REQUEST_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 = getcommandname(command & NBD_CMD_MASK_COMMAND);
+
+			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);
+			if (command & NBD_CMD_FLAG_DATALOG) {
+				while (len > 0) {
+					uint32_t tmplen = len;
+
+					if (tmplen > BUFSIZE)
+						tmplen = BUFSIZE;
+					doread(readfd, tmpbuf, tmplen);
+					len -= tmplen;
+				}
+			}
+
+			break;
+		case NBD_REPLY_MAGIC:
+			doread(readfd, sizeof(magic)+(char *)(&rep), sizeof(struct nbd_reply)-sizeof(magic));
+			handle = ntohll(*((long long int *)(rep.handle)));
+			error = ntohl(rep.error);
+
+			printf("< H=%016llx E=0x%08x\n",
+			       (long long unsigned int) handle,
+			       error);
+			break;
+
+		default:
+			printf("? Unknown transaction type %08x\n",magic);
+			break;
+		}
+
+	}
+	/* never reached */
+	return 0;
+}
-- 
2.33.1


Reply to: