// IfsDiskError.bcpl -- Disk error reporting // Copyright Xerox Corporation 1982 // Last modified October 3, 1982 2:18 PM by Taft get "Ifs.decl" get "IfsSystemInfo.decl" get "IfsFiles.decl" get "IfsDirs.decl" get "Disks.d" get "Tfs.d" external [ // outgoing procedures InitDiskError; RecordDiskError; InterpretDiskError // incoming procedures VFileReadPage; VFileWritePage; LockCell; UnlockCell Ws; PutTemplate; Plural; Zero // outgoing statics newDiskErrorReported // incoming statics infoVMD ] static [ newDiskErrorReported = false ] structure DE: // hard disk errors, recorded in dePage of <System>Info [ numErrors word // total number of errors numSameError word // number of consecutive occurrences of this error cb @CB // copy of disk command block at time of error ec word // TFS error code haveDR word // following information is valid fsID @DirName // name of file system in which error occurred dr @DR // copy of directory record for file suffering error ] manifest lenDE = size DE/16 compileif lenDE gr 1 lshift logStdPageLength then [ Barf("DE structure too large for one IFS page") ] manifest maxLenDR = maxLenDRHeader+lenPathName+lenDIFRec //---------------------------------------------------------------------------- let InitDiskError() be //---------------------------------------------------------------------------- [ let de = VFileWritePage(infoVMD, dePage) Zero(de, lenDE) newDiskErrorReported = false ] //---------------------------------------------------------------------------- and RecordDiskError(cb, fd, ec) be //---------------------------------------------------------------------------- // Records a disk error that has occurred. // cb is the disk command block for which the error occurred. // fd, if nonzero, is alleged to designate the file in which the error occurred. // ec is the TFS error code. [ let de = VFileWritePage(infoVMD, dePage) de>>DE.numErrors = de>>DE.numErrors+1 test MultEq(lv cb>>CB.diskAddress, lv de>>DE.cb.diskAddress, 3) // disk address & drive ifso de>>DE.numSameError = de>>DE.numSameError+1 ifnot de>>DE.numSameError = 1 MoveBlock(lv de>>DE.cb, cb, lCB) de>>DE.ec = ec de>>DE.haveFD = false if fd ne 0 then [ let fs = fsQ!0 while fs ne 0 do [ if fd>>FD.fs eq fs & fs>>IFS.lpdt↑(fd>>FD.dr>>DR.unit) eq cb>>CB.cbz>>CBZ.disk then [ MoveBlock(lv de>>DE.fsID, fs>>IFS.id, fs>>IFS.id>>String.length rshift 1 +1) MoveBlock(lv de>>DE.dr, fd>>FD.dr, Min(fd>>FD.dr>>DR.length, maxLenDR)) de>>DE.haveFD = true break ] fs = fs!0 ] ] newDiskErrorReported = true ] //---------------------------------------------------------------------------- and InterpretDiskError(s) be //---------------------------------------------------------------------------- [ let de = VFileReadPage(infoVMD, dePage) LockCell(lv de) if de>>DE.numErrors ne 0 then [ PutTemplate(s, "Unrecoverable disk error (code = $UD) on drive $UD, cyl $UD, hd $UD, sec $UD*n", de>>DE.ec, de>>DE.cb.drive, de>>DE.cb.track, de>>DE.cb.head, de>>DE.cb.sector) PutTemplate(s, "Command: header = $P, label = $P, data = $P*n", InterpCmd, de>>DE.cb.CommH, InterpCmd, de>>DE.cb.CommL, InterpCmd, de>>DE.cb.CommD) PutTemplate(s, "Status: header = $UO, label = $UO, data = $UO*n", de>>DE.cb.StatusH, de>>DE.cb.StatusL, de>>DE.cb.StatusD) let block = lv de>>DE.cb.CommH for rec = 0 to 2 do [ let status = block>>KCBblock.Status if (status & dstErrors) ne 0 then [ let interp = status<<DST.ECCerror? "checksum (ECC)", status<<DST.CompErr? "compare", 0 if interp ne 0 then PutTemplate(s, "Interpretation: $S error in $S field*n", interp, selecton rec into [ case 0: "header"; case 1: "label"; case 2: "data"]) ] block = block+lKCBbl ] PutTemplate(s, "Total of $UD error$S", de>>DE.numErrors, Plural(de>>DE.numErrors)) if de>>DE.numSameError ugr 1 then PutTemplate(s, ", including $UD consecutive occurrence$S of this error", de>>DE.numSameError, Plural(de>>DE.numSameError)) ] UnlockCell(lv de) ] //---------------------------------------------------------------------------- and InterpCmd(s, cmd) be //---------------------------------------------------------------------------- PutTemplate(s, (selecton cmd into [ case 0: "no-op" case diskRead: "read" case diskWrite: "write" case diskCheck: "check" default: "?[$UO]" ], cmd)