[PATCH 04/33] Support for new disk hot plug actions with DOMAINs.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Czarnowska, Anna 
Sent: Monday, July 05, 2010 11:23 AM
To: Neil Brown
Cc: linux-raid@xxxxxxxxxxxxxxx; Czarnowska, Anna; Hawrylewicz Czarnowski, Przemyslaw; Labun, Marcin; Neubauer, Wojciech; Williams, Dan J; Ciechanowski, Ed; dledford@xxxxxxxxxx
Subject: [PATCH 04/33] Support for new disk hot plug actions with DOMAINs.

From: Doug Ledford <dledford@xxxxxxxxxx>

  Nowhere near complete, just the initial stages.
  Added support for the call to mdadm.c, some
  sanity checks, helper functions, etc.

Signed-off-by: Doug Ledford <dledford@xxxxxxxxxx>
---
 Incremental.c |  131 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 config.c      |    5 +-
 mdadm.c       |   32 ++++++++++++--
 mdadm.h       |    5 ++
 util.c        |   24 ++++++++++
 5 files changed, 189 insertions(+), 8 deletions(-)

diff --git a/Incremental.c b/Incremental.c index a99811d..d1d9ee1 100644
--- a/Incremental.c
+++ b/Incremental.c
@@ -35,6 +35,10 @@ static int count_active(struct supertype *st, int mdfd, char **availp,  static void find_reject(int mdfd, struct supertype *st, struct mdinfo *sra,
                  int number, __u64 events, int verbose,
                  char *array_name);
+static int IncrementalNewPart(char *devname, int verbose, int export,
+                       struct domain_ent *domain);
+static int IncrementalNewDisk(char *devname, int verbose, int export,
+                       struct domain_ent *domain);
 
 int Incremental(char *devname, int verbose, int runstop,
            struct supertype *st, char *homehost, int require_homehost, @@ -888,3 +892,130 @@ int IncrementalRemove(char *devname, int verbose)
      devlist.disposition = 'r';
      return Manage_subdevs(ent->dev, mdfd, &devlist, verbose);  }
+
+/*
+ * IncrementalNewPart - We have a partition or a whole disk device, and 
+we
+ * have a domain that says not to partition the device, so we will 
+either
+ * use the whole disk or the partition directly.
+ */
+static int IncrementalNewPart(char *devname, int verbose, int export,
+                       struct domain_ent *domain)
+{
+     struct mdstat_ent *mdstat, *md;
+     struct stat stb;
+     int dfd;
+
+     mdstat = arrays_in_domain(devname, domain);
+     for (md = mdstat; md; md = md->next)
+           printf(Name ": %s\n", md->dev);
+     /* We've finished with the easy tests that allow us to kick drives
+     * out without touching actual physical media, now we need to start
+     * the slower checks.
+     */
+     dfd = dev_open_check(devname, O_RDONLY|O_EXCL, &stb);
+     if (dfd < 0) 
+           return 1;
+     if (guess_super(dfd) != NULL) {
+           /* This won't happen with our udev rules, but someone might
+           * try this by hand, make them use normal incremental mode
+           * instead if the device has a superblock already */
+           fprintf(stderr, Name ": superblock present on %s.\n", devname);
+           close(dfd);
+           return 1;
+     }
+     /*
+     * OK, at this point we have a valid block device without a
+     * superblock.  If we aren't in force mode, then don't use the
+     * device unless it's "clean", meaning no filesystems, no lvm,
+     * no anything.  The requirement here is that both the first and
+     * last 4k of the device must be one of three patterns: 0x00, 0x5a,
+     * or 0xff.
+     */
+
+     return 0;
+}
+
+/*
+ * IncrementalNewDisk - We have a whole disk device, and we have a 
+domain
+ * that says to partition the disk.  However, we will get called 
+whether
+ * the partition is the correct partition or not, so we need to skip 
+devs
+ * that already have the right partition and partition bare devs or
+ * repartition devs with stuff already on them only if the force option
+ * is present on our domain.
+ */
+static int IncrementalNewDisk(char *devname, int verbose, int export,
+                       struct domain_ent *domain)
+{
+     struct stat stb;
+     int dfd;
+
+     dfd = dev_open_check(devname, O_RDONLY|O_EXCL, &stb);
+     if (dfd < 0) 
+           return 1;
+     if (guess_super(dfd) != NULL) {
+           /* This won't happen with our udev rules, but someone might
+           * try this by hand, make them use normal incremental mode
+           * instead if the device has a superblock already */
+           fprintf(stderr, Name ": superblock present on %s.\n", devname);
+           close(dfd);
+           return 1;
+     }
+     /*
+     * OK, at this point we have a valid block device without a
+     * superblock.  If we aren't in force mode, then don't use the
+     * device unless it's "clean", meaning no filesystems, no lvm,
+     * no anything.  The requirement here is that both the first and
+     * last 4k of the device must be one of three patterns: 0x00, 0x5a,
+     * or 0xff.
+     */
+
+     return 0;
+}
+
+/*
+ * IncrementalNew - We've got a device that doesn't appear to have any
+ * current existing raid superblock on it, check to see if we should be
+ * claiming it based on DOMAIN entries in the config file.
+ *
+ * @devname - The device to investigate
+ *
+ * Special note: if we have partitioned devices, the whole disk device 
+is
+ * going to get called into this code, we need to detect that the 
+device
+ * is already in use and leave it be, where as if we get a truly new
+ * device we may need to partition it and set it up for the partitions 
+to
+ * be added to various arrays later on in the hot plug process.
+ */
+int IncrementalNew(char *devname, int verbose, int export) {
+     struct domain_ent *domain;
+     char *devpath;
+     int rv;
+
+     domain = conf_get_domain(devname);
+     if (!domain)
+           return 0;
+     if (action(domain) <= incremental)
+           /* Nothing to do.  We only get called in the case that there
+           * is no current superblock on the device in question, and
+           * since our matching domain says we should either ignore or
+           * use devices incrementally, they have to already have a
+           * superblock.  Since we don't, we're done.
+           */
+           return 0;
+     devpath = get_devpath_from_devname(devname);
+     if (strstr(devpath, "part") || action(domain) != partition)
+           /* We are on a partition, not a whole disk, or we are on a
+           * whole disk but we want to use the whole disk instead
+           * of partitioning it */
+           rv = IncrementalNewPart(devname, verbose, export, domain);
+     else
+           /* Only use this if we are dealing with a disk that would
+           * need partitioned.  This will get called even when our
+           * disk actually already belongs to all the right arrays
+           * and there is nothing to be done, so only do work here
+           * if we really need to */
+           rv = IncrementalNewDisk(devname, verbose, export, domain);
+     free(devpath);
+     return rv;
+}
+
diff --git a/config.c b/config.c
index 10c10e2..bd80cd6 100644
--- a/config.c
+++ b/config.c
@@ -810,8 +810,7 @@ void domainline(char *line)
            }
      }
      /* Some sanity checks now that all the options are parsed */
-     if ((de->action & force) &&
-         ((de->action & action_mask) <= incremental)) {
+     if (force(de) && (action(de) <= incremental)) {
            fprintf(stderr, Name ": force makes no sense with ignore or "
                  "incremental, removing.\n");
            de->action &= action_mask;
@@ -822,7 +821,7 @@ void domainline(char *line)
            free(de->spare_group);
            de->spare_group = NULL;
      }
-     if ((de->action & action_mask) == partition) {
+     if (action(de) == partition) {
            for (prev_path = NULL, path = de->paths; path; )
                  if ((strstr(path->path, "part") != NULL) ||
                      (path->path[strlen(path->path) - 1] == '*')) { diff --git a/mdadm.c b/mdadm.c index 770fdfd..a111b47 100644
--- a/mdadm.c
+++ b/mdadm.c
@@ -73,6 +73,7 @@ int main(int argc, char *argv[])
      int test = 0;
      int export = 0;
      int assume_clean = 0;
+     int new_disk = 0;
      char *symlinks = NULL;
      /* autof indicates whether and how to create device node.
       * bottom 3 bits are style.  Rest (when shifted) are number of parts @@ -909,6 +910,9 @@ int main(int argc, char *argv[])
            case O(INCREMENTAL, 'r'):
                  rebuild_map = 1;
                  continue;
+           case O(INCREMENTAL, 'g'):
+                 new_disk = 1;
+                 continue;
            }
            /* We have now processed all the valid options. Anything else is
             * an error
@@ -1513,6 +1517,11 @@ int main(int argc, char *argv[])
            if (rebuild_map) {
                  RebuildMap();
            }
+           if (export && !new_disk) {
+                 fprintf(stderr, Name
+           ": --incremental --export only supported with --grab.\n");
+                 break;
+           }
            if (scan) {
                  if (runstop <= 0) {
                        fprintf(stderr, Name
@@ -1524,8 +1533,18 @@ int main(int argc, char *argv[])
                   ": --incremental --scan --fail not supported.\n");
                        break;
                  }
+                 if (new_disk > 0) {
+                       fprintf(stderr, Name
+                 ": --incremental --scan --grab not supported.\n");
+                       break;
+                 }
                  rv = IncrementalScan(verbose);
            }
+           if (devmode == 'f' && new_disk) {
+                 fprintf(stderr, Name
+           ": --incremental --fail --grab makes no sense.\n");
+                 break;
+           }
            if (!devlist) {
                  if (!rebuild_map && !scan) {
                        fprintf(stderr, Name
@@ -1540,12 +1559,15 @@ int main(int argc, char *argv[])
                  rv = 1;
                  break;
            }
-           if (devmode == 'f') {
+           if (devmode == 'f')
                  rv = IncrementalRemove(devlist->devname, verbose-quiet);
-                 break;
-           }
-           rv = Incremental(devlist->devname, verbose-quiet, runstop,
-                       ss, homehost, require_homehost, autof);
+           else if (new_disk > 0)
+                 rv = IncrementalNew(devlist->devname, verbose-quiet,
+                                 export);
+           else
+                 rv = Incremental(devlist->devname, verbose-quiet,
+                             runstop, ss, homehost,
+                             require_homehost, autof);
            break;
      case AUTODETECT:
            autodetect();
diff --git a/mdadm.h b/mdadm.h
index 4d5a630..3862853 100644
--- a/mdadm.h
+++ b/mdadm.h
@@ -292,6 +292,9 @@ enum domain_actions {
                  other metadata on them */
 };
 
+#define action(domain) ((domain)->action & action_mask) #define 
+force(domain) ((domain)->action & force)
+
 struct domain_ent {
      char              *spare_group; /* only set this in monitor mode
                                     when we know what arrays we
@@ -854,6 +857,7 @@ extern int Incremental_container(struct supertype *st, char *devname,  extern void RebuildMap(void);  extern int IncrementalScan(int verbose);  extern int IncrementalRemove(char *devname, int verbose);
+extern int IncrementalNew(char *devname, int verbose, int export);
 extern int CreateBitmap(char *filename, int force, char uuid[16],
                  unsigned long chunksize, unsigned long daemon_sleep,
                  unsigned long write_behind,
@@ -876,6 +880,7 @@ extern int check_partitions(int fd, char *dname, unsigned long long freesize);
 
 extern int get_mdp_major(void);
 extern int dev_open(char *dev, int flags);
+extern int dev_open_check(char *dev, int flags, struct stat *stb);
 extern int open_dev(int devnum);
 extern int open_dev_excl(int devnum);
 extern int is_standard(char *dev, int *nump); diff --git a/util.c b/util.c index 1793b68..b93e21d 100644
--- a/util.c
+++ b/util.c
@@ -975,6 +975,30 @@ int dev_open(char *dev, int flags)
      return fd;
 }
 
+int dev_open_check(char *devname, int flags, struct stat *stb) {
+     int dfd;
+
+     dfd = dev_open(devname, flags);
+     if (dfd < 0) {
+           fprintf(stderr, Name ": cannot open %s: %s.\n",
+                 devname, strerror(errno));
+           return -1;
+     }
+     if (fstat(dfd, stb) < 0) {
+           fprintf(stderr, Name ": fstat failed on %s: %s.\n",
+                 devname, strerror(errno));
+           close(dfd);
+           return -1;
+     }
+     if ((stb->st_mode & S_IFMT) != S_IFBLK) {
+           fprintf(stderr, Name ": %s is not a block device.\n", devname);
+           close(dfd);
+           return -1;
+     }
+     return dfd;
+}
+
 int open_dev(int devnum)
 {
      char buf[20];
--
1.6.4.2


--
To unsubscribe from this list: send the line "unsubscribe linux-raid" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux RAID Wiki]     [ATA RAID]     [Linux SCSI Target Infrastructure]     [Linux Block]     [Linux IDE]     [Linux SCSI]     [Linux Hams]     [Device Mapper]     [Device Mapper Cryptographics]     [Kernel]     [Linux Admin]     [Linux Net]     [GFS]     [RPM]     [git]     [Yosemite Forum]


  Powered by Linux