]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - Manage.c
Teach sysfs_add_disk() callers to use ->recovery_start versus 'insync' parameter
[thirdparty/mdadm.git] / Manage.c
index f2b32662ede7d1dd69de30e654cebf158beab08e..6f0a6a203f1d28beb4c493d72f055a5494cebebe 100644 (file)
--- a/Manage.c
+++ b/Manage.c
@@ -1,7 +1,7 @@
 /*
  * mdadm - manage Linux "md" devices aka RAID arrays.
  *
- * Copyright (C) 2001-2006 Neil Brown <neilb@suse.de>
+ * Copyright (C) 2001-2009 Neil Brown <neilb@suse.de>
  *
  *
  *    This program is free software; you can redistribute it and/or modify
  *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
  *    Author: Neil Brown
- *    Email: <neilb@cse.unsw.edu.au>
- *    Paper: Neil Brown
- *           School of Computer Science and Engineering
- *           The University of New South Wales
- *           Sydney, 2052
- *           Australia
+ *    Email: <neilb@suse.de>
  */
 
 #include "mdadm.h"
@@ -145,7 +140,7 @@ static void remove_devices(int devnum, char *path)
                strcpy(path2, path);
                pe = path2 + strlen(path2);
        } else
-               path = NULL;
+               path2 = path = NULL;
        
        for (part = 0; part < 16; part++) {
                if (part) {
@@ -166,6 +161,7 @@ static void remove_devices(int devnum, char *path)
                                unlink(path2);
                }
        }
+       free(path2);
 }
        
 
@@ -310,24 +306,6 @@ int Manage_resize(char *devname, int fd, long long size, int raid_disks)
        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,
                   mddev_dev_t devlist, int verbose)
 {
@@ -446,11 +424,15 @@ int Manage_subdevs(char *devname, int fd,
                } else {
                        j = 0;
 
-                       if (stat(dv->devname, &stb)) {
+                       tfd = dev_open(dv->devname, O_RDONLY);
+                       if (tfd < 0 || fstat(tfd, &stb) != 0) {
                                fprintf(stderr, Name ": cannot find %s: %s\n",
                                        dv->devname, strerror(errno));
+                               if (tfd >= 0)
+                                       close(tfd);
                                return 1;
                        }
+                       close(tfd);
                        if ((stb.st_mode & S_IFMT) != S_IFBLK) {
                                fprintf(stderr, Name ": %s is not a "
                                        "block device.\n",
@@ -472,7 +454,7 @@ int Manage_subdevs(char *devname, int fd,
                                return 1;
                        }
                        /* Make sure it isn't in use (in 2.6 or later) */
-                       tfd = open(dv->devname, O_RDONLY|O_EXCL|O_DIRECT);
+                       tfd = dev_open(dv->devname, O_RDONLY|O_EXCL|O_DIRECT);
                        if (tfd < 0) {
                                fprintf(stderr, Name ": Cannot open %s: %s\n",
                                        dv->devname, strerror(errno));
@@ -588,9 +570,20 @@ int Manage_subdevs(char *devname, int fd,
                                                                fprintf(stderr, Name ": re-added %s\n", dv->devname);
                                                        continue;
                                                }
+                                               if (errno == ENOMEM || errno == EROFS) {
+                                                       fprintf(stderr, Name ": add new device failed for %s: %s\n",
+                                                               dv->devname, strerror(errno));
+                                                       return 1;
+                                               }
                                                /* fall back on normal-add */
                                        }
                                }
+                               if (dv->re_add) {
+                                       fprintf(stderr, Name
+                                               ": --re-add for %s to %s is not possible\n",
+                                               dv->devname, devname);
+                                       return 1;
+                               }
                        } else {
                                /* non-persistent. Must ensure that new drive
                                 * is at least array.size big.
@@ -623,7 +616,7 @@ int Manage_subdevs(char *devname, int fd,
                                int dfd;
                                if (dv->writemostly == 1)
                                        disc.state |= 1 << MD_DISK_WRITEMOSTLY;
-                               dfd = open(dv->devname, O_RDWR | O_EXCL|O_DIRECT);
+                               dfd = dev_open(dv->devname, O_RDWR | O_EXCL|O_DIRECT);
                                if (tst->ss->add_to_super(tst, &disc, dfd,
                                                          dv->devname)) {
                                        close(dfd);
@@ -663,6 +656,7 @@ int Manage_subdevs(char *devname, int fd,
                                                disc.state |= (1<<MD_DISK_SYNC);
                                                break;
                                        }
+                               free(used);
                        }
                        if (dv->writemostly == 1)
                                disc.state |= (1 << MD_DISK_WRITEMOSTLY);
@@ -702,6 +696,7 @@ int Manage_subdevs(char *devname, int fd,
                                tst->ss->getinfo_super(tst, &new_mdi);
                                new_mdi.disk.major = disc.major;
                                new_mdi.disk.minor = disc.minor;
+                               new_mdi.recovery_start = 0;
                                if (sysfs_add_disk(sra, &new_mdi) != 0) {
                                        fprintf(stderr, Name ": add new device to external metadata"
                                                " failed for %s\n", dv->devname);
@@ -746,7 +741,14 @@ int Manage_subdevs(char *devname, int fd,
                                                " to container - odd\n");
                                        return 1;
                                }
-                               if (!sysfs_unique_holder(dnum, stb.st_rdev)) {
+                               /* in the detached case it is not possible to
+                                * check if we are the unique holder, so just
+                                * rely on the 'detached' checks
+                                */
+                               if (strcmp(dv->devname, "detached") == 0 ||
+                                   sysfs_unique_holder(dnum, stb.st_rdev))
+                                       /* pass */;
+                               else {
                                        fprintf(stderr, Name
                                                ": %s is %s, cannot remove.\n",
                                                dnprintable,