]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - super1.c
Just updaqte copyright dates and email address
[thirdparty/mdadm.git] / super1.c
index a1e0cbe17cd129da53df49a4cbb047d96d5b8e3a..cc0a5e3003194b4e38de66c8566a728d3b06a45f 100644 (file)
--- a/super1.c
+++ b/super1.c
@@ -1,7 +1,7 @@
 /*
  * mdadm - manage Linux "md" devices aka RAID arrays.
  *
- * Copyright (C) 2001-2004 Neil Brown <neilb@cse.unsw.edu.au>
+ * Copyright (C) 2001-2006 Neil Brown <neilb@suse.de>
  *
  *
  *    This program is free software; you can redistribute it and/or modify
@@ -28,8 +28,6 @@
  */
 
 #include "mdadm.h"
-#include <endian.h>
-#include "asm/byteorder.h"
 /*
  * The version-1 superblock :
  * All numeric fields are little-endian.
@@ -60,8 +58,8 @@ struct mdp_superblock_1 {
                                 */
 
        /* These are only valid with feature bit '4' */
-       __u64   reshape_position;       /* next address in array-space for reshape */
        __u32   new_level;      /* new level we are reshaping to                */
+       __u64   reshape_position;       /* next address in array-space for reshape */
        __u32   delta_disks;    /* change in number of raid_disks               */
        __u32   new_layout;     /* new layout                                   */
        __u32   new_chunk;      /* new chunk size (bytes)                       */
@@ -195,9 +193,10 @@ static void examine_super1(void *sbv)
        printf("\n");
        if (sb->feature_map & __cpu_to_le32(MD_FEATURE_BITMAP_OFFSET)) {
                printf("Internal Bitmap : %ld sectors from superblock\n",
-                      __le32_to_cpu(sb->bitmap_offset));
+                      (long)__le32_to_cpu(sb->bitmap_offset));
+       }
        if (sb->feature_map & __le32_to_cpu(MD_FEATURE_RESHAPE_ACTIVE)) {
-               printf("  Reshape pos'n : %llu%s\n", __le64_to_cpu(sb->reshape_position)/2,
+               printf("  Reshape pos'n : %llu%s\n", (unsigned long long)__le64_to_cpu(sb->reshape_position)/2,
                       human_size(__le64_to_cpu(sb->reshape_position)<<9));
                if (__le32_to_cpu(sb->delta_disks)) {
                        printf("  Delta Devices : %d", __le32_to_cpu(sb->delta_disks));
@@ -219,8 +218,9 @@ static void examine_super1(void *sbv)
                                printf("     New Layout : %s\n", c?c:"-unknown-");
                        }
                        if (__le32_to_cpu(sb->level) == 10) {
-                               printf("     New Layout : near=%d, far=%d\n",
+                               printf("     New Layout : near=%d, %s=%d\n",
                                       __le32_to_cpu(sb->new_layout)&255,
+                                      (__le32_to_cpu(sb->new_layout)&0x10000)?"offset":"far",
                                       (__le32_to_cpu(sb->new_layout)>>8)&255);
                        }
                }
@@ -251,8 +251,10 @@ static void examine_super1(void *sbv)
        }
        if (__le32_to_cpu(sb->level) == 10) {
                int lo = __le32_to_cpu(sb->layout);
-               printf("         Layout : near=%d, far=%d\n",
-                      lo&255, (lo>>8)&255);
+               printf("         Layout : near=%d, %s=%d\n",
+                      lo&255,
+                      (lo&0x10000)?"offset":"far",
+                      (lo>>8)&255);
        }
        switch(__le32_to_cpu(sb->level)) {
        case 0:
@@ -354,7 +356,7 @@ static void uuid_from_super1(int uuid[4], void * sbv)
                cuuid[i] = super->set_uuid[i];
 }
 
-static void getinfo_super1(struct mdinfo *info, mddev_ident_t ident, void *sbv)
+static void getinfo_super1(struct mdinfo *info, void *sbv)
 {
        struct mdp_superblock_1 *sb = sbv;
        int working = 0;
@@ -369,6 +371,11 @@ static void getinfo_super1(struct mdinfo *info, mddev_ident_t ident, void *sbv)
        info->array.layout = __le32_to_cpu(sb->layout);
        info->array.md_minor = -1;
        info->array.ctime = __le64_to_cpu(sb->ctime);
+       info->array.utime = __le64_to_cpu(sb->utime);
+       info->array.chunk_size = __le32_to_cpu(sb->chunksize)*512;
+
+       info->data_offset = __le64_to_cpu(sb->data_offset);
+       info->component_size = __le64_to_cpu(sb->size);
 
        info->disk.major = 0;
        info->disk.minor = 0;
@@ -395,8 +402,18 @@ static void getinfo_super1(struct mdinfo *info, mddev_ident_t ident, void *sbv)
 
        memcpy(info->uuid, sb->set_uuid, 16);
 
-       strncpy(ident->name, sb->set_name, 32);
-       ident->name[32] = 0;
+       strncpy(info->name, sb->set_name, 32);
+       info->name[32] = 0;
+
+       if (sb->feature_map & __le32_to_cpu(MD_FEATURE_RESHAPE_ACTIVE)) {
+               info->reshape_active = 1;
+               info->reshape_progress = __le64_to_cpu(sb->reshape_position);
+               info->new_level = __le32_to_cpu(sb->new_level);
+               info->delta_disks = __le32_to_cpu(sb->delta_disks);
+               info->new_layout = __le32_to_cpu(sb->new_layout);
+               info->new_chunk = __le32_to_cpu(sb->new_chunk)<<9;
+       } else
+               info->reshape_active = 0;
 
        for (i=0; i< __le32_to_cpu(sb->max_dev); i++) {
                role = __le16_to_cpu(sb->dev_roles[i]);
@@ -409,14 +426,21 @@ static void getinfo_super1(struct mdinfo *info, mddev_ident_t ident, 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;
                }
        }
@@ -452,8 +476,16 @@ static int update_super1(struct mdinfo *info, void *sbv, char *update, char *dev
                /* make sure resync happens */
                sb->resync_offset = ~0ULL;
        }
-       if (strcmp(update, "uuid") == 0)
+       if (strcmp(update, "uuid") == 0) {
                memcpy(sb->set_uuid, info->uuid, 16);
+               if (__le32_to_cpu(sb->feature_map)&MD_FEATURE_BITMAP_OFFSET) {
+                       struct bitmap_super_s *bm;
+                       bm = (struct bitmap_super_s*)(sbv+1024);
+                       memcpy(bm->uuid, info->uuid, 16);
+               }
+       }
+       if (strcmp(update, "_reshape_progress")==0)
+               sb->reshape_position = __cpu_to_le64(info->reshape_progress);
 
        sb->sb_csum = calc_sb_1_csum(sb);
        return rv;
@@ -543,6 +575,8 @@ static void add_to_super1(void *sbv, mdu_disk_info_t *dk)
                *rp = 0xfffe;
 }
 
+static void locate_bitmap1(struct supertype *st, int fd, void *sbv);
+
 static int store_super1(struct supertype *st, int fd, void *sbv)
 {
        struct mdp_superblock_1 *sb = sbv;
@@ -606,6 +640,14 @@ static int store_super1(struct supertype *st, int fd, void *sbv)
        if (write(fd, sb, sbsize) != sbsize)
                return 4;
 
+       if (sb->feature_map & __cpu_to_le32(MD_FEATURE_BITMAP_OFFSET)) {
+               struct bitmap_super_s *bm = (struct bitmap_super_s*)
+                       ((char*)sb)+1024;
+               if (__le32_to_cpu(bm->magic) == BITMAP_MAGIC) {
+                       locate_bitmap1(st, fd, sbv);
+                       write(fd, bm, sizeof(*bm));
+               }
+       }
        fsync(fd);
        return 0;
 }
@@ -621,8 +663,8 @@ static int write_init_super1(struct supertype *st, void *sbv,
        int rfd;
        int rv;
 
-       unsigned long size;
-       unsigned long long dsize;
+       unsigned long size, space;
+       unsigned long long dsize, array_size;
        long long sb_offset;
 
 
@@ -685,6 +727,7 @@ static int write_init_super1(struct supertype *st, void *sbv,
         * Depending on the array size, we might leave extra space
         * for a bitmap.
         */
+       array_size = __le64_to_cpu(sb->size);
        switch(st->minor_version) {
        case 0:
                sb_offset = dsize;
@@ -692,14 +735,14 @@ static int write_init_super1(struct supertype *st, void *sbv,
                sb_offset &= ~(4*2-1);
                sb->super_offset = __cpu_to_le64(sb_offset);
                sb->data_offset = __cpu_to_le64(0);
-               if (sb_offset-64*2 >= array_size)
+               if (sb_offset-64*2 >= array_size && array_size > 8*1024*1024*2)
                        sb->data_size = __cpu_to_le64(sb_offset-64*2);
                else
                        sb->data_size = __cpu_to_le64(sb_offset);
                break;
        case 1:
                sb->super_offset = __cpu_to_le64(0);
-               if (dsize - 64*2 >= array_size)
+               if (dsize - 64*2 >= array_size && array_size > 8*1024*1024*2)
                        space = 64*2;
                else
                        space = 4*2;
@@ -708,7 +751,7 @@ static int write_init_super1(struct supertype *st, void *sbv,
                break;
        case 2:
                sb_offset = 4*2;
-               if (dsize - 4*2 - 64*2 >= array_size)
+               if (dsize - 4*2 - 64*2 >= array_size && array_size > 8*1024*1024*2)
                        space = 64*2;
                else
                        space = 4*2;
@@ -750,8 +793,8 @@ static int compare_super1(void **firstp, void *secondv)
                return 1;
 
        if (!first) {
-               first = malloc(1024);
-               memcpy(first, second, 1024);
+               first = malloc(1024+sizeof(bitmap_super_t));
+               memcpy(first, second, 1024+sizeof(bitmap_super_t));
                *firstp = first;
                return 0;
        }
@@ -774,7 +817,8 @@ static int load_super1(struct supertype *st, int fd, void **sbp, char *devname)
        unsigned long long dsize;
        unsigned long long sb_offset;
        struct mdp_superblock_1 *super;
-
+       int uuid[4];
+       struct bitmap_super_s *bsb;
 
 
        if (st->ss == NULL) {
@@ -833,7 +877,7 @@ static int load_super1(struct supertype *st, int fd, void **sbp, char *devname)
        /*
         * Calculate the position of the superblock.
         * It is always aligned to a 4K boundary and
-        * depeding on minor_version, it can be:
+        * depending on minor_version, it can be:
         * 0: At least 8K, but less than 12K, from end of device
         * 1: At start of device
         * 2: 4K from start of device.
@@ -897,6 +941,28 @@ static int load_super1(struct supertype *st, int fd, void **sbp, char *devname)
                return 2;
        }
        *sbp = super;
+
+       /* Now check on the bitmap superblock */
+       if ((__le32_to_cpu(super->feature_map)&MD_FEATURE_BITMAP_OFFSET) == 0)
+               return 0;
+       /* Read the bitmap superblock and make sure it looks
+        * valid.  If it doesn't clear the bit.  An --assemble --force
+        * should get that written out.
+        */
+       locate_bitmap1(st, fd, super);
+       if (read(fd, ((char*)super)+1024, sizeof(struct bitmap_super_s))
+           != sizeof(struct bitmap_super_s))
+               goto no_bitmap;
+
+       uuid_from_super1(uuid, super);
+       bsb = (struct bitmap_super_s *)(((char*)super)+1024);
+       if (__le32_to_cpu(bsb->magic) != BITMAP_MAGIC ||
+           memcmp(bsb->uuid, uuid, 16) != 0)
+               goto no_bitmap;
+       return 0;
+
+ no_bitmap:
+       super->feature_map = __cpu_to_le32(__le32_to_cpu(super->feature_map) & ~1);
        return 0;
 }
 
@@ -909,7 +975,8 @@ static struct supertype *match_metadata_desc1(char *arg)
        st->ss = &super1;
        st->max_devs = 384;
        if (strcmp(arg, "1") == 0 ||
-           strcmp(arg, "1.0") == 0) {
+           strcmp(arg, "1.0") == 0 ||
+           strcmp(arg, "default/large") == 0) {
                st->minor_version = 0;
                return st;
        }
@@ -1013,25 +1080,27 @@ add_internal_bitmap1(struct supertype *st, void *sbv,
 }
 
 
-void locate_bitmap1(struct supertype *st, int fd, void *sbv)
+static void locate_bitmap1(struct supertype *st, int fd, void *sbv)
 {
        unsigned long long offset;
        struct mdp_superblock_1 *sb;
+       int mustfree = 0;
 
-       if (!sbv)
-               if (st->ss->load_super(st, fd, sbv, NULL))
+       if (!sbv) {
+               if (st->ss->load_super(st, fd, &sbv, NULL))
                        return; /* no error I hope... */
-
+               mustfree = 1;
+       }
        sb = sbv;
 
        offset = __le64_to_cpu(sb->super_offset);
        offset += (long) __le32_to_cpu(sb->bitmap_offset);
-       if (!sbv)
+       if (mustfree)
                free(sb);
        lseek64(fd, offset<<9, 0);
 }
 
-int write_bitmap1(struct supertype *st, int fd, void *sbv)
+static int write_bitmap1(struct supertype *st, int fd, void *sbv)
 {
        struct mdp_superblock_1 *sb = sbv;
        bitmap_super_t *bms = (bitmap_super_t*)(((char*)sb)+1024);
@@ -1042,7 +1111,9 @@ int write_bitmap1(struct supertype *st, int fd, void *sbv)
 
        locate_bitmap1(st, fd, sbv);
 
-       write(fd, ((char*)sb)+1024, sizeof(bitmap_super_t));
+       if (write(fd, ((char*)sb)+1024, sizeof(bitmap_super_t)) !=
+           sizeof(bitmap_super_t))
+               return -2;
        towrite = __le64_to_cpu(bms->sync_size) / (__le32_to_cpu(bms->chunksize)>>9);
        towrite = (towrite+7) >> 3; /* bits to bytes */
        memset(buf, 0xff, sizeof(buf));