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

[PATCH 7/7] nbd-trplay: 1st usable version



Initial version.

Signed-off-by: Manfred Spraul <manfred.spraul@de.bosch.com>
---
 nbd-trplay.c | 150 ++++++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 124 insertions(+), 26 deletions(-)

diff --git a/nbd-trplay.c b/nbd-trplay.c
index fa13e49..1a46ea2 100644
--- a/nbd-trplay.c
+++ b/nbd-trplay.c
@@ -25,7 +25,7 @@
 #include "nbd-helper.h"
 
 #define BUFSIZE	131072
-static char tmpbuf[BUFSIZE];
+static char g_tmpbuf[BUFSIZE];
 
 #define	VERBOSE_DEBUG	3
 #define	VERBOSE_DETAILS	2
@@ -35,15 +35,20 @@ static char tmpbuf[BUFSIZE];
 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, void *buf, size_t len) {
+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)
+                        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);
                 }
@@ -52,6 +57,97 @@ static inline void doread(int f, void *buf, size_t len) {
         }
 }
 
+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 */
+		if (command & NBD_CMD_FLAG_DATALOG) {
+				while (len > 0) {
+					uint32_t tmplen = len;
+
+					if (tmplen > BUFSIZE)
+						tmplen = BUFSIZE;
+					doread(logfd, g_tmpbuf, tmplen);
+					len -= tmplen;
+				}
+		}
+		break;
+	case NBD_CMD_WRITE:
+		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;
@@ -65,7 +161,7 @@ int main_loop(int logfd, int imagefd) {
 
 	while (1) {
 		/* Read a request or reply from the transaction file */
-		doread(logfd, &magic, sizeof(magic));
+		doread(logfd, (char*) &magic, sizeof(magic));
 		magic = ntohl(magic);
 		switch (magic) {
 		case NBD_REQUEST_MAGIC:
@@ -77,23 +173,16 @@ int main_loop(int logfd, int imagefd) {
 
 			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(logfd, tmpbuf, tmplen);
-					len -= tmplen;
-				}
+			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:
@@ -101,14 +190,16 @@ int main_loop(int logfd, int imagefd) {
 			handle = ntohll(*((long long int *)(rep.handle)));
 			error = ntohl(rep.error);
 
-			printf("< H=%016llx E=0x%08x\n",
-			       (long long unsigned int) handle,
-			       error);
+			if (g_verbose >= VERBOSE_NORMAL) {
+				printf("< H=%016llx E=0x%08x\n",
+				       (long long unsigned int) handle,
+				       error);
+			}
 			break;
 
 		default:
-			printf("? Unknown transaction type %08x\n",magic);
-			break;
+			printf("? Unknown transaction type %08x, replay impossible.\n",magic);
+			exit(1);
 		}
 
 	}
@@ -139,6 +230,9 @@ int main(int argc, char **argv) {
 	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++;
@@ -154,6 +248,7 @@ int main(int argc, char **argv) {
 				printf("  Invalid block count.\n");
 				return 1;
 			}
+			break;
 		case 'b':
 			g_blocksize = strtoul(optarg, NULL, 0);
 			if (g_blocksize == 0) {
@@ -164,18 +259,21 @@ int main(int argc, char **argv) {
 				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;
 		}
 	}
 
@@ -190,7 +288,7 @@ int main(int argc, char **argv) {
 
 	if (g_verbose >= VERBOSE_NORMAL) {
 		printf(" block size: %ld bytes (0x%lx bytes).\n", g_blocksize, g_blocksize);
-		printf(" max blocks to apply: %llx.\n", g_max_blocks);
+		printf(" max blocks to apply: %llu (0x%llx).\n", g_max_blocks, g_max_blocks);
 	}
 	main_loop(logfd, imagefd);
 
-- 
2.33.1


Reply to: