]> git.ipfire.org Git - thirdparty/mdadm.git/commitdiff
[PATCH] Make sure update_super returns correct value.
authorNeil Brown <neilb@suse.de>
Fri, 28 Apr 2006 04:10:38 +0000 (14:10 +1000)
committerNeil Brown <neilb@suse.de>
Fri, 28 Apr 2006 04:10:38 +0000 (14:10 +1000)
For 'force' and 'assemble', update_super must return true
if anything was changed.

Also fix a bug with wonly handling in super0.

Signed-off-by: Neil Brown <neilb@suse.de>
### Diffstat output
 ./super0.c |   18 ++++++++++++++----
 ./super1.c |    7 +++++++
 2 files changed, 21 insertions(+), 4 deletions(-)

diff ./super0.c~current~ ./super0.c

super0.c
super1.c

index a36b0a7862588394abb94dadba4b259c2a420574..49474d07fca284697691ff5de6d677ed0d2c3b43 100644 (file)
--- a/super0.c
+++ b/super0.c
@@ -317,6 +317,9 @@ static void getinfo_super0(struct mdinfo *info, void *sbv)
 
 static int update_super0(struct mdinfo *info, void *sbv, char *update, char *devname, int verbose)
 {
+       /* NOTE: for 'assemble' and 'force' we need to return non-zero if any change was made.
+        * For others, the return value is ignored.
+        */
        int rv = 0;
        mdp_super_t *sb = sbv;
        if (strcmp(update, "sparc2.2")==0 ) {
@@ -367,18 +370,25 @@ static int update_super0(struct mdinfo *info, void *sbv, char *update, char *dev
                                sb->disks[i].state = 0;
        }
        if (strcmp(update, "force")==0) {
+               __u32 ehi = sb->events_hi, elo = sb->events_lo;
                sb->events_hi = (info->events>>32) & 0xFFFFFFFF;
                sb->events_lo = (info->events) & 0xFFFFFFFF;
-               if (sb->level == 5 || sb->level == 4 || sb->level == 6)
+               if (sb->events_hi != ehi ||
+                   sb->events_lo != elo)
+                       rv = 1;
+               if ((sb->level == 5 || sb->level == 4 || sb->level == 6) &&
+                   (sb->state & (1 << MD_SB_CLEAN)) == 0) {
                        /* need to force clean */
                        sb->state |= (1 << MD_SB_CLEAN);
+                       rv = 1;
+               }
        }
        if (strcmp(update, "assemble")==0) {
                int d = info->disk.number;
                int wonly = sb->disks[d].state & (1<<MD_DISK_WRITEMOSTLY);
-               sb->disks[d].state &= ~(1<<MD_DISK_WRITEMOSTLY);
-               if (sb->disks[d].state != info->disk.state) {
-                       sb->disks[d].state = info->disk.state & wonly;
+               if ((sb->disks[d].state & ~(1<<MD_DISK_WRITEMOSTLY))
+                   != info->disk.state) {
+                       sb->disks[d].state = info->disk.state | wonly;
                        rv = 1;
                }
        }
index 27cec874293eb77356285b33c93639d648b19c9a..1ab077691b5028886c6b53f8107906cd560d1c1f 100644 (file)
--- a/super1.c
+++ b/super1.c
@@ -423,14 +423,21 @@ static void getinfo_super1(struct mdinfo *info, void *sbv)
 
 static int update_super1(struct mdinfo *info, void *sbv, char *update, char *devname, int verbose)
 {
+       /* NOTE: for 'assemble' and 'force' we need to return non-zero if any change was made.
+        * For others, the return value is ignored.
+        */
        int rv = 0;
        struct mdp_superblock_1 *sb = sbv;
 
        if (strcmp(update, "force")==0) {
+               if (sb->events != __cpu_to_le64(info->events))
+                       rv = 1;
                sb->events = __cpu_to_le64(info->events);
                switch(__le32_to_cpu(sb->level)) {
                case 5: case 4: case 6:
                        /* need to force clean */
+                       if (sb->resync_offset != ~0ULL)
+                               rv = 1;
                        sb->resync_offset = ~0ULL;
                }
        }