X-Git-Url: http://git.apps.os.sepia.ceph.com/?p=xfstests-dev.git;a=blobdiff_plain;f=src%2Flog-writes%2Flog-writes.c;h=a872429d3f41016f2429109acd48d24feb4e5999;hp=dbfeef7ad222dc4e0bb2cc890e97fbf6e243e147;hb=00b6ad8f265e21a355f6a92f939cd07cfe188fd8;hpb=9892f3155f63322843cb173ec032ba07a1975acf diff --git a/src/log-writes/log-writes.c b/src/log-writes/log-writes.c index dbfeef7a..a872429d 100644 --- a/src/log-writes/log-writes.c +++ b/src/log-writes/log-writes.c @@ -65,6 +65,9 @@ static int zero_range(struct log *log, u64 start, u64 len) memset(buf, 0, bufsize); while (len) { + if (len < bufsize) + bufsize = len; + ret = pwrite(log->replayfd, buf, bufsize, start); if (ret != bufsize) { fprintf(stderr, "Error zeroing file: %d\n", errno); @@ -117,6 +120,79 @@ int log_discard(struct log *log, struct log_write_entry *entry) return 0; } +#define DEFINE_LOG_FLAGS_STR_ENTRY(x) \ + {LOG_##x##_FLAG, #x} + +struct flags_to_str_entry { + u64 flags; + const char *str; +} log_flags_table[] = { + DEFINE_LOG_FLAGS_STR_ENTRY(FLUSH), + DEFINE_LOG_FLAGS_STR_ENTRY(FUA), + DEFINE_LOG_FLAGS_STR_ENTRY(DISCARD), + DEFINE_LOG_FLAGS_STR_ENTRY(MARK) +}; + +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) +#define LOG_FLAGS_BUF_SIZE 128 +/* + * Convert numeric flags to human readable flags. + * @flags: numeric flags + * @buf: output buffer for human readable string. + * must have enough space (LOG_FLAGS_BUF_SIZE) to contain all + * the string + */ +static void entry_flags_to_str(u64 flags, char *buf) +{ + int empty = 1; + int left_len; + int i; + + buf[0] = '\0'; + for (i = 0; i < ARRAY_SIZE(log_flags_table); i++) { + if (flags & log_flags_table[i].flags) { + if (!empty) + strncat(buf, "|", LOG_FLAGS_BUF_SIZE); + empty = 0; + strncat(buf, log_flags_table[i].str, LOG_FLAGS_BUF_SIZE); + flags &= ~log_flags_table[i].flags; + } + } + if (flags) { + if (!empty) + strncat(buf, "|", LOG_FLAGS_BUF_SIZE); + empty = 0; + left_len = LOG_FLAGS_BUF_SIZE - strnlen(buf, + LOG_FLAGS_BUF_SIZE); + if (left_len > 0) + snprintf(buf + strnlen(buf, LOG_FLAGS_BUF_SIZE), + left_len, "UNKNOWN.0x%llx", flags); + } + if (empty) + strncpy(buf, "NONE", LOG_FLAGS_BUF_SIZE); +} + +/* + * @log: the log we are replaying. + * @entry: entry to be replayed. + * + * @return: 0 if we should replay the entry, > 0 if we should skip it. + * + * Should we skip the entry in our log or replay onto the replay device. + */ +int log_should_skip(struct log *log, struct log_write_entry *entry) +{ + u64 sector = le64_to_cpu(entry->sector); + u64 nr_sectors = le64_to_cpu(entry->nr_sectors); + + if (!nr_sectors) + return 0; + if (sector + nr_sectors <= log->start_sector || + sector > log->end_sector) + return 1; + return 0; +} + /* * @entry: entry to be replayed. * @@ -155,8 +231,10 @@ int log_replay_next_entry(struct log *log, struct log_write_entry *entry, size_t read_size = read_data ? log->sectorsize : sizeof(struct log_write_entry); char *buf; + char flags_buf[LOG_FLAGS_BUF_SIZE]; ssize_t ret; off_t offset; + int skip = 0; if (log->cur_entry >= log->nr_entries) return 1; @@ -185,20 +263,32 @@ int log_replay_next_entry(struct log *log, struct log_write_entry *entry, log->cur_pos += read_size; } - if (log_writes_verbose) { - printf("replaying %d@%llu: sector %llu, size %llu, flags %llu\n", + flags = le64_to_cpu(entry->flags); + entry_flags_to_str(flags, flags_buf); + skip = log_should_skip(log, entry); + if (log_writes_verbose > 1 || (log_writes_verbose && !skip)) { + printf("%s %d@%llu: sector %llu, size %llu, flags 0x%llx(%s)\n", + skip ? "skipping" : "replaying", (int)log->cur_entry - 1, log->cur_pos / log->sectorsize, (unsigned long long)le64_to_cpu(entry->sector), (unsigned long long)size, - (unsigned long long)le64_to_cpu(entry->flags)); + (unsigned long long)flags, flags_buf); } if (!size) return 0; - flags = le64_to_cpu(entry->flags); if (flags & LOG_DISCARD_FLAG) return log_discard(log, entry); + if (skip) { + log->cur_pos = lseek(log->logfd, size, SEEK_CUR); + if (log->cur_pos == (off_t)-1) { + fprintf(stderr, "Error seeking in log: %d\n", errno); + return -1; + } + return 0; + } + buf = malloc(size); if (!buf) { fprintf(stderr, "Error allocating buffer %llu entry %llu\n", (unsigned long long)size, (unsigned long long)log->cur_entry - 1); @@ -265,7 +355,7 @@ int log_seek_entry(struct log *log, u64 entry_num) return -1; } if (log_writes_verbose > 1) - printf("seek entry %d@%llu: %llu, size %llu, flags %llu\n", + printf("seek entry %d@%llu: %llu, size %llu, flags 0x%llx\n", (int)i, log->cur_pos / log->sectorsize, (unsigned long long)le64_to_cpu(entry.sector), (unsigned long long)le64_to_cpu(entry.nr_sectors), @@ -303,6 +393,7 @@ int log_seek_next_entry(struct log *log, struct log_write_entry *entry, size_t read_size = read_data ? log->sectorsize : sizeof(struct log_write_entry); u64 flags; + char flags_buf[LOG_FLAGS_BUF_SIZE]; ssize_t ret; if (log->cur_entry >= log->nr_entries) @@ -330,14 +421,15 @@ int log_seek_next_entry(struct log *log, struct log_write_entry *entry, } else { log->cur_pos += read_size; } + flags = le64_to_cpu(entry->flags); + entry_flags_to_str(flags, flags_buf); if (log_writes_verbose > 1) - printf("seek entry %d@%llu: %llu, size %llu, flags %llu\n", + printf("seek entry %d@%llu: %llu, size %llu, flags 0x%llx(%s)\n", (int)log->cur_entry - 1, log->cur_pos / log->sectorsize, (unsigned long long)le64_to_cpu(entry->sector), (unsigned long long)le64_to_cpu(entry->nr_sectors), - (unsigned long long)le64_to_cpu(entry->flags)); + (unsigned long long)flags, flags_buf); - flags = le64_to_cpu(entry->flags); read_size = le64_to_cpu(entry->nr_sectors) * log->sectorsize; if (!read_size || (flags & LOG_DISCARD_FLAG)) return 0;