Changeset 576 in MondoRescue for branches/2.0.8/mondo/mondo/common/libmondo-raid.c
- Timestamp:
- May 25, 2006, 2:00:37 PM (18 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/2.0.8/mondo/mondo/common/libmondo-raid.c
r273 r576 395 395 396 396 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) { 398 400 fprintf(fout, " raid-level linear\n"); 399 401 } else { … … 401 403 raidrec->raid_level); 402 404 } 403 fprintf(fout, " chunk-size %d\n", raidrec->chunk_size);404 405 fprintf(fout, " nr-raid-disks %d\n", 405 406 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 } 408 411 if (raidrec->parity_disks.entries > 0) { 409 412 fprintf(fout, " nr-parity-disks %d\n", 410 413 raidrec->parity_disks.entries); 411 414 } 412 413 415 fprintf(fout, " persistent-superblock %d\n", 414 416 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 } 415 439 save_additional_vars_to_file(&raidrec->additional_vars, fout); 416 440 fprintf(fout, "\n"); … … 713 737 714 738 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")) { 716 742 raidrec->raid_level = -1; 717 743 } else { … … 726 752 } else if (!strcmp(label, "chunk-size")) { 727 753 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 } 728 766 } else if (!strcmp(label, "device")) { 729 767 get_next_raidtab_line(fin, labelB, valueB); … … 972 1010 973 1011 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); 1012 int 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 1254 int 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); 990 1264 return (1); 991 1265 } 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 1118 1267 retval += save_raidlist_to_raidtab(raidlist, raidtab_fname); 1119 1268 return (retval);
Note:
See TracChangeset
for help on using the changeset viewer.