]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - util.c
open_dev_excl: allow device to be read-only.
[thirdparty/mdadm.git] / util.c
diff --git a/util.c b/util.c
index 87c23dcfbc5eb9ca7dffb7082ddba889dbc96d3b..e0671eb6cbbe28944dd495564f2fa244151edc92 100644 (file)
--- a/util.c
+++ b/util.c
@@ -998,24 +998,34 @@ int dev_open(char *dev, int flags)
        return fd;
 }
 
-int open_dev(int devnum)
+int open_dev_flags(int devnum, int flags)
 {
        char buf[20];
 
        sprintf(buf, "%d:%d", dev2major(devnum), dev2minor(devnum));
-       return dev_open(buf, O_RDWR);
+       return dev_open(buf, flags);
+}
+
+int open_dev(int devnum)
+{
+       return open_dev_flags(devnum, O_RDONLY);
 }
 
 int open_dev_excl(int devnum)
 {
        char buf[20];
        int i;
+       int flags = O_RDWR;
 
        sprintf(buf, "%d:%d", dev2major(devnum), dev2minor(devnum));
        for (i=0 ; i<25 ; i++) {
-               int fd = dev_open(buf, O_RDWR|O_EXCL);
+               int fd = dev_open(buf, flags|O_EXCL);
                if (fd >= 0)
                        return fd;
+               if (errno == EACCES && flags == O_RDWR) {
+                       flags = O_RDONLY;
+                       continue;
+               }
                if (errno != EBUSY)
                        return fd;
                usleep(200000);
@@ -1191,6 +1201,7 @@ struct supertype *guess_super_type(int fd, enum guess_types guess_type)
                if (guess_type == guess_partitions && ss->add_to_super != NULL)
                        continue;
                memset(st, 0, sizeof(*st));
+               st->ignore_hw_compat = 1;
                rv = ss->load_super(st, fd, NULL);
                if (rv == 0) {
                        struct mdinfo info;
@@ -1206,9 +1217,11 @@ struct supertype *guess_super_type(int fd, enum guess_types guess_type)
        if (bestsuper != -1) {
                int rv;
                memset(st, 0, sizeof(*st));
+               st->ignore_hw_compat = 1;
                rv = superlist[bestsuper]->load_super(st, fd, NULL);
                if (rv == 0) {
                        superlist[bestsuper]->free_super(st);
+                       st->ignore_hw_compat = 0;
                        return st;
                }
        }
@@ -1370,7 +1383,8 @@ static int get_last_partition_end(int fd, unsigned long long *endofpart)
        return retval;
 }
 
-int check_partitions(int fd, char *dname, unsigned long long freesize)
+int check_partitions(int fd, char *dname, unsigned long long freesize,
+                       unsigned long long size)
 {
        /*
         * Check where the last partition ends
@@ -1393,6 +1407,12 @@ int check_partitions(int fd, char *dname, unsigned long long freesize)
                                Name ": metadata will over-write last partition on %s.\n",
                                dname);
                        return 1;
+               } else if (size && endofpart > size) {
+                       /* partitions will be truncated in new device */
+                       fprintf(stderr,
+                               Name ": array size is too small to cover all partitions on %s.\n",
+                               dname);
+                       return 1;
                }
        }
        return 0;