]> git.ipfire.org Git - thirdparty/mdadm.git/commitdiff
mdmon: get safe mode delay file descriptor early
authorTomasz Majchrzak <tomasz.majchrzak@intel.com>
Wed, 4 Oct 2017 08:18:21 +0000 (10:18 +0200)
committerJes Sorensen <jsorensen@fb.com>
Wed, 4 Oct 2017 15:41:57 +0000 (11:41 -0400)
After switch root new mdmon is started. It sends initrd mdmon a signal
to terminate. initrd mdmon receives it and switches the safe mode delay
to 1 ms in order to get array to clean state and flush last version of
metadata. The problem is sysfs filesystem is not available to initrd mdmon
after switch root so the original safe mode delay is unchanged. The delay
is set to few seconds - if there is a lot of traffic on the filesystem,
initrd mdmon doesn't terminate for a long time (no clean state). There
are 2 instances of mdmon. initrd mdmon flushes metadata when array goes
to clean state but this metadata might be already outdated.

Use file descriptor obtained on mdmon start to change safe mode delay.

Signed-off-by: Tomasz Majchrzak <tomasz.majchrzak@intel.com>
Signed-off-by: Jes Sorensen <jsorensen@fb.com>
managemon.c
mdmon.h

index cc3c6f103ba902bcb5739450d93a292031e7ba3d..4e8539877823106c656a96eb905f5a9e901f5bf9 100644 (file)
@@ -129,6 +129,8 @@ static void close_aa(struct active_array *aa)
                close(aa->metadata_fd);
        if (aa->sync_completed_fd >= 0)
                close(aa->sync_completed_fd);
+       if (aa->safe_mode_delay_fd >= 0)
+               close(aa->safe_mode_delay_fd);
 }
 
 static void free_aa(struct active_array *aa)
@@ -532,9 +534,15 @@ static void manage_member(struct mdstat_ent *mdstat,
        if (a->container == NULL)
                return;
 
-       if (sigterm && a->info.safe_mode_delay != 1) {
-               sysfs_set_safemode(&a->info, 1);
-               a->info.safe_mode_delay = 1;
+       if (sigterm && a->info.safe_mode_delay != 1 &&
+           a->safe_mode_delay_fd >= 0) {
+               long int new_delay = 1;
+               char delay[10];
+               ssize_t len;
+
+               len = snprintf(delay, sizeof(delay), "0.%03ld\n", new_delay);
+               if (write(a->safe_mode_delay_fd, delay, len) == len)
+                       a->info.safe_mode_delay = new_delay;
        }
 
        /* We don't check the array while any update is pending, as it
@@ -734,6 +742,8 @@ static void manage_new(struct mdstat_ent *mdstat,
        new->resync_start_fd = sysfs_open2(new->info.sys_name, NULL, "resync_start");
        new->metadata_fd = sysfs_open2(new->info.sys_name, NULL, "metadata_version");
        new->sync_completed_fd = sysfs_open2(new->info.sys_name, NULL, "sync_completed");
+       new->safe_mode_delay_fd = sysfs_open2(new->info.sys_name, NULL,
+                                             "safe_mode_delay");
 
        dprintf("inst: %s action: %d state: %d\n", inst,
                new->action_fd, new->info.state_fd);
diff --git a/mdmon.h b/mdmon.h
index 0b08c3d7da2a62e6b3934e0b2716cd85fd2dc759..818367cbb14c95755d8384702abcc155d41d0e96 100644 (file)
--- a/mdmon.h
+++ b/mdmon.h
@@ -35,6 +35,7 @@ struct active_array {
        int resync_start_fd;
        int metadata_fd; /* for monitoring rw/ro status */
        int sync_completed_fd; /* for checkpoint notification events */
+       int safe_mode_delay_fd;
        unsigned long long last_checkpoint; /* sync_completed fires for many
                                             * reasons this field makes sure the
                                             * kernel has made progress before