3 #include "fsck_helper.h"
5 static bool check_cluster(uint32_t pcn
, uint32_t cn
, uint32_t inodeidx
)
14 fetch_superblock(&sb
);
18 if (pcn
!= NULL_BLOCK
) {
22 if ((pcn
-(sb
->dzone_start
))%(BLOCKS_PER_CLUSTER
)) {
23 printf("Cluster number %d of inode number %d points to "
24 "unaligned block.\n", cn
, inodeidx
);
28 /* overflow is irrelevant here */
29 /* check if cluster address is in bounds */
30 cidx
= (pcn
-(sb
->dzone_start
))/(BLOCKS_PER_CLUSTER
);
31 if (cidx
>= sb
->dzone_size
) {
32 printf("Cluster number %d of inode number %d points to a place "
33 "outside data zone.\n", cn
, inodeidx
);
38 soReadRawBlock(sb
->ciutable_start
+(cidx
/RPB
), ciurefs
);
39 if (ciurefs
[cidx
%RPB
] != inodeidx
) {
40 printf("Entry in CIUT for cluster number %d points to inode "
41 "%d, bot it is used by inode %d.\n", cidx
,
42 ciurefs
[cidx
%RPB
], inodeidx
);
47 cctable_get(cidx
, &ccstat
);
50 cctable_set(cidx
, busy
);
53 printf("Cluster number %d is used by inode %d but is also "
54 "a free cluster.\n", cidx
, inodeidx
);
58 printf("Cluster %d is used several times by inode %d.\n",
63 printf("BUM! parse_clusters: cctable is corrupt.\n");
71 bool parse_clusters(uint32_t inodeidx
)
83 fetch_superblock(&sb
);
86 fret
= soReadInode(&inode
, inodeidx
);
87 if (fret
< 0) FABORT(fret
, "parse_cluster");
89 /* check data clusters */
90 cnmax
= (inode
.size
+ CLUSTER_SIZE
- 1)/CLUSTER_SIZE
;
91 for (i1
= 0; i1
< cnmax
; i1
++) {
92 fret
= soHandleFileCluster(inodeidx
, i1
, OP_GET
, &pcn
);
93 if (fret
< 0) FABORT(fret
, "parse_cluster");
95 if (check_cluster(pcn
, i1
, inodeidx
) == false) {
100 /* check reference clusters */
102 if (cnmax
> N_DIRECT
) {
103 if (check_cluster(inode
.i1
, -1, inodeidx
) == false) {
106 fret
= soReadCacheCluster(inode
.i1
, irefs
);
107 if (fret
< 0) FABORT(fret
, "parse_cluster");
108 for (i1
= 0; (i1
< cnmax
-N_DIRECT
) && (i1
< RPC
); ++i1
) {
109 if (check_cluster(irefs
[i1
], -1, inodeidx
) == false) {
115 if (cnmax
> (N_DIRECT
+ RPC
)) {
116 if (check_cluster(inode
.i2
, -1, inodeidx
) == false) {
119 fret
= soReadCacheCluster(inode
.i2
, iirefs
);
120 if (fret
< 0) FABORT(fret
, "parse_cluster");
121 for (i2
= 0; (i2
< RPC
) && (i2
*RPC
< cnmax
-N_DIRECT
-RPC
); ++i2
) {
122 if (check_cluster(iirefs
[i2
], -1, inodeidx
) == false) {
125 fret
= soReadCacheCluster(iirefs
[i2
], irefs
);
126 if (fret
< 0) FABORT(fret
, "parse_cluster");
127 for (i1
= 0; (i1
< RPC
) && (i2
*RPC
+i1
< cnmax
-N_DIRECT
-RPC
); ++i1
) {
128 if (check_cluster(irefs
[i1
], -1, inodeidx
) == false) {
139 /* assumes inodes are sane */
140 testresult_t
test_clusterused(void)
148 fetch_superblock(&sb
);
151 for (r
= 0; (r
< sb
->itotal
) && (ret
!= corrupt
); ++r
) {
152 ictable_get(r
, &icstat
);
153 soReadInode(&inode
, r
);
156 if ((inode
.mode
& INODE_TYPE_MASK
& (!INODE_FREE
)) != 0) {
157 /* inode is dirty - check */
158 if (parse_clusters(r
) == false) ret
= corrupt
;
162 if (parse_clusters(r
) == false) ret
= corrupt
;
165 printf("BUM! test_clusterused assumes inode control has "
166 "only idle and busy in it by now.\n");