Changeset 561 in MondoRescue for trunk/mondo/mondo/common/libmondo-raid.c
- Timestamp:
- May 20, 2006, 5:51:21 PM (18 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/mondo/mondo/common/libmondo-raid.c
r507 r561 344 344 345 345 fprintf(fout, "raiddev %s\n", raidrec->raid_device); 346 if (raidrec->raid_level == -1) { 346 if (raidrec->raid_level == -2) { 347 fprintf(fout, " raid-level multipath\n"); 348 } else if (raidrec->raid_level == -1) { 347 349 fprintf(fout, " raid-level linear\n"); 348 350 } else { … … 350 352 raidrec->raid_level); 351 353 } 352 fprintf(fout, " chunk-size %d\n", raidrec->chunk_size);353 354 fprintf(fout, " nr-raid-disks %d\n", 354 355 raidrec->data_disks.entries); 355 fprintf(fout, " nr-spare-disks %d\n", 356 raidrec->spare_disks.entries); 356 if (raidrec->spare_disks.entries > 0) { 357 fprintf(fout, " nr-spare-disks %d\n", 358 raidrec->spare_disks.entries); 359 } 357 360 if (raidrec->parity_disks.entries > 0) { 358 361 fprintf(fout, " nr-parity-disks %d\n", 359 362 raidrec->parity_disks.entries); 360 363 } 361 362 364 fprintf(fout, " persistent-superblock %d\n", 363 365 raidrec->persistent_superblock); 366 if (raidrec->chunk_size > -1) { 367 fprintf(fout, " chunk-size %d\n", raidrec->chunk_size); 368 } 369 if (raidrec->parity > -1) { 370 switch(raidrec->parity) { 371 case 0: 372 fprintf(fout, " parity-algorithm left-asymmetric\n"); 373 break; 374 case 1: 375 fprintf(fout, " parity-algorithm right-asymmetric\n"); 376 break; 377 case 2: 378 fprintf(fout, " parity-algorithm left-symmetric\n"); 379 break; 380 case 3: 381 fprintf(fout, " parity-algorithm right-symmetric\n"); 382 break; 383 default: 384 fatal_error("Unknown RAID parity algorithm."); 385 break; 386 } 387 } 364 388 save_additional_vars_to_file(&raidrec->additional_vars, fout); 365 389 fprintf(fout, "\n"); … … 642 666 643 667 if (!strcmp(label, "raid-level")) { 644 if (!strcmp(value, "linear")) { 668 if (!strcmp(value, "multipath")) { 669 raidrec->raid_level = -2; 670 } else if (!strcmp(value, "linear")) { 645 671 raidrec->raid_level = -1; 646 672 } else { … … 655 681 } else if (!strcmp(label, "chunk-size")) { 656 682 raidrec->chunk_size = atoi(value); 683 } else if (!strcmp(label, "parity-algorithm")) { 684 if (!strcmp(value, "left-asymmetric")) { 685 raidrec->parity = 0; 686 } else if (!strcmp(value, "right-asymmetric")) { 687 raidrec->parity = 1; 688 } else if (!strcmp(value, "left-symmetric")) { 689 raidrec->parity = 2; 690 } else if (!strcmp(value, "right-symmetric")) { 691 raidrec->parity = 3; 692 } else { 693 log_msg(1, "Unknown RAID parity algorithm '%s'\n.", value); 694 } 657 695 } else if (!strcmp(label, "device")) { 658 696 get_next_raidtab_line(fin, labelB, valueB); … … 898 936 899 937 900 int read_mdstat(struct s_mdstat *mdstat, char *mdstat_file) 901 { 902 FILE *fin; 903 char *tmp; 904 char *stub; 905 char *incoming = NULL; 906 char *p, *q, *r; 907 int diskno; 908 size_t n = 0; 909 910 malloc_string(incoming); 911 if (!(fin = fopen(mdstat_file, "r"))) { 912 log_msg(1, "%s not found", mdstat_file); 938 int parse_mdstat(struct raidlist_itself *raidlist, char *device_prefix) { 939 940 const char delims[] = " "; 941 942 FILE *fin; 943 int res = 0, row, i, index_min; 944 int lastpos = 0; 945 size_t len = 0; 946 char *token; 947 char *string = NULL; 948 char *pos; 949 char type; 950 char *strtmp; 951 952 // open file 953 if (!(fin = fopen(MDSTAT_FILE, "r"))) { 954 log_msg(1, "Could not open %s.\n", MDSTAT_FILE); 955 return 1; 956 } 957 // initialise record, build progress and row counters 958 raidlist->entries = 0; 959 raidlist->el[raidlist->entries].progress = 999; 960 row = 1; 961 // skip first output row - contains registered RAID levels 962 res = getline(&string, &len, fin); 963 // parse the rest 964 while ( !feof_unlocked(fin) ) { 965 res = getline(&string, &len, fin); 966 if (res <= 0) break; 967 // trim leading spaces 968 pos = string; 969 while (*pos == ' ') *pos++; 970 asprintf(&string, pos); 971 // 972 // if we have newline after only spaces, this is a blank line, update 973 // counters, otherwise do normal parsing 974 if (*string == '\n') { 975 row = 1; 976 raidlist->entries++; 977 raidlist->el[raidlist->entries].progress = 999; 978 } else { 979 switch (row) { 980 case 1: // device information 981 // check whether last line of record and if so skip 982 pos = strcasestr(string, "unused devices: "); 983 if (pos == string) { 984 //raidlist->entries--; 985 break; 986 } 987 // tokenise string 988 token = mr_strtok (string, delims, &lastpos); 989 // get RAID device name 990 asprintf(&strtmp,"%s%s", device_prefix, token); 991 strcpy(raidlist->el[raidlist->entries].raid_device, strtmp); 992 paranoid_free(strtmp); 993 paranoid_free(token); 994 // skip ':' and status 995 token = strtok (string, delims, &lastpos); 996 paranoid_free(token); 997 token = strtok (string, delims, &lastpos); 998 if (!strcmp(token, "inactive")) { 999 log_msg(1, "RAID device '%s' inactive.\n", 1000 raidlist->el[raidlist->entries].raid_device); 1001 paranoid_free(string); 1002 paranoid_free(token); 1003 return 1; 1004 } 1005 paranoid_free(token); 1006 1007 // get RAID level 1008 token = strtok (string, delims, &lastpos); 1009 if (!strcmp(token, "multipath")) { 1010 raidlist->el[raidlist->entries].raid_level = -2; 1011 } else if (!strcmp(token, "linear")) { 1012 raidlist->el[raidlist->entries].raid_level = -1; 1013 } else if (!strcmp(token, "raid0")) { 1014 raidlist->el[raidlist->entries].raid_level = 0; 1015 } else if (!strcmp(token, "raid1")) { 1016 raidlist->el[raidlist->entries].raid_level = 1; 1017 } else if (!strcmp(token, "raid4")) { 1018 raidlist->el[raidlist->entries].raid_level = 4; 1019 } else if (!strcmp(token, "raid5")) { 1020 raidlist->el[raidlist->entries].raid_level = 5; 1021 } else if (!strcmp(token, "raid6")) { 1022 raidlist->el[raidlist->entries].raid_level = 6; 1023 } else if (!strcmp(token, "raid10")) { 1024 raidlist->el[raidlist->entries].raid_level = 10; 1025 } else { 1026 log_msg(1, "Unknown RAID level '%s'.\n", token); 1027 paranoid_free(string); 1028 paranoid_free(token); 1029 return 1; 1030 } 1031 paranoid_free(token); 1032 1033 // get RAID devices (type, index, device) 1034 // Note: parity disk for RAID4 is last normal disk, there is no '(P)' 1035 raidlist->el[raidlist->entries].data_disks.entries = 0; 1036 raidlist->el[raidlist->entries].spare_disks.entries = 0; 1037 raidlist->el[raidlist->entries].failed_disks.entries = 0; 1038 while((token = strtok (string, delims, &lastpos))) { 1039 if ((pos = strstr(token, "("))) { 1040 type = *(pos+1); 1041 } else { 1042 type = ' '; 1043 } 1044 pos = strstr(token, "["); 1045 *pos = '\0'; 1046 switch(type) { 1047 case ' ': // normal data disks 1048 raidlist->el[raidlist->entries].data_disks.el[raidlist->el[raidlist->entries].data_disks.entries].index = atoi(pos + 1); 1049 asprintf(&strtmp,"%s%s", device_prefix, token); 1050 strcpy(raidlist->el[raidlist->entries].data_disks.el[raidlist->el[raidlist->entries].data_disks.entries].device, strtmp); 1051 paranoid_free(strtmp); 1052 raidlist->el[raidlist->entries].data_disks.entries++; 1053 break; 1054 case 'S': // spare disks 1055 raidlist->el[raidlist->entries].spare_disks.el[raidlist->el[raidlist->entries].spare_disks.entries].index = atoi(pos + 1); 1056 asprintf(&strtmp,"%s%s", device_prefix, token); 1057 strcpy(raidlist->el[raidlist->entries].spare_disks.el[raidlist->el[raidlist->entries].spare_disks.entries].device, strtmp); 1058 paranoid_free(strtmp); 1059 raidlist->el[raidlist->entries].spare_disks.entries++; 1060 break; 1061 case 'F': // failed disks 1062 raidlist->el[raidlist->entries].failed_disks.el[raidlist->el[raidlist->entries].failed_disks.entries].index = atoi(pos + 1); 1063 asprintf(&strtmp,"%s%s", device_prefix, token); 1064 strcpy(raidlist->el[raidlist->entries].failed_disks.el[raidlist->el[raidlist->entries].failed_disks.entries].device, strtmp); 1065 paranoid_free(strtmp); 1066 raidlist->el[raidlist->entries].failed_disks.entries++; 1067 log_it("At least one failed disk found in RAID array.\n"); 1068 break; 1069 default: // error 1070 log_msg(1, "Unknown device type '%c'\n", type); 1071 paranoid_free(string); 1072 paranoid_free(token); 1073 return 1; 1074 break; 1075 } 1076 paranoid_free(token); 1077 } 1078 1079 // adjust index for each device so that it starts with 0 for every type 1080 index_min = 99; 1081 for (i=0; i<raidlist->el[raidlist->entries].data_disks.entries;i++) { 1082 if (raidlist->el[raidlist->entries].data_disks.el[i].index < index_min) { 1083 index_min = raidlist->el[raidlist->entries].data_disks.el[i].index; 1084 } 1085 } 1086 if (index_min > 0) { 1087 for (i=0; i<raidlist->el[raidlist->entries].data_disks.entries;i++) { 1088 raidlist->el[raidlist->entries].data_disks.el[i].index = raidlist->el[raidlist->entries].data_disks.el[i].index - index_min; 1089 } 1090 } 1091 index_min = 99; 1092 for (i=0; i<raidlist->el[raidlist->entries].spare_disks.entries;i++) { 1093 if (raidlist->el[raidlist->entries].spare_disks.el[i].index < index_min) { 1094 index_min = raidlist->el[raidlist->entries].spare_disks.el[i].index; 1095 } 1096 } 1097 if (index_min > 0) { 1098 for (i=0; i<raidlist->el[raidlist->entries].spare_disks.entries;i++) { 1099 raidlist->el[raidlist->entries].spare_disks.el[i].index = raidlist->el[raidlist->entries].spare_disks.el[i].index - index_min; 1100 } 1101 } 1102 index_min = 99; 1103 for (i=0; i<raidlist->el[raidlist->entries].failed_disks.entries;i++) { 1104 if (raidlist->el[raidlist->entries].failed_disks.el[i].index < index_min) { 1105 index_min = raidlist->el[raidlist->entries].failed_disks.el[i].index; 1106 } 1107 } 1108 if (index_min > 0) { 1109 for (i=0; i<raidlist->el[raidlist->entries].failed_disks.entries;i++) { 1110 raidlist->el[raidlist->entries].failed_disks.el[i].index = raidlist->el[raidlist->entries].failed_disks.el[i].index - index_min; 1111 } 1112 } 1113 break; 1114 case 2: // config information 1115 // check for persistent super block 1116 if (strcasestr(string, "super non-persistent")) { 1117 raidlist->el[raidlist->entries].persistent_superblock = 0; 1118 } else { 1119 raidlist->el[raidlist->entries].persistent_superblock = 1; 1120 } 1121 // extract chunk size 1122 if (!(pos = strcasestr(string, "k chunk"))) { 1123 raidlist->el[raidlist->entries].chunk_size = -1; 1124 } else { 1125 while (*pos != ' ') { 1126 *pos--; 1127 if (pos < string) { 1128 log_it("String underflow!\n"); 1129 paranoid_free(string); 1130 return 1; 1131 } 1132 } 1133 raidlist->el[raidlist->entries].chunk_size = atoi(pos + 1); 1134 } 1135 // extract parity if present 1136 if ((pos = strcasestr(string, "algorithm"))) { 1137 raidlist->el[raidlist->entries].parity = atoi(pos + 9); 1138 } else { 1139 raidlist->el[raidlist->entries].parity = -1; 1140 } 1141 break; 1142 case 3: // optional build status information 1143 if (!(pos = strchr(string, '\%'))) { 1144 if (strcasestr(string, "delayed")) { 1145 raidlist->el[raidlist->entries].progress = -1; // delayed (therefore, stuck at 0%) 1146 } else { 1147 raidlist->el[raidlist->entries].progress = 999; // not found 1148 } 1149 } else { 1150 while (*pos != ' ') { 1151 *pos--; 1152 if (pos < string) { 1153 printf("ERROR: String underflow!\n"); 1154 paranoid_free(string); 1155 return 1; 1156 } 1157 } 1158 raidlist->el[raidlist->entries].progress = atoi(pos); 1159 } 1160 break; 1161 default: // error 1162 log_msg(1, "Row %d should not occur in record!\n", row); 1163 break; 1164 } 1165 row++; 1166 } 1167 } 1168 // close file 1169 fclose(fin); 1170 // free string 1171 paranoid_free(string); 1172 // return success 1173 return 0; 1174 1175 } 1176 1177 1178 1179 1180 int create_raidtab_from_mdstat(char *raidtab_fname) 1181 { 1182 struct raidlist_itself *raidlist; 1183 int retval = 0; 1184 1185 raidlist = malloc(sizeof(struct raidlist_itself)); 1186 1187 // FIXME: Prefix '/dev/' should really be dynamic! 1188 if (parse_mdstat(raidlist, "/dev/")) { 1189 log_to_screen("Sorry, cannot read %s", MDSTAT_FILE); 913 1190 return (1); 914 1191 } 915 mdstat->entries = 0; 916 for (getline(&incoming, &n, fin); !feof(fin); 917 getline(&incoming, &n, fin)) { 918 p = incoming; 919 if (*p != 'm' && *(p + 1) == 'm') { 920 p++; 921 } 922 if (strncmp(p, "md", 2)) { 923 continue; 924 } 925 // read first line --- mdN : active raidX ............ 926 mdstat->el[mdstat->entries].md = atoi(p + 2); 927 log_msg(8, "Storing /dev/md%d's info", atoi(p + 2)); 928 while (*p != ':' && *p) { 929 p++; 930 } 931 while ((*p != 'r' || *(p + 1) != 'a') && *p) { 932 p++; 933 } 934 if (!strncmp(p, "raid", 4)) { 935 mdstat->el[mdstat->entries].raidlevel = *(p + 4) - '0'; 936 } 937 p += 4; 938 while (*p != ' ' && *p) { 939 p++; 940 } 941 while (*p == ' ' && *p) { 942 p++; 943 } 944 for (diskno = 0; *p; diskno++) { 945 asprintf(&stub, "%s", p); 946 q = strchr(stub, '['); 947 if (q) { 948 *q = '\0'; 949 q++; 950 r = strchr(q, ']'); 951 if (r) { 952 *r = '\0'; 953 } 954 mdstat->el[mdstat->entries].disks.el[diskno].index = 955 atoi(q); 956 } else { 957 mdstat->el[mdstat->entries].disks.el[diskno].index = -1; 958 q = strchr(stub, ' '); 959 if (q) { 960 *q = '\0'; 961 } 962 } 963 asprintf(&tmp, "/dev/%s", stub); 964 paranoid_free(stub); 965 966 log_msg(8, "/dev/md%d : disk#%d : %s (%d)", 967 mdstat->el[mdstat->entries].md, diskno, tmp, 968 mdstat->el[mdstat->entries].disks.el[diskno].index); 969 strcpy(mdstat->el[mdstat->entries].disks.el[diskno].device, 970 tmp); 971 paranoid_free(tmp); 972 973 while (*p != ' ' && *p) { 974 p++; 975 } 976 while (*p == ' ' && *p) { 977 p++; 978 } 979 } 980 mdstat->el[mdstat->entries].disks.entries = diskno; 981 // next line --- skip it 982 if (!feof(fin)) { 983 getline(&incoming, &n, fin); 984 } else { 985 continue; 986 } 987 // next line --- the 'progress' line 988 if (!feof(fin)) { 989 getline(&incoming, &n, fin); 990 } else { 991 continue; 992 } 993 // log_msg(1, "Percentage line = '%s'", incoming); 994 if (!(p = strchr(incoming, '\%'))) { 995 mdstat->el[mdstat->entries].progress = 999; // not found 996 } else if (strstr(incoming, "DELAYED")) { 997 mdstat->el[mdstat->entries].progress = -1; // delayed (therefore, stuck at 0%) 998 } else { 999 for (*p = '\0'; *p != ' '; p--); 1000 mdstat->el[mdstat->entries].progress = atoi(p); 1001 } 1002 log_msg(8, "progress =%d", mdstat->el[mdstat->entries].progress); 1003 mdstat->entries++; 1004 } 1005 fclose(fin); 1006 paranoid_free(incoming); 1007 return (0); 1008 } 1009 1010 1011 1012 int create_raidtab_from_mdstat(char *raidtab_fname, char *mdstat_fname) 1013 { 1014 struct raidlist_itself *raidlist; 1015 struct s_mdstat *mdstat; 1016 int retval = 0; 1017 int i; 1018 1019 raidlist = malloc(sizeof(struct raidlist_itself)); 1020 mdstat = malloc(sizeof(struct s_mdstat)); 1021 1022 if (read_mdstat(mdstat, mdstat_fname)) { 1023 log_to_screen("Sorry, cannot read %s", mdstat_fname); 1024 return (1); 1025 } 1026 1027 for (i = 0; i < mdstat->entries; i++) { 1028 sprintf(raidlist->el[i].raid_device, "/dev/md%d", 1029 mdstat->el[i].md); 1030 raidlist->el[i].raid_level = mdstat->el[i].raidlevel; 1031 raidlist->el[i].persistent_superblock = 1; 1032 raidlist->el[i].chunk_size = 4; 1033 memcpy((void *) &raidlist->el[i].data_disks, 1034 (void *) &mdstat->el[i].disks, 1035 sizeof(struct list_of_disks)); 1036 // FIXME --- the above line does not allow for spare disks 1037 log_to_screen 1038 (_("FIXME - create_raidtab_from_mdstat does not allow for spare disks")); 1039 } 1040 raidlist->entries = i; 1192 1041 1193 retval += save_raidlist_to_raidtab(raidlist, raidtab_fname); 1042 1194 return (retval);
Note:
See TracChangeset
for help on using the changeset viewer.