summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2015-07-06 13:33:20 +1000
committerNeilBrown <neilb@suse.de>2015-07-06 13:33:20 +1000
commit30ddba7de56f598f2ebb5a8a36c7ee8282a54dbd (patch)
treea9f299f178d33ffff30e41e33bf2e45e3968735c
parentd3f6cf4f9bf670d36f51a8c0825755523fa6197c (diff)
downloadmdadm-30ddba7de56f598f2ebb5a8a36c7ee8282a54dbd.tar.gz
Manage/stop: guard against 'completed' being too large.
A race can allow 'completed' to read as 2^63-1, which takes a long time to count up to. So guard against that possibility. Signed-off-by: NeilBrown <neilb@suse.com>
-rw-r--r--Manage.c6
1 files changed, 5 insertions, 1 deletions
diff --git a/Manage.c b/Manage.c
index 17d66de..aeb90dd 100644
--- a/Manage.c
+++ b/Manage.c
@@ -400,6 +400,7 @@ int Manage_stop(char *devname, int fd, int verbose, int will_retry)
delay = 3000;
scfd = sysfs_open(mdi->sys_name, NULL, "sync_completed");
while (scfd >= 0 && delay > 0 && old_sync_max > 0) {
+ unsigned long long max_completed;
sysfs_get_ll(mdi, NULL, "reshape_position", &curr);
sysfs_fd_get_str(scfd, buf, sizeof(buf));
if (strncmp(buf, "none", 4) == 0) {
@@ -413,7 +414,10 @@ int Manage_stop(char *devname, int fd, int verbose, int will_retry)
break;
}
- if (sysfs_fd_get_ll(scfd, &completed) == 0 &&
+ if (sysfs_fd_get_two(scfd, &completed,
+ &max_completed) == 2 &&
+ /* 'completed' sometimes reads as max-uulong */
+ completed < max_completed &&
(completed > sync_max ||
(completed == sync_max && curr != position))) {
while (completed > sync_max) {