Changeset 561 in MondoRescue for trunk/mondo/mondo


Ignore:
Timestamp:
May 20, 2006, 5:51:21 PM (18 years ago)
Author:
bcornec
Message:

merge -r 542:560 $SVN_M/branches/stable

Location:
trunk/mondo/mondo
Files:
3 added
14 edited

Legend:

Unmodified
Added
Removed
  • trunk/mondo/mondo/common/libmondo-raid-EXT.h

    r59 r561  
    5353#endif
    5454
    55 extern int create_raidtab_from_mdstat(char *, char *);
    56 extern int read_mdstat(struct s_mdstat *mdstat, char *mdstat_file);
    57 
    58 extern int create_raidtab_from_mdstat(char *raidtab_fname,
    59                                       char *mdstat_fname);
     55extern int parse_mdstat(struct raidlist_itself *raidlist, char *device_prefix);
     56extern int create_raidtab_from_mdstat(char *raidtab_fname);
  • trunk/mondo/mondo/common/libmondo-raid.c

    r507 r561  
    344344
    345345    fprintf(fout, "raiddev %s\n", raidrec->raid_device);
    346     if (raidrec->raid_level == -1) {
     346    if (raidrec->raid_level == -2) {
     347        fprintf(fout, "    raid-level            multipath\n");
     348    } else if (raidrec->raid_level == -1) {
    347349        fprintf(fout, "    raid-level            linear\n");
    348350    } else {
     
    350352                raidrec->raid_level);
    351353    }
    352     fprintf(fout, "    chunk-size            %d\n", raidrec->chunk_size);
    353354    fprintf(fout, "    nr-raid-disks         %d\n",
    354355            raidrec->data_disks.entries);
    355     fprintf(fout, "    nr-spare-disks        %d\n",
    356             raidrec->spare_disks.entries);
     356    if (raidrec->spare_disks.entries > 0) {
     357        fprintf(fout, "    nr-spare-disks        %d\n",
     358                raidrec->spare_disks.entries);
     359    }
    357360    if (raidrec->parity_disks.entries > 0) {
    358361        fprintf(fout, "    nr-parity-disks       %d\n",
    359362                raidrec->parity_disks.entries);
    360363    }
    361 
    362364    fprintf(fout, "    persistent-superblock %d\n",
    363365            raidrec->persistent_superblock);
     366    if (raidrec->chunk_size > -1) {
     367      fprintf(fout, "    chunk-size            %d\n", raidrec->chunk_size);
     368    }
     369    if (raidrec->parity > -1) {
     370      switch(raidrec->parity) {
     371      case 0:
     372        fprintf(fout, "    parity-algorithm      left-asymmetric\n");
     373        break;
     374      case 1:
     375        fprintf(fout, "    parity-algorithm      right-asymmetric\n");
     376        break;
     377      case 2:
     378        fprintf(fout, "    parity-algorithm      left-symmetric\n");
     379        break;
     380      case 3:
     381        fprintf(fout, "    parity-algorithm      right-symmetric\n");
     382        break;
     383      default:
     384        fatal_error("Unknown RAID parity algorithm.");
     385        break;
     386      }
     387    }
    364388    save_additional_vars_to_file(&raidrec->additional_vars, fout);
    365389    fprintf(fout, "\n");
     
    642666
    643667    if (!strcmp(label, "raid-level")) {
    644         if (!strcmp(value, "linear")) {
     668        if (!strcmp(value, "multipath")) {
     669            raidrec->raid_level = -2;
     670        } else if (!strcmp(value, "linear")) {
    645671            raidrec->raid_level = -1;
    646672        } else {
     
    655681    } else if (!strcmp(label, "chunk-size")) {
    656682        raidrec->chunk_size = atoi(value);
     683    } else if (!strcmp(label, "parity-algorithm")) {
     684        if (!strcmp(value, "left-asymmetric")) {
     685            raidrec->parity = 0;
     686        } else if (!strcmp(value, "right-asymmetric")) {
     687            raidrec->parity = 1;
     688        } else if (!strcmp(value, "left-symmetric")) {
     689            raidrec->parity = 2;
     690        } else if (!strcmp(value, "right-symmetric")) {
     691            raidrec->parity = 3;
     692        } else {
     693            log_msg(1, "Unknown RAID parity algorithm '%s'\n.", value);
     694        }
    657695    } else if (!strcmp(label, "device")) {
    658696        get_next_raidtab_line(fin, labelB, valueB);
     
    898936
    899937
    900 int read_mdstat(struct s_mdstat *mdstat, char *mdstat_file)
    901 {
    902     FILE *fin;
    903     char *tmp;
    904     char *stub;
    905     char *incoming = NULL;
    906     char *p, *q, *r;
    907     int diskno;
    908     size_t n = 0;
    909 
    910     malloc_string(incoming);
    911     if (!(fin = fopen(mdstat_file, "r"))) {
    912         log_msg(1, "%s not found", mdstat_file);
     938int parse_mdstat(struct raidlist_itself *raidlist, char *device_prefix) {
     939
     940  const char delims[] = " ";
     941
     942  FILE   *fin;
     943  int    res = 0, row, i, index_min;
     944  int lastpos = 0;
     945  size_t len = 0;
     946  char   *token;
     947  char *string = NULL;
     948  char *pos;
     949  char type;
     950  char *strtmp;
     951
     952  // open file
     953  if (!(fin = fopen(MDSTAT_FILE, "r"))) {
     954    log_msg(1, "Could not open %s.\n", MDSTAT_FILE);
     955    return 1;
     956  }
     957  // initialise record, build progress and row counters
     958  raidlist->entries = 0;
     959  raidlist->el[raidlist->entries].progress = 999;
     960  row = 1;
     961  // skip first output row - contains registered RAID levels
     962  res = getline(&string, &len, fin);
     963  // parse the rest
     964  while ( !feof_unlocked(fin) ) {
     965    res = getline(&string, &len, fin);
     966    if (res <= 0) break;
     967    // trim leading spaces
     968    pos = string;
     969    while (*pos == ' ') *pos++;
     970    asprintf(&string, pos);
     971    //
     972    // if we have newline after only spaces, this is a blank line, update
     973    // counters, otherwise do normal parsing
     974    if (*string == '\n') {
     975      row = 1;
     976      raidlist->entries++;
     977      raidlist->el[raidlist->entries].progress = 999;
     978    } else {
     979      switch (row) {
     980      case 1:  // device information
     981    // check whether last line of record and if so skip
     982    pos = strcasestr(string, "unused devices: ");
     983    if (pos == string) {
     984      //raidlist->entries--;
     985      break;
     986    }
     987    // tokenise string
     988    token = mr_strtok (string, delims, &lastpos);
     989    // get RAID device name
     990    asprintf(&strtmp,"%s%s", device_prefix, token);
     991    strcpy(raidlist->el[raidlist->entries].raid_device, strtmp);
     992    paranoid_free(strtmp);
     993    paranoid_free(token);
     994    // skip ':' and status
     995    token = strtok (string, delims, &lastpos);
     996    paranoid_free(token);
     997    token = strtok (string, delims, &lastpos);
     998    if (!strcmp(token, "inactive")) {
     999      log_msg(1, "RAID device '%s' inactive.\n",
     1000         raidlist->el[raidlist->entries].raid_device);
     1001      paranoid_free(string);
     1002      paranoid_free(token);
     1003      return 1;
     1004    }
     1005    paranoid_free(token);
     1006
     1007    // get RAID level
     1008    token = strtok (string, delims, &lastpos);
     1009    if (!strcmp(token, "multipath")) {
     1010      raidlist->el[raidlist->entries].raid_level = -2;
     1011    } else if (!strcmp(token, "linear")) {
     1012      raidlist->el[raidlist->entries].raid_level = -1;
     1013    } else if (!strcmp(token, "raid0")) {
     1014      raidlist->el[raidlist->entries].raid_level = 0;
     1015    } else if (!strcmp(token, "raid1")) {
     1016      raidlist->el[raidlist->entries].raid_level = 1;
     1017    } else if (!strcmp(token, "raid4")) {
     1018      raidlist->el[raidlist->entries].raid_level = 4;
     1019    } else if (!strcmp(token, "raid5")) {
     1020      raidlist->el[raidlist->entries].raid_level = 5;
     1021    } else if (!strcmp(token, "raid6")) {
     1022      raidlist->el[raidlist->entries].raid_level = 6;
     1023    } else if (!strcmp(token, "raid10")) {
     1024      raidlist->el[raidlist->entries].raid_level = 10;
     1025    } else {
     1026      log_msg(1, "Unknown RAID level '%s'.\n", token);
     1027      paranoid_free(string);
     1028      paranoid_free(token);
     1029      return 1;
     1030    }
     1031    paranoid_free(token);
     1032
     1033    // get RAID devices (type, index, device)
     1034    // Note: parity disk for RAID4 is last normal disk, there is no '(P)'
     1035    raidlist->el[raidlist->entries].data_disks.entries = 0;
     1036    raidlist->el[raidlist->entries].spare_disks.entries = 0;
     1037    raidlist->el[raidlist->entries].failed_disks.entries = 0;
     1038    while((token = strtok (string, delims, &lastpos))) {
     1039      if ((pos = strstr(token, "("))) {
     1040        type = *(pos+1);
     1041      } else {
     1042        type = ' ';
     1043      }
     1044      pos = strstr(token, "[");
     1045      *pos = '\0';
     1046      switch(type) {
     1047      case ' ': // normal data disks
     1048        raidlist->el[raidlist->entries].data_disks.el[raidlist->el[raidlist->entries].data_disks.entries].index = atoi(pos + 1);
     1049        asprintf(&strtmp,"%s%s", device_prefix, token);
     1050        strcpy(raidlist->el[raidlist->entries].data_disks.el[raidlist->el[raidlist->entries].data_disks.entries].device, strtmp);
     1051        paranoid_free(strtmp);
     1052        raidlist->el[raidlist->entries].data_disks.entries++;
     1053        break;
     1054      case 'S': // spare disks
     1055        raidlist->el[raidlist->entries].spare_disks.el[raidlist->el[raidlist->entries].spare_disks.entries].index = atoi(pos + 1);
     1056        asprintf(&strtmp,"%s%s", device_prefix, token);
     1057        strcpy(raidlist->el[raidlist->entries].spare_disks.el[raidlist->el[raidlist->entries].spare_disks.entries].device, strtmp);
     1058        paranoid_free(strtmp);
     1059        raidlist->el[raidlist->entries].spare_disks.entries++;
     1060        break;
     1061      case 'F': // failed disks
     1062        raidlist->el[raidlist->entries].failed_disks.el[raidlist->el[raidlist->entries].failed_disks.entries].index = atoi(pos + 1);
     1063        asprintf(&strtmp,"%s%s", device_prefix, token);
     1064        strcpy(raidlist->el[raidlist->entries].failed_disks.el[raidlist->el[raidlist->entries].failed_disks.entries].device, strtmp);
     1065        paranoid_free(strtmp);
     1066        raidlist->el[raidlist->entries].failed_disks.entries++;
     1067        log_it("At least one failed disk found in RAID array.\n");
     1068        break;
     1069      default: // error
     1070        log_msg(1, "Unknown device type '%c'\n", type);
     1071        paranoid_free(string);
     1072        paranoid_free(token);
     1073        return 1;
     1074        break;
     1075      }
     1076      paranoid_free(token);
     1077    }
     1078
     1079    // adjust index for each device so that it starts with 0 for every type
     1080    index_min = 99;
     1081    for (i=0; i<raidlist->el[raidlist->entries].data_disks.entries;i++) {
     1082      if (raidlist->el[raidlist->entries].data_disks.el[i].index < index_min) {
     1083        index_min = raidlist->el[raidlist->entries].data_disks.el[i].index;
     1084      }
     1085    }
     1086    if (index_min > 0) {
     1087      for (i=0; i<raidlist->el[raidlist->entries].data_disks.entries;i++) {
     1088        raidlist->el[raidlist->entries].data_disks.el[i].index = raidlist->el[raidlist->entries].data_disks.el[i].index - index_min;   
     1089      }
     1090    }
     1091    index_min = 99;
     1092    for (i=0; i<raidlist->el[raidlist->entries].spare_disks.entries;i++) {
     1093      if (raidlist->el[raidlist->entries].spare_disks.el[i].index < index_min) {
     1094        index_min = raidlist->el[raidlist->entries].spare_disks.el[i].index;
     1095      }
     1096    }
     1097    if (index_min > 0) {
     1098      for (i=0; i<raidlist->el[raidlist->entries].spare_disks.entries;i++) {
     1099        raidlist->el[raidlist->entries].spare_disks.el[i].index = raidlist->el[raidlist->entries].spare_disks.el[i].index - index_min; 
     1100      }
     1101    }
     1102    index_min = 99;
     1103    for (i=0; i<raidlist->el[raidlist->entries].failed_disks.entries;i++) {
     1104      if (raidlist->el[raidlist->entries].failed_disks.el[i].index < index_min) {
     1105        index_min = raidlist->el[raidlist->entries].failed_disks.el[i].index;
     1106      }
     1107    }
     1108    if (index_min > 0) {
     1109      for (i=0; i<raidlist->el[raidlist->entries].failed_disks.entries;i++) {
     1110        raidlist->el[raidlist->entries].failed_disks.el[i].index = raidlist->el[raidlist->entries].failed_disks.el[i].index - index_min;   
     1111      }
     1112    }
     1113    break;
     1114      case 2:  // config information
     1115    // check for persistent super block
     1116    if (strcasestr(string, "super non-persistent")) {
     1117      raidlist->el[raidlist->entries].persistent_superblock = 0;
     1118    } else {
     1119      raidlist->el[raidlist->entries].persistent_superblock = 1;
     1120    }
     1121    // extract chunk size
     1122    if (!(pos = strcasestr(string, "k chunk"))) {
     1123      raidlist->el[raidlist->entries].chunk_size = -1;
     1124    } else {
     1125      while (*pos != ' ') {
     1126        *pos--;
     1127        if (pos < string) {
     1128          log_it("String underflow!\n");
     1129          paranoid_free(string);
     1130          return 1;
     1131        }
     1132      }
     1133      raidlist->el[raidlist->entries].chunk_size = atoi(pos + 1);
     1134    }
     1135    // extract parity if present
     1136    if ((pos = strcasestr(string, "algorithm"))) {
     1137      raidlist->el[raidlist->entries].parity = atoi(pos + 9);
     1138    } else {
     1139      raidlist->el[raidlist->entries].parity = -1;
     1140    }
     1141    break;
     1142      case 3:  // optional build status information
     1143    if (!(pos = strchr(string, '\%'))) {
     1144      if (strcasestr(string, "delayed")) {
     1145        raidlist->el[raidlist->entries].progress = -1;  // delayed (therefore, stuck at 0%)
     1146      } else {
     1147        raidlist->el[raidlist->entries].progress = 999; // not found
     1148      }
     1149    } else {
     1150      while (*pos != ' ') {
     1151        *pos--;
     1152        if (pos < string) {
     1153          printf("ERROR: String underflow!\n");
     1154          paranoid_free(string);
     1155          return 1;
     1156        }
     1157      }
     1158      raidlist->el[raidlist->entries].progress = atoi(pos);
     1159    }
     1160    break;
     1161      default: // error
     1162    log_msg(1, "Row %d should not occur in record!\n", row);
     1163    break;
     1164      }
     1165      row++;
     1166    }
     1167  }
     1168  // close file
     1169  fclose(fin);
     1170  // free string
     1171  paranoid_free(string);
     1172  // return success
     1173  return 0;
     1174
     1175}
     1176
     1177
     1178
     1179
     1180int create_raidtab_from_mdstat(char *raidtab_fname)
     1181{
     1182    struct raidlist_itself *raidlist;
     1183    int retval = 0;
     1184
     1185    raidlist = malloc(sizeof(struct raidlist_itself));
     1186
     1187    // FIXME: Prefix '/dev/' should really be dynamic!
     1188    if (parse_mdstat(raidlist, "/dev/")) {
     1189        log_to_screen("Sorry, cannot read %s", MDSTAT_FILE);
    9131190        return (1);
    9141191    }
    915     mdstat->entries = 0;
    916     for (getline(&incoming, &n, fin); !feof(fin);
    917          getline(&incoming, &n, fin)) {
    918         p = incoming;
    919         if (*p != 'm' && *(p + 1) == 'm') {
    920             p++;
    921         }
    922         if (strncmp(p, "md", 2)) {
    923             continue;
    924         }
    925 // read first line --- mdN : active raidX ............
    926         mdstat->el[mdstat->entries].md = atoi(p + 2);
    927         log_msg(8, "Storing /dev/md%d's info", atoi(p + 2));
    928         while (*p != ':' && *p) {
    929             p++;
    930         }
    931         while ((*p != 'r' || *(p + 1) != 'a') && *p) {
    932             p++;
    933         }
    934         if (!strncmp(p, "raid", 4)) {
    935             mdstat->el[mdstat->entries].raidlevel = *(p + 4) - '0';
    936         }
    937         p += 4;
    938         while (*p != ' ' && *p) {
    939             p++;
    940         }
    941         while (*p == ' ' && *p) {
    942             p++;
    943         }
    944         for (diskno = 0; *p; diskno++) {
    945             asprintf(&stub, "%s", p);
    946             q = strchr(stub, '[');
    947             if (q) {
    948                 *q = '\0';
    949                 q++;
    950                 r = strchr(q, ']');
    951                 if (r) {
    952                     *r = '\0';
    953                 }
    954                 mdstat->el[mdstat->entries].disks.el[diskno].index =
    955                     atoi(q);
    956             } else {
    957                 mdstat->el[mdstat->entries].disks.el[diskno].index = -1;
    958                 q = strchr(stub, ' ');
    959                 if (q) {
    960                     *q = '\0';
    961                 }
    962             }
    963             asprintf(&tmp, "/dev/%s", stub);
    964             paranoid_free(stub);
    965 
    966             log_msg(8, "/dev/md%d : disk#%d : %s (%d)",
    967                     mdstat->el[mdstat->entries].md, diskno, tmp,
    968                     mdstat->el[mdstat->entries].disks.el[diskno].index);
    969             strcpy(mdstat->el[mdstat->entries].disks.el[diskno].device,
    970                    tmp);
    971             paranoid_free(tmp);
    972 
    973             while (*p != ' ' && *p) {
    974                 p++;
    975             }
    976             while (*p == ' ' && *p) {
    977                 p++;
    978             }
    979         }
    980         mdstat->el[mdstat->entries].disks.entries = diskno;
    981 // next line --- skip it
    982         if (!feof(fin)) {
    983             getline(&incoming, &n, fin);
    984         } else {
    985             continue;
    986         }
    987 // next line --- the 'progress' line
    988         if (!feof(fin)) {
    989             getline(&incoming, &n, fin);
    990         } else {
    991             continue;
    992         }
    993 //  log_msg(1, "Percentage line = '%s'", incoming);
    994         if (!(p = strchr(incoming, '\%'))) {
    995             mdstat->el[mdstat->entries].progress = 999; // not found
    996         } else if (strstr(incoming, "DELAYED")) {
    997             mdstat->el[mdstat->entries].progress = -1;  // delayed (therefore, stuck at 0%)
    998         } else {
    999             for (*p = '\0'; *p != ' '; p--);
    1000             mdstat->el[mdstat->entries].progress = atoi(p);
    1001         }
    1002         log_msg(8, "progress =%d", mdstat->el[mdstat->entries].progress);
    1003         mdstat->entries++;
    1004     }
    1005     fclose(fin);
    1006     paranoid_free(incoming);
    1007     return (0);
    1008 }
    1009 
    1010 
    1011 
    1012 int create_raidtab_from_mdstat(char *raidtab_fname, char *mdstat_fname)
    1013 {
    1014     struct raidlist_itself *raidlist;
    1015     struct s_mdstat *mdstat;
    1016     int retval = 0;
    1017     int i;
    1018 
    1019     raidlist = malloc(sizeof(struct raidlist_itself));
    1020     mdstat = malloc(sizeof(struct s_mdstat));
    1021 
    1022     if (read_mdstat(mdstat, mdstat_fname)) {
    1023         log_to_screen("Sorry, cannot read %s", mdstat_fname);
    1024         return (1);
    1025     }
    1026 
    1027     for (i = 0; i < mdstat->entries; i++) {
    1028         sprintf(raidlist->el[i].raid_device, "/dev/md%d",
    1029                 mdstat->el[i].md);
    1030         raidlist->el[i].raid_level = mdstat->el[i].raidlevel;
    1031         raidlist->el[i].persistent_superblock = 1;
    1032         raidlist->el[i].chunk_size = 4;
    1033         memcpy((void *) &raidlist->el[i].data_disks,
    1034                (void *) &mdstat->el[i].disks,
    1035                sizeof(struct list_of_disks));
    1036         // FIXME --- the above line does not allow for spare disks
    1037         log_to_screen
    1038             (_("FIXME - create_raidtab_from_mdstat does not allow for spare disks"));
    1039     }
    1040     raidlist->entries = i;
     1192
    10411193    retval += save_raidlist_to_raidtab(raidlist, raidtab_fname);
    10421194    return (retval);
  • trunk/mondo/mondo/common/libmondo-raid.h

    r59 r561  
    4343#endif
    4444
    45 
    46 int create_raidtab_from_mdstat(char *, char *);
    47 int read_mdstat(struct s_mdstat *mdstat, char *mdstat_file);
    48 
    49 int create_raidtab_from_mdstat(char *raidtab_fname, char *mdstat_fname);
     45int create_raidtab_from_mdstat(char *raidtab_fname);
     46int parse_mdstat(struct raidlist_itself *raidlist, char *device_prefix);
  • trunk/mondo/mondo/common/libmondo-string.c

    r507 r561  
    22   $Id$
    33*/
    4 
    54
    65/**
     
    11391138}
    11401139
     1140
     1141/* New functions safe from a memory manageemnt point of view */
     1142/* Developped by Andree Leidenfrost */
     1143
     1144char *mr_strtok(char *instr, const char *delims, int *lastpos) {
     1145
     1146char *token = NULL;
     1147char *strptr = NULL;
     1148size_t pos1 = 0;
     1149size_t pos2 = 0;
     1150
     1151if (strlen(instr) <= *lastpos) {
     1152    *lastpos = 0;
     1153    return token;
     1154}
     1155
     1156strptr = instr + *lastpos;
     1157pos2 = strspn(strptr, delims);
     1158strptr += pos2;
     1159pos1 = strcspn(strptr, delims);
     1160token = malloc(sizeof(*token)*(pos1+1));
     1161strncpy(token, strptr, pos1);
     1162*lastpos = *lastpos + pos1 + pos2 + 1;
     1163
     1164return token;
     1165}
    11411166/* @} - end of stringGroup */
  • trunk/mondo/mondo/common/libmondo-string.h

    r59 r561  
    3434char *media_descriptor_string(t_bkptype);
    3535inline void turn_wildcard_chars_into_literal_chars(char *out, char *in);
     36
     37/* Valid external functions */
     38char *mr_strtok(char *instr, const char *delims, int *lastpos)
  • trunk/mondo/mondo/common/libmondo-tools.c

    r539 r561  
    282282    assert(raidrec != NULL);
    283283    raidrec->raid_device[0] = '\0';
    284     raidrec->raid_level = 0;
    285     raidrec->chunk_size = 4;
     284    raidrec->raid_level = -9;
    286285    raidrec->persistent_superblock = 1;
     286    raidrec->chunk_size = 64;
     287    raidrec->parity = -1;
    287288    raidrec->data_disks.entries = 0;
    288289    raidrec->spare_disks.entries = 0;
     
    994995        log_to_screen
    995996            (_("You have RAID partitions but no /etc/raidtab - creating one from /proc/mdstat"));
    996         create_raidtab_from_mdstat("/etc/raidtab", "/proc/mdstat");
     997        create_raidtab_from_mdstat("/etc/raidtab");
    997998    }
    998999
  • trunk/mondo/mondo/common/mondostructures.h

    r539 r561  
    133133   */
    134134    int index;
     135   
     136  /**
     137   * Type of disk.
     138   */
     139    char type;  // ' ' = data (default), S = spare, F = faulty
     140   
    135141};
    136142
     
    224230       */
    225231    int chunk_size;
     232   
     233      /**
     234       * The parity algorithm of this RAID device. (RAID5 only)
     235       */
     236    int parity; // 0=left-asymmetric, 1=right-asymmetric, 2=left-symmetric, 3=right-symmetric
    226237
    227238      /**
     
    249260       */
    250261    struct additional_raid_variables additional_vars;
     262
     263      /**
     264       * Resync progress for this device.
     265       */
     266    int progress;
    251267};
    252268
  • trunk/mondo/mondo/common/my-stuff.h

    r539 r561  
    2222 * The main header file for Mondo.
    2323 */
    24 #ifndef _MY_STUFF_H_
    25 #define _MY_STUFF_H_
    2624
    2725/* Required for the use of getline, ... */
    28 #define __USE_GNU
    2926#define _GNU_SOURCE
    3027
     
    8380#ifndef S_SPLINT_S
    8481#include <pthread.h>
     82#endif
    8583#include <assert.h>
    8684
     
    114112 */
    115113#define MONDO_CFG_FILE_STUB "tmp/mondo-restore.cfg"
     114
     115/**
     116 * The RAID kernel proc file
     117 */
     118#define MDSTAT_FILE "/proc/mdstat"
    116119
    117120/**
     
    428431
    429432
    430 
    431433#endif                          /* _MY_STUFF_H_ */
  • trunk/mondo/mondo/mondorestore/mondo-prep.c

    r507 r561  
    695695
    696696/**
     697 * Create @p RAID device using information from @p structure.
     698 * This will create the specified RAID devive using information provided in
     699 * raidlist by means of the mdadm tool.
     700 * @param raidlist The structure containing all RAID information
     701 * @param device The RAID device to create.
     702 * @return 0 for success, nonzero for failure.
     703 */
     704int create_raid_device_via_mdadm(struct raidlist_itself *raidlist, char *device)
     705{
     706  /** int **************************************************************/
     707  int i   = 0;
     708  int j   = 0;
     709  int res = 0;
     710 
     711  /** buffers ***********************************************************/
     712  char *devices = NULL;
     713  char *strtmp  = NULL;
     714  char *level   = NULL;
     715  char *program = NULL;
     716 
     717  // leave straight away if raidlist is initial or has no entries
     718  if (!raidlist || raidlist->entries == 0) {
     719    log_msg(1, "No RAID arrays found.");
     720    return 1;
     721  } else {
     722    log_msg(1, "%d RAID arrays found.", raidlist->entries);
     723  }
     724  // find raidlist entry for requested device
     725  for (i = 0; i < raidlist->entries; i++) {
     726    if (!strcmp(raidlist->el[i].raid_device, device)) break;
     727  }
     728  // check whether RAID device was found in raidlist
     729  if (i == raidlist->entries) {
     730    log_msg(1, "RAID device %s not found in list.", device);
     731    return 1;
     732  }
     733  // create device list from normal disks followed by spare ones
     734  asprintf(&devices, raidlist->el[i].data_disks.el[0].device);
     735  for (j = 1; j < raidlist->el[i].data_disks.entries; j++) {
     736    asprintf(&strtmp, "%s", devices);
     737    paranoid_free(devices);
     738    asprintf(&devices, "%s %s", strtmp,
     739         raidlist->el[i].data_disks.el[j].device);
     740    paranoid_free(strtmp);
     741  }
     742  for (j = 0; j < raidlist->el[i].spare_disks.entries; j++) {
     743    asprintf(&strtmp, "%s", devices);
     744    paranoid_free(devices);
     745    asprintf(&devices, "%s %s", strtmp,
     746         raidlist->el[i].spare_disks.el[j].device);
     747    paranoid_free(strtmp);
     748  }
     749  // translate RAID level
     750  if (raidlist->el[i].raid_level == -2) {
     751    asprintf(&level, "multipath");
     752  } else if (raidlist->el[i].raid_level == -1) {
     753    asprintf(&level, "linear");
     754  } else {
     755    asprintf(&level, "raid%d", raidlist->el[i].raid_level);
     756  }
     757  // create RAID device:
     758  // - RAID device, number of devices and devices mandatory
     759  // - parity algorithm, chunk size and spare devices optional
     760  // - faulty devices ignored
     761  // - persistent superblock always used as this is recommended
     762  asprintf(&program,
     763       "mdadm --create --force --run --auto=yes %s --level=%s --raid-devices=%d",
     764       raidlist->el[i].raid_device, level,
     765       raidlist->el[i].data_disks.entries);
     766  if (raidlist->el[i].parity != -1) {
     767    asprintf(&strtmp, "%s", program);
     768    paranoid_free(program);
     769    switch(raidlist->el[i].parity) {
     770    case 0:
     771      asprintf(&program, "%s --parity=%s", strtmp, "la");
     772      break;
     773    case 1:
     774      asprintf(&program, "%s --parity=%s", strtmp, "ra");
     775      break;
     776    case 2:
     777      asprintf(&program, "%s --parity=%s", strtmp, "ls");
     778      break;
     779    case 3:
     780      asprintf(&program, "%s --parity=%s", strtmp, "rs");
     781      break;
     782    default:
     783      fatal_error("Unknown RAID parity algorithm.");
     784      break;
     785    }
     786    paranoid_free(strtmp);
     787  }
     788  if (raidlist->el[i].chunk_size != -1) {
     789    asprintf(&strtmp, "%s", program);
     790    paranoid_free(program);
     791    asprintf(&program, "%s --chunk=%d", strtmp, raidlist->el[i].chunk_size);
     792    paranoid_free(strtmp);
     793  }
     794  if (raidlist->el[i].spare_disks.entries > 0) {
     795    asprintf(&strtmp, "%s", program);
     796    paranoid_free(program);
     797    asprintf(&program, "%s --spare-devices=%d", strtmp,
     798         raidlist->el[i].spare_disks.entries);
     799    paranoid_free(strtmp);
     800  }
     801  asprintf(&strtmp, "%s", program);
     802  paranoid_free(program);
     803  asprintf(&program, "%s %s", strtmp, devices);
     804  paranoid_free(strtmp);
     805  res = run_program_and_log_output(program, 1);
     806  // free memory
     807  paranoid_free(devices);
     808  paranoid_free(level);
     809  paranoid_free(program);
     810  // return to calling instance
     811  return res;
     812}
     813
     814
     815/**
    697816 * Format @p device as a @p format filesystem.
    698817 * This will use the format command returned by which_format_command_do_i_need().
     
    704823 * @return 0 for success, nonzero for failure.
    705824 */
    706 int format_device(char *device, char *format)
     825int format_device(char *device, char *format, struct raidlist_itself *raidlist)
    707826{
    708827    /** int **************************************************************/
     
    836955
    837956        log_msg(1, "Making %s", device);
    838         sprintf(program, "mkraid --really-force %s", device);
    839         res = run_program_and_log_output(program, 1);
    840         log_msg(1, "%s returned %d", program, res);
    841         system("sync");
    842         sleep(3);
    843         start_raid_device(device);
    844         if (g_fprep) {
    845             fprintf(g_fprep, "%s\n", program);
     957        // use mkraid if it exists, otherwise use mdadm
     958        if (run_program_and_log_output("which mkraid", FALSE)) {
     959            res = create_raid_device_via_mdadm(raidlist, device);
     960            log_msg(1, "Creating RAID device %s via mdadm returned %d", device, res);
     961        } else {
     962            sprintf(program, "mkraid --really-force %s", device);
     963            res = run_program_and_log_output(program, 1);
     964            log_msg(1, "%s returned %d", program, res);
     965            system("sync");
     966            sleep(3);
     967            start_raid_device(device);
     968            if (g_fprep) {
     969                fprintf(g_fprep, "%s\n", program);
     970            }
    846971        }
    847972        system("sync");
    848973        sleep(2);
    849 
    850974//      log_to_screen("Starting %s", device);
    851975//      sprintf(program, "raidstart %s", device);
     
    853977//      log_msg(1, "%s returned %d", program, res);
    854978//      system("sync"); sleep(1);
    855         if (g_fprep) {
    856             fprintf(g_fprep, "%s\n", program);
    857         }
    858979#endif
    859980        system("sync");
     
    9231044 * @return The number of errors encountered (0 for success).
    9241045 */
    925 int format_everything(struct mountlist_itself *mountlist,
    926                       bool interactively)
     1046int format_everything(struct mountlist_itself *mountlist, bool interactively,
     1047                          struct raidlist_itself *raidlist)
    9271048{
    9281049    /** int **************************************************************/
     
    9831104            if (do_it) {
    9841105                // NB: format_device() also stops/starts RAID device if necessary
    985                 retval += format_device(me->device, me->format);
     1106                retval += format_device(me->device, me->format, raidlist);
    9861107            }
    9871108            g_current_progress += progress_step;
     
    10001121    log_msg(1, "Creating LVMs");
    10011122    if (does_file_exist("/tmp/i-want-my-lvm")) {
    1002         wait_until_software_raids_are_prepped("/proc/mdstat", 10);
     1123        wait_until_software_raids_are_prepped("/proc/mdstat", 100);
    10031124        log_to_screen(_("Configuring LVM"));
    10041125        if (!g_text_mode) {
     
    10761197
    10771198            if (do_it)
    1078                 retval += format_device(me->device, me->format);
     1199                retval += format_device(me->device, me->format, raidlist);
    10791200        }
    10801201
     
    22462367    sprintf(program, "vinum stop -f %s", raid_device);
    22472368#else
    2248     sprintf(program, "raidstop %s", raid_device);
    2249 //      sprintf (program, "raidstop " RAID_DEVICE_STUB "*");
     2369    // use raidstop if it exists, otherwise use mdadm
     2370    if (run_program_and_log_output("which raidstop", FALSE)) {
     2371        sprintf(program, "mdadm -S %s", raid_device);
     2372    } else {
     2373        sprintf(program, "raidstop %s", raid_device);
     2374    }
    22502375#endif
    22512376    log_msg(1, "program = %s", program);
  • trunk/mondo/mondo/mondorestore/mondo-restore.c

    r507 r561  
    839839                    }
    840840
    841                     fmt_errs = format_everything(mountlist, FALSE);
     841                    fmt_errs = format_everything(mountlist, FALSE, raidlist);
    842842                    if (!fmt_errs) {
    843843                        log_to_screen
     
    857857                if (ask_me_yes_or_no
    858858                    (_("Do you want to format your hard drives?"))) {
    859                     fmt_errs = format_everything(mountlist, TRUE);
     859                    fmt_errs = format_everything(mountlist, TRUE, raidlist);
    860860                    if (!fmt_errs) {
    861861                        done = TRUE;
     
    11641164                system("sync");
    11651165                log_to_screen(_("Please wait. This may take a few minutes."));
    1166                 res += format_everything(mountlist, FALSE);
     1166                res += format_everything(mountlist, FALSE, raidlist);
    11671167            }
    11681168            paranoid_fclose(g_fprep);
     
    34253425    }
    34263426
    3427     if (argc == 4 && strcmp(argv[1], "--mdconv") == 0) {
    3428         finish(create_raidtab_from_mdstat(argv[2], argv[3]));
     3427    if (argc == 3 && strcmp(argv[1], "--mdconv") == 0) {
     3428        finish(create_raidtab_from_mdstat(argv[2]));
    34293429    }
    34303430
     
    35253525            strcpy(g_mountlist_fname, "/tmp/mountlist.txt");
    35263526            load_mountlist(mountlist, g_mountlist_fname);
    3527             res = format_everything(mountlist, FALSE);
     3527            res = format_everything(mountlist, FALSE, raidlist);
    35283528            finish(res);
    35293529        }
  • trunk/mondo/mondo/mondorestore/mondo-rstr-tools.c

    r507 r561  
    1 /***************************************************************************
    2 mondo-rstr-tools.c  -  description
    3 -----------------
    4 
    5 begin: Sun Sep 21 16:40:35 EDT 2003
    6 copyright : (C) 2002 Mondo  Hugo Rabson
    7 email     : Hugo Rabson <hugorabson@msn.com>
    8 edited by : by Stan Benoit ?/2003
    9 email     : troff@nakedsoul.org
    10 cvsid     : $Id: mondo-rstr-tools.c
    11 ***************************************************************************/
    12 
    13 /***************************************************************************
    14  *                                                                         *
    15  *   This program is free software; you can redistribute it and/or modify  *
    16  *   it under the terms of the GNU General Public License as published by  *
    17  *   the Free Software Foundation; either version 2 of the License, or     *
    18  *   (at your option) any later version.                                   *
    19  *                                                                         *
    20  ***************************************************************************/
    21 /* mondo-rstr-tools.c               Hugo Rabson
    22 
    23 
    24 07/27
    25 - if the user is foolish enough to use /dev/md0 as boot device,
    26   call lilo -M /dev/hda to make sure lilo does its job properly
    27 - better NFS+nuke support
    28 
    29 07/20
    30 - use backup's i-want-my-lvm file
    31 - be sure to use archives' raidtab when restoring
    32 
    33 07/18
    34 - use /tmp/isodir for NFS if DR mode
    35 - better support of users who boot from LVM CD and nuke-restore non-LVM backups
    36 
    37 07/12
    38 - bugfix to allow user to burn ISOs to CDs and restore from CDs (not original src)
    39 
    40 06/29
    41 - mount ext3 partitions as ext2, just in case :)
    42 
    43 06/26
    44 - delete make_relevant_partition_bootable()
    45 
    46 06/19
    47 - futzed with the call to mount floppy, to stop it from locking up on my AMD64 system
    48 
    49 06/14
    50 - shell out to /mnt/RESTORING chroot in order to let user install GRUB
    51   manually if automatic GRUB installation fails
    52 
    53 06/15
    54 - Added check for different 'isodir' chosen by user than stored in the archive
    55   Conor Daly <conor.daly@met.ie>
    56 
    57 04/17
    58 - replaced INTERNAL_TAPE_BLK_SIZE with bkpinfo->internal_tape_block_size
    59 
    60 04/09
    61 - don't try to mount CD if tape bkp
    62 
    63 04/03
    64 - trying to copy tmp/mondo-restore.cfg to itself - silly! - fixed
    65 
    66 04/02
    67 - when extracting cfg file and mountlist from all.tar.gz (tape copy),
    68   use block size of INTERNAL_TAPE_BLK_SIZE, not TAPE_BLOCK_SIZE
    69 
    70 02/21
    71 - don't use 'mv -v' cos Busybox won't support it
    72 
    73 02/09
    74 - make hole for cfg file before moving it (line 2094 or so)
    75 
    76 02/03
    77 - changed a couple of refs to filelist.full, to filelist.full.gz
    78 
    79 01/16/2004
    80 - instead of copying filelist, use 'ln -sf' to link to original;
    81   saves space
    82 
    83 11/20/2003
    84 - also retrieve /tmp/mountlist.txt if user wants
    85 
    86 11/16
    87 - fixed NFS path bug affecting the extractions of filelist/biggielist
    88   during selective restore
    89 
    90 11/02
    91 - fixed mount_cdrom() to run properly w/ nfs restores
    92 - mount_device() returns 0 if swap mount fails cos swap isn't crucial
    93 
    94 10/17
    95 - run_grub() uses MNT_RESTORING instead of "/mnt/RESTORING"
    96 
    97 10/26
    98 - cleaned up run_grub()
    99 
    100 10/25
    101 - fixed mount_cdrom() to run properly w/ nfs restores
    102 
    103 10/21
    104 - mount_device() returns 0 if swap mount fails cos swap isn't crucial
    105 
    106 10/15
    107 - run_grub() now uses its initiative instead
    108   of calling grub-install
    109 
    110 10/10
    111 - don't leave copies of filelist.full lying around, clogging up
    112   the ramdisk, there's a good fellow :-)
    113 
    114 10/02
    115 - added 'dvd' to the range of media types I'll understand
    116 - fixed iso->cdr problem (thanks, Stan Benoit & Fred Beondo)
    117 
    118 09/24
    119 - try lots of tape devs if /dev/st0 fails
    120 
    121 09/23/2003
    122 - first incarnation
     1/*
     2 * $Id$
    1233*/
    1244
     
    25692449                                           int wait_for_percentage)
    25702450{
    2571     struct s_mdstat *mdstat;
     2451    struct raidlist_itself *raidlist;
    25722452    int unfinished_mdstat_devices = 9999, i;
    25732453    char *screen_message;
    25742454
    25752455    malloc_string(screen_message);
    2576     mdstat = malloc(sizeof(struct s_mdstat));
     2456    raidlist = malloc(sizeof(struct raidlist_itself));
    25772457
    25782458    assert(wait_for_percentage <= 100);
    25792459    iamhere("Help, my boat is sync'ing. (Get it? Urp! Urp!)");
    25802460    while (unfinished_mdstat_devices > 0) {
    2581         if (read_mdstat(mdstat, mdstat_file)) {
    2582             log_to_screen(_("Sorry, cannot read %s"), mdstat_file);
     2461        if (parse_mdstat(raidlist, "/dev/")) {
     2462            log_to_screen("Sorry, cannot read %s", MDSTAT_FILE);
     2463            log_msg(1,"Sorry, cannot read %s", MDSTAT_FILE);
    25832464            return;
    25842465        }
    2585         for (unfinished_mdstat_devices = i = 0; i < mdstat->entries; i++) {
    2586             if (mdstat->el[i].progress < wait_for_percentage) {
     2466        for (unfinished_mdstat_devices = i = 0; i <= raidlist->entries; i++) {
     2467            if (raidlist->el[i].progress < wait_for_percentage) {
    25872468                unfinished_mdstat_devices++;
    2588                 sprintf(screen_message, _("Sync'ing /dev/md%d"),
    2589                         mdstat->el[i].md);
     2469                log_msg(1,"Sync'ing %s (i=%d)", raidlist->el[i].raid_device, i);
     2470                sprintf(screen_message, "Sync'ing %s",
     2471                        raidlist->el[i].raid_device);
    25902472                open_evalcall_form(screen_message);
    2591                 if (mdstat->el[i].progress == -1)   // delayed while another partition inits
     2473                if (raidlist->el[i].progress == -1) // delayed while another partition inits
    25922474                {
    25932475                    continue;
    25942476                }
    2595                 while (mdstat->el[i].progress < wait_for_percentage) {
    2596                     update_evalcall_form(mdstat->el[i].progress);
     2477                while (raidlist->el[i].progress < wait_for_percentage) {
     2478                    log_msg(1,"Percentage sync'ed: %d", raidlist->el[i].progress);
     2479                    update_evalcall_form(raidlist->el[i].progress);
    25972480                    sleep(2);
    2598                     if (read_mdstat(mdstat, mdstat_file)) {
     2481                    // FIXME: Prefix '/dev/' should really be dynamic!
     2482                    if (parse_mdstat(raidlist, "/dev/")) {
    25992483                        break;
    26002484                    }
     
    26052489    }
    26062490    paranoid_free(screen_message);
    2607     paranoid_free(mdstat);
    2608 }
     2491    paranoid_free(raidlist);
     2492}
  • trunk/mondo/mondo/mondorestore/mondoprep.h

    r59 r561  
    5858int start_all_raid_devices(struct mountlist_itself *);
    5959int stop_all_raid_devices(struct mountlist_itself *);
    60 int format_everything(struct mountlist_itself *, bool);
     60int format_everything(struct mountlist_itself *, bool, struct raidlist_itself *);
    6161int partition_device(FILE *, const char *, int, int, const char *,
    6262                     long long);
     
    6565int partition_device_with_fdisk(FILE *, const char *, int, int,
    6666                                const char *, long long);
    67 int format_device(char *, char *);
     67int format_device(char *, char *, struct raidlist_itself *);
    6868int partition_drive(struct mountlist_itself *, char *);
    6969int partition_everything(struct mountlist_itself *);
  • trunk/mondo/mondo/mondorestore/mr-externs.h

    r127 r561  
    2727extern int edit_mountlist(char *mountlist_fname, struct mountlist_itself *,
    2828                          struct raidlist_itself *);
    29 extern int format_everything(struct mountlist_itself *, bool);
    30 extern int format_device(char *, char *);
     29extern int format_everything(struct mountlist_itself *, bool, struct raidlist_itself *);
     30extern int format_device(char *, char *, struct raidlist_itself *);
    3131extern void finish(int);
    3232extern void free_filelist(struct s_node *);
  • trunk/mondo/mondo/test/mktest

    r532 r561  
    55# test script for library functions
    66#
    7     gcc -O2 -I../common test-conf.c ../common/libmondo-conf.c ../common/libmondo-msg.c -o test-conf
     7
     8gcc -O2 -I../common test-conf.c ../common/libmondo-conf.c ../common/libmondo-msg.c -o test-conf
     9gcc -O2 -I../common test-string.c ../common/libmondo-string.c ../common/libmondo-msg.c -o test-string
     10
    811for f in "test-conf"; do
    912    chmod 755 $f
Note: See TracChangeset for help on using the changeset viewer.