]> www.infradead.org Git - mtd-utils.git/commitdiff
fs-tests: integck: add -e option to verify operations
authorArtem Bityutskiy <Artem.Bityutskiy@nokia.com>
Fri, 22 Apr 2011 13:37:05 +0000 (16:37 +0300)
committerArtem Bityutskiy <Artem.Bityutskiy@nokia.com>
Sun, 24 Apr 2011 16:12:30 +0000 (19:12 +0300)
Improve the test and add -e option which forces integck to verify all
operation it performs. This patch does not implement file writes and
holes operations so far - will be done in subsequent patches.

Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
tests/fs-tests/integrity/integck.c

index 9822b3bc5975d181e34391633d3ccc37d89fd9ed..f39745f45dcde20ccd0966122fe7d470597d8a88 100644 (file)
@@ -68,6 +68,7 @@
 static struct {
        long repeat_cnt;
        int power_cut_mode;
+       int verify_ops;
        int verbose;
        const char *mount_point;
 } args = {
@@ -529,6 +530,13 @@ static int dir_new(struct dir_info *parent, const char *name)
                free(path);
                return -1;
        }
+
+       if (args.verify_ops) {
+               struct stat st;
+
+               CHECK(lstat(path, &st) == 0);
+               CHECK(S_ISDIR(st.st_mode));
+       }
        free(path);
 
        add_dir_entry(parent, 'd', name, NULL);
@@ -569,8 +577,16 @@ static int dir_remove(struct dir_info *dir)
                return -1;
        }
 
+       if (args.verify_ops) {
+               struct stat st;
+
+               CHECK(lstat(path, &st) == -1);
+               CHECK(errno == ENOENT);
+       }
+
        /* Remove entry from parent directory */
        remove_dir_entry(dir->entry, 1);
+
        free(path);
        return 0;
 }
@@ -597,10 +613,17 @@ static int file_new(struct dir_info *parent, const char *name)
                free(path);
                return -1;
        }
-       free(path);
 
+       if (args.verify_ops) {
+               struct stat st;
+
+               CHECK(lstat(path, &st) == 0);
+               CHECK(S_ISREG(st.st_mode));
+       }
        file = add_dir_entry(parent, 'f', name, NULL);
        add_fd(file, fd);
+
+       free(path);
        return 0;
 }
 
@@ -610,6 +633,7 @@ static int link_new(struct dir_info *parent, const char *name,
        struct dir_entry_info *entry;
        char *path, *target;
        int ret;
+       struct stat st1, st2;
 
        entry = file->links;
        if (!entry)
@@ -617,6 +641,10 @@ static int link_new(struct dir_info *parent, const char *name,
 
        path = dir_path(parent, name);
        target = dir_path(entry->parent, entry->name);
+
+       if (args.verify_ops)
+               CHECK(lstat(target, &st1) == 0);
+
        ret = link(target, path);
        if (ret != 0) {
                if (errno == ENOSPC) {
@@ -629,9 +657,19 @@ static int link_new(struct dir_info *parent, const char *name,
                free(path);
                return ret;
        }
+
+       if (args.verify_ops) {
+               CHECK(lstat(path, &st2) == 0);
+               CHECK(S_ISREG(st2.st_mode));
+               CHECK(st1.st_ino == st2.st_ino);
+               CHECK(st2.st_nlink > 1);
+               CHECK(st2.st_nlink == st1.st_nlink + 1);
+       }
+
+       add_dir_entry(parent, 'f', name, file);
+
        free(target);
        free(path);
-       add_dir_entry(parent, 'f', name, file);
        return 0;
 }
 
@@ -665,10 +703,18 @@ static int file_unlink(struct dir_entry_info *entry)
                free(path);
                return -1;
        }
-       free(path);
+
+       if (args.verify_ops) {
+               struct stat st;
+
+               CHECK(lstat(path, &st) == -1);
+               CHECK(errno == ENOENT);
+       }
 
        /* Remove file entry from parent directory */
        remove_dir_entry(entry, 1);
+
+       free(path);
        return 0;
 }
 
@@ -984,6 +1030,9 @@ static int file_ftruncate(struct file_info *file, int fd, off_t new_length)
                return -1;
        }
 
+       if (args.verify_ops)
+               CHECK(lseek(fd, 0, SEEK_END) == new_length);
+
        return 0;
 }
 
@@ -1724,6 +1773,7 @@ static int rename_entry(struct dir_entry_info *entry)
        struct dir_info *parent;
        char *path, *to, *name;
        int ret, isdir, retry;
+       struct stat st1, st2;
 
        if (!entry->parent)
                return 0;
@@ -1757,6 +1807,9 @@ static int rename_entry(struct dir_entry_info *entry)
        if (!path)
                return 0;
 
+       if (args.verify_ops)
+               CHECK(lstat(path, &st1) == 0);
+
        ret = rename(path, to);
        if (ret != 0) {
                ret = 0;
@@ -1772,6 +1825,11 @@ static int rename_entry(struct dir_entry_info *entry)
                return ret;
        }
 
+       if (args.verify_ops) {
+               CHECK(lstat(to, &st2) == 0);
+               CHECK(st1.st_ino == st2.st_ino);
+       }
+
        free(path);
        free(to);
 
@@ -1870,6 +1928,18 @@ static char *pick_symlink_target(const char *symlink_path)
        return rel_path;
 }
 
+static void verify_symlink(const char *target, const char *path)
+{
+       int bytes;
+       char buf[PATH_MAX + 1];
+
+       bytes = readlink(path, buf, PATH_MAX);
+       CHECK(bytes >= 0);
+       CHECK(bytes < PATH_MAX);
+       buf[bytes] = '\0';
+       CHECK(!strcmp(buf, target));
+}
+
 static int symlink_new(struct dir_info *dir, const char *nm)
 {
        struct symlink_info *s;
@@ -1896,10 +1966,14 @@ static int symlink_new(struct dir_info *dir, const char *nm)
                free(path);
                return ret;
        }
-       free(path);
+
+       if (args.verify_ops)
+               verify_symlink(target, path);
 
        s = add_dir_entry(dir, 's', name, NULL);
        s->target_pathname = target;
+
+       free(path);
        free(name);
        return 0;
 }
@@ -1915,7 +1989,15 @@ static int symlink_remove(struct symlink_info *symlink)
                return -1;
        }
 
+       if (args.verify_ops) {
+               struct stat st;
+
+               CHECK(lstat(path, &st) == -1);
+               CHECK(errno == ENOENT);
+       }
+
        remove_dir_entry(symlink->entry, 1);
+
        free(path);
        return 0;
 }
@@ -2247,11 +2329,34 @@ static int rm_minus_rf_dir(const char *dir_name)
 
        CHECK(chdir(buf) == 0);
        CHECK(closedir(dir) == 0);
+
+       if (args.verify_ops) {
+               dir = opendir(dir_name);
+               CHECK(dir != NULL);
+               do {
+                       errno = 0;
+                       dent = readdir(dir);
+                       if (dent)
+                               CHECK(!strcmp(dent->d_name, ".") ||
+                                     !strcmp(dent->d_name, ".."));
+               } while (dent);
+               CHECK(errno == 0);
+               CHECK(closedir(dir) == 0);
+       }
+
        ret = rmdir(dir_name);
        if (ret) {
                pcv("cannot remove directory %s", dir_name);
                return -1;
        }
+
+       if (args.verify_ops) {
+               struct stat st;
+
+               CHECK(lstat(dir_name, &st) == -1);
+               CHECK(errno == ENOENT);
+       }
+
        return 0;
 }
 
@@ -2600,6 +2705,11 @@ static const char doc[] = PROGRAM_NAME " version " PROGRAM_VERSION
 "directories, etc) should be there and the contents of the files should be\n"
 "correct. This is repeated a number of times (set with -n, default 1).\n"
 "\n"
+"By default the test does not verify file-system modifications and assumes they\n"
+"are done correctly if the file-system returns success. However, the -e flag\n"
+"enables additional verifications and the test verifies all the file-system\n"
+"operations it performs.\n"
+"\n"
 "This test is also able to perform power cut testing. The underlying file-system\n"
 "or the device driver should be able to emulate power-cuts, by switching to R/O\n"
 "mode at random moments. And the file-system should return EROFS (read-only\n"
@@ -2612,16 +2722,20 @@ static const char optionsstr[] =
 "-n, --repeat=<count> repeat count, default is 1; zero value - repeat forever\n"
 "-p, --power-cut      power cut testing mode (-n parameter is ignored and the\n"
 "                     test continues forever)\n"
+"-e, --verify-ops     verify all operations, e.g., every time a file is written\n"
+"                     to, read the data back and verify it, every time a\n"
+"                     directory is created, check that it exists, etc\n"
 "-v, --verbose        be verbose about failures during power cut testing\n"
 "-h, -?, --help       print help message\n"
 "-V, --version        print program version\n";
 
 static const struct option long_options[] = {
-       { .name = "repeat",    .has_arg = 1, .flag = NULL, .val = 'n' },
-       { .name = "power-cut", .has_arg = 0, .flag = NULL, .val = 'p' },
-       { .name = "verbose",   .has_arg = 0, .flag = NULL, .val = 'v' },
-       { .name = "help",      .has_arg = 0, .flag = NULL, .val = 'h' },
-       { .name = "version",   .has_arg = 0, .flag = NULL, .val = 'V' },
+       { .name = "repeat",     .has_arg = 1, .flag = NULL, .val = 'n' },
+       { .name = "power-cut",  .has_arg = 0, .flag = NULL, .val = 'p' },
+       { .name = "verify-ops", .has_arg = 0, .flag = NULL, .val = 'e' },
+       { .name = "verbose",    .has_arg = 0, .flag = NULL, .val = 'v' },
+       { .name = "help",       .has_arg = 0, .flag = NULL, .val = 'h' },
+       { .name = "version",    .has_arg = 0, .flag = NULL, .val = 'V' },
        { NULL, 0, NULL, 0},
 };
 
@@ -2636,7 +2750,7 @@ static int parse_opts(int argc, char * const argv[])
        while (1) {
                int key, error = 0;
 
-               key = getopt_long(argc, argv, "n:pvVh?", long_options, NULL);
+               key = getopt_long(argc, argv, "n:pevVh?", long_options, NULL);
                if (key == -1)
                        break;
 
@@ -2649,6 +2763,9 @@ static int parse_opts(int argc, char * const argv[])
                case 'p':
                        args.power_cut_mode = 1;
                        break;
+               case 'e':
+                       args.verify_ops = 1;
+                       break;
                case 'v':
                        args.verbose = 1;
                        break;
@@ -2867,7 +2984,6 @@ int main(int argc, char *argv[])
                } while (ret);
        }
 
-
        free_test_data();
 
 out_free: