[PATCH 07/33] add general domain/subset lists manipulation routines

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

 



From: Czarnowska, Anna
Sent: Monday, July 05, 2010 11:24 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 07/33] add general domain/subset lists manipulation routines

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

set of utilities to create/maintain data structures:
* create (with special 'match any' subset)
* free
* duplicate/copy
for domain_ent, domain_path and subset structures.

Signed-off-by: Przemyslaw Czarnowski <przemyslaw.hawrylewicz.czarnowski@xxxxxxxxx>
---
 config.c |  307 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
 mdadm.h  |   16 +++-
 2 files changed, 299 insertions(+), 24 deletions(-)

diff --git a/config.c b/config.c
index b429968..248c1c1 100644
--- a/config.c
+++ b/config.c
@@ -696,44 +696,95 @@ void autoline(char *line)  }

 static struct domain_ent *domain_list = NULL;
+static struct domain_ent **dl_end = &domain_list;

-void free_domain(struct domain_ent *de)
+void free_domain_path_list(struct domain_path *dp_head)
 {
      struct domain_path *dp;

-     while (de->paths) {
-           dp = de->paths;
-           de->paths = dp->next;
+     while (dp_head) {
+           dp = dp_head;
+           dp_head = dp->next;
            free(dp->path);
            free(dp);
      }
+}
+
+void free_subset_list(struct subset *s) {
+     struct subset *s_tmp;
+
+     while(s) {
+           s_tmp = s;
+           s = s->next;
+           if (s_tmp->paths)
+                 free_domain_path_list(s_tmp->paths);
+           if (s_tmp->spare_group)
+                 free(s_tmp->spare_group);
+           free(s_tmp);
+     }
+     free(s);
+}
+
+void free_domain(struct domain_ent *de) {
+     free_domain_path_list(de->paths);
+     free_subset_list(de->subsets);
      if (de->spare_group)
            free(de->spare_group);
      if (de->table)
            free(de->table);
+     if (de->platform)
+           free(de->platform);
      free(de);
 }

-void domainline(char *line)
+void free_domain_list(struct domain_ent **de_head)
 {
-     char *w;
-     struct domain_ent *de;
-     struct domain_path *path, *prev_path;
-     int offset, a_seen=0, m_seen=0, sg_seen=0, p_seen=0, t_seen=0;
+     struct domain_ent *de_tmp;
+
+     while(*de_head) {
+           de_tmp = *de_head;
+           *de_head = (*de_head)->next;
+           free_domain(de_tmp);
+     }
+     *de_head = NULL;
+}
+
+/* creates single domain entry filled with default values */ struct
+domain_ent *create_domain_entry(void) {
+     struct domain_ent *de = malloc(sizeof(struct domain_ent));

-     de = malloc(sizeof(struct domain_ent));
      if (!de) {
            fprintf(stderr, Name ": unable to allocate memory for domain "
-                 "entry\n");
-           return;
+                            "entry\n");
+           return NULL;
      }
      de->paths = NULL;
      de->spare_group = NULL;
+     de->subsets = NULL;
      de->handler = NULL;
      de->table = NULL;
      de->action = incremental;
-     de->st = NULL;
+     de->platform = NULL;
      de->next = NULL;
+
+     return de;
+}
+
+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, p_seen=0, t_seen=0;
+
+     de = create_domain_entry();
+     if (!de) {
+           free_domain_list(&domain_list);
+           return;
+     }

      for (w=dl_next(line); w!=line; w=dl_next(w)) {
            if (strncasecmp("path=", w, 5) == 0) { @@ -741,6 +792,7 @@ void domainline(char *line)
                  if (!path) {
                        fprintf(stderr, Name ": unable to allocate "
                              "memory for domain path\n");
+                       free_domain_list(&domain_list);
                        free_domain(de);
                        return;
                  }
@@ -748,6 +800,7 @@ void domainline(char *line)
                  if (!path->path) {
                        fprintf(stderr, Name ": unable to allocate "
                              "memory for domain path\n");
+                       free_domain_list(&domain_list);
                        free_domain(de);
                        return;
                  }
@@ -777,6 +830,7 @@ void domainline(char *line)
                  if (offset == 13)
                        de->action |= force;
            } else if (strncasecmp("metadata=", w, 9) == 0) {
+                 struct supertype *st;
                  int i;
                  if (!m_seen)
                        m_seen = 1;
@@ -788,12 +842,14 @@ void domainline(char *line)
                  }
                  /* style of metadata on the devices. */

-                 for(i=0; superlist[i] && !de->st; i++)
-                       de->st = superlist[i]->match_metadata_desc(w+9);
+                 for(i=0; superlist[i] && !st; i++)
+                       st = superlist[i]->match_metadata_desc(w+9);

-                 if (!de->st)
+                 if (!st) {
                        fprintf(stderr, Name ": metadata format %s "
                              "unknown, ignored.\n", w+9);
+                       de->platform = strdup(w+9);
+                 }
            } else if (strncasecmp("spare-group=", w, 12) == 0) {
                  if (!sg_seen)
                        sg_seen = 1;
@@ -807,6 +863,7 @@ void domainline(char *line)
                  if (!de->spare_group) {
                        fprintf(stderr, Name ": failed to allocate "
                              "memory for spare_group\n");
+                       free_domain_list(&domain_list);
                        free_domain(de);
                        return;
                  }
@@ -829,6 +886,7 @@ void domainline(char *line)
                  if (!h) {
                        fprintf(stderr, Name ": failed to recognize "
                              "program %s\n", w+8);
+                       free_domain_list(&domain_list);
                        free_domain(de);
                        return;
                  }
@@ -846,6 +904,7 @@ void domainline(char *line)
                  if (!de->table) {
                        fprintf(stderr, Name ": failed to allocate "
                              "memory for table\n");
+                       free_domain_list(&domain_list);
                        free_domain(de);
                        return;
                  }
@@ -894,38 +953,242 @@ void domainline(char *line)
                  /* We freed all the paths, kill this domain */
                  fprintf(stderr, Name ": no valid paths in domain, "
                        "freeing.\n");
+                 free_domain_list(&domain_list);
                  free_domain(de);
                  return;
            }
            if (!de->table || !de->handler) {
                  fprintf(stderr, Name ": partition action requires "
                        "both a table and program setting.\n");
+                 free_domain_list(&domain_list);
                  free_domain(de);
                  return;
            }
            if (de->handler->validate(de)) {
                  fprintf(stderr, Name ": partition table file failed "
                        "validation.\n");
+                 free_domain_list(&domain_list);
                  free_domain(de);
                  return;
            }
      }
-     de->next = domain_list;
-     domain_list = de;
+     de->subsets = NULL;
+     de->next = NULL;
+     *dl_end = de;
+     dl_end = &de->next;
 }

+/* matches given path with domain_path structure */ int
+match_domain_path(struct domain_path *path, char *devpath) {
+     if (!path) /* empty path means "*" */
+           return 1;
+     for (; path; path = path->next)
+           if (path->path)
+                 if (fnmatch(path->path, devpath, 0) == 0)
+                       return 1;
+     return 0;
+}
+
+/* returns domain basing on path matching and superblock type (in that order).
+ * If st==NULL, just match paths.
+ */
 struct domain_ent *get_domain_from_devpath(char *devpath)  {
      struct domain_ent *de;
-     struct domain_path *path;

-     for (de = domain_list; de; de = de->next)
-           for (path = de->paths; path; path = path->next)
-                 if (fnmatch(path->path, devpath, 0) == 0)
+     if (!devpath)
+           return NULL;
+
+     for (de = domain_list; de; de = de->next) {
+           if (match_domain_path(de->paths, devpath))
                        return de;
+     }
      return NULL;
 }

+/* returns subset record created to indicate "match any" subset
+ * ie. paths and spare_group equal NULL */ struct subset
+*conf_get_any_subset(void) {
+     struct subset *s = malloc(sizeof(*s));
+     if (!s) {
+           fprintf(stderr, Name ": unable to allocate memory for domain "
+                                  "entry\n");
+           return NULL;
+     }
+     s->paths = NULL;
+     s->spare_group = NULL;
+     s->next = NULL;
+     return s;
+}
+
+static struct domain_path *create_domain_path(void) {
+     struct domain_path *dp = malloc(sizeof(*dp));
+
+     if (!dp) {
+           fprintf(stderr, Name ": unable to allocate memory for domain "
+                       "path entry\n");
+           return NULL;
+     }
+     dp->path = NULL;
+     dp->next = NULL;
+
+     return dp;
+}
+
+static struct domain_path *duplicate_domain_path_list(struct
+domain_path *s) {
+     struct domain_path *dp, *dp_new;
+     struct domain_path *dp_new_head = NULL;
+     struct domain_path **dp_end = NULL;
+
+     for (dp = s; dp; dp = dp->next) {
+           dp_new = create_domain_path();
+           if (!dp_new) {
+                 free_domain_path_list(dp_new_head);
+                 return NULL;
+           }
+
+           if (!dp_new_head) {
+                 dp_new_head = dp_new;
+           }
+
+           if (dp->path) {
+                 dp_new->path = strdup(dp->path);
+                 if (!dp_new->path) {
+                       free_domain_path_list(dp_new_head);
+                       return NULL;
+                 }
+           }
+           if (dp_end)
+                 *dp_end = dp_new;
+
+           dp_end = &dp_new->next;
+     }
+
+     return dp_new_head;
+}
+
+static struct subset *create_subset(void) {
+     struct subset *ss = malloc(sizeof(*ss));
+
+     if (!ss) {
+           fprintf(stderr, Name ": unable to allocate memory for subset "
+                            "entry\n");
+           return NULL;
+     }
+     ss->paths = NULL;
+     ss->spare_group = NULL;
+     ss->next = NULL;
+
+     return ss;
+}
+
+static struct subset *copy_subset(struct subset *s_new, struct subset
+*s) {
+     if (!s_new || !s)
+           return NULL;
+
+     if (s->paths) {
+           s_new->paths = duplicate_domain_path_list(s->paths);
+           if (!s_new->paths) {
+                 free(s_new);
+                 return NULL;
+           }
+     }
+
+     if (s->spare_group) {
+           s_new->spare_group = strdup(s->spare_group);
+           if (!s_new->spare_group) {
+                 free_domain_path_list(s_new->paths);
+                 free(s_new);
+                 return NULL;
+           }
+     }
+     s_new->next = NULL;
+
+     return s_new;
+}
+
+static struct subset *duplicate_subset_list(struct subset *s) {
+     struct subset *ss, *ss_new, *ss_new_head = NULL;
+     struct subset **ss_end = NULL;
+
+     for (ss = s; ss; ss = ss->next) {
+           ss_new = create_subset();
+           if (!ss_new) {
+                 free_subset_list(ss_new_head);
+                 return NULL;
+           }
+           if (!ss_new_head)
+                 ss_new_head = ss_new;
+
+           if (!copy_subset(ss_new, ss)) {
+                 free(ss_new);
+                 free_subset_list(ss_new_head);
+                 return NULL;
+           }
+
+           if (ss_end)
+                 *ss_end = ss_new;
+           ss_end = &ss_new->next;
+     }
+
+     return ss_new_head;
+}
+
+/* static will be enabled when function will be used in domain code */
+/*static*/ struct domain_ent *duplicate_domain(struct domain_ent *de) {
+     struct domain_ent *de_new = create_domain_entry();
+
+     if (!de_new)
+           return NULL;
+
+     if (de->paths) {
+           de_new->paths = duplicate_domain_path_list(de->paths);
+           if (!de_new->paths)
+                 goto fail_exit;
+     }
+     if (de->spare_group) {
+           de_new->spare_group = strdup(de->spare_group);
+           if (!de_new->spare_group)
+                 goto fail_exit;
+     }
+     de_new->handler = de->handler;
+     if (de->table) {
+           de_new->table = strdup(de->table);
+           if (!de_new->table)
+                 goto fail_exit;
+     }
+     if (de->subsets) {
+           de_new->subsets = duplicate_subset_list(de->subsets);
+           if (!de_new->subsets)
+                 goto fail_exit;
+     }
+
+     de_new->action = de->action;
+     if (de_new->platform) {
+           de_new->platform = strdup(de->platform);
+           if (!de_new->platform)
+                 goto fail_exit;
+     }
+
+     de_new->next = de->next;
+     de->next = de_new;
+
+     return de_new;
+fail_exit:
+     free(de_new->table);
+     free(de_new->spare_group);
+     free_domain_path_list(de_new->paths);
+     free(de_new);
+     return NULL;
+}

 int loaded = 0;

diff --git a/mdadm.h b/mdadm.h
index 509ee9f..7b950f8 100644
--- a/mdadm.h
+++ b/mdadm.h
@@ -312,12 +312,23 @@ struct domain_ent {
                                     are watching and can reconcile
                                     them to domains by checking
                                     constituent device paths */
-     struct domain_path {
+     struct domain_path {                /* user defined path(s) to choose
+                                    * domain boundaries */
            char              *path;
            struct domain_path      *next;
      }                 *paths;
+     struct subset {                    /* platform dependent limits. They
+                                   * can be either implicit platform
+                                   * confinements or those from
+                                   * metadata fields as pool id used
+                                   * in IMSM */
+           struct domain_path      *paths;
+           char        *spare_group;
+           struct subset     *next;
+     } *subsets;
+
      int               action;
-     struct supertype  *st;
+     char              *platform;
      struct domain_ent *next;
      struct partition_handler      *handler; /* only used when action is
                                   partition, this is the program @@ -913,6 +924,7 @@ extern struct domain_ent *conf_get_domain(char *devname);  extern int conf_get_domain_action(char *devname);  extern struct mdstat_ent *arrays_in_domain(char *devname,
                                 struct domain_ent *domain);
+extern struct subset *conf_get_any_subset(void);
 extern int conf_test_dev(char *devname);  extern int conf_test_metadata(const char *version, int is_homehost);  extern struct createinfo *conf_get_create_info(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