From 319f923c57c640dd35679817924d063e6741b623 Mon Sep 17 00:00:00 2001 From: Ludovic Pouzenc Date: Tue, 22 Feb 2011 14:41:01 +0000 Subject: Fonctions des slices terminées, module recovery qui contient l'algo de récupération terminé aussi. Main minimaliste pour lancer des tests à droite à gauche. Mises au points à coup de valgrind et ddd, ça a l'air presque bien, il reste peut être un bug ou deux dans des cas à la con. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit La fonction slicesFindLargest est coûteuse. On peut imaginer une version qui prends en argument : - le max potentiellement trouvable (permet d'éliminer plein de parcours dans la majorité des cas vue l'utilisation qui est faite des slices dans le recovery. La fonction retournerai le premier slice qui correspond à cette valeur de maximum. - un pointeur vers le slice à partir duquel commencer la recherche, qui serait le pointeur du slice trouvé la précédente fois. Permet dans le cas général de trouver vite. Il faut quand même reprendre la liste au début jusqu'à ce pointeur si on arrive à la fin de la liste sans avoir trouvé. git-svn-id: file:///var/svn/2011-ddhardrescue/trunk@3 d3078510-dda0-49f1-841c-895ef4b7ec81 --- src/recover.c | 95 +++++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 76 insertions(+), 19 deletions(-) (limited to 'src/recover.c') diff --git a/src/recover.c b/src/recover.c index c2c2eff..0f305a1 100755 --- a/src/recover.c +++ b/src/recover.c @@ -1,7 +1,10 @@ #include +#include #include "recover.h" -slices_t *recover(char *src, char *dst, char*ddOpts, address_t beginSector, address_t endSector, int depth) { +extern unsigned long c; + +slices_t *recover(char *src, char *dst, char*ddOpts, address_t beginSector, address_t endSector/*, int depth*/) { slices_t *slices; slice_t *sliceToRead; address_t firstError=0, median; @@ -16,17 +19,21 @@ slices_t *recover(char *src, char *dst, char*ddOpts, address_t beginSector, addr slicesAppend(slices, sliceToRead); // Main loop - while (!end && slices->count < (endSector-beginSector)/depth) { + while (!end) { // && slices->count < (endSector-beginSector)/depth) { // try to recover sliceToRead and split it if read error - switch ( tryRecoverUntilError(sliceToRead, &firstError) ) { + switch ( tryRecoverUntilError(sliceToRead, &firstError, src, dst, ddOpts) ) { case 0: // slice recovery has been executed without read error sliceToRead->status=S_RECOVERED; break; case EIO: - // slice recovery has encuontered a readerror - res=sliceSplit(sliceToRead, firstError, S_RECOVERED, S_UNREADABLE, S_UNKNOWN); - if (res!=0) { exit(5); } //TODO + // slice recovery has encountered a readerror + res=sliceSplit(slices, sliceToRead, firstError, S_RECOVERED, S_UNREADABLE, S_UNKNOWN); + if (res<1) { + //TODO + printf("sliceSplit return %d\n", res); + exit(5); + } break; default: exit(2); //TODO @@ -35,34 +42,84 @@ slices_t *recover(char *src, char *dst, char*ddOpts, address_t beginSector, addr /* Now, search the largest S_UNKNOWN zone split it in two parts */ sliceToRead=slicesFindLargest(slices, S_UNKNOWN); - if ( sliceToRead == NULL ) { exit(3); } //TODO + if ( sliceToRead == NULL ) { + // There is nothing more to recover, bailout + end=1; + continue; + } + median=(sliceToRead->begin+sliceToRead->end)/2; - res=sliceSplit(sliceToRead, median, S_UNKNOWN, S_UNKNOWN, S_UNKNOWN); - if (res!=0) { exit(4); } //TODO - - /* After splitting an S_UNKNOWN zone in two parts - take the second for further analysis. - We already now that this first one is just preceded by - a read error, and errors are frequently grouped in zones, - so trying to read a sector just after a faulty sector is - most likely a waste of time. - */ - sliceToRead=sliceToRead->next; + res=sliceSplit(slices, sliceToRead, median, S_UNKNOWN, S_UNKNOWN, S_UNKNOWN); + switch (res) { + case 1: + // No split, try analyse this zone + // Should be a slice of length 1 + break; + case 2: + /* After splitting an S_UNKNOWN zone in two parts + take the second for further analysis. + We already now that this first one is just preceded by + a read error, and errors are frequently grouped in zones, + so trying to read a sector just after a faulty sector is + most likely a waste of time. + */ + sliceToRead=sliceToRead->next; + break; + case 3: + // Internal error of sliceSlpit because this set of parameters prevent split by 3 + exit(5); // TODO + break; + case -1: + // Memory error + exit(4); //TODO + break; + default: + // API error, all necessary cases are already listed + exit(6); // TODO + } } return slices; } -int tryRecoverUntilError(slice_t *sliceToRead, address_t *firstError) { +int tryRecoverUntilError(slice_t *sliceToRead, address_t *firstError, char *src, char *dst, char*ddOpts) { //TODO : implement realy that + char ddinvocation[256]; int res; + address_t seek, count; + + c++; //XXX This is a debug counter + seek=sliceToRead->begin; + count=sliceToRead->end - seek + 1; + res=snprintf(ddinvocation, 255, "dd %s %s %s seek=%ld skip=%ld count=%ld", src, dst, ddOpts, seek, seek, count); + puts(ddinvocation); + + // Simulate that we have systematically a read error at first sector + *firstError=sliceToRead->begin; + res=EIO; + +/* + // Simulate for each read, tha we have an error just in the middle if read for mor than one sector if ( sliceToRead->begin == sliceToRead->end ) { res=0; } else { *firstError=(sliceToRead->begin + sliceToRead->end)/2; res=EIO; } +*/ + +/* + // Simulate for each read a pseudo random error position and generate some cases of full read without error + int error=sliceToRead->begin + rand()%count; + if ( error % 42 == 0 ) { + res=0; + } else { + res=EIO; + *firstError=error; + } +*/ + return res; } -- cgit v1.2.3