]> www.infradead.org Git - mtd-utils.git/commitdiff
fs-tests: integck: add recovery remounting function
authorArtem Bityutskiy <Artem.Bityutskiy@nokia.com>
Wed, 20 Apr 2011 14:25:01 +0000 (17:25 +0300)
committerArtem Bityutskiy <Artem.Bityutskiy@nokia.com>
Fri, 22 Apr 2011 11:29:53 +0000 (14:29 +0300)
When re-mountig to recover from the emulated power-cut failure then we should
do a bit less fancy things, e.g., we should not try to re-mount to R/O and R/W
modes forth and back, but we should instead just unmount directly.

Additionally, we should not die if mount fails because there may be a power
cut emulation during mounting. Thus, create a separate function for recovering
and try to recover in a loop.

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

index 0d69ee4b54f5cde9d8683fac65213c3d5c7f25eb..18164611489e9460fc8ab935fa3718190235c827 100644 (file)
@@ -2268,15 +2268,21 @@ static int remount_tested_fs(void)
                flags = fsinfo.mount_flags | MS_RDONLY | MS_REMOUNT;
                ret = mount(fsinfo.fsdev, fsinfo.mount_point, fsinfo.fstype,
                            flags, fsinfo.mount_opts);
-               if (ret)
+               if (ret) {
+                       pcv("cannot remount %s R/O (1)",
+                           fsinfo.mount_point);
                        return -1;
+               }
 
                flags = fsinfo.mount_flags | MS_REMOUNT;
                flags &= ~((unsigned long)MS_RDONLY);
                ret = mount(fsinfo.fsdev, fsinfo.mount_point, fsinfo.fstype,
                            flags, fsinfo.mount_opts);
-               if (ret)
+               if (ret) {
+                       pcv("remounted %s R/O (1), but cannot re-mount it R/W",
+                           fsinfo.mount_point);
                        return -1;
+               }
        }
 
        if (um) {
@@ -2284,31 +2290,47 @@ static int remount_tested_fs(void)
                        flags = fsinfo.mount_flags | MS_RDONLY | MS_REMOUNT;
                        ret = mount(fsinfo.fsdev, fsinfo.mount_point,
                                    fsinfo.fstype, flags, fsinfo.mount_opts);
-                       if (ret)
+                       if (ret) {
+                               pcv("cannot remount %s R/O (2)",
+                                   fsinfo.mount_point);
                                return -1;
+                       }
                }
 
-               CHECK(umount(fsinfo.mount_point) != -1);
+               ret = umount(fsinfo.mount_point);
+               if (ret) {
+                       pcv("cannot unmount %s", fsinfo.mount_point);
+                       return -1;
+               }
 
                if (!um_rorw) {
                        ret = mount(fsinfo.fsdev, fsinfo.mount_point,
                                    fsinfo.fstype, fsinfo.mount_flags,
                                    fsinfo.mount_opts);
-                       if (ret)
+                       if (ret) {
+                               pcv("unmounted %s, but cannot mount it back R/W",
+                                   fsinfo.mount_point);
                                return -1;
+                       }
                } else {
                        ret = mount(fsinfo.fsdev, fsinfo.mount_point,
                                    fsinfo.fstype, fsinfo.mount_flags | MS_RDONLY,
                                    fsinfo.mount_opts);
-                       if (ret)
+                       if (ret) {
+                               pcv("unmounted %s, but cannot mount it back R/O",
+                                   fsinfo.mount_point);
                                return -1;
+                       }
 
                        flags = fsinfo.mount_flags | MS_REMOUNT;
                        flags &= ~((unsigned long)MS_RDONLY);
                        ret = mount(fsinfo.fsdev, fsinfo.mount_point,
                                    fsinfo.fstype, flags, fsinfo.mount_opts);
-                       if (ret)
+                       if (ret) {
+                               pcv("unmounted %s, mounted R/O, but cannot re-mount it R/W",
+                                    fsinfo.mount_point);
                                return -1;
+                       }
                }
        }
 
@@ -2316,15 +2338,20 @@ static int remount_tested_fs(void)
                flags = fsinfo.mount_flags | MS_RDONLY | MS_REMOUNT;
                ret = mount(fsinfo.fsdev, fsinfo.mount_point, fsinfo.fstype,
                            flags, fsinfo.mount_opts);
-               if (ret)
+               if (ret) {
+                       pcv("cannot re-mount %s R/O (3)", fsinfo.mount_point);
                        return -1;
+               }
 
                flags = fsinfo.mount_flags | MS_REMOUNT;
                flags &= ~((unsigned long)MS_RDONLY);
                ret = mount(fsinfo.fsdev, fsinfo.mount_point, fsinfo.fstype,
                            flags, fsinfo.mount_opts);
-               if (ret)
+               if (ret) {
+                       pcv("remounted %s R/O (3), but cannot re-mount it back R/W",
+                            fsinfo.mount_point);
                        return -1;
+               }
        }
 
        /* Restore the previous working directory */
@@ -2664,9 +2691,91 @@ static void free_fs_info(struct dir_info *dir)
        }
 }
 
+/**
+ * Recover the tested file-system from an emulated power cut failure by
+ * unmounting it and mounting it again.
+ */
+static int recover_tested_fs(void)
+{
+       char *wd_save;
+       int ret;
+       unsigned long flags;
+       unsigned int  um_rorw, rorw2;
+
+       /* Save current working directory */
+       wd_save = malloc(PATH_MAX + 1);
+       CHECK(wd_save != NULL);
+       CHECK(getcwd(wd_save, PATH_MAX + 1) != NULL);
+
+       /* Temporarily change working directory to '/' */
+       CHECK(chdir("/") == 0);
+
+       /* Choose what to do */
+       um_rorw = rand() & 1;
+       rorw2 = rand() & 1;
+
+       CHECK(umount(fsinfo.mount_point) != -1);
+
+       if (!um_rorw) {
+               ret = mount(fsinfo.fsdev, fsinfo.mount_point,
+                           fsinfo.fstype, fsinfo.mount_flags,
+                           fsinfo.mount_opts);
+               if (ret) {
+                       pcv("unmounted %s, but cannot mount it back R/W",
+                           fsinfo.mount_point);
+                       return -1;
+               }
+       } else {
+               ret = mount(fsinfo.fsdev, fsinfo.mount_point,
+                           fsinfo.fstype, fsinfo.mount_flags | MS_RDONLY,
+                           fsinfo.mount_opts);
+               if (ret) {
+                       pcv("unmounted %s, but cannot mount it back R/O",
+                           fsinfo.mount_point);
+                       return -1;
+               }
+
+               flags = fsinfo.mount_flags | MS_REMOUNT;
+               flags &= ~((unsigned long)MS_RDONLY);
+               ret = mount(fsinfo.fsdev, fsinfo.mount_point,
+                           fsinfo.fstype, flags, fsinfo.mount_opts);
+               if (ret) {
+                       pcv("unmounted %s, mounted R/O, but cannot re-mount it R/W",
+                            fsinfo.mount_point);
+                       return -1;
+               }
+       }
+
+       if (rorw2) {
+               flags = fsinfo.mount_flags | MS_RDONLY | MS_REMOUNT;
+               ret = mount(fsinfo.fsdev, fsinfo.mount_point, fsinfo.fstype,
+                           flags, fsinfo.mount_opts);
+               if (ret) {
+                       pcv("cannot re-mount %s R/O", fsinfo.mount_point);
+                       return -1;
+               }
+
+               flags = fsinfo.mount_flags | MS_REMOUNT;
+               flags &= ~((unsigned long)MS_RDONLY);
+               ret = mount(fsinfo.fsdev, fsinfo.mount_point, fsinfo.fstype,
+                           flags, fsinfo.mount_opts);
+               if (ret) {
+                       pcv("remounted %s R/O, but cannot re-mount it back R/W",
+                            fsinfo.mount_point);
+                       return -1;
+               }
+       }
+
+       /* Restore the previous working directory */
+       CHECK(chdir(wd_save) == 0);
+       free(wd_save);
+       return 0;
+}
+
 int main(int argc, char *argv[])
 {
        int ret;
+       unsigned long long restart_count = 0;
 
        ret = parse_opts(argc, argv);
        if (ret)
@@ -2703,11 +2812,27 @@ int main(int argc, char *argv[])
                 * testing mode. Re-mount the file-system and re-start the
                 * test.
                 */
+               if (args.verbose)
+                       normsg("re-mount the FS and re-start - count %llu",
+                              ++restart_count);
+
                close_open_files();
                free_fs_info(top_dir);
-               ret = remount_tested_fs();
-               if (ret)
-                       break;
+
+               do {
+                       ret = recover_tested_fs();
+                       if (ret) {
+                               if (errno != EROFS)
+                                       goto out_free;
+                               /*
+                                * Mount may also fail due to an emulated power
+                                * cut while mounting - keep re-starting.
+                                */
+                               if (args.verbose)
+                                       normsg("could not mount, restart - count %llu",
+                                              ++restart_count);
+                       }
+               } while (ret);
        }
 
        close_open_files();