2 Copyright © 1995-2005, The AROS Development Team. All rights reserved.
13 #include "checksums.h"
15 #include "afsblocks.h"
16 #include "baseredef.h"
18 /**********************************************
19 Name : countUsedBlocksInBitmap
20 Descr.: count used blocks in a bitmap block
22 block - bitmap block to count in
23 maxcount- max blocks marked in a bitmap block
24 Output: nr of used blocks
25 ***********************************************/
26 ULONG countUsedBlocksInBitmap
28 struct AFSBase
*afsbase
,
29 struct Volume
*volume
,
35 ULONG count
=0,lg
,bits
;
36 struct BlockCache
*blockbuffer
;
38 if ((blockbuffer
=getBlock(afsbase
, volume
,block
))==0)
40 showText(afsbase
, "Couldn't read bitmap block %lu\nCount used blocks failed!",block
);
43 if (!calcChkSum(volume
->SizeBlock
, blockbuffer
->buffer
))
47 lg
=OS_BE2LONG(blockbuffer
->buffer
[i
]);
52 else if (lg
!=0xFFFFFFFF)
65 /* are there some bits left ? */
68 lg
=OS_BE2LONG(blockbuffer
->buffer
[i
]);
73 else if (lg
!=0xFFFFFFFF)
76 for (;maxcount
;maxcount
--)
86 showError(afsbase
, ERR_CHECKSUM
,block
);
90 /**************************************
91 Name : countUsedBlocks
92 Descr.: count used blocks of a volume
94 Output: nr of used blocks of the volume
95 ***************************************/
96 ULONG
countUsedBlocks(struct AFSBase
*afsbase
, struct Volume
*volume
) {
102 struct BlockCache
*blockbuffer
;
104 blocks
=volume
->countblocks
-volume
->bootblocks
; /* blocks to count */
105 maxinbitmap
= (volume
->SizeBlock
-1)*32; /* max blocks marked in a bitmapblock */
106 /* check bitmap blocks stored in rootblock */
109 if (maxinbitmap
>blocks
)
110 maxinbitmap
= blocks
;
111 if (volume
->bitmapblockpointers
[i
])
114 countUsedBlocksInBitmap
115 (afsbase
, volume
, volume
->bitmapblockpointers
[i
], maxinbitmap
);
116 blocks
-= maxinbitmap
;
121 /* check extension blocks if neccessary */
124 curblock
= volume
->bitmapextensionblock
;
125 while (curblock
!= 0)
128 blockbuffer
= getBlock(afsbase
, volume
, curblock
);
129 if (blockbuffer
== NULL
)
134 "Couldn't read bitmap extension block %lu\nCount used blocks failed!",
139 blockbuffer
->flags
|= BCF_USED
;
140 for (i
=0;i
<volume
->SizeBlock
-1;i
++)
142 if (maxinbitmap
> blocks
)
143 maxinbitmap
= blocks
;
144 if (blockbuffer
->buffer
[i
] != 0)
147 countUsedBlocksInBitmap
151 OS_BE2LONG(blockbuffer
->buffer
[i
]),
154 blocks
-= maxinbitmap
;
159 blockbuffer
->flags
&= ~BCF_USED
;
162 curblock
= OS_BE2LONG(blockbuffer
->buffer
[volume
->SizeBlock
-1]);
165 showError(afsbase
, ERR_MISSING_BITMAP_BLOCKS
);
170 ULONG
createNewBitmapBlocks(struct AFSBase
*afsbase
, struct Volume
*volume
) {
171 struct BlockCache
*bitmapblock
,*extensionblock
;
172 ULONG i
, blocks
, maxinbitmap
;
174 /* initialize a block as a bitmap block */
175 extensionblock
= getFreeCacheBlock(afsbase
, volume
, -1);
176 extensionblock
->flags
|= BCF_USED
;
177 bitmapblock
= getFreeCacheBlock(afsbase
, volume
, volume
->rootblock
+1);
178 /* all blocks are free */
179 for (i
=1;i
<volume
->SizeBlock
;i
++)
180 bitmapblock
->buffer
[i
] = 0xFFFFFFFF;
181 bitmapblock
->buffer
[0] = 0;
182 bitmapblock
->buffer
[0] = OS_LONG2BE(0-calcChkSum(volume
->SizeBlock
,bitmapblock
->buffer
));
183 /* get nr of blocks to mark in bitmap blocks */
184 blocks
= volume
->countblocks
- volume
->bootblocks
;
185 /* calc max blocks that can be marked in a single bitmap block */
186 maxinbitmap
= (volume
->SizeBlock
-1)*32;
187 /* first create bitmapblocks stored in rootblock */
190 if (maxinbitmap
> blocks
)
191 maxinbitmap
= blocks
;
192 volume
->bitmapblockpointers
[i
] = bitmapblock
->blocknum
;
193 writeBlock(afsbase
, volume
, bitmapblock
, -1);
194 bitmapblock
->blocknum
+= 1;
195 blocks
= blocks
- maxinbitmap
;
200 volume
->bitmapblockpointers
[i
++] = 0;
203 /* check extension blocks if necessary */
206 volume
->bitmapextensionblock
=bitmapblock
->blocknum
;
209 /* initialize extensionblock with zeros */
210 extensionblock
->blocknum
= bitmapblock
->blocknum
;
211 for (i
=0;i
<volume
->SizeBlock
;i
++)
212 extensionblock
->buffer
[i
] = 0;
213 /* fill extensionblock and write bitmapblocks */
214 for (i
=0;i
<volume
->SizeBlock
-1;i
++)
216 if (maxinbitmap
> blocks
)
217 maxinbitmap
= blocks
;
218 bitmapblock
->blocknum
+= 1;
219 extensionblock
->buffer
[i
] = OS_LONG2BE(bitmapblock
->blocknum
);
220 writeBlock(afsbase
, volume
, bitmapblock
, -1);
221 blocks
= blocks
-maxinbitmap
;
225 if (blocks
!= 0) /*write another extensionblock ? */
227 /* fill next extension */
228 extensionblock
->buffer
[volume
->SizeBlock
-1]=OS_LONG2BE(bitmapblock
->blocknum
+1);
230 writeBlock(afsbase
, volume
, extensionblock
, -1);
231 bitmapblock
->blocknum
+= 1;
232 } while (blocks
!= 0);
235 volume
->bitmapextensionblock
= 0;
236 extensionblock
->flags
&= ~BCF_USED
;
240 LONG
setBitmapFlag(struct AFSBase
*afsbase
, struct Volume
*volume
, LONG flag
) {
241 struct BlockCache
*blockbuffer
;
243 D(bug("[afs] setBitmapFlag()\n"));
244 blockbuffer
= getBlock(afsbase
, volume
, volume
->rootblock
);
245 if (blockbuffer
== NULL
)
247 blockbuffer
->buffer
[BLK_BITMAP_VALID_FLAG(volume
)] = flag
;
248 if ((blockbuffer
->flags
& BCF_WRITE
) == 0)
250 writeBlock(afsbase
, volume
, blockbuffer
, BLK_CHECKSUM
);
251 blockbuffer
->flags
|= BCF_WRITE
;
254 writeBlockDeferred(afsbase
, volume
, blockbuffer
, BLK_CHECKSUM
);
258 LONG
invalidBitmap(struct AFSBase
*afsbase
, struct Volume
*volume
) {
260 volume
->lastextensionblock
= 0;
261 volume
->lastposition
= 0;
262 volume
->bstartblock
= volume
->bootblocks
; /* reserved */
263 volume
->bitmapblock
= getBlock(afsbase
, volume
, volume
->bitmapblockpointers
[volume
->lastposition
]);
264 if (volume
->bitmapblock
!= NULL
)
266 volume
->bitmapblock
->flags
|= BCF_USED
;
267 if (setBitmapFlag(afsbase
, volume
, 0))
271 volume
->bitmapblock
->flags
&= ~BCF_USED
;
276 LONG
validBitmap(struct AFSBase
*afsbase
, struct Volume
*volume
) {
278 if (volume
->bitmapblock
->flags
& BCF_WRITE
)
280 writeBlockDeferred(afsbase
, volume
, volume
->bitmapblock
, 0);
282 volume
->bitmapblock
->flags
&= ~BCF_USED
;
283 setBitmapFlag(afsbase
, volume
, -1);
287 /*************************************************
288 Name : gotoBitmapBlock
289 Descr.: go to the bitmap block where a block is marked
290 Input : volume - which volume
291 block - the block we want to get infos about
292 longnr - returns the n-th long block is associated to
293 bitnr - returns the bitnr block is associated to
294 Note : bitmapblock is changed (should be initialized first!)
295 **************************************************/
298 struct AFSBase
*afsbase
,
299 struct Volume
*volume
,
305 struct BlockCache
*extensionblock
;
306 ULONG bblock
,togo
,maxinbitmap
;
308 block
-= volume
->bootblocks
; /* reserved blocks are not marked */
309 maxinbitmap
= (volume
->SizeBlock
-1)*32; /* max blocks marked in a bitmapblock */
310 *bitnr
= block
% maxinbitmap
; /* in the bblock-th block we have to mark the bit-th bit */
311 *longnr
= *bitnr
/32+1; /* int the longnr-th LONG is "block" marked (+1 because [0]=BLK_CHECKSUM) */
312 *bitnr
= *bitnr
% 32; /* in the bit-th bit of LONG "longnr" "block" is marked */
313 /* load new block ? */
315 (block
<volume
->bstartblock
) ||
316 (block
>=(volume
->bstartblock
+maxinbitmap
))
319 bblock
= block
/maxinbitmap
; /* in the bblock-th bitmap block is "block" marked */
320 if (volume
->bitmapblock
->flags
& BCF_WRITE
)
322 writeBlockDeferred(afsbase
, volume
, volume
->bitmapblock
, 0);
324 volume
->bitmapblock
->flags
&= ~BCF_USED
;
328 volume
->bitmapblock
= getBlock(afsbase
, volume
, volume
->bitmapblockpointers
[bblock
]);
332 volume
->lastextensionblock
= volume
->bitmapextensionblock
;
333 //kprintf("get block from extension %lu\n", volume->lastextensionblock);
334 /* 25 entries in rootblock already processed */
335 volume
->lastposition
= bblock
-25;
336 /* do we have to go to another extensionblock ? */
337 togo
= volume
->lastposition
/ (volume
->SizeBlock
-1);
338 //kprintf("togo=%lu\n", togo);
339 volume
->lastposition
%= volume
->SizeBlock
-1;
340 //kprintf("lp=%lu\n", volume->lastposition);
341 extensionblock
=getBlock(afsbase
, volume
, volume
->lastextensionblock
);
342 if (extensionblock
== NULL
)
344 showText(afsbase
, "Could not read bitmap extionsion block %lu!", volume
->lastextensionblock
);
347 //if (volume->lastposition == 5)
349 // kprintf("00: %08lx %08lx %08lx %08lx\n", extensionblock->buffer[0], extensionblock->buffer[1], extensionblock->buffer[2], extensionblock->buffer[3]);
350 // kprintf("10: %08lx %08lx %08lx %08lx\n", extensionblock->buffer[4], extensionblock->buffer[5], extensionblock->buffer[6], extensionblock->buffer[7]);
359 OS_BE2LONG(extensionblock
->buffer
[volume
->SizeBlock
-1])
361 if (extensionblock
== NULL
)
363 showText(afsbase
, "Could not read bitmap extension block %lu!", OS_BE2LONG(extensionblock
->buffer
[volume
->SizeBlock
-1]));
366 volume
->lastextensionblock
= extensionblock
->blocknum
;
369 volume
->bitmapblock
=
374 OS_BE2LONG(extensionblock
->buffer
[volume
->lastposition
])
377 volume
->bstartblock
= bblock
*maxinbitmap
;
378 if (volume
->bitmapblock
== NULL
)
380 showText(afsbase
, "Could not read bitmap block!");
383 volume
->bitmapblock
->flags
|= BCF_USED
;
388 LONG
markBlock(struct AFSBase
*afsbase
, struct Volume
*volume
, ULONG block
, ULONG mode
) {
389 ULONG bitnr
, longnr
,null
=0;
391 D(bug("[afs] markBlock: block=%lu mode=%lu\n",block
,mode
));
392 if (block
>=volume
->countblocks
)
394 if (!gotoBitmapBlock(afsbase
, volume
, block
, &longnr
, &bitnr
))
399 volume
->bitmapblock
->buffer
[longnr
] =
400 OS_LONG2BE(OS_BE2LONG(volume
->bitmapblock
->buffer
[longnr
]) | (1 << bitnr
));
401 volume
->usedblockscount
-= 1;
404 (volume
->lastaccess
<volume
->rootblock
) && (block
>=volume
->rootblock
)
408 ((volume
->lastaccess
>=volume
->rootblock
) && (block
>=volume
->rootblock
)) || // 2.case and ...
409 ((volume
->lastaccess
<volume
->rootblock
) && (block
<volume
->rootblock
)) // 3.case with ...
411 (block
<volume
->lastaccess
)
415 volume
->lastaccess
= block
;
420 volume
->bitmapblock
->buffer
[longnr
] =
421 OS_LONG2BE(OS_BE2LONG(volume
->bitmapblock
->buffer
[longnr
]) & ~(1 << bitnr
));
422 volume
->usedblockscount
+= 1;
423 volume
->lastaccess
= block
; /* all blocks before "block" are used! */
425 volume
->bitmapblock
->flags
|= BCF_WRITE
;
431 struct AFSBase
*afsbase
,
432 struct Volume
*volume
,
438 ULONG maxinbitmap
,maxblocks
;
441 maxinbitmap
= (volume
->SizeBlock
-1)*32; /* max blocks marked in a bitmapblock */
442 maxblocks
= maxinbitmap
-((longnr
-1)*32); /* blocks left to check */
443 if (maxblocks
> togo
)
448 while (maxblocks
>=32)
450 /* do we have a free block ?
451 if yes search within this long which block */
452 lg
= OS_BE2LONG(volume
->bitmapblock
->buffer
[longnr
]);
471 lg
= OS_BE2LONG(volume
->bitmapblock
->buffer
[longnr
]);
473 for (;maxblocks
;maxblocks
--)
483 if (!gotoBitmapBlock(afsbase
, volume
,block
,&longnr
,&trash
))
485 if ((longnr
!=1) || (trash
!=0))
486 showText(afsbase
, "Wrong bitmapblockjump!");
487 maxblocks
= togo
<maxinbitmap
? togo
: maxinbitmap
;
488 longnr
= 1; // skip checksum
493 ULONG
getFreeBlock(struct AFSBase
*afsbase
, struct Volume
*volume
) {
494 ULONG block
,longnr
,bitnr
,lg
,maxbitcount
;
496 D(bug("[afshandler] %s: enter\n", __FUNCTION__
));
497 /* check all blocks after rootblock */
498 block
= volume
->lastaccess
;
500 got exact position of last accessed block
501 this will update volume->bitmapblock and return
502 the long number and bit number that block is
504 if (!gotoBitmapBlock(afsbase
, volume
, block
, &longnr
, &bitnr
))
508 maxbitcount
= volume
->countblocks
-block
;
509 if (maxbitcount
!= 0)
511 maxbitcount
= ((32-bitnr
)<maxbitcount
) ? 32 : bitnr
+maxbitcount
;
512 lg
= OS_BE2LONG(volume
->bitmapblock
->buffer
[longnr
]);
513 for (;bitnr
<maxbitcount
;bitnr
++)
521 if (block
>=volume
->countblocks
)
522 block
= volume
->bootblocks
;
524 if (block
>=volume
->rootblock
)
531 volume
->countblocks
-block
-1,
537 block
= volume
->bootblocks
;
539 if (!gotoBitmapBlock(afsbase
, volume
, block
, &longnr
, &bitnr
))
541 block
= findFreeBlock(afsbase
, volume
, volume
->rootblock
-block
,longnr
, block
);
545 ULONG
allocBlock(struct AFSBase
*afsbase
, struct Volume
*volume
) {
548 block
= getFreeBlock(afsbase
, volume
);
551 D(bug("[afs] allocBlock: found a free block on %lu\n", block
));
552 if (!markBlock(afsbase
, volume
,block
,0))