Changeset 3147 in MondoRescue for branches/3.1/mondo/src/common/libmondo-raid.c
- Timestamp:
- Jun 19, 2013, 8:34:46 AM (11 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/3.1/mondo/src/common/libmondo-raid.c
r2937 r3147 15 15 #include "libmondo-tools-EXT.h" 16 16 #include "libmondo-string-EXT.h" 17 #include "libmondo-fork-EXT.h" 17 18 #include "lib-common-externs.h" 18 19 #include "libmondo-raid.h" … … 429 430 char *incoming = NULL; 430 431 char *p; 432 char *q; 431 433 432 434 assert(fin != NULL); … … 604 606 return (1); 605 607 } 608 malloc_string(label); 609 malloc_string(value); 606 610 items = 0; 607 611 log_it("Loading raidtab..."); … … 615 619 strcpy(raidlist->el[items].additional_vars.el[v].label, label); 616 620 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); 617 622 v++; 618 623 mr_free(label); … … 690 695 raidrec->raid_level = atoi(value); 691 696 } 697 log_msg(4,"Found raid level %d",raidrec->raid_level); 692 698 } else if (!strcmp(label, "nr-raid-disks")) { /* ignore it */ 693 699 } else if (!strcmp(label, "nr-spare-disks")) { /* ignore it */ … … 710 716 log_msg(1, "Unknown RAID parity algorithm '%s'\n.", value); 711 717 } 718 log_msg(4,"Found raid parity %d",raidrec->parity); 712 719 } else if (!strcmp(label, "device")) { 713 720 get_next_raidtab_line(fin, &labelB, &valueB); … … 735 742 strcpy(raidrec->additional_vars.el[v].label, label); 736 743 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; 738 747 } 739 748 } … … 950 959 951 960 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; 961 int parse_mdstat(char *mdstat_fname, struct raidlist_itself *raidlist, char *device_prefix) { 962 963 const char delims[] = " "; 964 965 FILE *fin = NULL; 966 int res = 0, row, i, index_min; 967 int v = 0; 968 int lastpos = 0; 969 size_t len = 0; 970 char *token = NULL; 971 char *string = NULL; 972 char *cmd = NULL; 973 char *pos = NULL; 974 char type; 975 char *strtmp = NULL; 976 char *strtmp2 = NULL; 965 977 966 978 // open file … … 1044 1056 raidlist->el[raidlist->entries].raid_level = 10; 1045 1057 } 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); 1052 1114 1053 1115 // get RAID devices (type, index, device) … … 1097 1159 } 1098 1160 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 1099 1207 // adjust index for each device so that it starts with 0 for every type 1100 1208 index_min = 99; 1101 1209 for (i=0; i<raidlist->el[raidlist->entries].data_disks.entries;i++) { 1102 1103 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 } 1105 1213 } 1106 1214 if (index_min > 0) { 1107 1108 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 } 1110 1218 } 1111 1219 index_min = 99; 1112 1220 for (i=0; i<raidlist->el[raidlist->entries].spare_disks.entries;i++) { 1113 1114 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 } 1116 1224 } 1117 1225 if (index_min > 0) { 1118 1119 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 } 1121 1229 } 1122 1230 index_min = 99; 1123 1231 for (i=0; i<raidlist->el[raidlist->entries].failed_disks.entries;i++) { 1124 1125 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 } 1127 1235 } 1128 1236 if (index_min > 0) { 1129 1130 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 } 1132 1240 } 1133 1241 break; 1134 1242 case 2: // config information 1135 1243 // check for persistent super block 1136 1244 if (strcasestr(string, "super non-persistent")) { 1137 1138 } else {1139 1140 }1141 // extract chunk size1142 if (!(pos = strcasestr(string, "k chunk"))) {1143 1144 } else {1145 1146 1147 1148 1149 paranoid_free(string);1150 1151 1152 1153 1154 }1155 // extract parity if present1156 if ((pos = strcasestr(string, "algorithm"))) {1157 1158 } else {1159 1160 }1161 break;1162 1163 if (!(pos = strchr(string, '\%'))) {1164 1165 1166 1167 1168 1169 } else {1170 1171 1172 1173 1174 paranoid_free(string);1175 1176 1177 1178 1179 }1180 break;1181 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 1189 1190 } 1191 // close file 1192 fclose(fin); 1193 // free string 1194 paranoid_free(string);1195 1196 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 1302 fclose(fin); 1303 // return success 1304 return 0; 1305 1306 } 1307 1308 1309 1310 1311 int create_raidtab_from_mdstat(char *mdstat_fname,char *raidtab_fname) 1204 1312 { 1205 1313 struct raidlist_itself *raidlist; … … 1209 1317 1210 1318 // 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); 1213 1321 return (1); 1214 1322 }
Note:
See TracChangeset
for help on using the changeset viewer.