]> git.ipfire.org Git - thirdparty/mdadm.git/commitdiff
Add support for internal bitmaps
authorNeil Brown <neilb@suse.de>
Tue, 7 Jun 2005 23:03:47 +0000 (23:03 +0000)
committerNeil Brown <neilb@suse.de>
Tue, 7 Jun 2005 23:03:47 +0000 (23:03 +0000)
For version 0.90 superblocks, an internal bitmap can be specified at create.

Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
Create.c
bitmap.c
md_p.h
mdadm.c
mdadm.h
super0.c

index de9a44f9b6693ccec4a5ef8ad5a2179542e787ec..5a359ee85b5b8d6f0500af179fdc85a16dd5288a 100644 (file)
--- a/Create.c
+++ b/Create.c
@@ -341,11 +341,26 @@ int Create(struct supertype *st, char *mddev, int mdfd,
        array.nr_disks = array.working_disks + array.failed_disks;
        array.layout = layout;
        array.chunk_size = chunk*1024;
-       printf("VERS = %d\n", vers);
+
 
        if (!st->ss->init_super(&super, &array))
                return 1;
 
+       if (bitmap_file && strcmp(bitmap_file, "internal")==0) {
+               if ((vers%100) < 2) {
+                       fprintf(stderr, Name ": internal bitmaps not supported by this kernel.\n");
+                       return 1;
+               }
+               if (!st->ss->add_internal_bitmap(super, bitmap_chunk, delay, 
+                                                size ? size : maxsize)) {
+                       fprintf(stderr, Name ": Given bitmap chunk size not supported.\n");
+                       return 1;
+               }
+               bitmap_file = NULL;
+       }
+
+
+
        if ((vers % 100) >= 1) { /* can use different versions */
                mdu_array_info_t inf;
                memset(&inf, 0, sizeof(inf));
@@ -362,6 +377,10 @@ int Create(struct supertype *st, char *mddev, int mdfd,
 
        if (bitmap_file) {
                int uuid[4];
+
+               if (bitmap_chunk == UnSet)
+                       bitmap_chunk = DEFAULT_BITMAP_CHUNK;
+
                st->ss->uuid_from_super(uuid, super);
                if (CreateBitmap(bitmap_file, force, (char*)uuid, bitmap_chunk, delay,
                                 array.size*2ULL /* FIXME wrong for raid10 */)) {
index 57969a67cea656872876572a2d34feac3f617a31..83a70bccdc9fe39b69296c949351c83f85c7be59 100644 (file)
--- a/bitmap.c
+++ b/bitmap.c
@@ -177,10 +177,11 @@ out:
        return info;
 }
 
-bitmap_info_t *bitmap_file_read(char *filename, int brief)
+bitmap_info_t *bitmap_file_read(char *filename, int brief, struct supertype *st)
 {
        int fd;
        bitmap_info_t *info;
+       struct stat stb;
 
        fd = open(filename, O_RDONLY);
        if (fd < 0) {
@@ -188,13 +189,24 @@ bitmap_info_t *bitmap_file_read(char *filename, int brief)
                                filename, strerror(errno));
                return NULL;
        }
+       fstat(fd, &stb);
+       if ((S_IFMT & stb.st_mode) == S_IFBLK) {
+               /* block device, so we are probably after an internal bitmap */
+               if (!st) st = guess_super(fd);
+               if (!st) {
+                       /* just look at device... */
+                       lseek(fd, 0, 0);
+               } else {        
+                       st->ss->locate_bitmap(st, fd);
+               }
+       }
 
        info = bitmap_fd_read(fd, brief);
        close(fd);
        return info;
 }
 
-int ExamineBitmap(char *filename, int brief)
+int ExamineBitmap(char *filename, int brief, struct supertype *st)
 {
        /*
         * Read the bitmap file and display its contents
@@ -204,7 +216,7 @@ int ExamineBitmap(char *filename, int brief)
        bitmap_info_t *info;
        int rv = 1;
 
-       info = bitmap_file_read(filename, brief);
+       info = bitmap_file_read(filename, brief, st);
        if (!info)
                return rv;
 
diff --git a/md_p.h b/md_p.h
index aeaf87889ff5ce18155f6881a1794028852b4909..31eaafd2cc0f8afb27b2a8d176a4b00e105d832a 100644 (file)
--- a/md_p.h
+++ b/md_p.h
@@ -96,6 +96,8 @@ typedef struct mdp_device_descriptor_s {
 #define MD_SB_CLEAN            0
 #define MD_SB_ERRORS           1
 
+#define        MD_SB_BITMAP_PRESENT    8 /* bitmap may be present nearby */
+
 typedef struct mdp_superblock_s {
        /*
         * Constant generic information
diff --git a/mdadm.c b/mdadm.c
index c8b8e4704d6b099c644181a80b87c22f9916d54b..39cad1aef890c819cbe6c3d50aa69743f1e55e9f 100644 (file)
--- a/mdadm.c
+++ b/mdadm.c
@@ -698,6 +698,10 @@ int main(int argc, char *argv[])
                                fprintf(stderr, Name ": bitmap file needed with -b in --assemble mode\n");
                                exit(2);
                        }
+                       if (strcmp(optarg, "internal")==0) {
+                               fprintf(stderr, Name ": there is no need to specify --bitmap when assembling arrays with internal bitmaps\n");
+                               continue;
+                       }
                        bitmap_fd = open(optarg, O_RDWR);
                        if (!*optarg || bitmap_fd < 0) {
                                fprintf(stderr, Name ": cannot open bitmap file %s: %s\n", optarg, strerror(errno));
@@ -863,6 +867,11 @@ int main(int argc, char *argv[])
                if (bitmap_chunk == UnSet) bitmap_chunk = DEFAULT_BITMAP_CHUNK;
                if (delay == 0) delay = DEFAULT_BITMAP_DELAY;
                if (bitmap_file) {
+                       if (strcmp(bitmap_file, "internal")==0) {
+                               fprintf(stderr, Name ": 'internal' bitmaps not supported with --build\n");
+                               rv |= 1;
+                               break;
+                       }
                        bitmap_fd = open(bitmap_file, O_RDWR,0);
                        if (bitmap_fd < 0 && errno != ENOENT) {
                                perror(Name ": cannot create bitmap file");
@@ -879,7 +888,6 @@ int main(int argc, char *argv[])
                           bitmap_file, bitmap_chunk, delay);
                break;
        case CREATE:
-               if (bitmap_chunk == UnSet) bitmap_chunk = DEFAULT_BITMAP_CHUNK;
                if (delay == 0) delay = DEFAULT_BITMAP_DELAY;
                if (ss == NULL) {
                        for(i=0; !ss && superlist[i]; i++) 
@@ -958,7 +966,7 @@ int main(int argc, char *argv[])
                                case 'Q':
                                        rv |= Query(dv->devname); continue;
                                case 'X':
-                                       rv |= ExamineBitmap(dv->devname, brief); continue;
+                                       rv |= ExamineBitmap(dv->devname, brief, ss); continue;
                                }
                                mdfd = open_mddev(dv->devname, 0);
                                if (mdfd>=0) {
diff --git a/mdadm.h b/mdadm.h
index 5733a0382abde1c0a37d23e4d9123c8f86ebfee6..fb1773d86643b359960c21a069f71c046b4353fb 100644 (file)
--- a/mdadm.h
+++ b/mdadm.h
@@ -185,6 +185,8 @@ extern struct superswitch {
        int (*load_super)(struct supertype *st, int fd, void **sbp, char *devname);
        struct supertype * (*match_metadata_desc)(char *arg);
        __u64 (*avail_size)(__u64 size);
+       int (*add_internal_bitmap)(void *sbv, int chunk, int delay, unsigned long long size);
+       void (*locate_bitmap)(struct supertype *st, int fd);
        int major;
 } super0, super1, *superlist[];
 
@@ -240,7 +242,7 @@ extern int Kill(char *dev, int force);
 extern int CreateBitmap(char *filename, int force, char uuid[16],
                        unsigned long chunksize, unsigned long daemon_sleep,
                        unsigned long long array_size);
-extern int ExamineBitmap(char *filename, int brief);
+extern int ExamineBitmap(char *filename, int brief, struct supertype *st);
 
 extern int md_get_version(int fd);
 extern int get_linux_version(void);
index 2b571473c4cbc735e033416fc20b4785ba273250..6ea5c15dc05e68c157564918c20bb0857a743d02 100644 (file)
--- a/super0.c
+++ b/super0.c
@@ -28,6 +28,7 @@
  */
 
 #include "mdadm.h"
+#include <asm/byteorder.h>
 
 /*
  * All handling for the 0.90.0 version superblock is in
@@ -81,6 +82,8 @@ static void examine_super0(void *sbv)
        printf("    Update Time : %.24s\n", ctime(&atime));
        printf("          State : %s\n",
               (sb->state&(1<<MD_SB_CLEAN))?"clean":"active");
+       if (sb->state & (1<<MD_SB_BITMAP_PRESENT))
+               printf("Internal Bitmap : present\n");
        printf(" Active Devices : %d\n", sb->active_disks);
        printf("Working Devices : %d\n", sb->working_disks);
        printf(" Failed Devices : %d\n", sb->failed_disks);
@@ -324,10 +327,10 @@ static __u64 event_super0(void *sbv)
 
 static int init_super0(void **sbp, mdu_array_info_t *info)
 {
-       mdp_super_t *sb = malloc(MD_SB_BYTES);
+       mdp_super_t *sb = malloc(MD_SB_BYTES + sizeof(bitmap_super_t));
        int spares;
        int rfd;
-       memset(sb, 0, MD_SB_BYTES);
+       memset(sb, 0, MD_SB_BYTES + sizeof(bitmap_super_t));
 
        if (info->major_version == -1) {
                /* zeroing the superblock */
@@ -441,6 +444,27 @@ static int write_init_super0(struct supertype *st, void *sbv, mdu_disk_info_t *d
        sb->this_disk = sb->disks[dinfo->number];
        sb->sb_csum = calc_sb0_csum(sb);
        rv = store_super0(fd, sb);
+
+       if (sb->state & (1<<MD_SB_BITMAP_PRESENT)) {
+               int towrite, n;
+               char buf[4096];
+               write(fd, ((char*)sb)+MD_SB_BYTES, sizeof(bitmap_super_t));
+               towrite = 64*1024 - MD_SB_BYTES - sizeof(bitmap_super_t);
+               memset(buf, 0xff, sizeof(buf));
+               while (towrite > 0) {
+                       n = towrite;
+                       if (n > sizeof(buf)) 
+                               n = sizeof(buf);
+                       n = write(fd, buf, n);
+                       if (n > 0)
+                               towrite -= n;
+                       else
+                               break;
+               }
+               if (towrite)
+                       rv = -2;
+       }
+
        close(fd);
        if (rv)
                fprintf(stderr, Name ": failed to write superblock to %s\n", devname);
@@ -591,6 +615,75 @@ static __u64 avail_size0(__u64 devsize)
        return MD_NEW_SIZE_SECTORS(devsize);
 }
 
+static int add_internal_bitmap0(void *sbv, int chunk, int delay, unsigned long long size)
+{
+       /*
+        * The bitmap comes immediately after the superblock and must be 60K in size
+        * at most.  The default size is between 30K and 60K
+        *
+        * size is in K,  chunk is in bytes !!!
+        */
+
+       unsigned long long bits = size;
+       unsigned long long max_bits = 60*1024*8;
+       unsigned long long min_chunk;
+       mdp_super_t *sb = sbv;
+       bitmap_super_t *bms = (bitmap_super_t*)(((char*)sb) + MD_SB_BYTES);
+
+       
+       min_chunk = 1024;
+       while (bits > max_bits) {
+               min_chunk *= 2;
+               bits = (bits+1)/2;
+       }
+       if (chunk == UnSet)
+               chunk = min_chunk;
+       else if (chunk < min_chunk)
+               return 0; /* chunk size too small */
+
+       sb->state |= (1<<MD_SB_BITMAP_PRESENT);
+
+       bms->magic = __le32_to_cpu(BITMAP_MAGIC);
+       bms->version = __le32_to_cpu(BITMAP_MAJOR);
+       uuid_from_super0((int*)bms->uuid, sb);
+       bms->chunksize = __le32_to_cpu(chunk);
+       bms->daemon_sleep = __le32_to_cpu(delay);
+       bms->sync_size = __le64_to_cpu(size);
+
+
+       return 1;
+}
+               
+
+void locate_bitmap0(struct supertype *st, int fd)
+{
+       unsigned long long dsize;
+       unsigned long size;
+       unsigned long long offset;
+#ifdef BLKGETSIZE64
+       if (ioctl(fd, BLKGETSIZE64, &dsize) != 0)
+#endif
+       {
+               if (ioctl(fd, BLKGETSIZE, &size))
+                       return;
+               else
+                       dsize = ((unsigned long long)size)<<9;
+       }
+
+       if (dsize < MD_RESERVED_SECTORS*2)
+               return;
+       
+       offset = MD_NEW_SIZE_SECTORS(dsize>>9);
+
+       offset *= 512;
+
+       offset += MD_SB_BYTES;
+
+       lseek64(fd, offset, 0);
+}
+
+       
+
 struct superswitch super0 = {
        .examine_super = examine_super0,
        .brief_examine_super = brief_examine_super0,
@@ -608,5 +701,7 @@ struct superswitch super0 = {
        .load_super = load_super0,
        .match_metadata_desc = match_metadata_desc0,
        .avail_size = avail_size0,
+       .add_internal_bitmap = add_internal_bitmap0,
+       .locate_bitmap = locate_bitmap0,
        .major = 0,
 };