Ignore:
Timestamp:
May 25, 2006, 2:00:37 PM (14 years ago)
Author:
bcornec
Message:

2.08 synced with stable as of r575
VERSION files updated

File:
1 edited

Legend:

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

    r273 r576  
    395395
    396396    fprintf(fout, "raiddev %s\n", raidrec->raid_device);
    397     if (raidrec->raid_level == -1) {
     397    if (raidrec->raid_level == -2) {
     398        fprintf(fout, "    raid-level            multipath\n");
     399    } else if (raidrec->raid_level == -1) {
    398400        fprintf(fout, "    raid-level            linear\n");
    399401    } else {
     
    401403                raidrec->raid_level);
    402404    }
    403     fprintf(fout, "    chunk-size            %d\n", raidrec->chunk_size);
    404405    fprintf(fout, "    nr-raid-disks         %d\n",
    405406            raidrec->data_disks.entries);
    406     fprintf(fout, "    nr-spare-disks        %d\n",
    407             raidrec->spare_disks.entries);
     407    if (raidrec->spare_disks.entries > 0) {
     408        fprintf(fout, "    nr-spare-disks        %d\n",
     409                raidrec->spare_disks.entries);
     410    }
    408411    if (raidrec->parity_disks.entries > 0) {
    409412        fprintf(fout, "    nr-parity-disks       %d\n",
    410413                raidrec->parity_disks.entries);
    411414    }
    412 
    413415    fprintf(fout, "    persistent-superblock %d\n",
    414416            raidrec->persistent_superblock);
     417    if (raidrec->chunk_size > -1) {
     418      fprintf(fout, "    chunk-size            %d\n", raidrec->chunk_size);
     419    }
     420    if (raidrec->parity > -1) {
     421      switch(raidrec->parity) {
     422      case 0:
     423        fprintf(fout, "    parity-algorithm      left-asymmetric\n");
     424        break;
     425      case 1:
     426        fprintf(fout, "    parity-algorithm      right-asymmetric\n");
     427        break;
     428      case 2:
     429        fprintf(fout, "    parity-algorithm      left-symmetric\n");
     430        break;
     431      case 3:
     432        fprintf(fout, "    parity-algorithm      right-symmetric\n");
     433        break;
     434      default:
     435        fatal_error("Unknown RAID parity algorithm.");
     436        break;
     437      }
     438    }
    415439    save_additional_vars_to_file(&raidrec->additional_vars, fout);
    416440    fprintf(fout, "\n");
     
    713737
    714738    if (!strcmp(label, "raid-level")) {
    715         if (!strcmp(value, "linear")) {
     739        if (!strcmp(value, "multipath")) {
     740            raidrec->raid_level = -2;
     741        } else if (!strcmp(value, "linear")) {
    716742            raidrec->raid_level = -1;
    717743        } else {
     
    726752    } else if (!strcmp(label, "chunk-size")) {
    727753        raidrec->chunk_size = atoi(value);
     754    } else if (!strcmp(label, "parity-algorithm")) {
     755        if (!strcmp(value, "left-asymmetric")) {
     756            raidrec->parity = 0;
     757        } else if (!strcmp(value, "right-asymmetric")) {
     758            raidrec->parity = 1;
     759        } else if (!strcmp(value, "left-symmetric")) {
     760            raidrec->parity = 2;
     761        } else if (!strcmp(value, "right-symmetric")) {
     762            raidrec->parity = 3;
     763        } else {
     764            log_msg(1, "Unknown RAID parity algorithm '%s'\n.", value);
     765        }
    728766    } else if (!strcmp(label, "device")) {
    729767        get_next_raidtab_line(fin, labelB, valueB);
     
    9721010
    9731011
    974 int read_mdstat(struct s_mdstat *mdstat, char *mdstat_file)
    975 {
    976     FILE *fin;
    977     char *tmp;
    978     char *stub;
    979     char *incoming;
    980     char *raid_devname;
    981     char *p, *q, *r;
    982     int diskno;
    983 
    984     malloc_string(tmp);
    985     malloc_string(stub);
    986     malloc_string(incoming);
    987     malloc_string(raid_devname);
    988     if (!(fin = fopen(mdstat_file, "r"))) {
    989         log_msg(1, "%s not found", mdstat_file);
     1012int parse_mdstat(struct raidlist_itself *raidlist, char *device_prefix) {
     1013
     1014  const char delims[] = " ";
     1015
     1016  FILE   *fin;
     1017  int    res = 0, row, i, index_min;
     1018  int lastpos = 0;
     1019  size_t len = 0;
     1020  char   *token;
     1021  char *string = NULL;
     1022  char *pos;
     1023  char type;
     1024  char *strtmp;
     1025
     1026  // open file
     1027  if (!(fin = fopen(MDSTAT_FILE, "r"))) {
     1028    log_msg(1, "Could not open %s.\n", MDSTAT_FILE);
     1029    return 1;
     1030  }
     1031  // initialise record, build progress and row counters
     1032  raidlist->entries = 0;
     1033  raidlist->el[raidlist->entries].progress = 999;
     1034  row = 1;
     1035  // skip first output row - contains registered RAID levels
     1036  res = getline(&string, &len, fin);
     1037  // parse the rest
     1038  while ( !feof_unlocked(fin) ) {
     1039    res = getline(&string, &len, fin);
     1040    if (res <= 0) break;
     1041    // trim leading spaces
     1042    pos = string;
     1043    while (*pos == ' ') *pos++;
     1044    asprintf(&string, pos);
     1045    //
     1046    // if we have newline after only spaces, this is a blank line, update
     1047    // counters, otherwise do normal parsing
     1048    if (*string == '\n') {
     1049      row = 1;
     1050      raidlist->entries++;
     1051      raidlist->el[raidlist->entries].progress = 999;
     1052    } else {
     1053      switch (row) {
     1054      case 1:  // device information
     1055    // check whether last line of record and if so skip
     1056    pos = strcasestr(string, "unused devices: ");
     1057    if (pos == string) {
     1058      //raidlist->entries--;
     1059      break;
     1060    }
     1061    // tokenise string
     1062    token = mr_strtok (string, delims, &lastpos);
     1063    // get RAID device name
     1064    asprintf(&strtmp,"%s%s", device_prefix, token);
     1065    strcpy(raidlist->el[raidlist->entries].raid_device, strtmp);
     1066    paranoid_free(strtmp);
     1067    paranoid_free(token);
     1068    // skip ':' and status
     1069    token = mr_strtok (string, delims, &lastpos);
     1070    paranoid_free(token);
     1071    token = mr_strtok (string, delims, &lastpos);
     1072    if (!strcmp(token, "inactive")) {
     1073      log_msg(1, "RAID device '%s' inactive.\n",
     1074         raidlist->el[raidlist->entries].raid_device);
     1075      paranoid_free(string);
     1076      paranoid_free(token);
     1077      return 1;
     1078    }
     1079    paranoid_free(token);
     1080
     1081    // get RAID level
     1082    token = mr_strtok (string, delims, &lastpos);
     1083    if (!strcmp(token, "multipath")) {
     1084      raidlist->el[raidlist->entries].raid_level = -2;
     1085    } else if (!strcmp(token, "linear")) {
     1086      raidlist->el[raidlist->entries].raid_level = -1;
     1087    } else if (!strcmp(token, "raid0")) {
     1088      raidlist->el[raidlist->entries].raid_level = 0;
     1089    } else if (!strcmp(token, "raid1")) {
     1090      raidlist->el[raidlist->entries].raid_level = 1;
     1091    } else if (!strcmp(token, "raid4")) {
     1092      raidlist->el[raidlist->entries].raid_level = 4;
     1093    } else if (!strcmp(token, "raid5")) {
     1094      raidlist->el[raidlist->entries].raid_level = 5;
     1095    } else if (!strcmp(token, "raid6")) {
     1096      raidlist->el[raidlist->entries].raid_level = 6;
     1097    } else if (!strcmp(token, "raid10")) {
     1098      raidlist->el[raidlist->entries].raid_level = 10;
     1099    } else {
     1100      log_msg(1, "Unknown RAID level '%s'.\n", token);
     1101      paranoid_free(string);
     1102      paranoid_free(token);
     1103      return 1;
     1104    }
     1105    paranoid_free(token);
     1106
     1107    // get RAID devices (type, index, device)
     1108    // Note: parity disk for RAID4 is last normal disk, there is no '(P)'
     1109    raidlist->el[raidlist->entries].data_disks.entries = 0;
     1110    raidlist->el[raidlist->entries].spare_disks.entries = 0;
     1111    raidlist->el[raidlist->entries].failed_disks.entries = 0;
     1112    while((token = mr_strtok (string, delims, &lastpos))) {
     1113      if ((pos = strstr(token, "("))) {
     1114        type = *(pos+1);
     1115      } else {
     1116        type = ' ';
     1117      }
     1118      pos = strstr(token, "[");
     1119      *pos = '\0';
     1120      switch(type) {
     1121      case ' ': // normal data disks
     1122        raidlist->el[raidlist->entries].data_disks.el[raidlist->el[raidlist->entries].data_disks.entries].index = atoi(pos + 1);
     1123        asprintf(&strtmp,"%s%s", device_prefix, token);
     1124        strcpy(raidlist->el[raidlist->entries].data_disks.el[raidlist->el[raidlist->entries].data_disks.entries].device, strtmp);
     1125        paranoid_free(strtmp);
     1126        raidlist->el[raidlist->entries].data_disks.entries++;
     1127        break;
     1128      case 'S': // spare disks
     1129        raidlist->el[raidlist->entries].spare_disks.el[raidlist->el[raidlist->entries].spare_disks.entries].index = atoi(pos + 1);
     1130        asprintf(&strtmp,"%s%s", device_prefix, token);
     1131        strcpy(raidlist->el[raidlist->entries].spare_disks.el[raidlist->el[raidlist->entries].spare_disks.entries].device, strtmp);
     1132        paranoid_free(strtmp);
     1133        raidlist->el[raidlist->entries].spare_disks.entries++;
     1134        break;
     1135      case 'F': // failed disks
     1136        raidlist->el[raidlist->entries].failed_disks.el[raidlist->el[raidlist->entries].failed_disks.entries].index = atoi(pos + 1);
     1137        asprintf(&strtmp,"%s%s", device_prefix, token);
     1138        strcpy(raidlist->el[raidlist->entries].failed_disks.el[raidlist->el[raidlist->entries].failed_disks.entries].device, strtmp);
     1139        paranoid_free(strtmp);
     1140        raidlist->el[raidlist->entries].failed_disks.entries++;
     1141        log_it("At least one failed disk found in RAID array.\n");
     1142        break;
     1143      default: // error
     1144        log_msg(1, "Unknown device type '%c'\n", type);
     1145        paranoid_free(string);
     1146        paranoid_free(token);
     1147        return 1;
     1148        break;
     1149      }
     1150      paranoid_free(token);
     1151    }
     1152
     1153    // adjust index for each device so that it starts with 0 for every type
     1154    index_min = 99;
     1155    for (i=0; i<raidlist->el[raidlist->entries].data_disks.entries;i++) {
     1156      if (raidlist->el[raidlist->entries].data_disks.el[i].index < index_min) {
     1157        index_min = raidlist->el[raidlist->entries].data_disks.el[i].index;
     1158      }
     1159    }
     1160    if (index_min > 0) {
     1161      for (i=0; i<raidlist->el[raidlist->entries].data_disks.entries;i++) {
     1162        raidlist->el[raidlist->entries].data_disks.el[i].index = raidlist->el[raidlist->entries].data_disks.el[i].index - index_min;   
     1163      }
     1164    }
     1165    index_min = 99;
     1166    for (i=0; i<raidlist->el[raidlist->entries].spare_disks.entries;i++) {
     1167      if (raidlist->el[raidlist->entries].spare_disks.el[i].index < index_min) {
     1168        index_min = raidlist->el[raidlist->entries].spare_disks.el[i].index;
     1169      }
     1170    }
     1171    if (index_min > 0) {
     1172      for (i=0; i<raidlist->el[raidlist->entries].spare_disks.entries;i++) {
     1173        raidlist->el[raidlist->entries].spare_disks.el[i].index = raidlist->el[raidlist->entries].spare_disks.el[i].index - index_min; 
     1174      }
     1175    }
     1176    index_min = 99;
     1177    for (i=0; i<raidlist->el[raidlist->entries].failed_disks.entries;i++) {
     1178      if (raidlist->el[raidlist->entries].failed_disks.el[i].index < index_min) {
     1179        index_min = raidlist->el[raidlist->entries].failed_disks.el[i].index;
     1180      }
     1181    }
     1182    if (index_min > 0) {
     1183      for (i=0; i<raidlist->el[raidlist->entries].failed_disks.entries;i++) {
     1184        raidlist->el[raidlist->entries].failed_disks.el[i].index = raidlist->el[raidlist->entries].failed_disks.el[i].index - index_min;   
     1185      }
     1186    }
     1187    break;
     1188      case 2:  // config information
     1189    // check for persistent super block
     1190    if (strcasestr(string, "super non-persistent")) {
     1191      raidlist->el[raidlist->entries].persistent_superblock = 0;
     1192    } else {
     1193      raidlist->el[raidlist->entries].persistent_superblock = 1;
     1194    }
     1195    // extract chunk size
     1196    if (!(pos = strcasestr(string, "k chunk"))) {
     1197      raidlist->el[raidlist->entries].chunk_size = -1;
     1198    } else {
     1199      while (*pos != ' ') {
     1200        *pos--;
     1201        if (pos < string) {
     1202          log_it("String underflow!\n");
     1203          paranoid_free(string);
     1204          return 1;
     1205        }
     1206      }
     1207      raidlist->el[raidlist->entries].chunk_size = atoi(pos + 1);
     1208    }
     1209    // extract parity if present
     1210    if ((pos = strcasestr(string, "algorithm"))) {
     1211      raidlist->el[raidlist->entries].parity = atoi(pos + 9);
     1212    } else {
     1213      raidlist->el[raidlist->entries].parity = -1;
     1214    }
     1215    break;
     1216      case 3:  // optional build status information
     1217    if (!(pos = strchr(string, '\%'))) {
     1218      if (strcasestr(string, "delayed")) {
     1219        raidlist->el[raidlist->entries].progress = -1;  // delayed (therefore, stuck at 0%)
     1220      } else {
     1221        raidlist->el[raidlist->entries].progress = 999; // not found
     1222      }
     1223    } else {
     1224      while (*pos != ' ') {
     1225        *pos--;
     1226        if (pos < string) {
     1227          printf("ERROR: String underflow!\n");
     1228          paranoid_free(string);
     1229          return 1;
     1230        }
     1231      }
     1232      raidlist->el[raidlist->entries].progress = atoi(pos);
     1233    }
     1234    break;
     1235      default: // error
     1236    log_msg(1, "Row %d should not occur in record!\n", row);
     1237    break;
     1238      }
     1239      row++;
     1240    }
     1241  }
     1242  // close file
     1243  fclose(fin);
     1244  // free string
     1245  paranoid_free(string);
     1246  // return success
     1247  return 0;
     1248
     1249}
     1250
     1251
     1252
     1253
     1254int create_raidtab_from_mdstat(char *raidtab_fname)
     1255{
     1256    struct raidlist_itself *raidlist;
     1257    int retval = 0;
     1258
     1259    raidlist = malloc(sizeof(struct raidlist_itself));
     1260
     1261    // FIXME: Prefix '/dev/' should really be dynamic!
     1262    if (parse_mdstat(raidlist, "/dev/")) {
     1263        log_to_screen("Sorry, cannot read %s", MDSTAT_FILE);
    9901264        return (1);
    9911265    }
    992     mdstat->entries = 0;
    993     for (fgets(incoming, MAX_STR_LEN - 1, fin); !feof(fin);
    994          fgets(incoming, MAX_STR_LEN - 1, fin)) {
    995         p = incoming;
    996         if (*p != 'm' && *(p + 1) == 'm') {
    997             p++;
    998         }
    999         if (strncmp(p, "md", 2)) {
    1000             continue;
    1001         }
    1002 // read first line --- mdN : active raidX ............
    1003         mdstat->el[mdstat->entries].md = atoi(p + 2);
    1004         log_msg(8, "Storing /dev/md%d's info", atoi(p + 2));
    1005         while (*p != ':' && *p) {
    1006             p++;
    1007         }
    1008         while ((*p != 'r' || *(p + 1) != 'a') && *p) {
    1009             p++;
    1010         }
    1011         if (!strncmp(p, "raid", 4)) {
    1012             mdstat->el[mdstat->entries].raidlevel = *(p + 4) - '0';
    1013         }
    1014         p += 4;
    1015         while (*p != ' ' && *p) {
    1016             p++;
    1017         }
    1018         while (*p == ' ' && *p) {
    1019             p++;
    1020         }
    1021         for (diskno = 0; *p; diskno++) {
    1022             strcpy(stub, p);
    1023 //      log_msg(1, "diskno=%d; tmp=%s", diskno, tmp);
    1024             q = strchr(stub, '[');
    1025             if (q) {
    1026                 *q = '\0';
    1027                 q++;
    1028                 r = strchr(q, ']');
    1029                 if (r) {
    1030                     *r = '\0';
    1031                 }
    1032                 mdstat->el[mdstat->entries].disks.el[diskno].index =
    1033                     atoi(q);
    1034             } else {
    1035                 mdstat->el[mdstat->entries].disks.el[diskno].index = -1;
    1036                 q = strchr(stub, ' ');
    1037                 if (q) {
    1038                     *q = '\0';
    1039                 }
    1040             }
    1041             sprintf(tmp, "/dev/%s", stub);
    1042             log_msg(8, "/dev/md%d : disk#%d : %s (%d)",
    1043                     mdstat->el[mdstat->entries].md, diskno, tmp,
    1044                     mdstat->el[mdstat->entries].disks.el[diskno].index);
    1045             strcpy(mdstat->el[mdstat->entries].disks.el[diskno].device,
    1046                    tmp);
    1047             while (*p != ' ' && *p) {
    1048                 p++;
    1049             }
    1050             while (*p == ' ' && *p) {
    1051                 p++;
    1052             }
    1053         }
    1054         mdstat->el[mdstat->entries].disks.entries = diskno;
    1055 // next line --- skip it
    1056         if (!feof(fin)) {
    1057             fgets(incoming, MAX_STR_LEN - 1, fin);
    1058         } else {
    1059             continue;
    1060         }
    1061 // next line --- the 'progress' line
    1062         if (!feof(fin)) {
    1063             fgets(incoming, MAX_STR_LEN - 1, fin);
    1064         } else {
    1065             continue;
    1066         }
    1067 //  log_msg(1, "Percentage line = '%s'", incoming);
    1068         if (!(p = strchr(incoming, '\%'))) {
    1069             mdstat->el[mdstat->entries].progress = 999; // not found
    1070         } else if (strstr(incoming, "DELAYED")) {
    1071             mdstat->el[mdstat->entries].progress = -1;  // delayed (therefore, stuck at 0%)
    1072         } else {
    1073             for (*p = '\0'; *p != ' '; p--);
    1074             mdstat->el[mdstat->entries].progress = atoi(p);
    1075         }
    1076         log_msg(8, "progress =%d", mdstat->el[mdstat->entries].progress);
    1077         mdstat->entries++;
    1078     }
    1079     fclose(fin);
    1080     paranoid_free(tmp);
    1081     paranoid_free(stub);
    1082     paranoid_free(incoming);
    1083     paranoid_free(raid_devname);
    1084     return (0);
    1085 }
    1086 
    1087 
    1088 
    1089 int create_raidtab_from_mdstat(char *raidtab_fname, char *mdstat_fname)
    1090 {
    1091     struct raidlist_itself *raidlist;
    1092     struct s_mdstat *mdstat;
    1093     int retval = 0;
    1094     int i;
    1095 
    1096     raidlist = malloc(sizeof(struct raidlist_itself));
    1097     mdstat = malloc(sizeof(struct s_mdstat));
    1098 
    1099     if (read_mdstat(mdstat, mdstat_fname)) {
    1100         log_to_screen("Sorry, cannot read %s", mdstat_fname);
    1101         return (1);
    1102     }
    1103 
    1104     for (i = 0; i < mdstat->entries; i++) {
    1105         sprintf(raidlist->el[i].raid_device, "/dev/md%d",
    1106                 mdstat->el[i].md);
    1107         raidlist->el[i].raid_level = mdstat->el[i].raidlevel;
    1108         raidlist->el[i].persistent_superblock = 1;
    1109         raidlist->el[i].chunk_size = 4;
    1110         memcpy((void *) &raidlist->el[i].data_disks,
    1111                (void *) &mdstat->el[i].disks,
    1112                sizeof(struct list_of_disks));
    1113         // FIXME --- the above line does not allow for spare disks
    1114         log_to_screen
    1115             ("FIXME - create_raidtab_from_mdstat does not allow for spare disks");
    1116     }
    1117     raidlist->entries = i;
     1266
    11181267    retval += save_raidlist_to_raidtab(raidlist, raidtab_fname);
    11191268    return (retval);
Note: See TracChangeset for help on using the changeset viewer.