[PATCH 05/33] Partition action support in DOMAIN line

[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 05/33] Partition action support in DOMAIN line

From: Doug Ledford <dledford@xxxxxxxxxx>

Add the table and program options for partition action and make them a requirement.
Stub entries for making partition handling be done via an indirection layer so we can easily support different partitioning methods required for different platforms.
Modify config parsing and domain struct to use a partition handler entry instead of just a program name.

    Signed-off-by: Doug Ledford <dledford@xxxxxxxxxx>
---
 Incremental.c |   17 ++++++++++++---
 config.c      |   59 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 mdadm.h       |   20 +++++++++++++++++++
 util.c        |   59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 150 insertions(+), 5 deletions(-)

diff --git a/Incremental.c b/Incremental.c index d1d9ee1..ca70a35 100644
--- a/Incremental.c
+++ b/Incremental.c
@@ -947,7 +947,7 @@ static int IncrementalNewDisk(char *devname, int verbose, int export,
                        struct domain_ent *domain)
 {
      struct stat stb;
-     int dfd;
+     int dfd, rv;
 
      dfd = dev_open_check(devname, O_RDONLY|O_EXCL, &stb);
      if (dfd < 0)
@@ -960,16 +960,25 @@ static int IncrementalNewDisk(char *devname, int verbose, int export,
            close(dfd);
            return 1;
      }
+
+     if (domain->handler->check_table(dfd, verbose, export, domain) == 0) {
+           close(dfd);
+           return 0;
+     }
      /*
       * 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
+     * superblock, the partition table doesn't match, and we are a
+     * partition domain.  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;
+     if (check_clean(dfd) || force(domain)) {
+           rv = domain->handler->write_table(dfd, verbose, export, domain);
+     }
+     close(dfd);
+     return rv;
 }
 
 /*
diff --git a/config.c b/config.c
index bd80cd6..b429968 100644
--- a/config.c
+++ b/config.c
@@ -707,6 +707,10 @@ void free_domain(struct domain_ent *de)
            free(dp->path);
            free(dp);
      }
+     if (de->spare_group)
+           free(de->spare_group);
+     if (de->table)
+           free(de->table);
      free(de);
 }
 
@@ -715,7 +719,7 @@ void domainline(char *line)
      char *w;
      struct domain_ent *de;
      struct domain_path *path, *prev_path;
-     int offset, a_seen=0, m_seen=0, sg_seen=0;
+     int offset, a_seen=0, m_seen=0, sg_seen=0, p_seen=0, t_seen=0;
 
      de = malloc(sizeof(struct domain_ent));
      if (!de) {
@@ -725,6 +729,8 @@ void domainline(char *line)
      }
      de->paths = NULL;
      de->spare_group = NULL;
+     de->handler = NULL;
+     de->table = NULL;
      de->action = incremental;
      de->st = NULL;
      de->next = NULL;
@@ -804,6 +810,45 @@ void domainline(char *line)
                        free_domain(de);
                        return;
                  }
+           } else if (strncasecmp("program=", w, 8) == 0) {
+                 int i = 0;
+                 struct partition_handler *h = partition_list[i];
+                 if (!p_seen)
+                       p_seen = 1;
+                 else {
+                       fprintf(stderr, Name ": only one program= "
+                             "entry allowed per domain line, "
+                             "ignoring\n");
+                       continue;
+                 }
+                 while(h) {
+                       if (strncasecmp(w+8, h->match, strlen(h->match)) == 0)
+                             break;
+                       h = partition_list[++i];
+                 }
+                 if (!h) {
+                       fprintf(stderr, Name ": failed to recognize "
+                             "program %s\n", w+8);
+                       free_domain(de);
+                       return;
+                 }
+                 de->handler = h;
+           } else if (strncasecmp("table=", w, 6) == 0) {
+                 if (!t_seen)
+                       t_seen = 1;
+                 else {
+                       fprintf(stderr, Name ": only one table= "
+                             "entry allowed per domain line, "
+                             "ignoring\n");
+                       continue;
+                 }
+                 de->table = strdup(w+6);
+                 if (!de->table) {
+                       fprintf(stderr, Name ": failed to allocate "
+                             "memory for table\n");
+                       free_domain(de);
+                       return;
+                 }
            } else {
                  fprintf(stderr, Name ": unrecognized option %s on "
                        "domain line\n", w);
@@ -852,6 +897,18 @@ void domainline(char *line)
                  free_domain(de);
                  return;
            }
+           if (!de->table || !de->handler) {
+                 fprintf(stderr, Name ": partition action requires "
+                       "both a table and program setting.\n");
+                 free_domain(de);
+                 return;
+           }
+           if (de->handler->validate(de)) {
+                 fprintf(stderr, Name ": partition table file failed "
+                       "validation.\n");
+                 free_domain(de);
+                 return;
+           }
      }
      de->next = domain_list;
      domain_list = de;
diff --git a/mdadm.h b/mdadm.h
index 3862853..509ee9f 100644
--- a/mdadm.h
+++ b/mdadm.h
@@ -295,6 +295,17 @@ enum domain_actions {  #define action(domain) ((domain)->action & action_mask)  #define force(domain) ((domain)->action & force)
 
+struct domain_ent;
+
+extern struct partition_handler {
+     char              *match; /* string we match in mdadm.conf */
+     int               (*validate)(struct domain_ent *domain);
+     int               (*check_table)(int dfd, int verbose, int export,
+                                    struct domain_ent *domain);
+     int               (*write_table)(int dfd, int verbose, int export,
+                                    struct domain_ent *domain); } *partition_list[];
+
 struct domain_ent {
      char              *spare_group; /* only set this in monitor mode
                                     when we know what arrays we
@@ -308,6 +319,14 @@ struct domain_ent {
      int               action;
      struct supertype  *st;
      struct domain_ent *next;
+     struct partition_handler      *handler; /* only used when action is
+                                  partition, this is the program
+                                  to call to actually partition
+                                  the drive */
+     char              *table; /* This is the location of a file to
+                                pass to the partition program,
+                                used both for setting and checking
+                                the partitions on drives */
 };
 
 /* structures read from config file */
@@ -876,6 +895,7 @@ extern int parse_layout_faulty(char *layout);  extern int check_ext2(int fd, char *name);  extern int check_reiser(int fd, char *name);  extern int check_raid(int fd, char *name);
+extern int check_clean(int fd);
 extern int check_partitions(int fd, char *dname, unsigned long long freesize);
 
 extern int get_mdp_major(void);
diff --git a/util.c b/util.c
index b93e21d..169f804 100644
--- a/util.c
+++ b/util.c
@@ -536,6 +536,35 @@ int check_raid(int fd, char *name)
      return 1;
 }
 
+int check_clean(int dfd)
+{
+     void *head, *tail, *pattern;
+     int i=0, head_clean=0, tail_clean=0;
+     unsigned char patterns[]={0x00,0x5a,0xff};
+
+     head = malloc(4096);
+     tail = malloc(4096);
+     pattern = malloc(4096);
+     if (!head || !tail || !pattern)
+           return 0;
+     if (lseek(dfd, 0, SEEK_SET) == -1)
+           return 0;
+     if (read(dfd, head, 4096) != 4096)
+           return 0;
+     if (lseek(dfd, -4096, SEEK_END) == -1)
+           return 0;
+     if (read(dfd, tail, 4096) != 4096)
+           return 0;
+     while (i < 3) {
+           memset(pattern, patterns[i++], 4096);
+           if (memcmp(head, pattern, 4096) == 0)
+                 head_clean++;
+           if (memcmp(tail, pattern, 4096) == 0)
+                 tail_clean++;
+     }
+     return (head_clean && tail_clean);
+}
+
 int ask(char *mesg)
 {
      char *add = "";
@@ -1746,3 +1775,33 @@ char *get_devpath_from_devname(char *devname)
      closedir(by_path);
      return NULL;
 }
+
+static int sfdisk_validate(struct domain_ent *domain) {
+     return 0;
+}
+
+static int sfdisk_check_table(int dfd, int verbose, int export,
+                       struct domain_ent *domain)
+{
+     return 0;
+}
+
+static int sfdisk_write_table(int dfd, int verbose, int export,
+                       struct domain_ent *domain)
+{
+     return 0;
+}
+
+static struct partition_handler sfdisk_handler = {
+     .match            = "sfdisk",
+     .validate   = sfdisk_validate,
+     .check_table      = sfdisk_check_table,
+     .write_table      = sfdisk_write_table,
+};
+
+struct partition_handler *partition_list[] = {
+     &sfdisk_handler,
+     NULL
+};
+
--
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