Changeset 558 in MondoRescue for branches/stable/mondo/mondo/common/libmondo-raid.c
- Timestamp:
- May 20, 2006, 4:54:20 PM (18 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/stable/mondo/mondo/common/libmondo-raid.c
r541 r558 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 size_t len = 0; 1019 char *token, *string = NULL, *pos, type, *strtmp; 1020 1021 // open file 1022 if (!(fin = fopen(MDSTAT_FILE, "r"))) { 1023 log_msg(1, "Could not open %s.\n", MDSTAT_FILE); 1024 return 1; 1025 } 1026 // initialise record, build progress and row counters 1027 raidlist->entries = 0; 1028 raidlist->el[raidlist->entries].progress = 999; 1029 row = 1; 1030 // skip first output row - contains registered RAID levels 1031 res = getline(&string, &len, fin); 1032 // parse the rest 1033 while ( !feof_unlocked(fin) ) { 1034 res = getline(&string, &len, fin); 1035 if (res <= 0) break; 1036 // trim leading spaces 1037 pos = string; 1038 while (*pos == ' ') *pos++; 1039 memmove(string, pos, strlen(string)); 1040 // if we have newline after only spaces, this is a blank line, update 1041 // counters, otherwise do normal parsing 1042 if (*string == '\n') { 1043 row = 1; 1044 raidlist->entries++; 1045 raidlist->el[raidlist->entries].progress = 999; 1046 } else { 1047 switch (row) { 1048 case 1: // device information 1049 // check whether last line of record and if so skip 1050 pos = strcasestr(string, "unused devices: "); 1051 if (pos == string) { 1052 //raidlist->entries--; 1053 break; 1054 } 1055 // tokenise string 1056 token = strtok (string, delims); 1057 // get RAID device name 1058 asprintf(&strtmp,"%s%s", device_prefix, token); 1059 strcpy(raidlist->el[raidlist->entries].raid_device, strtmp); 1060 paranoid_free(strtmp); 1061 // skip ':' and status 1062 token = strtok (NULL, delims); 1063 token = strtok (NULL, delims); 1064 if (!strcmp(token, "inactive")) { 1065 log_msg(1, "RAID device '%s' inactive.\n", 1066 raidlist->el[raidlist->entries].raid_device); 1067 paranoid_free(string); 1068 return 1; 1069 } 1070 // get RAID level 1071 token = strtok (NULL, delims); 1072 if (!strcmp(token, "multipath")) { 1073 raidlist->el[raidlist->entries].raid_level = -2; 1074 } else if (!strcmp(token, "linear")) { 1075 raidlist->el[raidlist->entries].raid_level = -1; 1076 } else if (!strcmp(token, "raid0")) { 1077 raidlist->el[raidlist->entries].raid_level = 0; 1078 } else if (!strcmp(token, "raid1")) { 1079 raidlist->el[raidlist->entries].raid_level = 1; 1080 } else if (!strcmp(token, "raid4")) { 1081 raidlist->el[raidlist->entries].raid_level = 4; 1082 } else if (!strcmp(token, "raid5")) { 1083 raidlist->el[raidlist->entries].raid_level = 5; 1084 } else if (!strcmp(token, "raid6")) { 1085 raidlist->el[raidlist->entries].raid_level = 6; 1086 } else if (!strcmp(token, "raid10")) { 1087 raidlist->el[raidlist->entries].raid_level = 10; 1088 } else { 1089 log_msg(1, "Unknown RAID level '%s'.\n", token); 1090 paranoid_free(string); 1091 return 1; 1092 } 1093 // get RAID devices (type, index, device) 1094 // Note: parity disk for RAID4 is last normal disk, there is no '(P)' 1095 raidlist->el[raidlist->entries].data_disks.entries = 0; 1096 raidlist->el[raidlist->entries].spare_disks.entries = 0; 1097 raidlist->el[raidlist->entries].failed_disks.entries = 0; 1098 while((token = strtok (NULL, delims))) { 1099 if ((pos = strstr(token, "("))) { 1100 type = *(pos+1); 1101 } else { 1102 type = ' '; 1103 } 1104 pos = strstr(token, "["); 1105 *pos = '\0'; 1106 switch(type) { 1107 case ' ': // normal data disks 1108 raidlist->el[raidlist->entries].data_disks.el[raidlist->el[raidlist->entries].data_disks.entries].index = atoi(pos + 1); 1109 asprintf(&strtmp,"%s%s", device_prefix, token); 1110 strcpy(raidlist->el[raidlist->entries].data_disks.el[raidlist->el[raidlist->entries].data_disks.entries].device, strtmp); 1111 paranoid_free(strtmp); 1112 raidlist->el[raidlist->entries].data_disks.entries++; 1113 break; 1114 case 'S': // spare disks 1115 raidlist->el[raidlist->entries].spare_disks.el[raidlist->el[raidlist->entries].spare_disks.entries].index = atoi(pos + 1); 1116 asprintf(&strtmp,"%s%s", device_prefix, token); 1117 strcpy(raidlist->el[raidlist->entries].spare_disks.el[raidlist->el[raidlist->entries].spare_disks.entries].device, strtmp); 1118 paranoid_free(strtmp); 1119 raidlist->el[raidlist->entries].spare_disks.entries++; 1120 break; 1121 case 'F': // failed disks 1122 raidlist->el[raidlist->entries].failed_disks.el[raidlist->el[raidlist->entries].failed_disks.entries].index = atoi(pos + 1); 1123 asprintf(&strtmp,"%s%s", device_prefix, token); 1124 strcpy(raidlist->el[raidlist->entries].failed_disks.el[raidlist->el[raidlist->entries].failed_disks.entries].device, strtmp); 1125 paranoid_free(strtmp); 1126 raidlist->el[raidlist->entries].failed_disks.entries++; 1127 log_it("At least one failed disk found in RAID array.\n"); 1128 break; 1129 default: // error 1130 log_msg(1, "Unknown device type '%c'\n", type); 1131 paranoid_free(string); 1132 return 1; 1133 break; 1134 } 1135 } 1136 // adjust index for each device so that it starts with 0 for every type 1137 index_min = 99; 1138 for (i=0; i<raidlist->el[raidlist->entries].data_disks.entries;i++) { 1139 if (raidlist->el[raidlist->entries].data_disks.el[i].index < index_min) { 1140 index_min = raidlist->el[raidlist->entries].data_disks.el[i].index; 1141 } 1142 } 1143 if (index_min > 0) { 1144 for (i=0; i<raidlist->el[raidlist->entries].data_disks.entries;i++) { 1145 raidlist->el[raidlist->entries].data_disks.el[i].index = raidlist->el[raidlist->entries].data_disks.el[i].index - index_min; 1146 } 1147 } 1148 index_min = 99; 1149 for (i=0; i<raidlist->el[raidlist->entries].spare_disks.entries;i++) { 1150 if (raidlist->el[raidlist->entries].spare_disks.el[i].index < index_min) { 1151 index_min = raidlist->el[raidlist->entries].spare_disks.el[i].index; 1152 } 1153 } 1154 if (index_min > 0) { 1155 for (i=0; i<raidlist->el[raidlist->entries].spare_disks.entries;i++) { 1156 raidlist->el[raidlist->entries].spare_disks.el[i].index = raidlist->el[raidlist->entries].spare_disks.el[i].index - index_min; 1157 } 1158 } 1159 index_min = 99; 1160 for (i=0; i<raidlist->el[raidlist->entries].failed_disks.entries;i++) { 1161 if (raidlist->el[raidlist->entries].failed_disks.el[i].index < index_min) { 1162 index_min = raidlist->el[raidlist->entries].failed_disks.el[i].index; 1163 } 1164 } 1165 if (index_min > 0) { 1166 for (i=0; i<raidlist->el[raidlist->entries].failed_disks.entries;i++) { 1167 raidlist->el[raidlist->entries].failed_disks.el[i].index = raidlist->el[raidlist->entries].failed_disks.el[i].index - index_min; 1168 } 1169 } 1170 break; 1171 case 2: // config information 1172 // check for persistent super block 1173 if (strcasestr(string, "super non-persistent")) { 1174 raidlist->el[raidlist->entries].persistent_superblock = 0; 1175 } else { 1176 raidlist->el[raidlist->entries].persistent_superblock = 1; 1177 } 1178 // extract chunk size 1179 if (!(pos = strcasestr(string, "k chunk"))) { 1180 raidlist->el[raidlist->entries].chunk_size = -1; 1181 } else { 1182 while (*pos != ' ') { 1183 *pos--; 1184 if (pos < string) { 1185 log_it("String underflow!\n"); 1186 paranoid_free(string); 1187 return 1; 1188 } 1189 } 1190 raidlist->el[raidlist->entries].chunk_size = atoi(pos + 1); 1191 } 1192 // extract parity if present 1193 if ((pos = strcasestr(string, "algorithm"))) { 1194 raidlist->el[raidlist->entries].parity = atoi(pos + 9); 1195 } else { 1196 raidlist->el[raidlist->entries].parity = -1; 1197 } 1198 break; 1199 case 3: // optional build status information 1200 if (!(pos = strchr(string, '\%'))) { 1201 if (strcasestr(string, "delayed")) { 1202 raidlist->el[raidlist->entries].progress = -1; // delayed (therefore, stuck at 0%) 1203 } else { 1204 raidlist->el[raidlist->entries].progress = 999; // not found 1205 } 1206 } else { 1207 while (*pos != ' ') { 1208 *pos--; 1209 if (pos < string) { 1210 printf("ERROR: String underflow!\n"); 1211 paranoid_free(string); 1212 return 1; 1213 } 1214 } 1215 raidlist->el[raidlist->entries].progress = atoi(pos); 1216 } 1217 break; 1218 default: // error 1219 log_msg(1, "Row %d should not occur in record!\n", row); 1220 break; 1221 } 1222 row++; 1223 } 1224 } 1225 // close file 1226 fclose(fin); 1227 // free string 1228 paranoid_free(string); 1229 // return success 1230 return 0; 1231 1232 } 1233 1234 1235 1236 1237 int create_raidtab_from_mdstat(char *raidtab_fname) 1238 { 1239 struct raidlist_itself *raidlist; 1240 int retval = 0; 1241 1242 raidlist = malloc(sizeof(struct raidlist_itself)); 1243 1244 // FIXME: Prefix '/dev/' should really be dynamic! 1245 if (parse_mdstat(raidlist, "/dev/")) { 1246 log_to_screen("Sorry, cannot read %s", MDSTAT_FILE); 990 1247 return (1); 991 1248 } 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; 1249 1118 1250 retval += save_raidlist_to_raidtab(raidlist, raidtab_fname); 1119 1251 return (retval);
Note:
See TracChangeset
for help on using the changeset viewer.