1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
|
#include <errno.h>
#include "recover.h"
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;
int res;
// Initialization : we want to try to recover the beginning of the whole zone
slices=slicesNew();
sliceToRead=sliceNew(beginSector, endSector, S_UNKNOWN, NULL);
if (sliceToRead==NULL) {
exit(1);//TODO
}
slicesAppend(slices, sliceToRead);
// Main loop
while (!end && slices->count < (endSector-beginSector)/depth) {
// try to recover sliceToRead and split it if read error
switch ( tryRecoverUntilError(sliceToRead, &firstError) ) {
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
break;
default:
exit(2); //TODO
}
/* Now, search the largest S_UNKNOWN zone
split it in two parts */
sliceToRead=slicesFindLargest(slices, S_UNKNOWN);
if ( sliceToRead == NULL ) { exit(3); } //TODO
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;
}
return slices;
}
int tryRecoverUntilError(slice_t *sliceToRead, address_t *firstError) {
//TODO : implement realy that
int res;
if ( sliceToRead->begin == sliceToRead->end ) {
res=0;
} else {
*firstError=(sliceToRead->begin + sliceToRead->end)/2;
res=EIO;
}
return res;
}
|