RE: [AUTOREBUILD 7/8] Monitor: Respect policy in auto-rebuild in mdadm monitoring.

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

 



>From 92f0a71f94a4568647e137f8f0d857be7fd482df Mon Sep 17 00:00:00 2001
From: Marcin Labun <marcin.labun@xxxxxxxxx>
Date: Wed, 29 Sep 2010 05:32:29 +0200
Subject: [AUTOREBUILD 7/8] Monitor: Respect policy in auto-rebuild in mdadm monitoring.

Respect policy definition from mdadm.conf.
For each degraded volume/container, its policy is retrieved. In next steps
potential donor container/volume is searched for a spare disk,
For each spare disk we check if the domain matches and verify is the action
token allows for spare sharing. *spare* action is minimum to let spare sharing 
in the same policy domain.

Signed-off-by: Marcin Labun <marcin.labun@xxxxxxxxx>
---
 Monitor.c |   97 +++++++++++++++++++++++++++++++++++++++++++++++++++++-------
 1 files changed, 85 insertions(+), 12 deletions(-)

diff --git a/Monitor.c b/Monitor.c
index 62cbe98..dd9e707 100644
--- a/Monitor.c
+++ b/Monitor.c
@@ -724,6 +724,33 @@ static int dev_suitable(unsigned devid, int devstate, unsigned long long size)
      return 0;
 }
 
+struct state *get_parent(struct state *st)
+{
+     if (is_external(st->metadata_version))
+           return st->parent;
+     else
+           return st;
+}
+
+static struct supertype *get_super(struct state *st)
+{
+     struct supertype *super = NULL;
+     char *metadata = NULL;
+     int i;
+
+     if (is_external(st->metadata_version)) {
+           st = st->parent;
+           if (!st)
+                 return NULL;
+           metadata = st->metadata_version + strlen("external:");
+     } else {
+           metadata = st->metadata_version;
+     }
+     for (i = 0; !super && superlist[i]; i++)
+           super = superlist[i]->match_metadata_desc(metadata);
+     return super;
+}
+
 
 /* If an array has active < raid && spare == 0
  * Look for another array/container with unused, unfailed spare
@@ -736,40 +763,51 @@ static void spare_sharing(struct state *statelist, char *mailaddr,
      struct state *st, *stp, *vol, *st2 = NULL;
      int i, ext, found;
      struct mdinfo *sra = NULL;
+     struct domainlist *dl = NULL;
+     struct supertype *super = NULL;
 
      for (st = statelist; st; st = st->next) {
            if (st->err || st->active == st->raid || st->spare > 0)
                  continue;
-
            found = 0;
            ext = is_external(st->metadata_version);
            /*
             * for exernal metadata spare will be moved to parent container
             */
-           if (ext) {
-                 stp = st->parent;
-                 if (!stp)
-                       continue;
-           } else {
-                 stp = st;
-           }
-           /* get member device state updated */
+           stp = get_parent(st);
+           if (!stp)
+                 continue;
+           super = get_super(st);
+           if (!super)
+                 continue;
+           /* get the disk state updated */
            sra = get_raid_disk_info(stp);
            if (!sra) {
                  dprintf("no sra for device: %s\n", stp->devname);
                  continue;
            }
-           sysfs_free(sra);
            for (i = 0; i < stp->total; i++)
                  if (dev_suitable(stp->devid[i], stp->devstate[i],
                               st->min_size))
                        break;
-           if (i < stp->total)
+           if (i < stp->total) {
                  /* there is a spare in array/parent container,
                   * it was probably just added
                   * but mdmon has not started recovery yet
                   * we will not add any more spares for now */
+                 sysfs_free(sra);
+                 continue;
+           }
+
+           /* get the array/volume domain */
+           dl = domain_from_array(sra, super->ss->name);
+           sysfs_free(sra);
+           if (!dl) {
+                 dprintf("domain: %p name: %s dev: %s meta: %s\n",
+                       dl, (dl) ? dl->dom : "NULL", stp->devname,
+                       super->ss->name);
                  continue;
+           }
 
            /* search for an array/container with unused spare */
            for (st2 = statelist; st2; st2 = st2->next) {
@@ -791,12 +829,47 @@ static void spare_sharing(struct state *statelist, char *mailaddr,
                        if (st2->active < st2->raid)
                              continue;
                  }
-                 /* support for domain comparision needed */
+
+                 /* update the disk info in st2 state */
+                 sra = get_raid_disk_info(st2);
+                 if (!sra) {
+                       fprintf(stderr, "no sra for device: %s\n",
+                             st2->devname);
+                       continue;
+                 }
+                 sysfs_free(sra);
                  for (i = 0; i < st2->total; i++) {
+                       struct dev_policy *policy = NULL;
+                       struct mdinfo dinfo;
+                       enum policy_action action;
                        if (!dev_suitable(st2->devid[i],
                                      st2->devstate[i],
                                      st->min_size))
                              continue;
+
+                       dinfo.disk.major = major(st2->devid[i]);
+                       dinfo.disk.minor = minor(st2->devid[i]);
+
+                       policy = disk_policy(&dinfo);
+                       /* Can only add a spare if device has at least
+                          one domains */
+                       if (pol_find(policy, pol_domain) == NULL)
+                             continue;
+
+                       if (!domain_test(dl, policy, super->ss->name)) {
+                             /* domain test fails */
+                             dprintf("domain test fails: %s"
+                                   "(name: %s value: %s metadata: %s)\n",
+                                   dl->dom,
+                                   (policy) ? policy->name : "NULL",
+                                   (policy) ? policy->value : "NULL",
+                                   super->ss->name);
+                             continue;
+                       }
+                       /* check if spare sharing alowed */
+                       action = policy_action(policy, super->ss->name);
+                       if (action < act_spare)
+                             continue;
                        if (move_spare(st2, stp, &st2->devid[i],
                                     mailaddr, mailfrom, alert_cmd,
                                     dosyslog)) {
-- 
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