Network Block Device @PACKAGE_VERSION@

nbd-trdump.c

Go to the documentation of this file.
00001 /*
00002  * nbd-trdump.c
00003  *
00004  * Takes an nbd transaction log file on stdin and translates it into something
00005  * comprehensible
00006  */
00007 
00008 #include <stdlib.h>
00009 #include <stdio.h>
00010 #include <string.h>
00011 #include <sys/time.h>
00012 #include <sys/types.h>
00013 #include <stdint.h>
00014 #include <unistd.h>
00015 #include "config.h"
00016 /* We don't want to do syslog output in this program */
00017 #undef ISSERVER
00018 #include "cliserv.h"
00019 #include "nbd.h"
00020 
00021 static inline void doread(int f, void *buf, size_t len) {
00022         ssize_t res;
00023 
00024         while(len>0) {
00025                 if((res=read(f, buf, len)) <=0) {
00026                         if (!res)
00027                                 exit(0);
00028                         perror ("Error reading transactions");
00029                         exit(1);
00030                 }
00031                 len-=res;
00032                 buf+=res;
00033         }
00034 }
00035 
00036 int main(int argc, char**argv) {
00037         struct nbd_request req;
00038         struct nbd_reply rep;
00039         uint32_t magic;
00040         uint64_t handle;
00041         uint32_t error;
00042         uint32_t command;
00043         uint32_t len;
00044         uint64_t offset;
00045         char * ctext;
00046         int readfd = 0; /* stdin */
00047 
00048         if(argc > 1) {
00049                 int retval=0;
00050                 if(strcmp(argv[1], "--help") && strcmp(argv[1], "-h")) {
00051                         printf("E: unknown option %s.\n", argv[1]);
00052                         retval=1;
00053                 }
00054                 printf("This is nbd-trdump, part of nbd %s.\n", PACKAGE_VERSION);
00055                 printf("Use: %s < transactionlog\n", argv[0]);
00056                 return retval;
00057         }
00058 
00059         while (1) {
00060                 /* Read a request or reply from the transaction file */
00061                 doread(readfd, &magic, sizeof(magic));
00062                 magic = ntohl(magic);
00063                 switch (magic) {
00064                 case NBD_REQUEST_MAGIC:
00065                         doread(readfd, sizeof(magic)+(char *)(&req), sizeof(struct nbd_request)-sizeof(magic));
00066                         handle = ntohll(*((long long int *)(req.handle)));
00067                         offset = ntohll(req.from);
00068                         len = ntohl(req.len);
00069                         command = ntohl(req.type);
00070                         
00071                         switch (command & NBD_CMD_MASK_COMMAND) {
00072                         case NBD_CMD_READ:
00073                                 ctext="NBD_CMD_READ";
00074                                 break;
00075                         case NBD_CMD_WRITE:
00076                                 ctext="NBD_CMD_WRITE";
00077                                 break;
00078                         case NBD_CMD_DISC:
00079                                 ctext="NBD_CMD_DISC";
00080                                 break;
00081                         case NBD_CMD_FLUSH:
00082                                 ctext="NBD_CMD_FLUSH";
00083                                 break;
00084                         default:
00085                                 ctext="UNKNOWN";
00086                                 break;
00087                         }
00088                         printf("> H=%016llx C=0x%08x (%13s+%4s) O=%016llx L=%08x\n",
00089                                (long long unsigned int) handle,
00090                                command,
00091                                ctext,
00092                                (command & NBD_CMD_FLAG_FUA)?"FUA":"NONE",
00093                                (long long unsigned int) offset,
00094                                len);
00095                         
00096                         break;
00097                 case NBD_REPLY_MAGIC:
00098                         doread(readfd, sizeof(magic)+(char *)(&rep), sizeof(struct nbd_reply)-sizeof(magic));
00099                         handle = ntohll(*((long long int *)(rep.handle)));
00100                         error = ntohl(rep.error);
00101                         
00102                         printf("< H=%016llx E=0x%08x\n",
00103                                (long long unsigned int) handle,
00104                                error);
00105                         break;
00106                         
00107                 default:
00108                         printf("? Unknown transaction type %08x\n",magic);
00109                         break;
00110                 }
00111                 
00112         }
00113         /* never reached */
00114         return 0;
00115 }