You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
75 lines
3.0 KiB
75 lines
3.0 KiB
6 years ago
|
commit c76242c56efb4d799bb15af1035a5f503cb4b8f3
|
||
|
Author: Tomasz Majchrzak <tomasz.majchrzak@intel.com>
|
||
|
Date: Wed Oct 4 10:18:21 2017 +0200
|
||
|
|
||
|
mdmon: get safe mode delay file descriptor early
|
||
|
|
||
|
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>
|
||
|
|
||
|
diff --git a/managemon.c b/managemon.c
|
||
|
index cc3c6f1..4e85398 100644
|
||
|
--- a/managemon.c
|
||
|
+++ b/managemon.c
|
||
|
@@ -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 0b08c3d..818367c 100644
|
||
|
--- 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
|