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=fab447a86f86266a756f7645399780047b33b292;hp=a215fefa833f92bd4cb2fa4f6709eb093028a3a0;hb=b65b808ee3df0b35fc013ef959e59b99ed27aae1;hpb=b1e2e6b0279e9a9d0d1b4125377114ba1e5936bd diff --git a/src/log-writes/log-writes.c b/src/log-writes/log-writes.c index a215fefa..fab447a8 100644 --- a/src/log-writes/log-writes.c +++ b/src/log-writes/log-writes.c @@ -117,6 +117,47 @@ int log_discard(struct log *log, struct log_write_entry *entry) return 0; } +/* + * @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. + * + * @return: 1 if the entry is sane, 0 if it is invalid. + * + * Check if this is a sane log entry. + */ +int log_entry_valid(struct log_write_entry *entry) +{ + u64 flags = le64_to_cpu(entry->flags); + + /* Suspect all zeroes entry */ + if (!flags && !entry->nr_sectors) + return 0; + /* Suspect non zero padded entry */ + if (flags != LOG_MARK_FLAG && entry->data[0] != 0) + return 0; + return 1; +} + /* * @log: the log we are replaying. * @entry: where we put the entry. @@ -137,6 +178,7 @@ int log_replay_next_entry(struct log *log, struct log_write_entry *entry, char *buf; ssize_t ret; off_t offset; + int skip = 0; if (log->cur_entry >= log->nr_entries) return 1; @@ -146,24 +188,34 @@ int log_replay_next_entry(struct log *log, struct log_write_entry *entry, fprintf(stderr, "Error reading entry: %d\n", errno); return -1; } + if (!log_entry_valid(entry)) { + fprintf(stderr, "Malformed entry @%llu\n", + log->cur_pos / log->sectorsize); + return -1; + } log->cur_entry++; size = le64_to_cpu(entry->nr_sectors) * log->sectorsize; if (read_size < log->sectorsize) { - if (lseek(log->logfd, - log->sectorsize - sizeof(struct log_write_entry), - SEEK_CUR) == (off_t)-1) { + log->cur_pos = lseek(log->logfd, + log->sectorsize - sizeof(struct log_write_entry), SEEK_CUR); + if (log->cur_pos == (off_t)-1) { fprintf(stderr, "Error seeking in log: %d\n", errno); return -1; } + } else { + log->cur_pos += read_size; } - if (log_writes_verbose) - printf("replaying %d: sector %llu, size %llu, flags %llu\n", - (int)log->cur_entry - 1, + skip = log_should_skip(log, entry); + if (log_writes_verbose > 1 || (log_writes_verbose && !skip)) { + printf("%s %d@%llu: sector %llu, size %llu, flags %llu\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)); + } if (!size) return 0; @@ -171,6 +223,15 @@ int log_replay_next_entry(struct log *log, struct log_write_entry *entry, 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); @@ -183,6 +244,7 @@ int log_replay_next_entry(struct log *log, struct log_write_entry *entry, free(buf); return -1; } + log->cur_pos += size; offset = le64_to_cpu(entry->sector) * log->sectorsize; ret = pwrite(log->replayfd, buf, size, offset); @@ -212,7 +274,8 @@ int log_seek_entry(struct log *log, u64 entry_num) } /* Skip the first sector containing the log super block */ - if (lseek(log->logfd, log->sectorsize, SEEK_SET) == (off_t)-1) { + log->cur_pos = lseek(log->logfd, log->sectorsize, SEEK_SET); + if (log->cur_pos == (off_t)-1) { fprintf(stderr, "Error seeking in file: %d\n", errno); return -1; } @@ -229,9 +292,14 @@ int log_seek_entry(struct log *log, u64 entry_num) fprintf(stderr, "Error reading entry: %d\n", errno); return -1; } + if (!log_entry_valid(&entry)) { + fprintf(stderr, "Malformed entry @%llu\n", + log->cur_pos / log->sectorsize); + return -1; + } if (log_writes_verbose > 1) - printf("seek entry %d: %llu, size %llu, flags %llu\n", - (int)i, + printf("seek entry %d@%llu: %llu, size %llu, flags %llu\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), (unsigned long long)le64_to_cpu(entry.flags)); @@ -240,7 +308,8 @@ int log_seek_entry(struct log *log, u64 entry_num) if (!(flags & LOG_DISCARD_FLAG)) seek_size += le64_to_cpu(entry.nr_sectors) * log->sectorsize; - if (lseek(log->logfd, seek_size, SEEK_CUR) == (off_t)-1) { + log->cur_pos = lseek(log->logfd, seek_size, SEEK_CUR); + if (log->cur_pos == (off_t)-1) { fprintf(stderr, "Error seeking in file: %d\n", errno); return -1; } @@ -277,29 +346,37 @@ int log_seek_next_entry(struct log *log, struct log_write_entry *entry, fprintf(stderr, "Error reading entry: %d\n", errno); return -1; } + if (!log_entry_valid(entry)) { + fprintf(stderr, "Malformed entry @%llu\n", + log->cur_pos / log->sectorsize); + return -1; + } log->cur_entry++; if (read_size < log->sectorsize) { - if (lseek(log->logfd, - log->sectorsize - sizeof(struct log_write_entry), - SEEK_CUR) == (off_t)-1) { + log->cur_pos = lseek(log->logfd, + log->sectorsize - sizeof(struct log_write_entry), SEEK_CUR); + if (log->cur_pos == (off_t)-1) { fprintf(stderr, "Error seeking in log: %d\n", errno); return -1; } + } else { + log->cur_pos += read_size; } if (log_writes_verbose > 1) - printf("seek entry %d: %llu, size %llu, flags %llu\n", - (int)log->cur_entry - 1, + printf("seek entry %d@%llu: %llu, size %llu, flags %llu\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)); - flags = le32_to_cpu(entry->flags); - read_size = le32_to_cpu(entry->nr_sectors) * log->sectorsize; + 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; - if (lseek(log->logfd, read_size, SEEK_CUR) == (off_t)-1) { + log->cur_pos = lseek(log->logfd, read_size, SEEK_CUR); + if (log->cur_pos == (off_t)-1) { fprintf(stderr, "Error seeking in log: %d\n", errno); return -1; } @@ -369,8 +446,8 @@ struct log *log_open(char *logfile, char *replayfile) log->nr_entries = le64_to_cpu(super.nr_entries); log->max_zero_size = 128 * 1024 * 1024; - if (lseek(log->logfd, log->sectorsize - sizeof(super), SEEK_CUR) == - (off_t) -1) { + log->cur_pos = lseek(log->logfd, log->sectorsize - sizeof(super), SEEK_CUR); + if (log->cur_pos == (off_t) -1) { fprintf(stderr, "Error seeking to first entry: %d\n", errno); log_free(log); return NULL;