DIRECTORY BootFile USING[ DiskFileID, Location ], Disk USING[ Channel, invalid, Label, labelCheck, ok, PageNumber, PageCount, Status], DiskFace USING[ DontCare, RelID], File USING[ FP, FileID, Handle, nullFP, PageCount, PageNumber, PropertyStorage, RC, Volume, VolumeFile, VolumeFlusher, VolumeID ], Rope USING[ ROPE ], VolumeFormat USING[ LogicalPage, LogicalPageCount, LogicalRoot, LogicalRun, LogicalRunObject, LVBootFile, PVBootFile, RunPageCount, VAMObject ], PhysicalVolume USING[ Physical, PhysicalRC, SubVolumeDetails ], VMBacking USING[ Run, RunTableObject ]; FileInternal: CEDAR DEFINITIONS = BEGIN -- ******** Data Types and minor subroutines ******** -- --File.--FileID: TYPE = RECORD[INT]; --File.--VolumeObject: TYPE = MONITORED RECORD[ rest: REF VolumeObject _ NIL, id: File.VolumeID, subVolumes: LIST OF PhysicalVolume.SubVolumeDetails, initialised: BOOL _ FALSE, destroyed: BOOL _ FALSE, root: LONG POINTER TO VolumeFormat.LogicalRoot _ NIL, rootStatus: File.RC _ inconsistent, vamStatus: File.RC _ inconsistent, vamChanged: BOOL _ FALSE, checkpointing: BOOL _ TRUE, name: Rope.ROPE _ NIL, size: VolumeFormat.LogicalPageCount, free: VolumeFormat.LogicalPageCount _ 0, vam: VAM _ NIL, vamFile: File.Handle _ NIL, lastFileID: FileID _ NULL, freeboard: INT _ 0, flusher: File.VolumeFlusher _ NIL, flusherData: REF ANY _ NIL, flushing: BOOL _ FALSE]; Handle: TYPE = REF Object; --File.--Object: PUBLIC TYPE = MONITORED RECORD[ fp: File.FP _ File.nullFP, -- fp.id is immutable; fp.da is under the per-file interlock volume: File.Volume _ NIL, -- immutable rest: Handle _ NIL, -- chain in file hash table used by FileTableImpl inside its monitor reissued: BOOL _ FALSE, -- marker used by FileTableImpl inside its monitor users: INT _ 0, -- per-file shared/exclusive interlock. Accessed under FileImpl monitor lock state: { none, opened, deleted } _ none, headerVMPages: INT _ 0, -- how many to free headerVM: LONG POINTER _ NIL, properties: File.PropertyStorage _ NIL, size: File.PageCount _ 0, logicalRunTable: LONG POINTER TO VolumeFormat.LogicalRunObject _ NIL, runTable: RunTable _ NIL ]; RunTable: TYPE = REF VMBacking.RunTableObject; PhysicalRun: TYPE = VMBacking.Run; TranslateStatus: PROC[status: Disk.Status] RETURNS [File.RC] = INLINE BEGIN RETURN[ SELECT status FROM Disk.ok => ok, Disk.labelCheck => software, Disk.invalid => wentOffline, ENDCASE => hardware ] END; LockAndCloseFiles: PROC; UnlockFiles: PROC; LockVolume: PROC[volume: File.Volume]; ReadRootPage: PROC[volume: File.Volume]; InitRootPage: PROC[volume: File.Volume, name: Rope.ROPE] RETURNS[File.RC]; LockMode: TYPE = { shared, exclusive }; Lock: PROC[file: Handle, mode: LockMode]; Unlock: PROC[file: Handle]; -- ******** Bad page table ******** -- PhysicalPageBad: PROC[physical: PhysicalVolume.Physical, address: Disk.PageNumber] RETURNS[ PhysicalVolume.PhysicalRC ]; GetBadPages: PROC[subVolume: PhysicalVolume.SubVolumeDetails, work: PROC[VolumeFormat.LogicalPage]]; -- ******** Access to volume root page and volume's list of sub-volumes ******** -- TranslateLogicalRun: PROC[logicalRun: VolumeFormat.LogicalRun, volume: File.Volume] RETURNS[channel: Disk.Channel, diskPage: Disk.PageNumber]; RecordRootFile: PROC[volume: File.Volume, root: File.VolumeFile, fp: File.FP, page: File.PageNumber, id: DiskFace.RelID, link: DiskFace.DontCare, channel: Disk.Channel]; NewID: PROC[volume: File.Volume] RETURNS [File.FileID]; WriteLogicalMarkers: PROC[volume: File.Volume] RETURNS[File.RC]; InitLogicalMarkers: PROC[volume: File.Volume] RETURNS[File.RC]; -- ******** Volume Allocation Map ******** -- VAM: TYPE = LONG POINTER TO VolumeFormat.VAMObject; Alloc: PROC[volume: File.Volume, first: VolumeFormat.LogicalPage, size, min: VolumeFormat.LogicalPageCount] RETURNS[given: VolumeFormat.LogicalRun]; Free: PROC[volume: File.Volume, logicalRun: VolumeFormat.LogicalRun]; Commit: PROC[volume: File.Volume]; Flush: PROC[volume: File.Volume, lack: VolumeFormat.LogicalPageCount] RETURNS[BOOL]; -- ******** Header and Run-table management ******** -- GetHeaderVM: PROC[file: Handle, runs: CARDINAL]; FreeHeaderVM: PROC[file: Handle]; TranslateLogicalRunTable: PROC[file: Handle] RETURNS[ File.PageCount ]; AddRun: PROC[file: Handle, run: POINTER TO PhysicalRun, logicalPage: VolumeFormat.LogicalPage, okPages: VolumeFormat.RunPageCount]; LastLogicalPage: PROC[file: Handle] RETURNS [VolumeFormat.LogicalPage]; RemoveFromRunTable: PROC[file: Handle, remove: INT]; FindRun: PROC[start: File.PageNumber, nPages: File.PageCount, runTable: RunTable] RETURNS[diskPage: Disk.PageNumber, size: Disk.PageCount, channel: Disk.Channel]; RegisterVMFile: PROC[file: File.Handle]; -- ******** Operations involving access to pages within a volume ******** -- FreeRun: PROC[logicalRun: VolumeFormat.LogicalRun, volume: File.Volume, verifyLabel: POINTER TO Disk.Label _ NIL]; EnumeratePagesProc: TYPE = PROC[status: Disk.Status, da: VolumeFormat.LogicalPage, label: POINTER TO Disk.Label] RETURNS[exit: BOOL _ FALSE]; EnumeratePages: PROC[volume: File.Volume, start: VolumeFormat.LogicalPage, work: EnumeratePagesProc]; -- ******** Global table of file objects ******** -- AllocForCreate: PROC RETURNS[Handle]; Insert: PROC [Handle]; DontInsert: PROC; Lookup: PROC [volume: File.Volume, fp: File.FP] RETURNS[Handle]; -- ******** Boot Locations ******** -- GetFileLocation: PROC [file: File.Handle, firstPage: File.PageNumber] RETURNS[location: BootFile.Location]; GetLogicalLocation: PROC [volume: File.Volume, root: VolumeFormat.LVBootFile] RETURNS[location: BootFile.Location]; GetPhysicalLocation: PROC [physical: PhysicalVolume.Physical, root: VolumeFormat.PVBootFile] RETURNS[location: BootFile.Location]; SetPhysicalLocation: PROC [physical: PhysicalVolume.Physical, root: VolumeFormat.PVBootFile, diskFileID: BootFile.DiskFileID] RETURNS[PhysicalVolume.PhysicalRC]; END. ÚCedar Nucleus (Files): internal interface FileInternal.mesa Andrew Birrell December 7, 1983 6:10 pm Last Edited by: Levin, August 8, 1983 5:54 pm The remaining fields (and fp.da) are accessed only under the per-file interlock, or during initialization or finalization of the object -- ******** Checkpoint and Rollback (and ReadRootPage) ******** -- Lock all existing file objects, and ensure next access will re-open them; suspend future file object creations. Unlock existing file objects and allow creation of new ones. Lock volume to suspend subsequent access to its monitored data or VAM file; unlock by calling ReadRootPage. Reads the volume's VAM from disk and records free page count; unlocks if volume was locked for a checkpoint. Writes a root page for the volume. Size and ID are taken from "volume", name is as given. Other fields of "volume" and the root page are initialised, but no VAM is created. On normal exit (reulst is "ok"), the volume is well enough initialized that calling EraseVolume will succeed; equally, it is well enough initialized that the rootStatus will be ok in some subsequent run. Result comes from the write of the root page (and is kept as volume.rootStatus). Unlocks if volume was locked for a checkpoint. Acquire lock on file (for use by LockAndCloseFiles in FileTableImpl) Release previously acquired lock on file (for use by UnlockFiles in FileTableImpl) Record page as bad in the physical volume root Enumerate the bad pages in the subvolume Gives physical-volume-relative data for a logical-volume-relative run Records the root file in the logical volume root page. Issues a new unique ID, ensuring all issued ID's are recorded in the volume root Replicates critical logical root information in the volume marker pages. See PhysicalVolumeImpl. Replicates critical logical root information in the volume marker pages. See PhysicalVolumeImpl. Must be called only from InitRootPage: see comment beside implementation of this procedure. This mess is caused by the physical and logical marker info being on a single page. Find a logical run marked free in the in-core VAM. May be smaller than "size", but is never smaller than "min" Mark the logical run free in the in-core VAM. Ensure the volume's VAM is up to date on disk Try to ensure there are at least "lack" free pages on the volume by running any volume flusher. Returns TRUE iff it might have succeeded. Allocate VM for a file's header, initializing file.logicalRunTable. Free VM that was used for file's header. Copy file's logical run table into newly allocated physical run table. Add pages to the file's physical and logical run tables Returns the logical page number of the last page of the file. Removes pages from the file's physical and logical run tables Find the physical location of contiguous initial subset of the given pages of the file. Write labels of specified pages marking them as "free". High speed enumeration of page labels. Calls "work" sequentially with successive page labels. Tries its best to avoid missing disk revolutions. Allocate an object, but don't place it in the table. Insert the object into the table (after successful creation). Note that a handle returned from AllocForCreate has been abandoned Look-up the [volume,fp] in the table, inserting if needed. Get location for passing to germ. Also writes bootchain links into the file. Get location of the appropriate logical root file Get location of the appropriate physical root file Set location of the appropriate physical root file Ê$˜Jšœ*™*Jšœ™Jšœ(™(J™-šÏk ˜ Jšœ œ˜'JšœœJ˜TJšœ œ˜!JšœœœBœ0˜‚Jšœœœ˜Jšœ œ~˜Jšœœ+˜?Jšœ œ˜'—J˜Jšœœ œ˜!J˜Jš˜J˜J˜JšÏc8˜8˜Jšž œœœœ˜$J˜šž œœ œœ˜/Jšœœœ˜Jšœ˜Jšœ œœ!˜4Jšœ œœ˜Jšœ œœ˜Jš œœœœœ˜5Jšœœ˜#Jšœœ˜"Jšœ œœ˜Jšœœœ˜Jšœ œœ˜J˜$J˜(Jšœœœ˜Jšœœ˜Jšœœ˜Jšœ œ˜Jšœœ˜"Jšœ œœœ˜Jšœ œœ˜—J˜Jšœœœ˜J˜š ž œœœ œœ˜0Jšœ œž<˜WJšœœž ˜'JšœœžD˜XJšœ œœž2˜JJšœœžM˜]Jšœ9žœ8™‡Jšœ(˜(Jšœœž˜+Jšœ œœœ˜Jšœ#œ˜'Jšœ˜Jšœœ!œ˜EJšœœ˜—J˜Jšœ œœ˜.J˜Jšœ œ˜"J˜šÏnœœœ ˜EJš˜šœ˜šœ˜J˜J˜J˜Jšœ˜——Jšœ˜J˜J˜—J˜J˜—Jšž œ*ž ™B˜šŸœœ˜Jšœo™o—J˜šŸ œœ˜Jšœ<™<—J˜šŸ œœ˜&Jšœl™l—J˜šŸ œœ˜(Jšœl™l—J˜š Ÿ œœ!œœœ˜JJšœþ™þ—J˜Jšœ œ˜'J˜šŸœœ˜)JšœD™D—J˜šŸœœ˜JšœR™RJ™J˜—J˜J˜—Jšž&˜&˜šŸœœ>œ˜xJ™.——˜šŸ œœ3œ˜dJ™(J˜J˜—J˜J˜—JšžS˜S˜šŸœœ:˜Sšœ3˜:JšœE™E——J˜šŸœœ6œ]˜©Jšœ6™6—J˜šŸœœœ˜7JšœP™P—J˜šŸœœœœ˜@J™aJ˜—šŸœœœœ˜?J™”J˜J˜—J˜J˜—Jšž-˜-˜Jš œœœœœ˜3J˜šŸœœ6˜AJ˜)šœ!˜(Jšœo™o——J˜šŸœœ;˜EJšœ-™-—J˜šŸœœ˜"Jšœ-™-—J˜šŸœœ;œœ˜TJšœŠ™ŠJ˜J˜J˜—J˜J˜—Jšž7˜7˜šŸ œœœ˜0JšœC™C—J˜šŸ œœ˜!Jšœ(™(—J˜šŸœœœ˜GJšœF™F—J˜šŸœœ˜Jšœœœ ˜J˜&šœ$˜$Jšœ7™7——J˜šŸœœœ˜GJšœ=™=—J˜šŸœœœ˜4Jšœ=™=—J˜šŸœœD˜QšœI˜PJšœW™W——J˜šŸœœ˜(J˜—J˜J˜—JšžL˜L˜š ŸœœHœœœ˜rJšœ7™7—J˜JšŸœœœ;œœ œœœ˜J˜šŸœœQ˜eJšœ‘™‘J˜—J˜J˜—Jšž4˜4˜šŸœœœ ˜%J™4—J˜šŸœœ ˜J™=—J˜šŸ œœ˜JšœB™B—J˜šŸœœ œœ ˜@J™;J˜J˜—J˜J˜—Jšž&˜&˜šŸœœ1œ˜kJ™M—J˜šŸœœ6œ˜sJ™1—J˜šŸœœDœ˜‚J™2—J˜šŸœœeœ˜¡J™2—J˜—Jšœ˜J˜J˜—…—*-(