-- 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.