3 * Revision 12.12 1999/05/14 11:31:34 Michiel
4 * Long filename support implemented; bugfixes
6 * Revision 12.11 1999/02/22 16:25:30 Michiel
7 * Changes for increasing deldir capacity
9 * Revision 12.10 1998/09/27 11:26:37 Michiel
10 * Adapted for supermode
13 * Revision 12.9 1998/09/03 07:12:14 Michiel
15 * bugfixes 118, 121, 123 and superindexblocks and td64 support
17 * Revision 12.8 1998/05/29 19:31:18 Michiel
20 * Revision 12.7 1998/05/22 22:59:58 Michiel
23 * Revision 12.6 1997/03/03 22:04:04 Michiel
26 * Revision 12.5 1996/03/07 10:03:38 Michiel
27 * enforcer hit in CheckUpdate fixed (Working tree)
29 * Revision 12.4 1996/01/30 12:49:46 Michiel
30 * update of rext->curranseqnr added
32 * Revision 12.3 1996/01/03 10:02:59 Michiel
33 * reserved rovingpointer added
35 * Revision 12.2 1995/11/15 15:56:33 Michiel
36 * Rootblock extension update added
37 * volume_data datestamp added
38 * RemoveEmptyXBlock now calls ResToBeFreed to prevent state overlap
39 * CommitReservedToBeFreed() added
41 * Revision 12.1 1995/11/07 15:04:07 Michiel
43 * ReservedToBeFreed cache (CommitReservedToBeFreed())
44 * Changed update order
46 * Revision 11.14 1995/11/02 10:00:31 Michiel
47 * using UpdateDataCache (16.2)
49 * Revision 11.13 1995/10/03 09:55:22 Michiel
50 * rootblock is datestamped at Update()
52 * Revision 11.12 1995/07/21 06:55:32 Michiel
55 * Revision 11.11 1995/07/11 17:29:31 Michiel
56 * ErrorMsg () calls use messages.c variables now.
58 * Revision 11.10 1995/07/11 09:23:36 Michiel
61 * Revision 11.9 1995/05/20 12:12:12 Michiel
62 * Updated messages to reflect Ami-FileLock
66 * Revision 11.8 1995/04/12 19:22:15 Michiel
67 * fixed the 'cache inconsistency' bug, caused by
68 * an Update() at the wrong moment
70 * Revision 11.7 1995/02/28 18:36:55 Michiel
71 * Use of blocks_dirty added
72 * Update order changed (see 12.6 bugfix)
74 * Revision 11.6 1995/02/15 16:43:39 Michiel
76 * Using new headers (struct.h & blocks.h)
78 * Revision 11.5 1995/02/09 04:54:20 Michiel
79 * Bugfix: Makeblockdirty should unlock block to prevent
80 * pfs to run out of buffers
82 * Revision 11.4 1995/01/29 07:34:57 Michiel
83 * Hash table implemented
85 * Revision 11.3 1995/01/18 04:29:34 Michiel
86 * Bugfixes. Now ready for beta release.
88 * Revision 11.2 1995/01/08 16:22:44 Michiel
89 * *** empty log message ***
91 * Revision 11.1 1995/01/03 17:16:19 Michiel
92 * New update algorithm based on reallocation at makeblockdirty time
93 * combined with bitmap-reserved allocation
95 * Revision 10.4 1994/12/05 08:06:20 Michiel
96 * Last version of old algorithm
98 * Revision 10.3 1994/11/15 17:52:30 Michiel
99 * Bugfix: added a DirectUpdate of anblks after indexblk reallocation
101 * Revision 10.2 1994/10/27 11:36:07 Michiel
102 * Fixed bug that caused unneeded "Abandoned savewrite .." message
104 * Revision 10.1 1994/10/24 11:16:28 Michiel
108 #define __USE_SYSBASE
114 #include <exec/types.h>
120 #include "update_protos.h"
121 #include "volume_protos.h"
122 #include "disk_protos.h"
123 #include "allocation_protos.h"
124 #include "anodes_protos.h"
125 #include "lru_protos.h"
126 #include "ass_protos.h"
127 #include "init_protos.h"
133 static void RemoveEmptyABlocks(struct volumedata
*volume
, globaldata
*g
);
134 static void RemoveEmptyDBlocks(struct volumedata
*volume
, globaldata
*g
);
135 static void RemoveEmptyIBlocks(struct volumedata
*volume
, globaldata
*g
);
136 static void RemoveEmptySBlocks(struct volumedata
*volume
, globaldata
*g
);
137 static ULONG
GetAnodeOfDBlk(struct cdirblock
*blk
, struct canode
*anode
, globaldata
*g
);
138 static BOOL
IsFirstDBlk(struct cdirblock
*blk
, globaldata
*g
);
139 static BOOL
IsEmptyABlk(struct canodeblock
*ablk
, globaldata
*g
);
140 static BOOL
IsEmptyIBlk(struct cindexblock
*blk
, globaldata
*g
);
141 static BOOL
UpdateList (struct cachedblock
*blk
, globaldata
*g
);
142 static void CommitReservedToBeFreed (globaldata
*g
);
143 static BOOL
UpdateDirtyBlock (struct cachedblock
*blk
, globaldata
*g
);
145 static void UpdateBlocknr(struct cachedblock
*blk
, ULONG newblocknr
, globaldata
*g
);
146 static void UpdateABLK(struct cachedblock
*, ULONG
, globaldata
*);
147 static void UpdateDBLK(struct cachedblock
*, ULONG
, globaldata
*);
148 static void UpdateIBLK(struct cachedblock
*, ULONG
, globaldata
*);
149 static void UpdateSBLK(struct cachedblock
*, ULONG
, globaldata
*);
150 static void UpdateBMBLK(struct cachedblock
*blk
, ULONG newblocknr
, globaldata
*g
);
151 static void UpdateBMIBLK(struct cachedblock
*blk
, ULONG newblocknr
, globaldata
*g
);
153 static void UpdateRBlkExtension (struct cachedblock
*blk
, ULONG newblocknr
, globaldata
*g
);
156 static void UpdateDELDIR (struct cachedblock
*blk
, ULONG newblocknr
, globaldata
*g
);
159 /**********************************************************************/
163 /**********************************************************************/
165 #define IsFirstABlk(blk) (blk->blk.seqnr == 0)
166 #define IsFirstIBlk(blk) (blk->blk.seqnr == 0)
167 #define IsEmptyDBlk(blk) (FIRSTENTRY(blk)->next == 0)
169 /* indicates current state of update */
170 #define updateok g->updateok
174 * --> remove empty blocks
175 * --> update freelist
176 * --> save reserved blocks at new location, free the old
178 * Result FALSE/TRUE done nothing/volume updated
180 BOOL
UpdateDisk (globaldata
*g
)
182 struct DateStamp time
;
183 struct volumedata
*volume
= g
->currentvolume
;
192 if (volume
&& g
->dirty
&& !g
->softprotect
)
195 * For performance reasons avoid concurrent access to same physical
196 * device. Note that the lock can be broken safely, it's only used
197 * to avoid excessive seeking due to competing updates.
203 UpdateDataCache (g
); /* flush DiskRead DiskWrite cache */
206 /* make sure rootblockextension is reallocated */
207 if (volume
->rblkextension
)
208 MakeBlockDirty ((struct cachedblock
*)volume
->rblkextension
, g
);
211 /* commit user space free list */
214 /* remove empty dir, anode, index and superblocks */
215 RemoveEmptyDBlocks(volume
, g
);
216 RemoveEmptyABlocks(volume
, g
);
217 RemoveEmptyIBlocks(volume
, g
);
218 RemoveEmptySBlocks(volume
, g
);
220 /* update anode, dir, index and superblocks (not changed by UpdateFreeList) */
221 for (i
=0; i
<=HASHM_DIR
; i
++)
222 updateok
&= UpdateList ((struct cachedblock
*)HeadOf(&volume
->dirblks
[i
]), g
);
223 for (i
=0; i
<=HASHM_ANODE
; i
++)
224 updateok
&= UpdateList ((struct cachedblock
*)HeadOf(&volume
->anblks
[i
]), g
);
225 updateok
&= UpdateList ((struct cachedblock
*)HeadOf(&volume
->indexblks
), g
);
226 updateok
&= UpdateList ((struct cachedblock
*)HeadOf(&volume
->superblks
), g
);
228 updateok
&= UpdateList ((struct cachedblock
*)HeadOf(&volume
->deldirblks
), g
);
232 if (volume
->rblkextension
)
234 struct crootblockextension
*rext
= volume
->rblkextension
;
236 /* reserved roving and anode roving */
237 rext
->blk
.reserved_roving
= alloc_data
.res_roving
;
238 rext
->blk
.rovingbit
= alloc_data
.rovingbit
;
239 rext
->blk
.curranseqnr
= andata
.curranseqnr
;
241 /* volume datestamp */
243 rext
->blk
.volume_date
[0] = (UWORD
)time
.ds_Days
;
244 rext
->blk
.volume_date
[1] = (UWORD
)time
.ds_Minute
;
245 rext
->blk
.volume_date
[2] = (UWORD
)time
.ds_Tick
;
246 rext
->blk
.datestamp
= volume
->rootblk
->datestamp
;
248 updateok
&= UpdateDirtyBlock ((struct cachedblock
*)rext
, g
);
253 /* commit reserved to be freed list */
254 CommitReservedToBeFreed(g
);
256 /* update bitmap and bitmap index blocks */
257 updateok
&= UpdateList ((struct cachedblock
*)HeadOf(&volume
->bmblks
), g
);
258 updateok
&= UpdateList ((struct cachedblock
*)HeadOf(&volume
->bmindexblks
), g
);
260 /* update root (MUST be done last) */
263 RawWrite((UBYTE
*)volume
->rootblk
, volume
->rootblk
->rblkcluster
, ROOTBLOCK
, g
);
264 volume
->rootblk
->datestamp
++;
265 volume
->rootblockchangeflag
= FALSE
;
267 /* make sure update is really done */
268 g
->request
->iotd_Req
.io_Command
= CMD_UPDATE
;
269 DoIO((struct IORequest
*)g
->request
);
274 ErrorMsg (AFS_ERROR_UPDATE_FAIL
, NULL
, g
);
280 unlock_device_unit(g
);
284 if (volume
&& g
->dirty
&& g
->softprotect
)
285 ErrorMsg (AFS_ERROR_UPDATE_FAIL
, NULL
, g
);
299 static void RemoveEmptyDBlocks(struct volumedata
*volume
, globaldata
*g
)
301 struct cdirblock
*blk
, *next
;
305 for (i
=0; i
<=HASHM_DIR
; i
++)
307 for (blk
= HeadOf(&volume
->dirblks
[i
]); (next
=blk
->next
); blk
=next
)
309 if (IsEmptyDBlk(blk
) && !IsFirstDBlk(blk
, g
) && !ISLOCKED(blk
) )
311 previous
= GetAnodeOfDBlk(blk
, &anode
, g
);
312 RemoveFromAnodeChain(&anode
, previous
, blk
->blk
.anodenr
, g
);
314 FreeReservedBlock(blk
->blocknr
, g
);
315 ResToBeFreed(blk
->oldblocknr
, g
);
316 FreeLRU((struct cachedblock
*)blk
);
322 static ULONG
GetAnodeOfDBlk(struct cdirblock
*blk
, struct canode
*anode
, globaldata
*g
)
326 GetAnode(anode
, blk
->blk
.anodenr
, g
);
327 while (anode
->blocknr
!= blk
->blocknr
&& anode
->next
) //anode.next purely safety
330 GetAnode(anode
, anode
->next
, g
);
336 static BOOL
IsFirstDBlk(struct cdirblock
*blk
, globaldata
*g
)
341 GetAnode(&anode
, blk
->blk
.anodenr
, g
);
342 first
= (anode
.blocknr
== blk
->blocknr
);
351 static void RemoveEmptyIBlocks(struct volumedata
*volume
, globaldata
*g
)
353 struct cindexblock
*blk
, *next
;
355 for (blk
= HeadOf(&volume
->indexblks
); (next
=blk
->next
); blk
=next
)
357 if (blk
->changeflag
&& !IsFirstIBlk(blk
) && IsEmptyIBlk(blk
,g
) && !ISLOCKED(blk
) )
359 UpdateIBLK((struct cachedblock
*)blk
, 0, g
);
361 FreeReservedBlock(blk
->blocknr
, g
);
362 ResToBeFreed(blk
->oldblocknr
, g
);
363 FreeLRU((struct cachedblock
*)blk
);
368 static void RemoveEmptySBlocks(struct volumedata
*volume
, globaldata
*g
)
370 struct cindexblock
*blk
, *next
;
372 for (blk
= HeadOf(&volume
->superblks
); (next
=blk
->next
); blk
=next
)
374 if (blk
->changeflag
&& !IsFirstIBlk(blk
) && IsEmptyIBlk(blk
, g
) && !ISLOCKED(blk
) )
376 volume
->rblkextension
->blk
.superindex
[blk
->blk
.seqnr
] = 0;
377 volume
->rblkextension
->changeflag
= TRUE
;
379 FreeReservedBlock(blk
->blocknr
, g
);
380 ResToBeFreed(blk
->oldblocknr
, g
);
381 FreeLRU((struct cachedblock
*)blk
);
386 static void RemoveEmptyABlocks(struct volumedata
*volume
, globaldata
*g
)
388 struct canodeblock
*blk
, *next
;
389 ULONG indexblknr
, indexoffset
, i
;
390 struct cindexblock
*index
;
392 for (i
=0; i
<=HASHM_ANODE
; i
++)
394 for (blk
= HeadOf(&volume
->anblks
[i
]); (next
=blk
->next
); blk
=next
)
396 if (blk
->changeflag
&& !IsFirstABlk(blk
) && IsEmptyABlk(blk
, g
) && !ISLOCKED(blk
) )
398 indexblknr
= ((struct canodeblock
*)blk
)->blk
.seqnr
/ andata
.indexperblock
;
399 indexoffset
= ((struct canodeblock
*)blk
)->blk
.seqnr
% andata
.indexperblock
;
403 FreeReservedBlock(blk
->blocknr
, g
);
404 ResToBeFreed(blk
->oldblocknr
, g
);
405 FreeLRU((struct cachedblock
*)blk
);
407 /* and remove the reference (this one should already be in the cache) */
408 index
= GetIndexBlock(indexblknr
, g
);
409 index
->blk
.index
[indexoffset
] = 0;
410 index
->changeflag
= TRUE
;
416 static BOOL
IsEmptyABlk(struct canodeblock
*ablk
, globaldata
*g
)
418 struct anode
*anodes
;
422 /* zoek bezette anode */
423 anodes
= ablk
->blk
.nodes
;
424 for(j
=0; j
<andata
.anodesperblock
&& !found
; j
++)
425 found
|= (anodes
[j
].blocknr
!= 0);
428 return found
; /* not found -> empty */
431 static BOOL
IsEmptyIBlk(struct cindexblock
*blk
, globaldata
*g
)
436 index
= blk
->blk
.index
;
437 for(i
=0; i
<andata
.indexperblock
; i
++)
439 found
= index
[i
] != 0;
448 static BOOL
UpdateList (struct cachedblock
*blk
, globaldata
*g
)
451 struct cbitmapblock
*blk2
;
460 FreeReservedBlock (blk
->oldblocknr
, g
);
461 blk2
= (struct cbitmapblock
*)blk
;
462 blk2
->blk
.datestamp
= blk2
->volume
->rootblk
->datestamp
;
464 error
= RawWrite ((UBYTE
*)&blk
->data
, RESCLUSTER
, blk
->blocknr
, g
);
468 blk
->changeflag
= FALSE
;
477 ErrorMsg (AFS_ERROR_UPDATE_FAIL
, NULL
, g
);
481 static BOOL
UpdateDirtyBlock (struct cachedblock
*blk
, globaldata
*g
)
490 FreeReservedBlock (blk
->oldblocknr
, g
);
492 error
= RawWrite ((UBYTE
*)&blk
->data
, RESCLUSTER
, blk
->blocknr
, g
);
495 ErrorMsg (AFS_ERROR_UPDATE_FAIL
, NULL
, g
);
500 blk
->changeflag
= FALSE
;
504 static void CommitReservedToBeFreed (globaldata
*g
)
507 for (i
=0;i
<alloc_data
.rtbf_index
;i
++)
509 if (alloc_data
.reservedtobefreed
[i
])
511 FreeReservedBlock (alloc_data
.reservedtobefreed
[i
], g
);
512 alloc_data
.reservedtobefreed
[i
] = 0;
516 alloc_data
.rtbf_index
= 0;
519 /* Check if an update is needed (see atomic.fw)
520 * rtbf_threshold indicates how full the rtbf cache is allowed to be,
521 * normally RTBF_THRESHOLD, RTBF_POSTPONED_TH for intermediate checks.
523 void CheckUpdate (ULONG rtbf_threshold
, globaldata
*g
)
525 if (g
->currentvolume
&&
526 ((alloc_data
.rtbf_index
> rtbf_threshold
) ||
527 (alloc_data
.tobefreed_index
> TBF_THRESHOLD
) ||
528 (g
->rootblock
->reserved_free
< RESFREE_THRESHOLD
+ 5 + alloc_data
.tbf_resneed
)))
532 if (g
->rootblock
->reserved_free
<= RESFREE_THRESHOLD
)
533 alloc_data
.res_alert
= TRUE
;
535 alloc_data
.res_alert
= FALSE
;
540 /**********************************************************************/
544 /**********************************************************************/
546 /* --> part of update
547 * marks a directory or anodeblock dirty. Nothing happens if it already
548 * was dirty. If it wasn't, the block will be reallocated and marked dirty.
549 * If the reallocation fails, an error is displayed.
551 * result: TRUE = was clean; FALSE: was already dirty
553 * LOCKing the block until next packet proves to be too restrictive,
554 * so unlock afterwards.
556 BOOL
MakeBlockDirty (struct cachedblock
*blk
, globaldata
*g
)
561 if (!(blk
->changeflag
))
567 blocknr
= AllocReservedBlock (g
);
570 blk
->oldblocknr
= blk
->blocknr
;
571 blk
->blocknr
= blocknr
;
572 UpdateBlocknr (blk
, blocknr
, g
);
577 ErrorMsg(AFS_BETA_WARNING_2
, NULL
, g
);
579 blk
->changeflag
= TRUE
;
582 blk
->used
= oldlock
; // unlock block
591 static void UpdateBlocknr (struct cachedblock
*blk
, ULONG newblocknr
, globaldata
*g
)
593 switch (((UWORD
*)blk
->data
)[0])
595 case DBLKID
: /* dirblock */
596 UpdateDBLK (blk
, newblocknr
, g
);
599 case ABLKID
: /* anodeblock */
600 UpdateABLK (blk
, newblocknr
, g
);
603 case IBLKID
: /* indexblock */
604 UpdateIBLK (blk
, newblocknr
, g
);
607 case BMBLKID
: /* bitmapblock */
608 UpdateBMBLK (blk
, newblocknr
, g
);
611 case BMIBLKID
: /* bitmapindexblock */
612 UpdateBMIBLK (blk
, newblocknr
, g
);
616 case EXTENSIONID
: /* rootblockextension */
617 UpdateRBlkExtension (blk
, newblocknr
, g
);
622 case DELDIRID
: /* deldir */
623 UpdateDELDIR (blk
, newblocknr
, g
);
627 case SBLKID
: /* superblock */
628 UpdateSBLK (blk
, newblocknr
, g
);
634 static void UpdateDBLK (struct cachedblock
*blk
, ULONG newblocknr
, globaldata
*g
)
636 struct cdirblock
*dblk
= (struct cdirblock
*)blk
;
638 ULONG oldblocknr
= dblk
->oldblocknr
;
642 /* get old anode (all 1-block anodes) */
643 GetAnode (&anode
, dblk
->blk
.anodenr
, g
);
644 while ((anode
.blocknr
!= oldblocknr
) && anode
.next
) //anode.next purely safety
645 GetAnode (&anode
, anode
.next
, g
);
648 if (anode
.blocknr
!= oldblocknr
)
650 DB(Trace(4, "UpdateDBLK", "anode.blocknr=%ld, dblk->blocknr=%ld\n",
651 anode
.blocknr
, dblk
->blocknr
));
652 ErrorMsg (AFS_ERROR_CACHE_INCONSISTENCY
, NULL
, g
);
655 /* This must happen AFTER anode correction, because Update() could be called,
656 * causing trouble (invalid checkpoint: dirblock uptodate, anode not)
658 blk
->changeflag
= TRUE
;
659 anode
.blocknr
= newblocknr
;
660 SaveAnode(&anode
, anode
.nr
, g
);
662 ReHash(blk
, g
->currentvolume
->dirblks
, HASHM_DIR
);
665 static void UpdateABLK (struct cachedblock
*blk
, ULONG newblocknr
, globaldata
*g
)
667 struct cindexblock
*index
;
668 ULONG indexblknr
, indexoffset
, temp
;
670 blk
->changeflag
= TRUE
;
672 temp
= ((struct canodeblock
*)blk
)->blk
.seqnr
;
673 indexblknr
= temp
/ andata
.indexperblock
;
674 indexoffset
= temp
% andata
.indexperblock
;
676 /* this one should already be in the cache */
677 index
= GetIndexBlock(indexblknr
, g
);
678 index
->blk
.index
[indexoffset
] = newblocknr
;
679 MakeBlockDirty ((struct cachedblock
*)index
, g
);
680 ReHash(blk
, g
->currentvolume
->anblks
, HASHM_ANODE
);
683 static void UpdateIBLK(struct cachedblock
*blk
, ULONG newblocknr
, globaldata
*g
)
685 struct cindexblock
*superblk
;
688 blk
->changeflag
= TRUE
;
691 temp
= divide (((struct cindexblock
*)blk
)->blk
.seqnr
, andata
.indexperblock
);
692 superblk
= GetSuperBlock (temp
/* & 0xffff */, g
);
693 superblk
->blk
.index
[temp
>> 16] = newblocknr
;
694 MakeBlockDirty ((struct cachedblock
*)superblk
, g
);
698 blk
->volume
->rootblk
->idx
.small
.indexblocks
[((struct cindexblock
*)blk
)->blk
.seqnr
] = newblocknr
;
699 blk
->volume
->rootblockchangeflag
= TRUE
;
703 static void UpdateSBLK(struct cachedblock
*blk
, ULONG newblocknr
, globaldata
*g
)
705 blk
->changeflag
= TRUE
;
706 blk
->volume
->rblkextension
->blk
.superindex
[((struct cindexblock
*)blk
)->blk
.seqnr
] = newblocknr
;
709 static void UpdateBMBLK (struct cachedblock
*blk
, ULONG newblocknr
, globaldata
*g
)
711 struct cindexblock
*indexblock
;
712 struct cbitmapblock
*bmb
= (struct cbitmapblock
*)blk
;
715 blk
->changeflag
= TRUE
;
716 temp
= divide (bmb
->blk
.seqnr
, andata
.indexperblock
);
717 indexblock
= GetBitmapIndex (temp
/* & 0xffff */, g
);
718 indexblock
->blk
.index
[temp
>> 16] = newblocknr
;
719 MakeBlockDirty ((struct cachedblock
*)indexblock
, g
); /* recursie !! */
722 /* validness of seqnr is checked when block is loaded */
723 static void UpdateBMIBLK (struct cachedblock
*blk
, ULONG newblocknr
, globaldata
*g
)
725 blk
->changeflag
= TRUE
;
727 blk
->volume
->rootblk
->idx
.large
.bitmapindex
[((struct cindexblock
*)blk
)->blk
.seqnr
] = newblocknr
;
728 blk
->volume
->rootblockchangeflag
= TRUE
;
732 static void UpdateRBlkExtension (struct cachedblock
*blk
, ULONG newblocknr
, globaldata
*g
)
734 blk
->changeflag
= TRUE
;
735 blk
->volume
->rootblk
->extension
= newblocknr
;
736 blk
->volume
->rootblockchangeflag
= TRUE
;
741 static void UpdateDELDIR (struct cachedblock
*blk
, ULONG newblocknr
, globaldata
*g
)
743 blk
->changeflag
= TRUE
;
744 blk
->volume
->rblkextension
->blk
.deldir
[((struct cdeldirblock
*)blk
)->blk
.seqnr
] = newblocknr
;
745 MakeBlockDirty((struct cachedblock
*)blk
->volume
->rblkextension
, g
);
749 /* Update datestamp (copy from rootblock
750 * Call before writing block (lru.c)
752 void UpdateDatestamp (struct cachedblock
*blk
, globaldata
*g
)
754 struct cdirblock
*dblk
= (struct cdirblock
*)blk
;
755 struct crootblockextension
*rext
= (struct crootblockextension
*)blk
;
757 switch (((UWORD
*)blk
->data
)[0])
759 case DBLKID
: /* dirblock */
760 case ABLKID
: /* anodeblock */
761 case IBLKID
: /* indexblock */
762 case BMBLKID
: /* bitmapblock */
763 case BMIBLKID
: /* bitmapindexblock */
764 case DELDIRID
: /* deldir */
765 case SBLKID
: /* superblock */
766 dblk
->blk
.datestamp
= g
->currentvolume
->rootblk
->datestamp
;
769 case EXTENSIONID
: /* rootblockextension */
770 rext
->blk
.datestamp
= g
->currentvolume
->rootblk
->datestamp
;