]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - Manage.c
Use O_EXCL when opening component devices to be assembled into an array
[thirdparty/mdadm.git] / Manage.c
index d8cc1362dc5c1aecfdc41a924270a763c6d9539f..b323fd3c241b514c24a3138b7f332e09c8841fd8 100644 (file)
--- a/Manage.c
+++ b/Manage.c
@@ -1,7 +1,7 @@
 /*
- * mdctl - manage Linux "md" devices aka RAID arrays.
+ * mdadm - manage Linux "md" devices aka RAID arrays.
  *
- * Copyright (C) 2001 Neil Brown <neilb@cse.unsw.edu.au>
+ * Copyright (C) 2001-2002 Neil Brown <neilb@cse.unsw.edu.au>
  *
  *
  *    This program is free software; you can redistribute it and/or modify
@@ -27,7 +27,7 @@
  *           Australia
  */
 
-#include "mdctl.h"
+#include "mdadm.h"
 #include "md_u.h"
 #include "md_p.h"
 
@@ -77,7 +77,6 @@ int Manage_runstop(char *devname, int fd, int runstop)
        /* Run or stop the array. array must already be configured
         * required >= 0.90.0
         */
-       mdu_array_info_t array;
        mdu_param_t param; /* unused */
 
        if (runstop == -1 && md_get_version(fd) < 9000) {
@@ -115,9 +114,47 @@ int Manage_runstop(char *devname, int fd, int runstop)
        return 0;
 }
 
+int Manage_resize(char *devname, int fd, long long size, int raid_disks)
+{
+       mdu_array_info_t info;
+       if (ioctl(fd, GET_ARRAY_INFO, &info) != 0) {
+               fprintf(stderr, Name ": Cannot get array information for %s: %s\n",
+                       devname, strerror(errno));
+               return 1;
+       }
+       if (size >= 0)
+               info.size = size;
+       if (raid_disks > 0)
+               info.raid_disks = raid_disks;
+       if (ioctl(fd, SET_ARRAY_INFO, &info) != 0) {
+               fprintf(stderr, Name ": Cannot set device size/shape for %s: %s\n",
+                       devname, strerror(errno));
+               return 1;
+       }
+       return 0;
+}
+
+int Manage_reconfig(char *devname, int fd, int layout)
+{
+       mdu_array_info_t info;
+       if (ioctl(fd, GET_ARRAY_INFO, &info) != 0) {
+               fprintf(stderr, Name ": Cannot get array information for %s: %s\n",
+                       devname, strerror(errno));
+               return 1;
+       }
+       info.layout = layout;
+       printf("layout set to %d\n", info.layout);
+       if (ioctl(fd, SET_ARRAY_INFO, &info) != 0) {
+               fprintf(stderr, Name ": Cannot set layout for %s: %s\n",
+                       devname, strerror(errno));
+               return 1;
+       }
+       return 0;
+}
+
 int Manage_subdevs(char *devname, int fd,
-                  int devcnt, char *devnames[], int devmodes[])
- {
+                  mddev_dev_t devlist)
+{
        /* do something to each dev.
         * devmode can be
         *  'a' - add the device
@@ -128,37 +165,57 @@ int Manage_subdevs(char *devname, int fd,
         */
        mdu_array_info_t array;
        mdu_disk_info_t disc;
+       mddev_dev_t dv;
        struct stat stb;
-       int i,j;
+       int j;
+       int save_errno;
+       static char buf[4096];
 
        if (ioctl(fd, GET_ARRAY_INFO, &array)) {
                fprintf(stderr, Name ": cannot get array info for %s\n",
                        devname);
                return 1;
        }
-       for (i=0 ; i<devcnt; i++) {
-               if (stat(devnames[i], &stb)) {
+       for (dv = devlist ; dv; dv=dv->next) {
+               if (stat(dv->devname, &stb)) {
                        fprintf(stderr, Name ": cannot find %s: %s\n",
-                               devnames[i], strerror(errno));
+                               dv->devname, strerror(errno));
                        return 1;
                }
                if ((stb.st_mode & S_IFMT) != S_IFBLK) {
                        fprintf(stderr, Name ": %s is not a block device.\n",
-                               devnames[i]);
+                               dv->devname);
                        return 1;
                }
-               switch(devmodes[i]){
+               switch(dv->disposition){
                default:
-                       fprintf(stderr, Name ": internal error - devmode[%d]=%d\n",
-                               i, devmodes[i]);
+                       fprintf(stderr, Name ": internal error - devmode[%s]=%d\n",
+                               dv->devname, dv->disposition);
                        return 1;
                case 'a':
                        /* add the device - hot or cold */
-                       if (ioctl(fd, HOT_ADD_DISK, stb.st_rdev)==0) {
+                       /* Make sure it isn' in use (in 2.6 or later) */
+                       fd = open(dv->devname, O_RDONLY|O_EXCL);
+                       if (fd < 0) {
+                               fprintf(stderr, Name ": Cannot open %s: %s\n",
+                                       dv->devname, strerror(errno));
+                               return 1;
+                       }
+                       close(fd);
+                       if (ioctl(fd, HOT_ADD_DISK, (unsigned long)stb.st_rdev)==0) {
                                fprintf(stderr, Name ": hot added %s\n",
-                                       devnames[i]);
+                                       dv->devname);
                                continue;
                        }
+                       save_errno = errno;
+                       if (read(fd, buf, sizeof(buf)) > 0) {
+                               /* array is active, so don't try to add.
+                                * i.e. something is wrong 
+                                */
+                               fprintf(stderr, Name ": hot add failed for %s: %s\n",
+                                       dv->devname, strerror(save_errno));
+                               return 1;
+                       }
                        /* try ADD_NEW_DISK.
                         * we might be creating, we might be assembling,
                         * it is hard to tell.
@@ -166,6 +223,7 @@ int Manage_subdevs(char *devname, int fd,
                         * in case
                         */
                        for (j=0; j<array.nr_disks; j++) {
+                               disc.number = j;
                                if (ioctl(fd, GET_DISK_INFO, &disc))
                                        break;
                                if (disc.major==0 && disc.minor==0)
@@ -176,36 +234,36 @@ int Manage_subdevs(char *devname, int fd,
                        disc.number =j;
                        disc.raid_disk = j;
                        disc.state = 0;
-                       disc.major = MAJOR(stb.st_rdev);
-                       disc.minor = MINOR(stb.st_rdev);
+                       disc.major = major(stb.st_rdev);
+                       disc.minor = minor(stb.st_rdev);
                        if (ioctl(fd,ADD_NEW_DISK, &disc)) {
-                               fprintf(stderr, Name ": add new disk failed for %s: %s\n",
-                                       devnames[i], strerror(errno));
+                               fprintf(stderr, Name ": add new device failed for %s: %s\n",
+                                       dv->devname, strerror(errno));
                                return 1;
                        }
-                       fprintf(stderr, Name ": added %s\n", devnames[i]);
+                       fprintf(stderr, Name ": added %s\n", dv->devname);
                        break;
 
                case 'r':
                        /* hot remove */
                        /* FIXME check that it is a current member */
-                       if (ioctl(fd, HOT_REMOVE_DISK, stb.st_rdev)) {
+                       if (ioctl(fd, HOT_REMOVE_DISK, (unsigned long)stb.st_rdev)) {
                                fprintf(stderr, Name ": hot remove failed for %s: %s\n",
-                                       devnames[i], strerror(errno));
+                                       dv->devname, strerror(errno));
                                return 1;
                        }
-                       fprintf(stderr, Name ": hot removed %s\n", devnames[i]);
+                       fprintf(stderr, Name ": hot removed %s\n", dv->devname);
                        break;
 
                case 'f': /* set faulty */
                        /* FIXME check current member */
-                       if (ioctl(fd, SET_DISK_FAULTY, stb.st_rdev)) {
-                               fprintf(stderr, Name ": set disk faulty failed for %s:  %s\n",
-                                       devnames[i], strerror(errno));
+                       if (ioctl(fd, SET_DISK_FAULTY, (unsigned long) stb.st_rdev)) {
+                               fprintf(stderr, Name ": set device faulty failed for %s:  %s\n",
+                                       dv->devname, strerror(errno));
                                return 1;
                        }
                        fprintf(stderr, Name ": set %s faulty in %s\n",
-                               devnames[i], devname);
+                               dv->devname, devname);
                        break;
                }
        }