]> git.ipfire.org Git - thirdparty/mdadm.git/commitdiff
Create: Block rounding size to max
authorMariusz Tkaczyk <mariusz.tkaczyk@intel.com>
Mon, 1 Apr 2019 14:53:41 +0000 (16:53 +0200)
committerJes Sorensen <jsorensen@fb.com>
Wed, 10 Apr 2019 13:39:34 +0000 (09:39 -0400)
When passed size is smaller than chunk, mdadm rounds it to 0 but 0 there
means max available space.
Block it for every metadata. Remove the same check from imsm routine.

Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@intel.com>
Signed-off-by: Jes Sorensen <jsorensen@fb.com>
Create.c
super-intel.c

index 6f1b22884b689d508462afbe235030bca605f141..292f92a9ae639ecaa981e273e30a9f3686345460 100644 (file)
--- a/Create.c
+++ b/Create.c
 #include       "md_p.h"
 #include       <ctype.h>
 
+static int round_size_and_verify(unsigned long long *size, int chunk)
+{
+       if (*size == 0)
+               return 0;
+       *size &= ~(unsigned long long)(chunk - 1);
+       if (*size == 0) {
+               pr_err("Size cannot be smaller than chunk.\n");
+               return 1;
+       }
+       return 0;
+}
+
 static int default_layout(struct supertype *st, int level, int verbose)
 {
        int layout = UnSet;
@@ -248,11 +260,14 @@ int Create(struct supertype *st, char *mddev,
                pr_err("unknown level %d\n", s->level);
                return 1;
        }
+
        if (s->size == MAX_SIZE)
                /* use '0' to mean 'max' now... */
                s->size = 0;
        if (s->size && s->chunk && s->chunk != UnSet)
-               s->size &= ~(unsigned long long)(s->chunk - 1);
+               if (round_size_and_verify(&s->size, s->chunk))
+                       return 1;
+
        newsize = s->size * 2;
        if (st && ! st->ss->validate_geometry(st, s->level, s->layout, s->raiddisks,
                                              &s->chunk, s->size*2,
@@ -267,7 +282,8 @@ int Create(struct supertype *st, char *mddev,
                        /* default chunk was just set */
                        if (c->verbose > 0)
                                pr_err("chunk size defaults to %dK\n", s->chunk);
-                       s->size &= ~(unsigned long long)(s->chunk - 1);
+                       if (round_size_and_verify(&s->size, s->chunk))
+                               return 1;
                        do_default_chunk = 0;
                }
        }
@@ -413,7 +429,8 @@ int Create(struct supertype *st, char *mddev,
                                /* default chunk was just set */
                                if (c->verbose > 0)
                                        pr_err("chunk size defaults to %dK\n", s->chunk);
-                               s->size &= ~(unsigned long long)(s->chunk - 1);
+                               if (round_size_and_verify(&s->size, s->chunk))
+                                       return 1;
                                do_default_chunk = 0;
                        }
                }
index 5a7c9f8062e020e84ef10e6eab3ff660912a284d..2ba045aa3c396f9316f5f2a1bc8ac9b5ca71dde2 100644 (file)
@@ -7455,9 +7455,8 @@ static int validate_geometry_imsm(struct supertype *st, int level, int layout,
                                                        verbose);
        }
 
-       if (size && ((size < 1024) || (*chunk != UnSet &&
-           size < (unsigned long long) *chunk))) {
-               pr_err("Given size must be greater than 1M and chunk size.\n");
+       if (size && (size < 1024)) {
+               pr_err("Given size must be greater than 1M.\n");
                /* Depends on algorithm in Create.c :
                 * if container was given (dev == NULL) return -1,
                 * if block device was given ( dev != NULL) return 0.