3 * Revision 13.9 1998/09/27 11:26:37 Michiel
7 * Revision 13.8 1998/09/03 07:12:14 Michiel
9 * bugfixes 118, 121, 123 and superindexblocks and td64 support
11 * Revision 13.7 1997/03/03 22:04:04 Michiel
14 * Revision 13.6 1996/03/07 10:10:14 Michiel
16 * realloc anodebitmap bug (wt)
18 * Revision 13.5 1996/01/30 12:50:15 Michiel
19 * --- working tree overlap ---
20 * anodebitmap implemented
22 * Revision 13.4 1995/11/07 14:50:07 Michiel
23 * NewAnodeBlock: lock clear after use
24 * GetAnodeBlock: no lock on indexblock
26 * Revision 13.3 1995/10/20 10:10:58 Michiel
27 * Anode reserved area adaptions (16.3)
28 * --> AllocAnode changed
30 * Revision 13.2 1995/10/04 09:00:30 Michiel
31 * Bug in CorrectAnodeAC (instruction order) fixed
33 * Revision 13.1 1995/10/03 10:48:07 Michiel
34 * merged develop tree: anodecache
36 * Revision 12.9 1995/07/11 17:29:31 Michiel
37 * ErrorMsg () calls use messages.c variables now.
39 * Revision 12.8 1995/06/19 09:48:44 Michiel
40 * small optimise and a couple of debug statements in GetAnodeBlock
42 * Revision 12.7 1995/06/04 06:06:38 Michiel
43 * assembly divide function used
45 * Revision 12.6 1995/02/28 18:30:49 Michiel
46 * Splitted mode and UWORD optimize
48 * Revision 12.5 1995/02/15 16:43:39 Michiel
50 * Using new headers (struct.h & blocks.h)
52 * Revision 12.4 1995/01/29 07:34:57 Michiel
53 * Reserved Raw read/write and locking change
55 * Revision 12.3 1995/01/24 09:52:21 Michiel
58 * Revision 12.2 1995/01/18 04:29:34 Michiel
59 * Bugfixes. Now ready for beta release.
61 * Revision 12.1 1995/01/08 15:41:09 Michiel
64 * Revision 11.2 1994/12/30 11:21:40 Michiel
68 * Revision 11.1 1994/12/01 11:31:25 Michiel
70 * Uses new anodes.h include.
72 * Revision 10.2 1994/10/27 11:33:30 Michiel
73 * Added some MakeBlockDirty() calls in anode routines
75 * Revision 10.1 1994/10/24 11:16:28 Michiel
79 /* 9-10-94 Added usage of g->curranblk.
85 #include <exec/types.h>
86 #include <exec/memory.h>
93 #include "anodes_protos.h"
94 #include "allocation_protos.h"
95 #include "disk_protos.h"
96 #include "lru_protos.h"
97 #include "update_protos.h"
98 #include "ass_protos.h"
99 #include "volume_protos.h"
102 * Contents (local functions)
104 static struct anodechain
*MakeAnodeChain (ULONG anodenr
, globaldata
*g
);
105 static struct anodechain
*FindAnodeChain (ULONG anodenr
, globaldata
*g
);
106 static void FreeAnodeChain (struct anodechain
*chain
, globaldata
*g
);
107 static struct canodeblock
*big_GetAnodeBlock(UWORD seqnr
, globaldata
*g
);
108 static struct canodeblock
*big_NewAnodeBlock(UWORD
, globaldata
* );
109 static struct cindexblock
*NewIndexBlock(UWORD
, globaldata
* );
110 static struct cindexblock
*NewSuperBlock (UWORD seqnr
, globaldata
*g
);
111 static void MakeAnodeBitmap (BOOL formatting
, globaldata
*g
);
112 static void ReallocAnodeBitmap (ULONG newseqnr
, globaldata
*g
);
115 /*********************************************************************/
116 /* Anode cache functions */
117 /*********************************************************************/
120 * Get anodechain of anodenr, making it if necessary.
121 * Returns chain or NULL for failure
123 struct anodechain
*GetAnodeChain(ULONG anodenr
, globaldata
*g
)
125 struct anodechain
*ac
;
127 if (!(ac
= FindAnodeChain(anodenr
, g
)))
128 ac
= MakeAnodeChain(anodenr
, g
);
136 * Called when a reference to an anodechain ceases to exist
138 void DetachAnodeChain(struct anodechain
*chain
, globaldata
*g
)
141 if (!chain
->refcount
)
142 FreeAnodeChain(chain
, g
);
149 static struct anodechain
*MakeAnodeChain(ULONG anodenr
, globaldata
*g
)
151 struct anodechain
*ac
;
152 struct anodechainnode
*node
, *newnode
;
154 ENTER("MakeAnodeChain");
155 if (!(ac
= AllocMemP(sizeof(struct anodechain
), g
)))
160 GetAnode(&node
->an
, anodenr
, g
);
161 while (node
->an
.next
)
163 if (!(newnode
= AllocMemP(sizeof(struct anodechainnode
), g
)))
165 node
->next
= newnode
;
166 GetAnode(&newnode
->an
, node
->an
.next
, g
);
170 MinAddHead(&g
->currentvolume
->anodechainlist
, ac
);
174 FreeAnodeChain(ac
, g
);
181 * Return anodechain found, or 0 if not found
183 static struct anodechain
*FindAnodeChain (ULONG anodenr
, globaldata
*g
)
185 struct anodechain
*chain
;
187 ENTER("FindAnodeChain");
188 for (chain
= HeadOf(&g
->currentvolume
->anodechainlist
); chain
->next
; chain
=chain
->next
)
190 if (chain
->head
.an
.nr
== anodenr
)
198 * Free an anodechain. Anodechain will be removed from list if it is
201 static void FreeAnodeChain (struct anodechain
*chain
, globaldata
*g
)
203 struct anodechainnode
*node
, *nextnode
;
205 ENTER("FreeAnodeChain");
206 for (node
=chain
->head
.next
; node
; node
=nextnode
)
208 nextnode
= node
->next
;
219 * Tries to fetch the block that follows after anodeoffset. Returns success,
220 * updates anodechainpointer and anodeoffset. If failed, acnode will point to
221 * the tail of the anodechain
223 BOOL
NextBlockAC (struct anodechainnode
**acnode
, ULONG
*anodeoffset
, globaldata
*g
)
226 return CorrectAnodeAC (acnode
, anodeoffset
, g
);
230 * Correct anodeoffset overflow. Corrects anodechainnode pointer pointed to by acnode.
231 * Returns success. If correction was not possible, acnode will be the tail of the
232 * anodechain. Anodeoffset is updated to point to a block within the current
235 BOOL
CorrectAnodeAC (struct anodechainnode
**acnode
, ULONG
*anodeoffset
, globaldata
*g
)
237 while (*anodeoffset
>= (*acnode
)->an
.clustersize
)
239 if (!(*acnode
)->next
)
242 *anodeoffset
-= (*acnode
)->an
.clustersize
;
243 *acnode
= (*acnode
)->next
;
250 /*********************************************************************/
252 /*********************************************************************/
255 * Tries to fetch the block that follows after anodeoffset. Returns
256 * success and anodeoffset is updated.
258 BOOL
NextBlock (struct canode
*anode
, ULONG
*anodeoffset
, globaldata
*g
)
261 return CorrectAnode(anode
, anodeoffset
, g
);
265 * Correct anodeoffset overflow
267 BOOL
CorrectAnode (struct canode
*anode
, ULONG
*anodeoffset
, globaldata
*g
)
269 while(*anodeoffset
>= anode
->clustersize
)
274 *anodeoffset
-= anode
->clustersize
;
275 GetAnode(anode
, anode
->next
, g
);
282 * Retrieve an anode from disk
284 void GetAnode (struct canode
*anode
, ULONG anodenr
, globaldata
*g
)
287 UWORD seqnr
, anodeoffset
;
288 struct canodeblock
*ablock
;
290 if(g
->anodesplitmode
)
292 anodenr_t
*split
= (anodenr_t
*)&anodenr
;
293 seqnr
= split
->seqnr
;
294 anodeoffset
= split
->offset
;
298 temp
= divide(anodenr
, andata
.anodesperblock
);
299 seqnr
= temp
; // 1e block = 0
300 anodeoffset
= temp
>> 16;
303 ablock
= GetAnodeBlock(seqnr
, g
);
306 anode
->clustersize
= ablock
->blk
.nodes
[anodeoffset
].clustersize
;
307 anode
->blocknr
= ablock
->blk
.nodes
[anodeoffset
].blocknr
;
308 anode
->next
= ablock
->blk
.nodes
[anodeoffset
].next
;
313 anode
->clustersize
= anode
->next
= 0;
315 // ErrorMsg (AFS_ERROR_DNV_ALLOC_INFO, NULL);
322 void SaveAnode (struct canode
*anode
, ULONG anodenr
, globaldata
*g
)
325 UWORD seqnr
, anodeoffset
;
326 struct canodeblock
*ablock
;
328 if (g
->anodesplitmode
)
330 anodenr_t
*split
= (anodenr_t
*)&anodenr
;
331 seqnr
= split
->seqnr
;
332 anodeoffset
= split
->offset
;
336 temp
= divide(anodenr
,andata
.anodesperblock
);
337 seqnr
= temp
; // 1e block = 0
338 anodeoffset
= temp
>> 16;
344 ablock
= GetAnodeBlock (seqnr
, g
);
347 ablock
->blk
.nodes
[anodeoffset
].clustersize
= anode
->clustersize
;
348 ablock
->blk
.nodes
[anodeoffset
].blocknr
= anode
->blocknr
;
349 ablock
->blk
.nodes
[anodeoffset
].next
= anode
->next
;
350 MakeBlockDirty ((struct cachedblock
*)ablock
, g
);
354 DB(Trace(5,"SaveAnode","ERR: anode = 0x%lx\n",anodenr
));
355 // ErrorMsg (AFS_ERROR_DNV_ALLOC_BLOCK, NULL);
360 /* allocates an anode and marks it as reserved
361 * connect is anodenr to connect to (0 = no connection)
363 ULONG
AllocAnode (ULONG connect
, globaldata
*g
)
366 struct canodeblock
*ablock
;
367 struct anode
*anodes
;
369 ULONG seqnr
= 0, field
;
371 if (connect
&& g
->anodesplitmode
)
373 /* try to place new anode in same block */
374 ablock
= big_GetAnodeBlock (seqnr
= connect
>>16, g
);
377 anodes
= ablock
->blk
.nodes
;
378 for (k
= andata
.anodesperblock
-1; k
> -1 && !found
; k
--)
379 found
= (anodes
[k
].clustersize
== 0 &&
380 anodes
[k
].blocknr
== 0 &&
381 anodes
[k
].next
== 0);
386 for (i
= andata
.curranseqnr
/32; i
< andata
.maxanseqnr
/32 + 1; i
++)
388 field
= andata
.anblkbitmap
[i
];
391 for (j
= 31; j
>= 0; j
--)
393 if (field
& (1 << j
))
396 ablock
= big_GetAnodeBlock(seqnr
, g
);
399 anodes
= ablock
->blk
.nodes
;
400 for (k
=0; k
<andata
.reserved
&& !found
; k
++)
401 found
= (anodes
[k
].clustersize
== 0 &&
402 anodes
[k
].blocknr
== 0 &&
403 anodes
[k
].next
== 0);
408 /* mark anodeblock as full */
409 andata
.anblkbitmap
[i
] &= ~(1 << j
);
411 /* anodeblock does not exist */
418 seqnr
= andata
.maxanseqnr
+ 1;
425 /* give up connect mode and try again */
427 return AllocAnode (0, g
);
429 /* start over if not started from start of list;
430 * else make new block
432 if (andata
.curranseqnr
)
434 andata
.curranseqnr
= 0;
435 return AllocAnode (0, g
);
439 if (!(ablock
= big_NewAnodeBlock (seqnr
, g
)))
441 anodes
= ablock
->blk
.nodes
;
453 anodes
[k
].clustersize
= 0;
454 anodes
[k
].blocknr
= 0xffffffff;
457 MakeBlockDirty((struct cachedblock
*)ablock
, g
);
458 andata
.curranseqnr
= seqnr
;
460 if(g
->anodesplitmode
)
461 return (ULONG
)(seqnr
<<16 | k
);
463 return (ULONG
)(seqnr
*andata
.anodesperblock
+ k
);
468 * frees an anode for later reuse
471 void FreeAnode (ULONG anodenr
, globaldata
*g
)
473 struct canode anode
= {0};
475 /* don't kill reserved anodes */
476 if (anodenr
< ANODE_USERFIRST
)
478 anode
.blocknr
= (ULONG
)~0L;
481 SaveAnode (&anode
, anodenr
, g
);
482 andata
.anblkbitmap
[(anodenr
>>16)/32] |= 1 << (31 - (anodenr
>>16)%32);
486 /***********************************************************************/
487 /* LOCAL functions */
488 /***********************************************************************/
491 /* MODE_BIG has indexblocks, and negative blocknrs indicating freenode
492 ** blocks instead of anodeblocks
494 static struct canodeblock
*big_GetAnodeBlock (UWORD seqnr
, globaldata
*g
)
498 struct canodeblock
*ablock
;
499 struct cindexblock
*indexblock
;
500 struct volumedata
*volume
= g
->currentvolume
;
502 temp
= divide (seqnr
, andata
.indexperblock
);
504 /* not in cache, put it in */
505 /* get the indexblock */
506 if (!(indexblock
= GetIndexBlock (temp
/*& 0xffff*/, g
)))
508 DB(Trace(5, "GetAnodeBlock","ERR: index not found\n"));
513 if (!(blocknr
= indexblock
->blk
.index
[temp
>> 16]))
515 DB(Trace(5,"GetAnodeBlock","ERR: index zero\n"));
520 ablock
= (struct canodeblock
*)CheckCache (volume
->anblks
, HASHM_ANODE
, blocknr
, g
);
524 if (!(ablock
= (struct canodeblock
*)AllocLRU(g
)))
526 DB(Trace(5,"GetAnodeBlock","ERR: alloclru failed\n"));
530 DB(Trace(10,"GetAnodeBlock", "seqnr = %ld blocknr = %lx\n", seqnr
, blocknr
));
533 if (RawRead ((UBYTE
*)&ablock
->blk
, RESCLUSTER
, blocknr
, g
) != 0)
535 DB(Trace(5,"GetAnodeBlock","Read ERR: seqnr = %d blocknr = %lx\n", seqnr
, blocknr
));
536 FreeLRU ((struct cachedblock
*)ablock
);
541 if (ablock
->blk
.id
!= ABLKID
)
544 args
[0] = ablock
->blk
.id
;
546 FreeLRU ((struct cachedblock
*)ablock
);
547 ErrorMsg (AFS_ERROR_DNV_WRONG_ANID
, args
, g
);
552 ablock
->volume
= volume
;
553 ablock
->blocknr
= blocknr
;
554 ablock
->used
= FALSE
;
555 ablock
->changeflag
= FALSE
;
556 Hash (ablock
, volume
->anblks
, HASHM_ANODE
);
562 /* MODE_BIG has difference between anodeblocks and fnodeblocks
564 static struct canodeblock
*big_NewAnodeBlock (UWORD seqnr
, globaldata
*g
)
566 struct canodeblock
*blok
;
567 struct volumedata
*volume
= g
->currentvolume
;
568 struct cindexblock
*indexblock
;
571 UWORD indexoffset
, oldlock
;
573 DB(Trace(10, "NewAnodeBlock", "seqnr = %ld\n", seqnr
));
576 indexblnr
= seqnr
/andata
.indexperblock
;
577 indexoffset
= seqnr
%andata
.indexperblock
;
578 if (!(indexblock
= GetIndexBlock(indexblnr
, g
)))
579 if (!(indexblock
= NewIndexBlock(indexblnr
, g
)))
582 oldlock
= indexblock
->used
;
584 if (!(blok
= (struct canodeblock
*)AllocLRU(g
)) ||
585 !(blocknr
= AllocReservedBlock(g
)) )
588 indexblock
->blk
.index
[indexoffset
] = blocknr
;
590 blok
->volume
= volume
;
591 blok
->blocknr
= blocknr
;
593 blok
->blk
.id
= ABLKID
;
594 blok
->blk
.seqnr
= seqnr
;
595 blok
->changeflag
= TRUE
;
596 Hash(blok
, volume
->anblks
, HASHM_ANODE
);
597 MakeBlockDirty((struct cachedblock
*)indexblock
, g
);
598 indexblock
->used
= oldlock
; // unlock block
600 ReallocAnodeBitmap (seqnr
, g
);
606 /**********************************************************************/
608 /**********************************************************************/
612 * returns 0 if failure
614 struct cindexblock
*GetIndexBlock (UWORD nr
, globaldata
*g
)
617 struct cindexblock
*indexblk
;
618 struct cindexblock
*superblk
;
619 struct volumedata
*volume
= g
->currentvolume
;
621 /* check cache (can be empty) */
622 for (indexblk
= HeadOf(&volume
->indexblks
); indexblk
->next
; indexblk
=indexblk
->next
)
624 if (indexblk
->blk
.seqnr
== nr
)
631 /* not in cache, put it in
636 /* temp is chopped by auto cast */
637 temp
= divide(nr
, andata
.indexperblock
);
638 if (!(superblk
= GetSuperBlock (temp
, g
)))
640 DB(Trace(5, "GetIndexBlock", "ERR: superblock not found\n"));
644 if (!(blocknr
= superblk
->blk
.index
[temp
>>16]))
646 DB(Trace(5, "GetIndexBlock", "ERR: super zero\n"));
652 if ((nr
>MAXSMALLINDEXNR
) || !(blocknr
= volume
->rootblk
->idx
.small
.indexblocks
[nr
]))
656 /* allocate space from cache */
657 if (!(indexblk
= (struct cindexblock
*)AllocLRU(g
)))
660 DB(Trace(10,"GetIndexBlock","seqnr = %d\n, blocknr = %lx\n", nr
, blocknr
));
662 if (RawRead ((UBYTE
*)&indexblk
->blk
, RESCLUSTER
, blocknr
, g
) != 0) {
663 FreeLRU ((struct cachedblock
*)indexblk
);
667 if (indexblk
->blk
.id
== IBLKID
)
669 indexblk
->volume
= volume
;
670 indexblk
->blocknr
= blocknr
;
671 indexblk
->used
= FALSE
;
672 indexblk
->changeflag
= FALSE
;
673 MinAddHead (&volume
->indexblks
, indexblk
);
677 ULONG args
[5] = { indexblk
->blk
.id
, IBLKID
, blocknr
, nr
, andata
.indexperblock
};
678 FreeLRU ((struct cachedblock
*)indexblk
);
679 ErrorMsg (AFS_ERROR_DNV_WRONG_INDID
, args
, g
);
687 static struct cindexblock
*NewIndexBlock (UWORD seqnr
, globaldata
*g
)
689 struct cindexblock
*blok
;
690 struct cindexblock
*superblok
= NULL
;
691 struct volumedata
*volume
= g
->currentvolume
;
694 UWORD superoffset
= 0;
696 DB(Trace(10,"NewIndexBlock", "seqnr = %ld\n", seqnr
));
700 superblnr
= seqnr
/andata
.indexperblock
;
701 superoffset
= seqnr
%andata
.indexperblock
;
702 if (!(superblok
= GetSuperBlock (superblnr
, g
)))
703 if (!(superblok
= NewSuperBlock (superblnr
, g
)))
708 else if (seqnr
> MAXSMALLINDEXNR
) {
712 if (!(blok
= (struct cindexblock
*)AllocLRU(g
)) ||
713 !(blocknr
= AllocReservedBlock(g
)) )
716 FreeLRU((struct cachedblock
*)blok
);
721 superblok
->blk
.index
[superoffset
] = blocknr
;
723 volume
->rootblk
->idx
.small
.indexblocks
[seqnr
] = blocknr
;
724 volume
->rootblockchangeflag
= TRUE
;
727 blok
->volume
= volume
;
728 blok
->blocknr
= blocknr
;
730 blok
->blk
.id
= IBLKID
;
731 blok
->blk
.seqnr
= seqnr
;
732 blok
->changeflag
= TRUE
;
733 MinAddHead(&volume
->indexblks
, blok
);
738 struct cindexblock
*GetSuperBlock (UWORD nr
, globaldata
*g
)
741 struct cindexblock
*superblk
;
742 struct volumedata
*volume
= g
->currentvolume
;
744 /* check supermode */
746 DB(Trace(1, "GetSuperBlock", "ERR: Illegaly entered\n"));
750 /* check cache (can be empty) */
751 for (superblk
= HeadOf(&volume
->superblks
); superblk
->next
; superblk
=superblk
->next
)
753 if (superblk
->blk
.seqnr
== nr
)
760 /* not in cache, put it in
763 if ((nr
>MAXSUPER
) || !(blocknr
= volume
->rblkextension
->blk
.superindex
[nr
]))
766 /* allocate space from cache */
767 if (!(superblk
= (struct cindexblock
*)AllocLRU(g
)))
770 DB(Trace(10,"GetSuperBlock","seqnr = %d\n, blocknr = %lx\n", nr
, blocknr
));
772 if (RawRead ((UBYTE
*)&superblk
->blk
, RESCLUSTER
, blocknr
, g
) != 0) {
773 FreeLRU ((struct cachedblock
*)superblk
);
777 if (superblk
->blk
.id
== SBLKID
)
779 superblk
->volume
= volume
;
780 superblk
->blocknr
= blocknr
;
781 superblk
->used
= FALSE
;
782 superblk
->changeflag
= FALSE
;
783 MinAddHead (&volume
->superblks
, superblk
);
787 ULONG args
[5] = { superblk
->blk
.id
, SBLKID
, blocknr
, nr
, 0 };
788 FreeLRU ((struct cachedblock
*)superblk
);
789 ErrorMsg (AFS_ERROR_DNV_WRONG_INDID
, args
, g
);
796 static struct cindexblock
*NewSuperBlock (UWORD seqnr
, globaldata
*g
)
798 struct cindexblock
*blok
;
799 struct volumedata
*volume
= g
->currentvolume
;
801 DB(Trace(10,"NewSuperBlock", "seqnr = %ld\n", seqnr
));
803 if ((seqnr
> MAXSUPER
) ||
804 !(blok
= (struct cindexblock
*)AllocLRU(g
)) )
807 if (!(volume
->rblkextension
->blk
.superindex
[seqnr
] = AllocReservedBlock(g
)))
809 FreeLRU((struct cachedblock
*)blok
);
813 volume
->rblkextension
->changeflag
= TRUE
;
815 blok
->volume
= volume
;
816 blok
->blocknr
= volume
->rblkextension
->blk
.superindex
[seqnr
];
818 blok
->blk
.id
= SBLKID
;
819 blok
->blk
.seqnr
= seqnr
;
820 blok
->changeflag
= TRUE
;
821 MinAddHead(&volume
->superblks
, blok
);
826 /* Remove anode from anodechain
827 * If previous==0, anode->next becomes head.
828 * Otherwise previous->next becomes anode->next.
832 * anode = anode to be removed
833 * previous = previous in chain; or 0 if anode is head
834 * head = anodenr of head of list
836 void RemoveFromAnodeChain (const struct canode
*anode
, ULONG previous
, ULONG head
, globaldata
*g
)
838 struct canode sparenode
;
842 GetAnode(&sparenode
, previous
, g
);
843 sparenode
.next
= anode
->next
;
844 SaveAnode(&sparenode
, sparenode
.nr
, g
);
845 FreeAnode(anode
->nr
, g
);
849 /* anode is head of list (check both tails here) */
852 /* There is a next entry -> becomes head */
853 GetAnode(&sparenode
, anode
->next
, g
);
854 SaveAnode(&sparenode
, head
, g
); // overwrites [anode]
855 FreeAnode(anode
->next
, g
);
859 /* No anode->next: Free list. */
866 /*********************************************************************/
868 /*********************************************************************/
870 void InitAnodes (struct volumedata
*volume
, BOOL formatting
, globaldata
*g
)
874 ErrorMsg (AFS_ERROR_ANODE_INIT
, NULL
, g
);
878 g
->getanodeblock
= big_GetAnodeBlock
;
880 andata
.curranseqnr
= volume
->rblkextension
?
881 volume
->rblkextension
->blk
.curranseqnr
: 0;
882 andata
.anodesperblock
= (volume
->rootblk
->reserved_blksize
- sizeof(anodeblock_t
)) /
884 andata
.indexperblock
= (volume
->rootblk
->reserved_blksize
- sizeof(indexblock_t
)) /
886 andata
.maxanodeseqnr
= g
->supermode
?
887 ((MAXSUPER
+1) * andata
.indexperblock
* andata
.indexperblock
* andata
.anodesperblock
- 1) :
888 (MAXSMALLINDEXNR
* andata
.indexperblock
- 1);
889 andata
.reserved
= andata
.anodesperblock
- RESERVEDANODES
;
890 MakeAnodeBitmap (formatting
, g
);
895 /* Find out how large the anblkbitmap must be, allocate it and
896 * initialise it. Free any preexisting anblkbitmap
898 * The anode bitmap is used for allocating anodes. It has the
899 * following properties:
900 * - It is maintained in memory only (not on disk).
901 * - Intialization is lazy: all anodes are marked as available
902 * - When allocation anodes (see AllocAnode), this bitmap is used
903 * to find available anodes. It then checks with the actual
904 * anode (which should be 0,0,0 if available). If it isn't really
905 * available, the anodebitmap is updated, otherwise the anode is
908 static void MakeAnodeBitmap (BOOL formatting
, globaldata
*g
)
910 struct cindexblock
*iblk
;
911 struct cindexblock
*sblk
;
915 if (andata
.anblkbitmap
)
916 FreeMemP (andata
.anblkbitmap
, g
);
918 /* count number of anodeblocks and allocate bitmap */
927 for (s
=MAXSUPER
; s
>= 0 && !g
->currentvolume
->rblkextension
->blk
.superindex
[s
]; s
--);
931 sblk
= GetSuperBlock (s
, g
);
932 for (i
=andata
.indexperblock
- 1; i
>= 0 && !sblk
->blk
.index
[i
]; i
--);
936 for (s
=0, i
=MAXSMALLINDEXNR
; i
>= 0 && !g
->rootblock
->idx
.small
.indexblocks
[i
]; i
--);
941 iblk
= GetIndexBlock (s
* andata
.indexperblock
+ i
, g
);
942 for (j
=andata
.indexperblock
- 1; j
>= 0 && !iblk
->blk
.index
[j
]; j
--);
947 andata
.maxanseqnr
= s
* andata
.indexperblock
* andata
.indexperblock
948 + i
* andata
.indexperblock
+ j
;
949 size
= ((s
* andata
.indexperblock
+ i
+ 1) * andata
.indexperblock
+ 7) / 8;
953 andata
.maxanseqnr
= i
* andata
.indexperblock
+ j
;
954 size
= ((i
+1) * andata
.indexperblock
+ 7) / 8;
956 andata
.anblkbitmapsize
= (size
+ 3) & 0xfffffffc;
957 andata
.anblkbitmap
= AllocMemP (andata
.anblkbitmapsize
, g
);
959 for (i
= 0; i
< andata
.anblkbitmapsize
/4; i
++)
960 andata
.anblkbitmap
[i
] = 0xffffffff; /* all available */
965 ErrorMsg(AFS_ERROR_ANODE_ERROR
, NULL
, g
);
969 /* test if new anodeseqnr causes change in anblkbitmap */
970 static void ReallocAnodeBitmap (ULONG newseqnr
, globaldata
*g
)
972 ULONG
*newbitmap
, newsize
;
975 if (newseqnr
> andata
.maxanseqnr
)
977 andata
.maxanseqnr
= newseqnr
;
978 newsize
= ((newseqnr
/andata
.indexperblock
+ 1)
979 * andata
.indexperblock
+ 7) / 8;
980 if (newsize
> andata
.anblkbitmapsize
)
982 newsize
= (newsize
+ 3) & 0xfffffffc; /* longwords */
983 newbitmap
= AllocMemP (newsize
, g
);
984 for (t
=0; t
< newsize
/4; t
++)
985 newbitmap
[t
] = 0xffffffff;
986 memcpy (newbitmap
, andata
.anblkbitmap
, andata
.anblkbitmapsize
);
987 FreeMemP (andata
.anblkbitmap
, g
);
988 andata
.anblkbitmap
= newbitmap
;
989 andata
.anblkbitmapsize
= newsize
;