diff options
Diffstat (limited to 'src/recover.c')
-rwxr-xr-x | src/recover.c | 95 |
1 files changed, 76 insertions, 19 deletions
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 <errno.h> +#include <stdio.h> #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; } |