Changeset 3161 in MondoRescue for branches/3.1/mondo/src/common/libmondo-raid.c
- Timestamp:
- Jun 25, 2013, 10:53:14 PM (11 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/3.1/mondo/src/common/libmondo-raid.c
r3147 r3161 430 430 char *incoming = NULL; 431 431 char *p; 432 char *q;433 432 434 433 assert(fin != NULL); … … 974 973 char type; 975 974 char *strtmp = NULL; 976 char *strtmp2 = NULL; 977 978 // open file 979 if (!(fin = fopen(MDSTAT_FILE, "r"))) { 980 log_msg(1, "Could not open %s.\n", MDSTAT_FILE); 981 return 1; 982 } 983 // initialise record, build progress and row counters 984 raidlist->entries = 0; 985 raidlist->el[raidlist->entries].progress = 999; 986 row = 1; 987 // skip first output row - contains registered RAID levels 988 res = getline(&string, &len, fin); 989 // parse the rest 990 while ( !feof_unlocked(fin) ) { 991 res = getline(&string, &len, fin); 992 if (res <= 0) break; 993 // trim leading spaces 994 pos = string; 995 while (*pos == ' ') pos += 1; 996 mr_asprintf(strtmp, "%s", pos); 997 strcpy(string, strtmp); 998 mr_free(strtmp); 999 // if we have newline after only spaces, this is a blank line, update 1000 // counters, otherwise do normal parsing 1001 if (*string == '\n') { 1002 row = 1; 1003 raidlist->entries++; 1004 raidlist->el[raidlist->entries].progress = 999; 1005 } else { 1006 switch (row) { 1007 case 1: // device information 1008 // check whether last line of record and if so skip 1009 pos = strcasestr(string, "unused devices: "); 1010 if (pos == string) { 1011 //raidlist->entries--; 1012 break; 1013 } 1014 // tokenise string 1015 token = mr_strtok(string, delims, &lastpos); 1016 // get RAID device name 1017 mr_asprintf(strtmp,"%s%s", device_prefix, token); 1018 strcpy(raidlist->el[raidlist->entries].raid_device, strtmp); 975 976 // open file 977 if (!(fin = fopen(MDSTAT_FILE, "r"))) { 978 log_msg(1, "Could not open %s.\n", MDSTAT_FILE); 979 return 1; 980 } 981 // initialise record, build progress and row counters 982 raidlist->entries = 0; 983 raidlist->el[raidlist->entries].progress = 999; 984 row = 1; 985 // skip first output row - contains registered RAID levels 986 res = getline(&string, &len, fin); 987 // parse the rest 988 while ( !feof_unlocked(fin) ) { 989 res = getline(&string, &len, fin); 990 if (res <= 0) break; 991 // trim leading spaces 992 pos = string; 993 while (*pos == ' ') pos += 1; 994 mr_asprintf(strtmp, "%s", pos); 995 strcpy(string, strtmp); 1019 996 mr_free(strtmp); 1020 mr_free(token); 1021 // skip ':' and status 1022 token = mr_strtok(string, delims, &lastpos); 1023 mr_free(token); 1024 token = mr_strtok(string, delims, &lastpos); 1025 if (!strcmp(token, "inactive")) { 1026 log_msg(1, "RAID device '%s' inactive.\n", 1027 raidlist->el[raidlist->entries].raid_device); 1028 paranoid_free(string); 1029 mr_free(token); 1030 return 1; 1031 } 1032 mr_free(token); 1033 1034 // get RAID level 1035 token = mr_strtok(string, delims, &lastpos); 1036 // skip potential auto-read-only entry 1037 if (!strcmp(token, "(auto-read-only)")) { 1038 mr_free(token); 1039 token = mr_strtok (string, delims, &lastpos); 1040 } 1041 if (!strcmp(token, "multipath")) { 1042 raidlist->el[raidlist->entries].raid_level = -2; 1043 } else if (!strcmp(token, "linear")) { 1044 raidlist->el[raidlist->entries].raid_level = -1; 1045 } else if (!strcmp(token, "raid0")) { 1046 raidlist->el[raidlist->entries].raid_level = 0; 1047 } else if (!strcmp(token, "raid1")) { 1048 raidlist->el[raidlist->entries].raid_level = 1; 1049 } else if (!strcmp(token, "raid4")) { 1050 raidlist->el[raidlist->entries].raid_level = 4; 1051 } else if (!strcmp(token, "raid5")) { 1052 raidlist->el[raidlist->entries].raid_level = 5; 1053 } else if (!strcmp(token, "raid6")) { 1054 raidlist->el[raidlist->entries].raid_level = 6; 1055 } else if (!strcmp(token, "raid10")) { 1056 raidlist->el[raidlist->entries].raid_level = 10; 997 // if we have newline after only spaces, this is a blank line, update 998 // counters, otherwise do normal parsing 999 if (*string == '\n') { 1000 row = 1; 1001 raidlist->entries++; 1002 raidlist->el[raidlist->entries].progress = 999; 1057 1003 } else { 1058 1004 switch (row) { 1059 1005 case 1: // device information 1060 1006 // check whether last line of record and if so skip 1061 log_msg(8, "This is the device line\n");1062 1007 pos = strcasestr(string, "unused devices: "); 1063 if (pos != NULL) { 1008 if (pos == string) { 1009 //raidlist->entries--; 1064 1010 break; 1065 1011 } … … 1071 1017 } 1072 1018 // 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'; 1019 mr_asprintf(strtmp,"%s%s", device_prefix, token); 1020 strcpy(raidlist->el[raidlist->entries].raid_device, strtmp); 1076 1021 mr_free(strtmp); 1077 1022 mr_free(token); … … 1079 1024 v = raidlist->el[raidlist->entries].additional_vars.entries; 1080 1025 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));1026 mr_asprintf(cmd,"mdadm --detail %s | grep UUID | cut -d: -f2- | sed 's/^ *//'", raidlist->el[raidlist->entries].raid_device); 1027 mr_asprintf(strtmp, "%s", call_program_and_get_last_line_of_output(cmd, TRUE)); 1083 1028 strcpy(raidlist->el[raidlist->entries].additional_vars.el[v].value, strtmp); 1084 1029 mr_free(strtmp); … … 1086 1031 // store the Version value in the additional_vars structure 1087 1032 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));1033 mr_asprintf(cmd,"mdadm --detail %s | grep Version | cut -d: -f2- | sed 's/^ *//'", raidlist->el[raidlist->entries].raid_device); 1034 mr_asprintf(strtmp, "%s", call_program_and_get_last_line_of_output(cmd, TRUE)); 1090 1035 strcpy(raidlist->el[raidlist->entries].additional_vars.el[v].value, strtmp); 1091 1036 mr_free(strtmp); … … 1093 1038 raidlist->el[raidlist->entries].additional_vars.entries = v; 1094 1039 // skip ':' and status 1095 token = mr_strtok 1040 token = mr_strtok(string, delims, &lastpos); 1096 1041 if (token == NULL) { 1097 1042 // should not happen ! … … 1099 1044 } 1100 1045 mr_free(token); 1101 token = mr_strtok 1046 token = mr_strtok(string, delims, &lastpos); 1102 1047 if (token == NULL) { 1103 1048 // should not happen ! … … 1105 1050 } 1106 1051 if (!strcmp(token, "inactive")) { 1107 log_msg(1, "RAID device '%s' inactive.\n", 1108 raidlist->el[raidlist->entries].raid_device); 1052 log_msg(1, "RAID device '%s' inactive.\n", raidlist->el[raidlist->entries].raid_device); 1109 1053 mr_free(string); 1110 1054 mr_free(token); … … 1113 1057 mr_free(token); 1114 1058 1115 // get RAID devices (type, index, device) 1116 // Note: parity disk for RAID4 is last normal disk, there is no '(P)' 1117 raidlist->el[raidlist->entries].data_disks.entries = 0; 1118 raidlist->el[raidlist->entries].spare_disks.entries = 0; 1119 raidlist->el[raidlist->entries].failed_disks.entries = 0; 1120 while((token = mr_strtok (string, delims, &lastpos))) { 1121 if ((pos = strstr(token, "("))) { 1122 type = *(pos+1); 1123 } else { 1124 type = ' '; 1125 } 1126 pos = strstr(token, "["); 1127 *pos = '\0'; 1128 switch(type) { 1129 case ' ': // normal data disks 1130 raidlist->el[raidlist->entries].data_disks.el[raidlist->el[raidlist->entries].data_disks.entries].index = atoi(pos + 1); 1131 mr_asprintf(strtmp,"%s%s", device_prefix, token); 1132 strcpy(raidlist->el[raidlist->entries].data_disks.el[raidlist->el[raidlist->entries].data_disks.entries].device, strtmp); 1133 mr_free(strtmp); 1134 raidlist->el[raidlist->entries].data_disks.entries++; 1135 break; 1136 case 'S': // spare disks 1137 raidlist->el[raidlist->entries].spare_disks.el[raidlist->el[raidlist->entries].spare_disks.entries].index = atoi(pos + 1); 1138 mr_asprintf(strtmp,"%s%s", device_prefix, token); 1139 strcpy(raidlist->el[raidlist->entries].spare_disks.el[raidlist->el[raidlist->entries].spare_disks.entries].device, strtmp); 1140 mr_free(strtmp); 1141 raidlist->el[raidlist->entries].spare_disks.entries++; 1142 break; 1143 case 'F': // failed disks 1144 raidlist->el[raidlist->entries].failed_disks.el[raidlist->el[raidlist->entries].failed_disks.entries].index = atoi(pos + 1); 1145 mr_asprintf(strtmp,"%s%s", device_prefix, token); 1146 strcpy(raidlist->el[raidlist->entries].failed_disks.el[raidlist->el[raidlist->entries].failed_disks.entries].device, strtmp); 1147 mr_free(strtmp); 1148 raidlist->el[raidlist->entries].failed_disks.entries++; 1149 log_it("At least one failed disk found in RAID array.\n"); 1150 break; 1151 default: // error 1152 log_msg(1, "Unknown device type '%c'\n", type); 1153 paranoid_free(string); 1154 paranoid_free(token); 1155 return 1; 1156 break; 1157 } 1158 mr_free(token); 1159 } 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 1207 // adjust index for each device so that it starts with 0 for every type 1208 index_min = 99; 1209 for (i=0; i<raidlist->el[raidlist->entries].data_disks.entries;i++) { 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 } 1213 } 1214 if (index_min > 0) { 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 } 1218 } 1219 index_min = 99; 1220 for (i=0; i<raidlist->el[raidlist->entries].spare_disks.entries;i++) { 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 } 1224 } 1225 if (index_min > 0) { 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 } 1229 } 1230 index_min = 99; 1231 for (i=0; i<raidlist->el[raidlist->entries].failed_disks.entries;i++) { 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 } 1235 } 1236 if (index_min > 0) { 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 } 1240 } 1241 break; 1242 case 2: // config information 1243 // check for persistent super block 1244 if (strcasestr(string, "super non-persistent")) { 1059 // get RAID level 1060 token = mr_strtok(string, delims, &lastpos); 1061 if (token == NULL) { 1062 // should not happen ! 1063 break; 1064 } 1065 // skip potential auto-read-only entry 1066 if (!strcmp(token, "(auto-read-only)")) { 1067 mr_free(token); 1068 token = mr_strtok (string, delims, &lastpos); 1069 if (token == NULL) { 1070 // should not happen ! 1071 break; 1072 } 1073 } 1074 if (!strcmp(token, "multipath")) { 1075 raidlist->el[raidlist->entries].raid_level = -2; 1076 } else if (!strcmp(token, "linear")) { 1077 raidlist->el[raidlist->entries].raid_level = -1; 1078 } else if (!strcmp(token, "raid0")) { 1079 raidlist->el[raidlist->entries].raid_level = 0; 1080 } else if (!strcmp(token, "raid1")) { 1081 raidlist->el[raidlist->entries].raid_level = 1; 1082 } else if (!strcmp(token, "raid4")) { 1083 raidlist->el[raidlist->entries].raid_level = 4; 1084 } else if (!strcmp(token, "raid5")) { 1085 raidlist->el[raidlist->entries].raid_level = 5; 1086 } else if (!strcmp(token, "raid6")) { 1087 raidlist->el[raidlist->entries].raid_level = 6; 1088 } else if (!strcmp(token, "raid10")) { 1089 raidlist->el[raidlist->entries].raid_level = 10; 1090 } else { 1091 log_msg(1, "Unknown RAID level '%s'.\n", token); 1092 mr_free(string); 1093 mr_free(token); 1094 return 1; 1095 } 1096 mr_free(token); 1097 1098 // get RAID devices (type, index, device) 1099 // Note: parity disk for RAID4 is last normal disk, there is no '(P)' 1100 raidlist->el[raidlist->entries].data_disks.entries = 0; 1101 raidlist->el[raidlist->entries].spare_disks.entries = 0; 1102 raidlist->el[raidlist->entries].failed_disks.entries = 0; 1103 while((token = mr_strtok (string, delims, &lastpos))) { 1104 if ((pos = strstr(token, "("))) { 1105 type = *(pos+1); 1106 } else { 1107 type = ' '; 1108 } 1109 pos = strstr(token, "["); 1110 *pos = '\0'; 1111 switch(type) { 1112 case ' ': // normal data disks 1113 raidlist->el[raidlist->entries].data_disks.el[raidlist->el[raidlist->entries].data_disks.entries].index = atoi(pos + 1); 1114 mr_asprintf(strtmp,"%s%s", device_prefix, token); 1115 strcpy(raidlist->el[raidlist->entries].data_disks.el[raidlist->el[raidlist->entries].data_disks.entries].device, strtmp); 1116 mr_free(strtmp); 1117 raidlist->el[raidlist->entries].data_disks.entries++; 1118 break; 1119 case 'S': // spare disks 1120 raidlist->el[raidlist->entries].spare_disks.el[raidlist->el[raidlist->entries].spare_disks.entries].index = atoi(pos + 1); 1121 mr_asprintf(strtmp,"%s%s", device_prefix, token); 1122 strcpy(raidlist->el[raidlist->entries].spare_disks.el[raidlist->el[raidlist->entries].spare_disks.entries].device, strtmp); 1123 mr_free(strtmp); 1124 raidlist->el[raidlist->entries].spare_disks.entries++; 1125 break; 1126 case 'F': // failed disks 1127 raidlist->el[raidlist->entries].failed_disks.el[raidlist->el[raidlist->entries].failed_disks.entries].index = atoi(pos + 1); 1128 mr_asprintf(strtmp,"%s%s", device_prefix, token); 1129 strcpy(raidlist->el[raidlist->entries].failed_disks.el[raidlist->el[raidlist->entries].failed_disks.entries].device, strtmp); 1130 mr_free(strtmp); 1131 raidlist->el[raidlist->entries].failed_disks.entries++; 1132 log_it("At least one failed disk found in RAID array.\n"); 1133 break; 1134 default: // error 1135 log_msg(1, "Unknown device type '%c'\n", type); 1136 mr_free(string); 1137 mr_free(token); 1138 return 1; 1139 break; 1140 } 1141 mr_free(token); 1142 } 1143 1144 // adjust index for each device so that it starts with 0 for every type 1145 index_min = 99; 1146 for (i=0; i<raidlist->el[raidlist->entries].data_disks.entries;i++) { 1147 if (raidlist->el[raidlist->entries].data_disks.el[i].index < index_min) { 1148 index_min = raidlist->el[raidlist->entries].data_disks.el[i].index; 1149 } 1150 } 1151 if (index_min > 0) { 1152 for (i=0; i<raidlist->el[raidlist->entries].data_disks.entries;i++) { 1153 raidlist->el[raidlist->entries].data_disks.el[i].index = raidlist->el[raidlist->entries].data_disks.el[i].index - index_min; 1154 } 1155 } 1156 index_min = 99; 1157 for (i=0; i<raidlist->el[raidlist->entries].spare_disks.entries;i++) { 1158 if (raidlist->el[raidlist->entries].spare_disks.el[i].index < index_min) { 1159 index_min = raidlist->el[raidlist->entries].spare_disks.el[i].index; 1160 } 1161 } 1162 if (index_min > 0) { 1163 for (i=0; i<raidlist->el[raidlist->entries].spare_disks.entries;i++) { 1164 raidlist->el[raidlist->entries].spare_disks.el[i].index = raidlist->el[raidlist->entries].spare_disks.el[i].index - index_min; 1165 } 1166 } 1167 index_min = 99; 1168 for (i=0; i<raidlist->el[raidlist->entries].failed_disks.entries;i++) { 1169 if (raidlist->el[raidlist->entries].failed_disks.el[i].index < index_min) { 1170 index_min = raidlist->el[raidlist->entries].failed_disks.el[i].index; 1171 } 1172 } 1173 if (index_min > 0) { 1174 for (i=0; i<raidlist->el[raidlist->entries].failed_disks.entries;i++) { 1175 raidlist->el[raidlist->entries].failed_disks.el[i].index = raidlist->el[raidlist->entries].failed_disks.el[i].index - index_min; 1176 } 1177 } 1178 break; 1179 case 2: // config information 1180 // check for persistent super block 1181 if (strcasestr(string, "super non-persistent")) { 1245 1182 raidlist->el[raidlist->entries].persistent_superblock = 0; 1246 1183 } else { … … 1252 1189 } else { 1253 1190 while (*pos != ' ') { 1254 1255 1256 1257 1258 1259 1191 pos -= 1; 1192 if (pos < string) { 1193 log_it("String underflow!\n"); 1194 mr_free(string); 1195 return 1; 1196 } 1260 1197 } 1261 1198 raidlist->el[raidlist->entries].chunk_size = atoi(pos + 1); … … 1271 1208 if (!(pos = strchr(string, '\%'))) { 1272 1209 if (strcasestr(string, "delayed")) { 1273 1210 raidlist->el[raidlist->entries].progress = -1; // delayed (therefore, stuck at 0%) 1274 1211 } else { 1275 1212 raidlist->el[raidlist->entries].progress = 999; // not found 1276 1213 } 1277 1214 } else { 1278 1215 while (*pos != ' ') { 1279 1280 1281 1282 1283 1284 1216 pos -= 1; 1217 if (pos < string) { 1218 printf("ERROR: String underflow!\n"); 1219 mr_free(string); 1220 return 1; 1221 } 1285 1222 } 1286 1223 raidlist->el[raidlist->entries].progress = atoi(pos); 1287 1224 } 1288 1225 break; 1289 1226 default: // error or IN PROGRESS 1290 1227 if (raidlist->el[raidlist->entries].progress != -1 && 1291 1228 raidlist->el[raidlist->entries].progress != 999) { … … 1293 1230 } 1294 1231 break; 1295 1296 1297 } 1298 1299 1232 } 1233 row++; 1234 } 1235 // free string 1236 mr_free(string); 1300 1237 } 1301 1238 // close file
Note:
See TracChangeset
for help on using the changeset viewer.