-- MarkerPageImpl.mesa (last edited by: Luniewski on: January 12, 1981 11:05 AM) -- It is not clear how much checking to do when something comes on line. For the time being, We do no real checking, assuming that marker pages are set up right. This may be the correct philosophy, since marker pages are copies of the truth for the scavenger. DIRECTORY DiskChannel USING [Drive, GetAttributes, nullDrive], File USING [ID, nullID], FMPrograms USING [], FileInternal USING [maxPermissions], LabelTransfer USING [WriteLabels], LogicalVolume USING [Handle, LogicalSubvolumeMarker], MarkerPage USING [CacheKey, SubVolumeMarkerPage], PhysicalVolume USING [Error, ErrorType, ID, nullID], PhysicalVolumeFormat USING [Handle, PageNumber, PhysicalSubvolumeMarker], PilotFileTypes USING [tSubVolumeMarkerPage], SimpleSpace USING [Create, Handle, Map, Page, Unmap], SubVolume USING [Find, Handle], Utilities USING [LongPointerFromPage]; MarkerPageImpl: MONITOR IMPORTS DiskChannel, LabelTransfer, PhysicalVolume, SimpleSpace, SubVolume, Utilities EXPORTS FMPrograms, MarkerPage SHARES File = BEGIN -- Buffer variables for accessing marker pages markerPageBuffer: SimpleSpace.Handle = SimpleSpace.Create[1, hyperspace]; marker: LONG POINTER TO MarkerPage.SubVolumeMarkerPage = Utilities.LongPointerFromPage[SimpleSpace.Page[markerPageBuffer]]; cacheSize: CARDINAL = 5; -- should be one for each possible disk cache: ARRAY [0..cacheSize) OF RECORD [ occupied: BOOLEAN, drive: DiskChannel.Drive, physicalID: PhysicalVolume.ID, markerID: File.ID] ← ALL[[FALSE, , , ]]; NotFound: PUBLIC ERROR = CODE; MarkerPageError: ERROR [ {cacheFull, impossibleCacheVarient, subvolumeNotFound}] = CODE; -- Create the marker page for the i'th subvolume. The ID is in the cache, and the page groups have been set up properly CreateMarkerPage: PUBLIC ENTRY PROCEDURE [ pvHandle: PhysicalVolumeFormat.Handle, lvHandle: LogicalVolume.Handle, physicalSubvolumeNumber: CARDINAL] = BEGIN OPEN sv: pvHandle.subVolumes[physicalSubvolumeNumber]; page: LONG CARDINAL ← sv.pvPage + sv.nPages; [] ← LabelTransfer.WriteLabels[ file: [FindMarkerID[[physicalID[pvHandle.pvID]]], LOOPHOLE[pvHandle.pvID], local[FALSE, FALSE, page --Should be driveSize--, PilotFileTypes.tSubVolumeMarkerPage]], pageGroup: [page, page, page + 1]]; MarkerPageMap[FindMarkerID[[physicalID[pvHandle.pvID]]], page]; marker↑ ← [physical: [pvID: pvHandle.pvID, label: pvHandle.label, bootingInfo: pvHandle.bootingInfo, maxBadPages: pvHandle.maxBadPages, labelLength: pvHandle.labelLength, svNumber: physicalSubvolumeNumber, descriptor: sv], logical: [labelLength: lvHandle.labelLength, type: lvHandle.type, label: lvHandle.label, bootingInfo: lvHandle.bootingInfo, clientRootFile: lvHandle.clientRootFile]]; MarkerPageUnmap[]; END; Enter: PUBLIC ENTRY PROCEDURE [ drive: DiskChannel.Drive, physicalID: PhysicalVolume.ID] = BEGIN i: CARDINAL; FOR i IN [0..LENGTH[cache]) DO IF drive = cache[i].drive THEN { cache[i] ← [TRUE, drive, physicalID, File.nullID]; RETURN; }; ENDLOOP; FOR i IN [0..LENGTH[cache]) DO IF ~cache[i].occupied THEN { cache[i] ← [TRUE, drive, physicalID, File.nullID]; RETURN; }; ENDLOOP; MarkerPageError[cacheFull]; END; EnterMarkerID: PUBLIC ENTRY PROCEDURE [ c: MarkerPage.CacheKey, markerID: File.ID] = BEGIN ENABLE UNWIND => NULL; i: CARDINAL ← FindInternal[c]; cache[i].markerID ← markerID; END; -- Find is exported because some PhysicalVolume operations use it. Find: PUBLIC ENTRY PROCEDURE [c: MarkerPage.CacheKey] RETURNS [ drive: DiskChannel.Drive, physicalID: POINTER TO READONLY PhysicalVolume.ID, markerID: POINTER TO READONLY File.ID] = BEGIN ENABLE UNWIND => NULL; i: CARDINAL ← FindInternal[c]; RETURN[cache[i].drive, @cache[i].physicalID, @cache[i].markerID]; END; Flush: PUBLIC ENTRY PROCEDURE [c: MarkerPage.CacheKey] = BEGIN ENABLE UNWIND => NULL; i: CARDINAL ← FindInternal[c]; cache[i].occupied ← FALSE; END; GetNextPhysicalVolume: PUBLIC ENTRY PROCEDURE [thisPvID: PhysicalVolume.ID] RETURNS [nextPvID: PhysicalVolume.ID, drive: DiskChannel.Drive] = BEGIN i: CARDINAL; found: BOOLEAN ← (thisPvID = PhysicalVolume.nullID); FOR i IN [0..LENGTH[cache]) DO IF cache[i].occupied THEN IF found THEN RETURN[LOOPHOLE[cache[i].physicalID], cache[i].drive] ELSE found ← (thisPvID = LOOPHOLE[cache[i].physicalID]); ENDLOOP; IF found THEN RETURN[PhysicalVolume.nullID, DiskChannel.nullDrive] ELSE RETURN WITH ERROR PhysicalVolume.Error[physicalVolumeUnknown]; END; UpdateLogicalMarkerPages: PUBLIC ENTRY PROCEDURE [ lvHandle: LogicalVolume.Handle] = BEGIN svH: SubVolume.Handle ← NIL; lpage: LONG CARDINAL ← 0; found: BOOLEAN; WHILE lpage < lvHandle.volumeSize DO [found, svH] ← SubVolume.Find[lvHandle.vID, lpage]; IF ~found THEN ERROR MarkerPageError[subvolumeNotFound]; MarkerPageMap[ FindMarkerID[[drive[DiskChannel.GetAttributes[svH.channel].drive]]], svH.pvPage + svH.nPages]; marker.logical.bootingInfo ← lvHandle.bootingInfo; marker.logical.clientRootFile ← lvHandle.clientRootFile; MarkerPageUnmap[]; lpage ← svH.lvPage + svH.nPages; ENDLOOP; END; UpdatePhysicalMarkerPages: PUBLIC ENTRY PROCEDURE [ pvHandle: PhysicalVolumeFormat.Handle] = BEGIN i: CARDINAL; FOR i IN [0..pvHandle.subVolumeCount) DO OPEN sv: pvHandle.subVolumes[i]; MarkerPageMap[ FindMarkerID[[physicalID[pvHandle.pvID]]], sv.pvPage + sv.nPages]; marker.physical.bootingInfo ← pvHandle.bootingInfo; MarkerPageUnmap[]; ENDLOOP; END; -- Internal Procedures FindInternal: INTERNAL PROCEDURE [c: MarkerPage.CacheKey] RETURNS [i: CARDINAL] = BEGIN FOR i IN [0..LENGTH[cache]) DO IF cache[i].occupied THEN WITH c SELECT FROM drive => IF h = cache[i].drive THEN RETURN; physicalID => IF id = cache[i].physicalID THEN RETURN; ENDCASE => ERROR MarkerPageError[impossibleCacheVarient]; ENDLOOP; ERROR NotFound; END; FindMarkerID: INTERNAL PROCEDURE [c: MarkerPage.CacheKey] RETURNS [File.ID] = INLINE { RETURN[cache[FindInternal[c]].markerID]; }; MarkerPageMap: INTERNAL PROCEDURE [ID: File.ID, page: LONG CARDINAL] = BEGIN SimpleSpace.Map[ markerPageBuffer, [[ID, FileInternal.maxPermissions], page], FALSE]; END; MarkerPageUnmap: INTERNAL PROCEDURE = { SimpleSpace.Unmap[markerPageBuffer]; }; END..... LOG Time: October 1, 1979 12:20 PM By: Forrest Action: Created from volumeImpl.mesa Time: October 16, 1979 12:44 PM By: Forrest Action: Fix bug in Update SVM pages Time: May 20, 1980 4:14 PM By: Luniewski Action: PhysicalVolume => PhysicalVolumeFormat Time: July 24, 1980 9:14 AM By: Luniewski Action: Deleted Export to SpecialVolume. Made GetNextPhysicalVolume export to MarkerPage. Time: September 17, 1980 2:44 PM By: Luniewski Action: Added maxBadpages to marker page. Time: January 12, 1981 11:05 AM By: Luniewski Action: Changes for new LabelTransfer interface.