]> git.ipfire.org Git - thirdparty/mdadm.git/commitdiff
Manage/stop: guard against 'completed' being too large.
authorNeilBrown <neilb@suse.de>
Mon, 6 Jul 2015 03:33:20 +0000 (13:33 +1000)
committerNeilBrown <neilb@suse.de>
Mon, 6 Jul 2015 03:33:20 +0000 (13:33 +1000)
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>
Manage.c

index 17d66de9c08f29f9d5fd213c6ff80229da68337f..aeb90dd25a079eab5b6307d58e4390cb010f188c 100644 (file)
--- 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) {