2 Copyright © 1995-2013, 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
) {
68 void clearCache(struct AFSBase
*afsbase
, struct BlockCache
*cache
) {
72 if ((cache
->flags
& BCF_WRITE
) == 0)
79 showText(afsbase
, "You MUST re-insert ejected volume");
85 (struct AFSBase
*afsbase
, struct Volume
*volume
)
87 struct BlockCache
*block
;
89 for (block
= volume
->blockcache
; block
!= NULL
; block
= block
->next
)
91 if ((block
->flags
& (BCF_WRITE
| BCF_USED
)) == BCF_WRITE
)
93 writeDisk(afsbase
, volume
, block
->blocknum
, 1, block
->buffer
);
94 block
->flags
&= ~BCF_WRITE
;
99 struct BlockCache
*getCacheBlock
100 (struct AFSBase
*afsbase
, struct Volume
*volume
, ULONG blocknum
)
102 struct BlockCache
*cache
;
103 struct BlockCache
*bestcache
=NULL
;
106 /* Check if block is already cached, or else reuse least-recently-used buffer */
107 D(bug("[afs] getCacheBlock: getting cacheblock %lu\n",blocknum
));
108 cache
= volume
->blockcache
;
109 while ((cache
!= NULL
) && !found
)
111 if (cache
->blocknum
== blocknum
)
113 if (!(cache
->flags
& BCF_USED
))
115 D(bug("[afs] getCacheBlock: already cached (counter=%lu)\n",
122 if (blocknum
!= volume
->rootblock
)
124 /* should only occur while using setBitmap()
125 ->that's ok (see setBitmap()) */
126 D(bug("Concurrent access on block %lu!\n",blocknum
));
135 else if ((cache
->flags
& (BCF_USED
| BCF_WRITE
)) == 0)
137 if (bestcache
!= NULL
)
139 if (bestcache
->newness
> cache
->newness
)
150 if (bestcache
!= NULL
)
153 bestcache
->blocknum
= 0;
155 /* Mark buffer as the most recently used */
156 bestcache
->newness
= ++volume
->cachecounter
;
158 /* Reset cache history if counter has overflowed */
159 if (volume
->cachecounter
== 0)
161 for (cache
= volume
->blockcache
; cache
!= NULL
; cache
= cache
->next
)
167 /* We should only run out of cache blocks if blocks need to be
168 written, so write them and try again */
169 flushCache(afsbase
, volume
);
170 bestcache
= getCacheBlock(afsbase
, volume
, blocknum
);
171 if (bestcache
== NULL
)
172 showText(afsbase
, "Oh, ohhhhh, where is all the cache gone? BUG!!!");
178 /***************************************************************************
179 Name : getFreeCacheBlock
180 Descr.: Get a cache block to fill. The returned cache block's buffer will
181 have arbitrary contents. However, to ensure cache integrity, an
182 existing cache block for the specified block will be returned if
184 Input : volume - the volume the block is on.
185 blocknum - the block number the cache block will be used for.
186 Output: an unfilled cache block for the specified block.
187 ***************************************************************************/
188 struct BlockCache
*getFreeCacheBlock
189 (struct AFSBase
*afsbase
, struct Volume
*volume
, ULONG blocknum
)
191 struct BlockCache
*cache
;
193 cache
= getCacheBlock(afsbase
, volume
, blocknum
);
194 cache
->blocknum
= blocknum
;
199 void checkCache(struct AFSBase
*afsbase
, struct Volume
*volume
) {
200 struct BlockCache
*bc
;
202 bc
= volume
->blockcache
;
205 if (((bc
->flags
& BCF_USED
) != 0) && (bc
->blocknum
!= volume
->rootblock
))
207 showText(afsbase
, "Unreleased block: %lu!", bc
->blocknum
);
214 void umpBlock(struct AFSBase
*afsbase
, struct BlockCache
*block
) {
217 for (i
=0; i
<=31; i
++) {
218 D(bug("0x%x: ",i
*16));
220 D(bug(" %x", OS_BE2LONG(block
->buffer
[i
*4+j
])));
226 struct BlockCache
*getBlock
227 (struct AFSBase
*afsbase
, struct Volume
*volume
, ULONG blocknum
)
229 struct BlockCache
*blockbuffer
;
231 blockbuffer
= getCacheBlock(afsbase
, volume
, blocknum
);
232 if (blockbuffer
!= NULL
)
234 if (blockbuffer
->blocknum
== 0)
236 blockbuffer
->blocknum
= blocknum
;
237 if (readDisk(afsbase
, volume
, blocknum
, 1, blockbuffer
->buffer
) != 0)
243 D(bug("[afs] getBlock: using cache block with address 0x%p\n", blockbuffer
));
249 struct AFSBase
*afsbase
,
250 struct Volume
*volume
,
251 struct BlockCache
*blockbuffer
,
255 /* Update checksum if requested by caller */
256 if(checksumoffset
!= -1)
258 blockbuffer
->buffer
[checksumoffset
] = 0;
259 blockbuffer
->buffer
[checksumoffset
] =
260 OS_LONG2BE(0 - calcChkSum(volume
->SizeBlock
,blockbuffer
->buffer
));
263 /* Ensure bitmap isn't marked valid while there are dirty blocks in the cache */
264 if (blockbuffer
->blocknum
== volume
->rootblock
)
265 flushCache(afsbase
, volume
);
267 /* Write block to disk */
268 writeDisk(afsbase
, volume
, blockbuffer
->blocknum
, 1, blockbuffer
->buffer
);
269 blockbuffer
->flags
&= ~BCF_WRITE
;
273 VOID writeBlockDeferred
275 struct AFSBase
*afsbase
,
276 struct Volume
*volume
,
277 struct BlockCache
*blockbuffer
,
281 /* Update checksum if requested by caller */
282 if(checksumoffset
!= -1)
284 blockbuffer
->buffer
[checksumoffset
] = 0;
285 blockbuffer
->buffer
[checksumoffset
] =
286 OS_LONG2BE(0 - calcChkSum(volume
->SizeBlock
,blockbuffer
->buffer
));
289 /* Mark block as needing to be written when the time comes */
290 blockbuffer
->flags
|= BCF_WRITE
;