Added a test for MUIA_Listview_SelectChange.
[AROS.git] / rom / filesys / pfs3 / fs / update.c
bloba63625c95c33d7c76a63496e6b9f1d6a9f2988ac
1 /* $Id$ */
2 /* $Log: update.c $
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
11 * ErrorMsg param
13 * Revision 12.9 1998/09/03 07:12:14 Michiel
14 * versie 17.4
15 * bugfixes 118, 121, 123 and superindexblocks and td64 support
17 * Revision 12.8 1998/05/29 19:31:18 Michiel
18 * fixed bug 108
20 * Revision 12.7 1998/05/22 22:59:58 Michiel
21 * Datestamps added
23 * Revision 12.6 1997/03/03 22:04:04 Michiel
24 * Release 16.21
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
42 * Real atomic update:
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
53 * DELDIR adaptions
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
59 * DELDIR stuff
61 * Revision 11.9 1995/05/20 12:12:12 Michiel
62 * Updated messages to reflect Ami-FileLock
63 * CUTDOWN version
64 * protection update
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
75 * Release version
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
105 * first RCS revision
106 * */
108 #define __USE_SYSBASE
111 * includes
114 #include <exec/types.h>
115 #include <ctype.h>
116 #include "debug.h"
118 #include "blocks.h"
119 #include "struct.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"
130 * prototypes
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);
152 #if VERSION23
153 static void UpdateRBlkExtension (struct cachedblock *blk, ULONG newblocknr, globaldata *g);
154 #endif
155 #if DELDIR
156 static void UpdateDELDIR (struct cachedblock *blk, ULONG newblocknr, globaldata *g);
157 #endif
159 /**********************************************************************/
160 /* UPDATEDISK */
161 /* UPDATEDISK */
162 /* UPDATEDISK */
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
173 * Snapshot to disk.
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;
184 BOOL success;
185 ULONG i;
187 ENTER("UpdateDisk");
190 * Do update
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.
199 lock_device_unit(g);
201 g->uip = TRUE;
202 updateok = TRUE;
203 UpdateDataCache (g); /* flush DiskRead DiskWrite cache */
205 #if VERSION23
206 /* make sure rootblockextension is reallocated */
207 if (volume->rblkextension)
208 MakeBlockDirty ((struct cachedblock *)volume->rblkextension, g);
209 #endif
211 /* commit user space free list */
212 UpdateFreeList(g);
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);
227 #if DELDIR
228 updateok &= UpdateList ((struct cachedblock *)HeadOf(&volume->deldirblks), g);
229 #endif
231 #if VERSION23
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 */
242 DateStamp (&time);
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);
250 #endif
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) */
261 if (updateok)
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);
270 success = TRUE;
272 else
274 ErrorMsg (AFS_ERROR_UPDATE_FAIL, NULL, g);
275 success = FALSE;
278 g->uip = FALSE;
280 unlock_device_unit(g);
282 else
284 if (volume && g->dirty && g->softprotect)
285 ErrorMsg (AFS_ERROR_UPDATE_FAIL, NULL, g);
287 success = FALSE;
290 g->dirty = FALSE;
292 EXIT("UpdateDisk");
293 return success;
297 * Empty Dirblocks
299 static void RemoveEmptyDBlocks(struct volumedata *volume, globaldata *g)
301 struct cdirblock *blk, *next;
302 struct canode anode;
303 ULONG previous, i;
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);
313 MinRemove(blk);
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)
324 ULONG prev = 0;
326 GetAnode(anode, blk->blk.anodenr, g);
327 while (anode->blocknr != blk->blocknr && anode->next) //anode.next purely safety
329 prev = anode->nr;
330 GetAnode(anode, anode->next, g);
333 return prev;
336 static BOOL IsFirstDBlk(struct cdirblock *blk, globaldata *g)
338 BOOL first;
339 struct canode anode;
341 GetAnode(&anode, blk->blk.anodenr, g);
342 first = (anode.blocknr == blk->blocknr);
344 return first;
349 * Empty block check
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);
360 MinRemove(blk);
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;
378 MinRemove(blk);
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;
401 /* kill the block */
402 MinRemove(blk);
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;
419 ULONG j;
420 BOOL found = 0;
422 /* zoek bezette anode */
423 anodes = ablk->blk.nodes;
424 for(j=0; j<andata.anodesperblock && !found; j++)
425 found |= (anodes[j].blocknr != 0);
427 found = !found;
428 return found; /* not found -> empty */
431 static BOOL IsEmptyIBlk(struct cindexblock *blk, globaldata *g)
433 ULONG *index, i;
434 BOOL found = 0;
436 index = blk->blk.index;
437 for(i=0; i<andata.indexperblock; i++)
439 found = index[i] != 0;
440 if (found)
441 break;
444 found = !found;
445 return found;
448 static BOOL UpdateList (struct cachedblock *blk, globaldata *g)
450 ULONG error;
451 struct cbitmapblock *blk2;
453 if (!updateok)
454 return FALSE;
456 while (blk->next)
458 if (blk->changeflag)
460 FreeReservedBlock (blk->oldblocknr, g);
461 blk2 = (struct cbitmapblock *)blk;
462 blk2->blk.datestamp = blk2->volume->rootblk->datestamp;
463 blk->oldblocknr = 0;
464 error = RawWrite ((UBYTE *)&blk->data, RESCLUSTER, blk->blocknr, g);
465 if (error)
466 goto update_error;
468 blk->changeflag = FALSE;
471 blk=blk->next;
474 return TRUE;
476 update_error:
477 ErrorMsg (AFS_ERROR_UPDATE_FAIL, NULL, g);
478 return FALSE;
481 static BOOL UpdateDirtyBlock (struct cachedblock *blk, globaldata *g)
483 ULONG error;
485 if (!updateok)
486 return FALSE;
488 if (blk->changeflag)
490 FreeReservedBlock (blk->oldblocknr, g);
491 blk->oldblocknr = 0;
492 error = RawWrite ((UBYTE *)&blk->data, RESCLUSTER, blk->blocknr, g);
493 if (error)
495 ErrorMsg (AFS_ERROR_UPDATE_FAIL, NULL, g);
496 return FALSE;
500 blk->changeflag = FALSE;
501 return TRUE;
504 static void CommitReservedToBeFreed (globaldata *g)
506 int i;
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)))
530 UpdateDisk (g);
532 if (g->rootblock->reserved_free <= RESFREE_THRESHOLD)
533 alloc_data.res_alert = TRUE;
534 else
535 alloc_data.res_alert = FALSE;
540 /**********************************************************************/
541 /* MAKEBLOCKDIRTY */
542 /* MAKEBLOCKDIRTY */
543 /* MAKEBLOCKDIRTY */
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)
558 ULONG blocknr;
559 UWORD oldlock;
561 if (!(blk->changeflag))
563 g->dirty = TRUE;
564 oldlock = blk->used;
565 LOCK(blk);
567 blocknr = AllocReservedBlock (g);
568 if (blocknr)
570 blk->oldblocknr = blk->blocknr;
571 blk->blocknr = blocknr;
572 UpdateBlocknr (blk, blocknr, g);
574 else
576 #ifdef BETAVERSION
577 ErrorMsg(AFS_BETA_WARNING_2, NULL, g);
578 #endif
579 blk->changeflag = TRUE;
582 blk->used = oldlock; // unlock block
583 return TRUE;
585 else
587 return FALSE;
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);
597 break;
599 case ABLKID: /* anodeblock */
600 UpdateABLK (blk, newblocknr, g);
601 break;
603 case IBLKID: /* indexblock */
604 UpdateIBLK (blk, newblocknr, g);
605 break;
607 case BMBLKID: /* bitmapblock */
608 UpdateBMBLK (blk, newblocknr, g);
609 break;
611 case BMIBLKID: /* bitmapindexblock */
612 UpdateBMIBLK (blk, newblocknr, g);
613 break;
615 #if VERSION23
616 case EXTENSIONID: /* rootblockextension */
617 UpdateRBlkExtension (blk, newblocknr, g);
618 break;
619 #endif
621 #if DELDIR
622 case DELDIRID: /* deldir */
623 UpdateDELDIR (blk, newblocknr, g);
624 break;
625 #endif
627 case SBLKID: /* superblock */
628 UpdateSBLK (blk, newblocknr, g);
629 break;
634 static void UpdateDBLK (struct cachedblock *blk, ULONG newblocknr, globaldata *g)
636 struct cdirblock *dblk = (struct cdirblock *)blk;
637 struct canode anode;
638 ULONG oldblocknr = dblk->oldblocknr;
640 LOCK(blk);
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);
647 /* change it.. */
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;
686 ULONG temp;
688 blk->changeflag = TRUE;
689 if (g->supermode)
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);
696 else
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;
713 ULONG temp;
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;
731 #if VERSION23
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;
738 #endif
740 #if DELDIR
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);
747 #endif
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;
767 break;
769 case EXTENSIONID: /* rootblockextension */
770 rext->blk.datestamp = g->currentvolume->rootblk->datestamp;
771 break;