2 Copyright © 1995-2005, The AROS Development Team. All rights reserved.
9 #include <aros/debug.h>
14 #include "checksums.h"
16 #include "afsblocks.h"
17 #include "baseredef.h"
19 /********************************************************
21 Descr.: initializes block cache for a volume
22 Input : volume - the volume to initializes cache for
23 numBuffers - number of buffers for cache
24 Output: first buffer (main cache pointer)
25 *********************************************************/
26 struct BlockCache
*initCache
28 struct AFSBase
*afsbase
,
29 struct Volume
*volume
,
33 struct BlockCache
*head
;
34 struct BlockCache
*cache
;
39 numBuffers
*(sizeof(struct BlockCache
)+BLOCK_SIZE(volume
)),
40 MEMF_PUBLIC
| MEMF_CLEAR
45 for (i
=0; i
<(numBuffers
-1); i
++)
47 cache
->buffer
= (ULONG
*)((char *)cache
+sizeof(struct BlockCache
));
49 (struct BlockCache
*)((char *)cache
->buffer
+BLOCK_SIZE(volume
));
52 cache
->buffer
= (ULONG
*)((char *)cache
+sizeof(struct BlockCache
));
57 "initCache: my Mem is 0x%p size 0x%lx\n",
59 numBuffers
*(sizeof(struct BlockCache
)+BLOCK_SIZE(volume
))
64 void freeCache(struct AFSBase
*afsbase
, struct BlockCache
*cache
) {
69 void clearCache(struct AFSBase
*afsbase
, struct BlockCache
*cache
) {
73 if ((cache
->flags
& BCF_WRITE
) == 0)
80 showText(afsbase
, "You MUST re-insert ejected volume");
86 (struct AFSBase
*afsbase
, struct Volume
*volume
)
88 struct BlockCache
*block
;
90 for (block
= volume
->blockcache
; block
!= NULL
; block
= block
->next
)
92 if ((block
->flags
& (BCF_WRITE
| BCF_USED
)) == BCF_WRITE
)
94 writeDisk(afsbase
, volume
, block
->blocknum
, 1, block
->buffer
);
95 block
->flags
&= ~BCF_WRITE
;
100 struct BlockCache
*getCacheBlock
101 (struct AFSBase
*afsbase
, struct Volume
*volume
, ULONG blocknum
)
103 struct BlockCache
*cache
;
104 struct BlockCache
*bestcache
=NULL
;
107 /* Check if block is already cached, or else reuse least-recently-used buffer */
108 D(bug("[afs] getCacheBlock: getting cacheblock %lu\n",blocknum
));
109 cache
= volume
->blockcache
;
110 while ((cache
!= NULL
) && !found
)
112 if (cache
->blocknum
== blocknum
)
114 if (!(cache
->flags
& BCF_USED
))
116 D(bug("[afs] getCacheBlock: already cached (counter=%lu)\n",
123 if (blocknum
!= volume
->rootblock
)
125 /* should only occur while using setBitmap()
126 ->that's ok (see setBitmap()) */
127 D(bug("Concurrent access on block %lu!\n",blocknum
));
136 else if ((cache
->flags
& (BCF_USED
| BCF_WRITE
)) == 0)
138 if (bestcache
!= NULL
)
140 if (bestcache
->newness
> cache
->newness
)
151 if (bestcache
!= NULL
)
154 bestcache
->blocknum
= 0;
156 /* Mark buffer as the most recently used */
157 bestcache
->newness
= ++volume
->cachecounter
;
159 /* Reset cache history if counter has overflowed */
160 if (volume
->cachecounter
== 0)
162 for (cache
= volume
->blockcache
; cache
!= NULL
; cache
= cache
->next
)
168 /* We should only run out of cache blocks if blocks need to be
169 written, so write them and try again */
170 flushCache(afsbase
, volume
);
171 bestcache
= getCacheBlock(afsbase
, volume
, blocknum
);
172 if (bestcache
== NULL
)
173 showText(afsbase
, "Oh, ohhhhh, where is all the cache gone? BUG!!!");
179 /***************************************************************************
180 Name : getFreeCacheBlock
181 Descr.: Get a cache block to fill. The returned cache block's buffer will
182 have arbitrary contents. However, to ensure cache integrity, an
183 existing cache block for the specified block will be returned if
185 Input : volume - the volume the block is on.
186 blocknum - the block number the cache block will be used for.
187 Output: an unfilled cache block for the specified block.
188 ***************************************************************************/
189 struct BlockCache
*getFreeCacheBlock
190 (struct AFSBase
*afsbase
, struct Volume
*volume
, ULONG blocknum
)
192 struct BlockCache
*cache
;
194 cache
= getCacheBlock(afsbase
, volume
, blocknum
);
195 cache
->blocknum
= blocknum
;
200 void checkCache(struct AFSBase
*afsbase
, struct Volume
*volume
) {
201 struct BlockCache
*bc
;
203 bc
= volume
->blockcache
;
206 if (((bc
->flags
& BCF_USED
) != 0) && (bc
->blocknum
!= volume
->rootblock
))
208 showText(afsbase
, "Unreleased block: %lu!", bc
->blocknum
);
215 void umpBlock(struct AFSBase
*afsbase
, struct BlockCache
*block
) {
218 for (i
=0; i
<=31; i
++) {
219 D(bug("0x%x: ",i
*16));
221 D(bug(" %x", OS_BE2LONG(block
->buffer
[i
*4+j
])));
227 struct BlockCache
*getBlock
228 (struct AFSBase
*afsbase
, struct Volume
*volume
, ULONG blocknum
)
230 struct BlockCache
*blockbuffer
;
232 blockbuffer
= getCacheBlock(afsbase
, volume
, blocknum
);
233 if (blockbuffer
!= NULL
)
235 if (blockbuffer
->blocknum
== 0)
237 blockbuffer
->blocknum
= blocknum
;
238 if (readDisk(afsbase
, volume
, blocknum
, 1, blockbuffer
->buffer
) != 0)
244 D(bug("[afs] getBlock: using cache block with address 0x%p\n", blockbuffer
));
250 struct AFSBase
*afsbase
,
251 struct Volume
*volume
,
252 struct BlockCache
*blockbuffer
,
256 /* Update checksum if requested by caller */
257 if(checksumoffset
!= -1)
259 blockbuffer
->buffer
[checksumoffset
] = 0;
260 blockbuffer
->buffer
[checksumoffset
] =
261 OS_LONG2BE(0 - calcChkSum(volume
->SizeBlock
,blockbuffer
->buffer
));
264 /* Ensure bitmap isn't marked valid while there are dirty blocks in the cache */
265 if (blockbuffer
->blocknum
== volume
->rootblock
)
266 flushCache(afsbase
, volume
);
268 /* Write block to disk */
269 writeDisk(afsbase
, volume
, blockbuffer
->blocknum
, 1, blockbuffer
->buffer
);
270 blockbuffer
->flags
&= ~BCF_WRITE
;
274 VOID writeBlockDeferred
276 struct AFSBase
*afsbase
,
277 struct Volume
*volume
,
278 struct BlockCache
*blockbuffer
,
282 /* Update checksum if requested by caller */
283 if(checksumoffset
!= -1)
285 blockbuffer
->buffer
[checksumoffset
] = 0;
286 blockbuffer
->buffer
[checksumoffset
] =
287 OS_LONG2BE(0 - calcChkSum(volume
->SizeBlock
,blockbuffer
->buffer
));
290 /* Mark block as needing to be written when the time comes */
291 blockbuffer
->flags
|= BCF_WRITE
;