Ignore:
Timestamp:
Jun 19, 2013, 8:34:46 AM (11 years ago)
Author:
Bruno Cornec
Message:
  • First pass on svn merge -r 2935:3146 ../3.0
File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/3.1/mondo/src/common/libmondo-raid.c

    r2937 r3147  
    1515#include "libmondo-tools-EXT.h"
    1616#include "libmondo-string-EXT.h"
     17#include "libmondo-fork-EXT.h"
    1718#include "lib-common-externs.h"
    1819#include "libmondo-raid.h"
     
    429430    char *incoming = NULL;
    430431    char *p;
     432    char *q;
    431433
    432434    assert(fin != NULL);
     
    604606        return (1);
    605607    }
     608    malloc_string(label);
     609    malloc_string(value);
    606610    items = 0;
    607611    log_it("Loading raidtab...");
     
    615619            strcpy(raidlist->el[items].additional_vars.el[v].label, label);
    616620            strcpy(raidlist->el[items].additional_vars.el[v].value, value);
     621            log_msg(2,"Found raidtab entry Label: %s Value: %s",raidlist->el[items].additional_vars.el[v].label,raidlist->el[items].additional_vars.el[v].value);
    617622            v++;
    618623            mr_free(label);
     
    690695            raidrec->raid_level = atoi(value);
    691696        }
     697        log_msg(4,"Found raid level %d",raidrec->raid_level);
    692698    } else if (!strcmp(label, "nr-raid-disks")) {   /* ignore it */
    693699    } else if (!strcmp(label, "nr-spare-disks")) {  /* ignore it */
     
    710716            log_msg(1, "Unknown RAID parity algorithm '%s'\n.", value);
    711717        }
     718        log_msg(4,"Found raid parity %d",raidrec->parity);
    712719    } else if (!strcmp(label, "device")) {
    713720        get_next_raidtab_line(fin, &labelB, &valueB);
     
    735742        strcpy(raidrec->additional_vars.el[v].label, label);
    736743        strcpy(raidrec->additional_vars.el[v].value, value);
    737         raidrec->additional_vars.entries = ++v;
     744        log_msg(4,"Found additional raid pair #%d: %s / %s",v,raidrec->additional_vars.el[v].label,raidrec->additional_vars.el[v].value);
     745        v++;
     746        raidrec->additional_vars.entries = v;
    738747    }
    739748}
     
    950959
    951960
    952 int parse_mdstat(struct raidlist_itself *raidlist, char *device_prefix) {
    953 
    954   const char delims[] = " ";
    955 
    956   FILE   *fin;
    957   int    res = 0, row, i, index_min;
    958   int lastpos = 0;
    959   size_t len = 0;
    960   char   *token;
    961   char *string = NULL;
    962   char *pos;
    963   char type;
    964   char *strtmp;
     961int parse_mdstat(char *mdstat_fname, struct raidlist_itself *raidlist, char *device_prefix) {
     962
     963const char delims[] = " ";
     964
     965FILE *fin = NULL;
     966int res = 0, row, i, index_min;
     967int v = 0;
     968int lastpos = 0;
     969size_t len = 0;
     970char *token = NULL;
     971char *string = NULL;
     972char *cmd = NULL;
     973char *pos = NULL;
     974char type;
     975char *strtmp = NULL;
     976char *strtmp2 = NULL;
    965977
    966978  // open file
     
    10441056      raidlist->el[raidlist->entries].raid_level = 10;
    10451057    } else {
    1046       log_msg(1, "Unknown RAID level '%s'.\n", token);
    1047       paranoid_free(string);
    1048       paranoid_free(token);
    1049       return 1;
    1050     }
    1051     mr_free(token);
     1058        switch (row) {
     1059        case 1:  // device information
     1060            // check whether last line of record and if so skip
     1061            log_msg(8, "This is the device line\n");
     1062            pos = strcasestr(string, "unused devices: ");
     1063            if (pos != NULL) {
     1064                break;
     1065            }
     1066            // tokenise string
     1067            token = mr_strtok(string, delims, &lastpos);
     1068            if (token == NULL) {
     1069                // should not happen !
     1070                break;
     1071            }
     1072            // get RAID device name
     1073            mr_asprintf(&strtmp,"%s%s", device_prefix, token);
     1074            strncpy(raidlist->el[raidlist->entries].raid_device, strtmp, 63);
     1075            raidlist->el[raidlist->entries].raid_device[63] = '\0';
     1076            mr_free(strtmp);
     1077            mr_free(token);
     1078            // store the UUID value in the additional_vars structure
     1079            v = raidlist->el[raidlist->entries].additional_vars.entries;
     1080            strcpy(raidlist->el[raidlist->entries].additional_vars.el[v].label, "UUID");
     1081            mr_asprintf(&cmd,"mdadm --detail %s | grep UUID | cut -d: -f2- | sed 's/^ *//'", raidlist->el[raidlist->entries].raid_device);
     1082            mr_asprintf(&strtmp, "%s", call_program_and_get_last_line_of_output(cmd));
     1083            strcpy(raidlist->el[raidlist->entries].additional_vars.el[v].value, strtmp);
     1084            mr_free(strtmp);
     1085            v++;
     1086            // store the Version value in the additional_vars structure
     1087            strcpy(raidlist->el[raidlist->entries].additional_vars.el[v].label, "Version");
     1088            mr_asprintf(&cmd,"mdadm --detail %s | grep Version | cut -d: -f2- | sed 's/^ *//'", raidlist->el[raidlist->entries].raid_device);
     1089            mr_asprintf(&strtmp, "%s", call_program_and_get_last_line_of_output(cmd));
     1090            strcpy(raidlist->el[raidlist->entries].additional_vars.el[v].value, strtmp);
     1091            mr_free(strtmp);
     1092            v++;
     1093            raidlist->el[raidlist->entries].additional_vars.entries = v;
     1094            // skip ':' and status
     1095            token = mr_strtok (string, delims, &lastpos);
     1096            if (token == NULL) {
     1097                // should not happen !
     1098                break;
     1099            }
     1100            mr_free(token);
     1101            token = mr_strtok (string, delims, &lastpos);
     1102            if (token == NULL) {
     1103                // should not happen !
     1104                break;
     1105            }
     1106            if (!strcmp(token, "inactive")) {
     1107                log_msg(1, "RAID device '%s' inactive.\n",
     1108                raidlist->el[raidlist->entries].raid_device);
     1109                mr_free(string);
     1110                mr_free(token);
     1111                return 1;
     1112            }
     1113            mr_free(token);
    10521114
    10531115    // get RAID devices (type, index, device)
     
    10971159    }
    10981160
     1161    // get RAID devices (type, index, device)
     1162    // Note: parity disk for RAID4 is last normal disk, there is no '(P)'
     1163    raidlist->el[raidlist->entries].data_disks.entries = 0;
     1164    raidlist->el[raidlist->entries].spare_disks.entries = 0;
     1165    raidlist->el[raidlist->entries].failed_disks.entries = 0;
     1166    while((token = mr_strtok (string, delims, &lastpos))) {
     1167        if ((pos = strstr(token, "("))) {
     1168                type = *(pos+1);
     1169        } else {
     1170                type = ' ';
     1171        }
     1172        pos = strstr(token, "[");
     1173        *pos = '\0';
     1174        switch(type) {
     1175        case ' ': // normal data disks
     1176                raidlist->el[raidlist->entries].data_disks.el[raidlist->el[raidlist->entries].data_disks.entries].index = atoi(pos + 1);
     1177                mr_asprintf(&strtmp,"%s%s", device_prefix, token);
     1178                strcpy(raidlist->el[raidlist->entries].data_disks.el[raidlist->el[raidlist->entries].data_disks.entries].device, strtmp);
     1179                mr_free(strtmp);
     1180                raidlist->el[raidlist->entries].data_disks.entries++;
     1181                break;
     1182        case 'S': // spare disks
     1183                raidlist->el[raidlist->entries].spare_disks.el[raidlist->el[raidlist->entries].spare_disks.entries].index = atoi(pos + 1);
     1184                mr_asprintf(&strtmp,"%s%s", device_prefix, token);
     1185                strcpy(raidlist->el[raidlist->entries].spare_disks.el[raidlist->el[raidlist->entries].spare_disks.entries].device, strtmp);
     1186                mr_free(strtmp);
     1187                raidlist->el[raidlist->entries].spare_disks.entries++;
     1188                break;
     1189        case 'F': // failed disks
     1190                raidlist->el[raidlist->entries].failed_disks.el[raidlist->el[raidlist->entries].failed_disks.entries].index = atoi(pos + 1);
     1191                mr_asprintf(&strtmp,"%s%s", device_prefix, token);
     1192                strcpy(raidlist->el[raidlist->entries].failed_disks.el[raidlist->el[raidlist->entries].failed_disks.entries].device, strtmp);
     1193                mr_free(strtmp);
     1194                raidlist->el[raidlist->entries].failed_disks.entries++;
     1195                log_it("At least one failed disk found in RAID array.\n");
     1196                break;
     1197        default: // error
     1198                log_msg(1, "Unknown device type '%c'\n", type);
     1199                mr_free(string);
     1200                mr_free(token);
     1201                return 1;
     1202                break;
     1203        }
     1204        mr_free(token);
     1205    }
     1206
    10991207    // adjust index for each device so that it starts with 0 for every type
    11001208    index_min = 99;
    11011209    for (i=0; i<raidlist->el[raidlist->entries].data_disks.entries;i++) {
    1102       if (raidlist->el[raidlist->entries].data_disks.el[i].index < index_min) {
    1103         index_min = raidlist->el[raidlist->entries].data_disks.el[i].index;
    1104       }
     1210        if (raidlist->el[raidlist->entries].data_disks.el[i].index < index_min) {
     1211            index_min = raidlist->el[raidlist->entries].data_disks.el[i].index;
     1212        }
    11051213    }
    11061214    if (index_min > 0) {
    1107       for (i=0; i<raidlist->el[raidlist->entries].data_disks.entries;i++) {
    1108         raidlist->el[raidlist->entries].data_disks.el[i].index = raidlist->el[raidlist->entries].data_disks.el[i].index - index_min;   
    1109       }
     1215        for (i=0; i<raidlist->el[raidlist->entries].data_disks.entries;i++) {
     1216                raidlist->el[raidlist->entries].data_disks.el[i].index = raidlist->el[raidlist->entries].data_disks.el[i].index - index_min;   
     1217        }
    11101218    }
    11111219    index_min = 99;
    11121220    for (i=0; i<raidlist->el[raidlist->entries].spare_disks.entries;i++) {
    1113       if (raidlist->el[raidlist->entries].spare_disks.el[i].index < index_min) {
    1114         index_min = raidlist->el[raidlist->entries].spare_disks.el[i].index;
    1115       }
     1221        if (raidlist->el[raidlist->entries].spare_disks.el[i].index < index_min) {
     1222                index_min = raidlist->el[raidlist->entries].spare_disks.el[i].index;
     1223        }
    11161224    }
    11171225    if (index_min > 0) {
    1118       for (i=0; i<raidlist->el[raidlist->entries].spare_disks.entries;i++) {
    1119         raidlist->el[raidlist->entries].spare_disks.el[i].index = raidlist->el[raidlist->entries].spare_disks.el[i].index - index_min; 
    1120       }
     1226        for (i=0; i<raidlist->el[raidlist->entries].spare_disks.entries;i++) {
     1227                raidlist->el[raidlist->entries].spare_disks.el[i].index = raidlist->el[raidlist->entries].spare_disks.el[i].index - index_min; 
     1228        }
    11211229    }
    11221230    index_min = 99;
    11231231    for (i=0; i<raidlist->el[raidlist->entries].failed_disks.entries;i++) {
    1124       if (raidlist->el[raidlist->entries].failed_disks.el[i].index < index_min) {
    1125         index_min = raidlist->el[raidlist->entries].failed_disks.el[i].index;
    1126       }
     1232        if (raidlist->el[raidlist->entries].failed_disks.el[i].index < index_min) {
     1233                index_min = raidlist->el[raidlist->entries].failed_disks.el[i].index;
     1234        }
    11271235    }
    11281236    if (index_min > 0) {
    1129       for (i=0; i<raidlist->el[raidlist->entries].failed_disks.entries;i++) {
    1130         raidlist->el[raidlist->entries].failed_disks.el[i].index = raidlist->el[raidlist->entries].failed_disks.el[i].index - index_min;   
    1131       }
     1237        for (i=0; i<raidlist->el[raidlist->entries].failed_disks.entries;i++) {
     1238                raidlist->el[raidlist->entries].failed_disks.el[i].index = raidlist->el[raidlist->entries].failed_disks.el[i].index - index_min;   
     1239        }
    11321240    }
    11331241    break;
    1134       case 2:  // config information
     1242case 2:  // config information
    11351243    // check for persistent super block
    11361244    if (strcasestr(string, "super non-persistent")) {
    1137       raidlist->el[raidlist->entries].persistent_superblock = 0;
    1138     } else {
    1139       raidlist->el[raidlist->entries].persistent_superblock = 1;
    1140     }
    1141     // extract chunk size
    1142     if (!(pos = strcasestr(string, "k chunk"))) {
    1143       raidlist->el[raidlist->entries].chunk_size = -1;
    1144     } else {
    1145       while (*pos != ' ') {
    1146         pos -= 1;
    1147         if (pos < string) {
    1148           log_it("String underflow!\n");
    1149           paranoid_free(string);
    1150           return 1;
    1151         }
    1152       }
    1153       raidlist->el[raidlist->entries].chunk_size = atoi(pos + 1);
    1154     }
    1155     // extract parity if present
    1156     if ((pos = strcasestr(string, "algorithm"))) {
    1157       raidlist->el[raidlist->entries].parity = atoi(pos + 9);
    1158     } else {
    1159       raidlist->el[raidlist->entries].parity = -1;
    1160     }
    1161     break;
    1162       case 3:  // optional build status information
    1163     if (!(pos = strchr(string, '\%'))) {
    1164       if (strcasestr(string, "delayed")) {
    1165         raidlist->el[raidlist->entries].progress = -1;  // delayed (therefore, stuck at 0%)
    1166       } else {
    1167         raidlist->el[raidlist->entries].progress = 999; // not found
    1168       }
    1169     } else {
    1170       while (*pos != ' ') {
    1171         pos -= 1;
    1172         if (pos < string) {
    1173           printf("ERROR: String underflow!\n");
    1174           paranoid_free(string);
    1175           return 1;
    1176         }
    1177       }
    1178       raidlist->el[raidlist->entries].progress = atoi(pos);
    1179     }
    1180     break;
    1181       default: // error or IN PROGRESS
    1182     if (raidlist->el[raidlist->entries].progress != -1 &&
    1183         raidlist->el[raidlist->entries].progress != 999) {
    1184         log_msg(1, "Row %d should not occur in record!\n", row);
    1185     }
    1186     break;
    1187       }
    1188       row++;
    1189     }
    1190   }
    1191   // close file
    1192   fclose(fin);
    1193   // free string
    1194   paranoid_free(string);
    1195   // return success
    1196   return 0;
    1197 
    1198 }
    1199 
    1200 
    1201 
    1202 
    1203 int create_raidtab_from_mdstat(char *raidtab_fname)
     1245                raidlist->el[raidlist->entries].persistent_superblock = 0;
     1246            } else {
     1247                raidlist->el[raidlist->entries].persistent_superblock = 1;
     1248            }
     1249            // extract chunk size
     1250            if (!(pos = strcasestr(string, "k chunk"))) {
     1251                raidlist->el[raidlist->entries].chunk_size = -1;
     1252            } else {
     1253                while (*pos != ' ') {
     1254                    pos -= 1;
     1255                    if (pos < string) {
     1256                            log_it("String underflow!\n");
     1257                            mr_free(string);
     1258                            return 1;
     1259                    }
     1260                }
     1261                raidlist->el[raidlist->entries].chunk_size = atoi(pos + 1);
     1262            }
     1263            // extract parity if present
     1264            if ((pos = strcasestr(string, "algorithm"))) {
     1265                raidlist->el[raidlist->entries].parity = atoi(pos + 9);
     1266            } else {
     1267                raidlist->el[raidlist->entries].parity = -1;
     1268            }
     1269            break;
     1270        case 3:  // optional build status information
     1271            if (!(pos = strchr(string, '\%'))) {
     1272                if (strcasestr(string, "delayed")) {
     1273                    raidlist->el[raidlist->entries].progress = -1;  // delayed (therefore, stuck at 0%)
     1274                } else {
     1275                    raidlist->el[raidlist->entries].progress = 999; // not found
     1276                }
     1277            } else {
     1278                while (*pos != ' ') {
     1279                    pos -= 1;
     1280                    if (pos < string) {
     1281                        printf("ERROR: String underflow!\n");
     1282                            mr_free(string);
     1283                            return 1;
     1284                    }
     1285                }
     1286                raidlist->el[raidlist->entries].progress = atoi(pos);
     1287            }
     1288            break;
     1289        default: // error or IN PROGRESS
     1290            if (raidlist->el[raidlist->entries].progress != -1 &&
     1291                raidlist->el[raidlist->entries].progress != 999) {
     1292                log_msg(1, "Row %d should not occur in record!\n", row);
     1293            }
     1294            break;
     1295        }
     1296        row++;
     1297    }
     1298    // free string
     1299    mr_free(string);
     1300}
     1301// close file
     1302fclose(fin);
     1303// return success
     1304return 0;
     1305
     1306}
     1307
     1308
     1309
     1310
     1311int create_raidtab_from_mdstat(char *mdstat_fname,char *raidtab_fname)
    12041312{
    12051313    struct raidlist_itself *raidlist;
     
    12091317
    12101318    // FIXME: Prefix '/dev/' should really be dynamic!
    1211     if (parse_mdstat(raidlist, "/dev/")) {
    1212         log_to_screen("Sorry, cannot read %s", MDSTAT_FILE);
     1319    if (parse_mdstat(mdstat_fname,raidlist, "/dev/")) {
     1320        log_to_screen("Sorry, cannot read %s", mdstat_fname);
    12131321        return (1);
    12141322    }
Note: See TracChangeset for help on using the changeset viewer.