diff --git a/Makefile b/Makefile index 05c7c39a..01f65e9d 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ BLOCKSTORE_OBJS := allocator.o blockstore.o blockstore_impl.o blockstore_init.o blockstore_write.o blockstore_sync.o blockstore_stable.o blockstore_rollback.o blockstore_flush.o crc32c.o ringloop.o timerfd_interval.o # -fsanitize=address CXXFLAGS := -g -O3 -Wall -Wno-sign-compare -Wno-comment -Wno-parentheses -Wno-pointer-arith -fPIC -fdiagnostics-color=always -all: $(BLOCKSTORE_OBJS) libfio_blockstore.so osd libfio_sec_osd.so test_blockstore stub_osd stub_bench osd_test +all: $(BLOCKSTORE_OBJS) libfio_blockstore.so osd libfio_sec_osd.so test_blockstore stub_osd stub_bench osd_test dump_journal clean: rm -f *.o @@ -19,6 +19,8 @@ timerfd_interval.o: timerfd_interval.cpp timerfd_interval.h ringloop.h %.o: %.cpp allocator.h blockstore_flush.h blockstore.h blockstore_impl.h blockstore_init.h blockstore_journal.h crc32c.h ringloop.h timerfd_interval.h object_id.h g++ $(CXXFLAGS) -c -o $@ $< +dump_journal: dump_journal.cpp crc32c.o blockstore_journal.h + g++ $(CXXFLAGS) -o $@ $< crc32c.o libblockstore.so: $(BLOCKSTORE_OBJS) g++ $(CXXFLAGS) -o libblockstore.so -shared $(BLOCKSTORE_OBJS) -ltcmalloc_minimal -luring diff --git a/blockstore_flush.cpp b/blockstore_flush.cpp index 1d53158e..c741aef6 100644 --- a/blockstore_flush.cpp +++ b/blockstore_flush.cpp @@ -331,6 +331,7 @@ resume_1: else { clean_disk_entry *new_entry = (clean_disk_entry*)(meta_new.buf + meta_new.pos*bs->clean_entry_size); + assert(new_entry->oid.inode == 0); new_entry->oid = cur.oid; new_entry->version = cur.version; if (!bs->inmemory_meta) diff --git a/dump_journal.cpp b/dump_journal.cpp new file mode 100644 index 00000000..230a282f --- /dev/null +++ b/dump_journal.cpp @@ -0,0 +1,165 @@ +#define _LARGEFILE64_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "blockstore_impl.h" +#include "crc32c.h" + +struct journal_dump_t +{ + char *journal_device; + uint32_t journal_block; + uint64_t journal_offset; + uint64_t journal_len; + uint64_t journal_pos; + int fd; + + void dump_block(void *buf); +}; + +int main(int argc, char *argv[]) +{ + if (argc < 5) + { + printf("USAGE: %s \n", argv[0]); + return 1; + } + journal_dump_t self; + self.journal_device = argv[1]; + self.journal_block = strtoul(argv[2], NULL, 10); + self.journal_offset = strtoull(argv[3], NULL, 10); + self.journal_len = strtoull(argv[4], NULL, 10); + if (self.journal_block < MEM_ALIGNMENT || (self.journal_block % MEM_ALIGNMENT) || + self.journal_block > 128*1024) + { + printf("Invalid journal block size\n"); + return 1; + } + self.fd = open(self.journal_device, O_DIRECT|O_RDONLY); + if (self.fd == -1) + { + printf("Failed to open journal\n"); + return 1; + } + void *data = memalign(MEM_ALIGNMENT, self.journal_block); + self.journal_pos = 0; + while (self.journal_pos < self.journal_len) + { + int r = pread(self.fd, data, self.journal_block, self.journal_offset+self.journal_pos); + assert(r == self.journal_block); + uint64_t s; + for (s = 0; s < self.journal_block; s += 8) + { + if (*((uint64_t*)(data+s)) != 0) + break; + } + if (s == self.journal_block) + { + printf("offset %08lx: zeroes\n", self.journal_pos); + self.journal_pos += self.journal_block; + } + else if (((journal_entry*)data)->magic == JOURNAL_MAGIC) + { + printf("offset %08lx:\n", self.journal_pos); + self.dump_block(data); + } + else + { + printf("offset %08lx: no magic in the beginning, looks like random data\n", self.journal_pos); + self.journal_pos += self.journal_block; + } + } + free(data); + close(self.fd); + return 0; +} + +void journal_dump_t::dump_block(void *buf) +{ + uint32_t pos = 0; + journal_pos += journal_block; + int entry = 0; + bool wrapped = false; + while (pos < journal_block) + { + journal_entry *je = (journal_entry*)(buf + pos); + if (je->magic != JOURNAL_MAGIC || je->type < JE_START || je->type > JE_DELETE) + { + break; + } + const char *crc32_valid = je_crc32(je) == je->crc32 ? "(valid)" : "(invalid)"; + printf("entry % 3d: crc32=%08x %s prev=%08x ", entry, je->crc32, crc32_valid, je->crc32_prev); + if (je->type == JE_START) + { + printf("je_start start=%08lx\n", je->start.journal_start); + } + else if (je->type == JE_SMALL_WRITE) + { + printf( + "je_small_write oid=%lu:%lu ver=%lu offset=%u len=%u loc=%08lx", + je->small_write.oid.inode, je->small_write.oid.stripe, + je->small_write.version, je->small_write.offset, je->small_write.len, + je->small_write.data_offset + ); + if (journal_pos + je->small_write.len > journal_len) + { + // data continues from the beginning of the journal + journal_pos = journal_block; + wrapped = true; + } + if (journal_pos != je->small_write.data_offset) + { + printf(" (mismatched, calculated = %lu)", journal_pos); + } + journal_pos += je->small_write.len; + if (journal_pos >= journal_len) + { + journal_pos = journal_block; + wrapped = true; + } + uint32_t data_crc32 = 0; + void *data = memalign(MEM_ALIGNMENT, je->small_write.len); + assert(pread(fd, data, je->small_write.len, journal_offset+je->small_write.data_offset) == je->small_write.len); + data_crc32 = crc32c(0, data, je->small_write.len); + free(data); + printf( + " data_crc32=%08x%s", je->small_write.crc32_data, + (data_crc32 != je->small_write.crc32_data) ? " (invalid)" : " (valid)" + ); + printf("\n"); + } + else if (je->type == JE_BIG_WRITE) + { + printf("je_big_write oid=%lu:%lu ver=%lu loc=%08lx\n", je->big_write.oid.inode, je->big_write.oid.stripe, je->big_write.version, je->big_write.location); + } + else if (je->type == JE_STABLE) + { + printf("je_stable oid=%lu:%lu ver=%lu\n", je->stable.oid.inode, je->stable.oid.stripe, je->stable.version); + } + else if (je->type == JE_ROLLBACK) + { + printf("je_rollback oid=%lu:%lu ver=%lu\n", je->rollback.oid.inode, je->rollback.oid.stripe, je->rollback.version); + } + else if (je->type == JE_DELETE) + { + printf("je_delete oid=%lu:%lu ver=%lu\n", je->del.oid.inode, je->del.oid.stripe, je->del.version); + } + pos += je->size; + entry++; + } + if (wrapped) + { + journal_pos = journal_len; + } +}