// IfsDDMgrSwap.bcpl -- Trident DiskDescriptor manager - swappable // Copyright Xerox Corporation 1979, 1980, 1981, 1982 // Last modified April 9, 1982 11:59 AM by Taft get "IfsDDMgr.decl" external [ // Outgoing procedures IFSCreateDDMgr; FlushKDs IFSOpenDD; IFSCloseDD; IFSLockDD; IFSUnlockDD; IFSReadDDPage // Incoming procedures DDDOPAGEIO; DDPageType; DDPageGroupAlign; DDPageGroupBase; DDPageGroupSize TFSWriteDiskDescriptor AllocateVMem; FreeVMem; LockCell; @VRRP; @VWRP Lock; Unlock; Allocate; Free; Zero; MoveBlock; Noop; SysErr // Outgoing statics ddVMI // Incoming statics sysZone; fsQ; ifsDDMgr ] static ddVMI //---------------------------------------------------------------------------- let IFSCreateDDMgr() = valof //---------------------------------------------------------------------------- // Creates the DDMgr for IFS, which manages DD pages through VMem. [ // Create and initialize the DDMgr let ddMgr = Allocate(sysZone, lenIFSDDMgr) Zero(ddMgr, lenIFSDDMgr) ddMgr>>IFSDDMgr.OpenDD = IFSOpenDD ddMgr>>IFSDDMgr.LockDD = IFSLockDD ddMgr>>IFSDDMgr.ReadDDPage = IFSReadDDPage ddMgr>>IFSDDMgr.UnlockDD = IFSUnlockDD ddMgr>>IFSDDMgr.FlushDD = Noop ddMgr>>IFSDDMgr.CloseDD = IFSCloseDD ddMgr>>IFSDDMgr.DestroyDDMgr = SysErr LockCell(lv ddMgr>>IFSDDMgr.buffer) // Create and initialize the DD Virtual Memory Interface ddVMI = Allocate(sysZone, lenVMI) ddVMI>>VMI.DOPAGEIO = DDDOPAGEIO ddVMI>>VMI.CleanupLocks = Noop ddVMI>>VMI.PageType = DDPageType ddVMI>>VMI.PageGroupAlign = DDPageGroupAlign ddVMI>>VMI.PageGroupBase = DDPageGroupBase ddVMI>>VMI.PageGroupSize = DDPageGroupSize ddVMI>>VMI.type = vmiTypeDD resultis ddMgr ] // Procedures called by TFS through the DDMgr object //---------------------------------------------------------------------------- and IFSLockDD(ddMgr, disk) be Lock(lv ddMgr>>IFSDDMgr.lock, true) //---------------------------------------------------------------------------- // Locks the DDMgr (waits if it is already locked) //---------------------------------------------------------------------------- and IFSUnlockDD(ddMgr, disk, dirty; numargs na) be //---------------------------------------------------------------------------- // If dirty is true, dirties the buffer. // Then unlocks the buffer and unlocks the DDMgr. [ if na ge 3 & dirty then [ VWRP(ddMgr>>IFSDDMgr.vPage) disk>>IFSDSK.dirty = true // KD likely to have changed ] ddMgr>>IFSDDMgr.buffer = 0 Unlock(lv ddMgr>>IFSDDMgr.lock) ] //---------------------------------------------------------------------------- and IFSReadDDPage(ddMgr, disk, page) = valof //---------------------------------------------------------------------------- // Reads the specified DD page and locks the resulting buffer. [ ddMgr>>IFSDDMgr.buffer = 0 // Unlock previous page if any ddMgr>>IFSDDMgr.vPage = disk>>IFSDSK.vmd>>VMD.base + page lshift logDDPageGroupSize ddMgr>>IFSDDMgr.buffer = VRRP(ddMgr>>IFSDDMgr.vPage) resultis ddMgr>>IFSDDMgr.buffer ] //---------------------------------------------------------------------------- and IFSOpenDD(ddMgr, disk) be //---------------------------------------------------------------------------- // Creates a VMD for referencing the DD pages on this disk [ let vmd = Allocate(sysZone, lenDDVMD) AllocateVMem(vmd, ddVMI, maxDDVMPages) vmd>>DDVMD.disk = disk disk>>IFSDSK.vmd = vmd // Record the initial state of this disk's KD in unused portion of page 1 IFSLockDD(ddMgr, disk) MoveBlock(lv (IFSReadDDPage(ddMgr, disk, 1))>>IFSKD.initialKD, lv disk>>TFSDSK.kd, lTFSKDHeader) IFSUnlockDD(ddMgr, disk, true) ] //---------------------------------------------------------------------------- and IFSCloseDD(ddMgr, disk) be //---------------------------------------------------------------------------- // Destroys the DDVMD for this disk [ FreeVMem(disk>>IFSDSK.vmd) Free(sysZone, disk>>IFSDSK.vmd) ] //---------------------------------------------------------------------------- and FlushKDs() be //---------------------------------------------------------------------------- // Procedure called every 15 seconds to flush to disk any TFSKDs that may // have changed in interesting ways. // Caller must have locked openLock to prevent the file system structure // changing out from under us. // Note that the IFSDSK.dirty word (unused by TFS) // is used as an indication that some "interesting" activity has occurred, // most likely an allocation or deallocation, which could cause // the lastSN and/or lastPageAlloc to change. [ // Force full TFSKD flush every 15 min ifsDDMgr>>IFSDDMgr.flushTimer = (ifsDDMgr>>IFSDDMgr.flushTimer+1) rem 60 // Enumerate all file systems. This deliberately does not catch any disks // that are not part of a file system. Such disks might not be using // the IFSDDMgr at all. let fs = fsQ!0 while fs ne 0 do [ for unit = 0 to fs>>IFS.numUnits-1 do [ let disk = fs>>IFS.lpdt^unit if disk>>IFSDSK.dirty % ifsDDMgr>>IFSDDMgr.flushTimer eq 0 then [ TFSWriteDiskDescriptor(disk) disk>>IFSDSK.dirty = false ] ] fs = fs!0 ] ]