[PATCH 30/33] Incremental for bare disks, checking routine + integration

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

 



From: Czarnowska, Anna 
Sent: Monday, July 05, 2010 11:43 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 30/33] Incremental for bare disks, checking routine + integration

From: Przemyslaw Czarnowski <przemyslaw.hawrylewicz.czarnowski@xxxxxxxxx>

The idea of this patch is to allow adding of bare device to the container if device is plugged into the same port as recently removed device.
Function 'bare_disk_match_array' has been added to look for special 'cookie'
file (named after /dev/disk/by-path name of missing device) containing the name of valid array. If it is found, container device name is returned.
This container is used with Manage_subdevs() add, to add device.

Signed-off-by: Przemyslaw Czarnowski <przemyslaw.hawrylewicz.czarnowski@xxxxxxxxx>
---
 Incremental.c |  180 ++++++++++++++++++++++++++++++++++++++++++++++++---------
 config.c      |    9 ++-
 mdadm.h       |    3 +-
 3 files changed, 160 insertions(+), 32 deletions(-)

diff --git a/Incremental.c b/Incremental.c index adaefb9..3783e37 100644
--- a/Incremental.c
+++ b/Incremental.c
@@ -29,6 +29,8 @@
  */
 
 #include   "mdadm.h"
+#include   <sys/types.h>
+#include   <dirent.h>
 
 static int count_active(struct supertype *st, int mdfd, char **availp,
                  struct mdinfo *info);
@@ -40,6 +42,87 @@ static int IncrementalNewPart(char *devname, int verbose, int export,  static int IncrementalNewDisk(char *devname, int verbose, int export,
                        struct domain_ent *domain);
 
+
+
+/* finds cookie file with matching path. If found, returns device name
+ * either for this array (native) or its parent container (external)  
+*/ char *bare_disk_match_array(char *devname, int fd, struct supertype 
+**st) {
+     char *dev_path;
+     char cookie_path[PATH_MAX];
+     FILE *cookie;
+     struct mdstat_ent *mds = NULL, *ent = NULL;
+     char *mdname = NULL;
+
+     if (!devname)
+           return NULL;
+
+     mds = mdstat_read(0, 0);
+     /* no active arrays */
+     if (!mds)
+           return NULL;
+
+     dev_path = get_devpath_from_devname(devname);
+     if (!dev_path) {
+           free_mdstat(mds);
+           return NULL;
+     }
+
+     snprintf(cookie_path, PATH_MAX, FAILED_SLOTS "/%s", dev_path);
+     if ((cookie = fopen(cookie_path, "r")) == NULL) {
+           fprintf(stderr, Name " : Cannot open %s cookie. "
+                            "Bare disk spare action disabled\n.",
+                 cookie_path);
+           free(dev_path);
+           return NULL;
+     }
+
+     /*
+     * find first active array using list instde 'cookie' file
+     */
+     while(fgets(cookie_path, PATH_MAX, cookie)) {
+           int devnum;
+           if (sscanf(cookie_path, "md%d", &devnum) != 1)
+                 continue;
+           ent = mdstat_by_devnum(&mds, devnum);
+           if (ent) /* found active array */
+                 break;
+     }
+     if (ent) {
+           char md_path[PATH_MAX];
+           struct mdstat_ent *parent = NULL;
+           int mdfd;
+           strcpy(md_path, "/dev/");
+           if (is_external(ent->metadata_version)) {
+                 parent = mdstat_get_parent(ent);
+                 if (!parent) {
+                       fprintf(stderr, Name " : Cannot find parent "
+                                   "container for array %s\n.",
+                             ent->dev);
+                       goto cleanup;
+                 }
+                 strncat(md_path + 5, parent->dev, PATH_MAX - 5);
+                 free_mdstat(parent);
+           } else {
+                 strncat(md_path + 5, ent->dev, PATH_MAX - 5);
+           }
+           mdfd = open_mddev(md_path, 0);
+           if (mdfd < 0)
+                 goto cleanup;
+           *st = guess_super(mdfd);
+           close(mdfd);
+           if (!*st)
+                 goto cleanup;
+           mdname = strdup(md_path);
+     }
+cleanup:
+     fclose(cookie);
+     free_mdstat(mds);
+     free(dev_path);
+     return mdname;
+}
+
 int Incremental(char *devname, int verbose, int runstop,
            struct supertype *st, char *homehost, int require_homehost,
            int autof)
@@ -1044,10 +1127,19 @@ static int IncrementalNewPart(char *devname, int verbose, int export,
      struct mdstat_ent *mdstat, *md;
      struct stat stb;
      int dfd;
+     struct supertype *st = NULL;
+     char *mdname;
+     int mdfd;
+     int rv = 0;
+     struct mddev_dev_s devlist;
 
      mdstat = arrays_in_domain(devname, domain);
      for (md = mdstat; md; md = md->next)
            printf(Name ": %s\n", md->dev);
+
+     /* any arrays for this domain? */
+     if (!mdstat)
+           return 1;
      /* 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.
@@ -1072,7 +1164,34 @@ static int IncrementalNewPart(char *devname, int verbose, int export,
       * or 0xff.
       */
 
-     return 0;
+     /* for bare action, check if 'cookie' exists for this device,
+     * temporarily get metadata from matching array and invoke standard
+     * Incremental with bare=1
+     */
+     if (conf_get_domain_action(devname, domain->platform) == same_port_bare &&
+         !strstr(devname, "part") &&
+         (mdname = bare_disk_match_array(devname, dfd, &st)) &&
+         !strcmp(st->ss->name, domain->platform)) {
+           free(st);
+           mdfd = open_mddev(mdname, 0);
+           if (!mdfd) {
+                 fprintf(stderr, Name ": cannot open array device %s.\n", mdname);
+                 close(dfd);
+                 return 1;
+           }
+           close(dfd);
+           memset(&devlist, 0, sizeof(devlist));
+           devlist.devname = devname;
+           devlist.disposition = 'a';
+           rv = Manage_subdevs(mdname, mdfd, &devlist, 0);
+           free(mdname);
+           mdname = NULL;
+           close(mdfd);
+           return rv;
+     }
+     free(mdname);
+     close(dfd);
+     return 1;
 }
 
 /*
@@ -1103,7 +1222,7 @@ static int IncrementalNewDisk(char *devname, int verbose, int export,
 
      if (domain->handler->check_table(dfd, verbose, export, domain) == 0) {
            close(dfd);
-           return 0;
+           return 1;
      }
      /*
       * OK, at this point we have a valid block device without a @@ -1138,33 +1257,38 @@ int IncrementalNew(char *devname, int verbose, int export)  {
      struct domain_ent *domain;
      char *devpath;
-     int rv;
+     int rv = 1;
+     int i;
 
-     domain = conf_get_domain(devname, NULL);
-     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);
+     for (i = 0; superlist[i]; i++) {
+           domain = conf_get_domain(devname, (char *)superlist[i]->name);
+           if (!domain)
+                 continue;
+           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.
+                 */
+                 continue;
+           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);
+           if (!rv)
+                 break;
+     }
      return rv;
 }
 
diff --git a/config.c b/config.c
index 5829182..ae06859 100644
--- a/config.c
+++ b/config.c
@@ -827,6 +827,9 @@ void domainline(char *line)
                        de->action = grow;
                  else if (strncasecmp("par", w+offset, 3) == 0)
                        de->action = partition;
+                 else if (strncasecmp("bar", w+offset, 3) == 0 ||
+                       strncasecmp("sam", w+offset, 3) == 0)
+                       de->action = same_port_bare;
                  if (offset == 13)
                        de->action |= force;
            } else if (strncasecmp("metadata=", w, 9) == 0) { @@ -1046,7 +1049,7 @@ struct domain_ent *get_domain_from_devpath(char *devpath, char *platform)
                        st = get_supertype_by_name(de->platform);
                        if (!st)
                              continue;
-                       
+
                        if (match_platform(st, platform)) {
                              st->ss->free_super(st);
                              free(st);
@@ -1947,9 +1950,9 @@ struct mdstat_ent *arrays_in_domain(char *devname, struct domain_ent *domain)
      return array_list;
 }
 
-int conf_get_domain_action(char *devname)
+int conf_get_domain_action(char *devname, char *platform)
 {
-     struct domain_ent *domain = conf_get_domain(devname, NULL);
+     struct domain_ent *domain = conf_get_domain(devname, platform);
      if (!domain)
            return incremental;
      return domain->action;
diff --git a/mdadm.h b/mdadm.h
index 6eeebd5..a1ec751 100644
--- a/mdadm.h
+++ b/mdadm.h
@@ -303,6 +303,7 @@ enum domain_actions {
                  appropriate things with the partitions */
      spare,
      grow,
+     same_port_bare,
      action_mask=511,
      force=512, /* so we can bitwise & this with actions to signify we
                  should forcibly take over drives even if they have @@ -955,7 +956,7 @@ extern mddev_dev_t conf_get_devs(void);  extern struct domain_ent *conf_get_domain(char *devname, char *platform);  extern struct subset *conf_get_subset(char *devname, struct supertype *st,
                              struct domain_ent *domain);
-extern int conf_get_domain_action(char *devname);
+extern int conf_get_domain_action(char *devname, char *platform);
 extern struct mdstat_ent *arrays_in_domain(char *devname,
                                 struct domain_ent *domain);
 extern struct subset *conf_get_any_subset(void);
--
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