]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - mdopen.c
mdadm.h: Introduced unaligned {get,put}_unaligned{16,32}()
[thirdparty/mdadm.git] / mdopen.c
index 0ea38749a58226f9766a36621ef1e4ae521082d2..98c54e433a5df1986af0e12dadb996b0f4f0836b 100644 (file)
--- a/mdopen.c
+++ b/mdopen.c
@@ -44,7 +44,7 @@ void make_parts(char *dev, int cnt)
        int nlen = strlen(dev) + 20;
        char *name;
        int dig = isdigit(dev[strlen(dev)-1]);
-       char orig[1024];
+       char orig[1001];
        char sym[1024];
        int err;
 
@@ -58,8 +58,10 @@ void make_parts(char *dev, int cnt)
                minor_num = minor(stb.st_rdev);
                odig = -1;
        } else if (S_ISLNK(stb.st_mode)) {
-               int len = readlink(dev, orig, sizeof(orig));
-               if (len < 0 || len > 1000)
+               int len;
+
+               len = readlink(dev, orig, sizeof(orig));
+               if (len < 0 || len >= (int)sizeof(orig))
                        return;
                orig[len] = 0;
                odig = isdigit(orig[len-1]);
@@ -100,6 +102,31 @@ void make_parts(char *dev, int cnt)
        free(name);
 }
 
+int create_named_array(char *devnm)
+{
+       int fd;
+       int n = -1;
+       static const char new_array_file[] = {
+               "/sys/module/md_mod/parameters/new_array"
+       };
+
+       fd = open(new_array_file, O_WRONLY);
+       if (fd < 0 && errno == ENOENT) {
+               if (system("modprobe md_mod") == 0)
+                       fd = open(new_array_file, O_WRONLY);
+       }
+       if (fd >= 0) {
+               n = write(fd, devnm, strlen(devnm));
+               close(fd);
+       }
+       if (fd < 0 || n != (int)strlen(devnm)) {
+               pr_err("Fail create %s when using %s\n", devnm, new_array_file);
+               return 0;
+       }
+
+       return 1;
+}
+
 /*
  * We need a new md device to assemble/build/create an array.
  * 'dev' is a name given us by the user (command line or mdadm.conf)
@@ -135,7 +162,7 @@ void make_parts(char *dev, int cnt)
  */
 
 int create_mddev(char *dev, char *name, int autof, int trustworthy,
-                char *chosen)
+                char *chosen, int block_udev)
 {
        int mdfd;
        struct stat stb;
@@ -147,6 +174,10 @@ int create_mddev(char *dev, char *name, int autof, int trustworthy,
        char devname[37];
        char devnm[32];
        char cbuf[400];
+
+       if (!use_udev())
+               block_udev = 0;
+
        if (chosen == NULL)
                chosen = cbuf;
 
@@ -194,7 +225,7 @@ int create_mddev(char *dev, char *name, int autof, int trustworthy,
                        return -1;
                }
                if (cname[0] == 0) {
-                       pr_err("%s is an invalid name for an md device (empty!).", dev);
+                       pr_err("%s is an invalid name for an md device (empty!).\n", dev);
                        return -1;
                }
                if (num < 0) {
@@ -302,34 +333,42 @@ int create_mddev(char *dev, char *name, int autof, int trustworthy,
 
        devnm[0] = 0;
        if (num < 0 && cname && ci->names) {
-               int fd;
-               int n = -1;
                sprintf(devnm, "md_%s", cname);
-               fd = open("/sys/module/md_mod/parameters/new_array", O_WRONLY);
-               if (fd >= 0) {
-                       n = write(fd, devnm, strlen(devnm));
-                       close(fd);
-               }
-               if (n < 0)
+               if (block_udev)
+                       udev_block(devnm);
+               if (!create_named_array(devnm)) {
                        devnm[0] = 0;
+                       udev_unblock();
+               }
        }
-       if (devnm[0])
-               ;
-       else if (num < 0) {
-               /* need to choose a free number. */
-               char *_devnm = find_free_devnm(use_mdp);
-               if (_devnm == NULL) {
-                       pr_err("No avail md devices - aborting\n");
-                       return -1;
+       if (num >= 0) {
+               sprintf(devnm, "md%d", num);
+               if (block_udev)
+                       udev_block(devnm);
+               if (!create_named_array(devnm)) {
+                       devnm[0] = 0;
+                       udev_unblock();
                }
-               strcpy(devnm, _devnm);
-       } else {
-               sprintf(devnm, "%s%d", use_mdp?"md_d":"md", num);
-               if (mddev_busy(devnm)) {
-                       pr_err("%s is already in use.\n",
-                               dev);
-                       return -1;
+       }
+       if (devnm[0] == 0) {
+               if (num < 0) {
+                       /* need to choose a free number. */
+                       char *_devnm = find_free_devnm(use_mdp);
+                       if (_devnm == NULL) {
+                               pr_err("No avail md devices - aborting\n");
+                               return -1;
+                       }
+                       strcpy(devnm, _devnm);
+               } else {
+                       sprintf(devnm, "%s%d", use_mdp?"md_d":"md", num);
+                       if (mddev_busy(devnm)) {
+                               pr_err("%s is already in use.\n",
+                                      dev);
+                               return -1;
+                       }
                }
+               if (block_udev)
+                       udev_block(devnm);
        }
 
        sprintf(devname, "/dev/%s", devnm);
@@ -416,21 +455,22 @@ int create_mddev(char *dev, char *name, int autof, int trustworthy,
  */
 int open_mddev(char *dev, int report_errors)
 {
-       int mdfd = open(dev, O_RDWR);
-       if (mdfd < 0 && errno == EACCES)
-               mdfd = open(dev, O_RDONLY);
+       int mdfd = open(dev, O_RDONLY);
+
        if (mdfd < 0) {
                if (report_errors)
                        pr_err("error opening %s: %s\n",
                                dev, strerror(errno));
                return -1;
        }
-       if (md_get_version(mdfd) <= 0) {
+
+       if (md_array_valid(mdfd) == 0) {
                close(mdfd);
                if (report_errors)
                        pr_err("%s does not appear to be an md device\n", dev);
                return -2;
        }
+
        return mdfd;
 }