]> git.ipfire.org Git - thirdparty/mdadm.git/commitdiff
Manage: allow adding device that is just large enough to v1.x array.
authorNeilBrown <neilb@suse.de>
Mon, 13 Oct 2008 05:15:16 +0000 (16:15 +1100)
committerNeilBrown <neilb@suse.de>
Mon, 13 Oct 2008 05:15:16 +0000 (16:15 +1100)
When adding a device to an array, we check that it is large enough.

Currently the check makes sure there is also room for a reasonably
sized bitmap.  But if the array doesn't have a bitmap, then this test
might be too restrictive.
So when adding, only insist there is enough space for the current
bitmap.
When Creating, still require room for the standard sized bitmap.

This resolved Debian Bug 500309

Manage.c
bitmap.c
mdadm.h
super1.c

index 8297708dc39b9a885ea88ee67b52178d1fc07e6a..7b3fabe1d016e8f7813a9afa9a446fd2d5c01bf2 100644 (file)
--- a/Manage.c
+++ b/Manage.c
@@ -349,14 +349,6 @@ int Manage_subdevs(char *devname, int fd,
 
                        if (array.not_persistent == 0) {
 
-                               /* Make sure device is large enough */
-                               if (tst->ss->avail_size(tst, ldsize/512) <
-                                   array_size) {
-                                       fprintf(stderr, Name ": %s not large enough to join array\n",
-                                               dv->devname);
-                                       return 1;
-                               }
-
                                /* need to find a sample superblock to copy, and
                                 * a spare slot to use
                                 */
@@ -386,6 +378,15 @@ int Manage_subdevs(char *devname, int fd,
                                        fprintf(stderr, Name ": cannot find valid superblock in this array - HELP\n");
                                        return 1;
                                }
+
+                               /* Make sure device is large enough */
+                               if (tst->ss->avail_size(tst, ldsize/512) <
+                                   array_size) {
+                                       fprintf(stderr, Name ": %s not large enough to join array\n",
+                                               dv->devname);
+                                       return 1;
+                               }
+
                                /* Possibly this device was recently part of the array
                                 * and was temporarily removed, and is now being re-added.
                                 * If so, we can simply re-add it.
index fdf8884ddfe3d31524d6e583594adfa278425c82..b64793924bd04c01e870e147f359af05468f5e9a 100644 (file)
--- a/bitmap.c
+++ b/bitmap.c
@@ -115,6 +115,15 @@ unsigned long long bitmap_bits(unsigned long long array_size,
        return (array_size * 512 + chunksize - 1) / chunksize;
 }
 
+unsigned long bitmap_sectors(struct bitmap_super_s *bsb)
+{
+       unsigned long long bits = bitmap_bits(__le64_to_cpu(bsb->sync_size),
+                                             __le32_to_cpu(bsb->chunksize));
+       int bits_per_sector = 8*512;
+       return (bits + bits_per_sector - 1) / bits_per_sector;
+}
+
+
 bitmap_info_t *bitmap_fd_read(int fd, int brief)
 {
        /* Note: fd might be open O_DIRECT, so we must be
diff --git a/mdadm.h b/mdadm.h
index 5c18d15e594b84fb47c0d003e82fa5590ddbc4d4..ce140e586a37b774c2352181e6c13db4c94cfe39 100644 (file)
--- a/mdadm.h
+++ b/mdadm.h
@@ -474,6 +474,7 @@ extern int CreateBitmap(char *filename, int force, char uuid[16],
                        int major);
 extern int ExamineBitmap(char *filename, int brief, struct supertype *st);
 extern int bitmap_update_uuid(int fd, int *uuid, int swap);
+extern unsigned long bitmap_sectors(struct bitmap_super_s *bsb);
 
 extern int md_get_version(int fd);
 extern int get_linux_version(void);
index fe915f8d921ca498d02eef3a9cf92dfaedec8f22..e1d021904ec003c0320a056bb1dabd06bf06dc7d 100644 (file)
--- a/super1.c
+++ b/super1.c
@@ -1214,10 +1214,21 @@ static struct supertype *match_metadata_desc1(char *arg)
  */
 static __u64 avail_size1(struct supertype *st, __u64 devsize)
 {
+       struct mdp_superblock_1 *super = st->sb;
        if (devsize < 24)
                return 0;
 
-       devsize -= choose_bm_space(devsize);
+       if (super == NULL)
+               /* creating:  allow suitable space for bitmap */
+               devsize -= choose_bm_space(devsize);
+#ifndef MDASSEMBLE
+       else if (__le32_to_cpu(super->feature_map)&MD_FEATURE_BITMAP_OFFSET) {
+               /* hot-add. allow for actual size of bitmap */
+               struct bitmap_super_s *bsb;
+               bsb = (struct bitmap_super_s *)(((char*)super)+1024);
+               devsize -= bitmap_sectors(bsb);
+       }
+#endif
 
        switch(st->minor_version) {
        case -1: /* no specified.  Now time to set default */