📄 segio.c
字号:
} /* Register newly */ free->tid = mytid; free->errhdr = errhdr; UnlockSEG(); return E_OK;err_ret: UnlockSEG(); DEBUG_PRINT(("_NotifyDiskErr err = %d\n", err)); return err;}/* ------------------------------------------------------------------------ *//* * Disk I/0 routine */EXPORT UW MaxPageIO; /* Maximum number of pages available for consecutive input/output */LOCAL VP DiskIOSpace; /* Disk I/O space *//* * Read/write pfe page frames * cmd = TDC_READ read * cmd = TDC_WRITE write */EXPORT ER ReadWritePFE( PFE *pfe, W cmd ){ DBN dbn; DE *de; VB *adr; PTE pte; W n, sz; ER err; /* Disk blocks to be used */ dbn.id = pfe->dbn_id; dbn.no = pfe->dbn_no; if ( dbn.id == PAGEFILE_ID ) { /* In the case of page file, convert into real disk block numbers. */ dbn = PageFileDBN(dbn); } de = toDiskEntry(dbn.id); /* Map page frames to input/output space. */ pte.w = PTE_DISKIO; pte.c.pfa = PFEtoPFA(pfe); (void)CHG_PTE(DiskIOSpace, 0, pte.w, 0, TRUE); adr = DiskIOSpace; n = (W)de->blkcnt; /* Limit to blocks within the real disk. */ if ( dbn.no < 0 ) { adr -= de->info.blocksize * dbn.no; n += dbn.no; dbn.no = 0; } if ( (dbn.no + n) > de->info.blockcont ) { n = de->info.blockcont - dbn.no; } /* Read/write */ if ( cmd == TDC_READ ) { err = tk_srea_dev(de->devid, dbn.no, adr, n, &sz); } else { err = tk_swri_dev(de->devid, dbn.no, adr, n, &sz); } /* Flush cache */ if ( cmd == TDC_READ ) { WriteBackDCachePage(adr, 0); } else { InvalidateCachePage(adr, 0); } if ( err < E_OK ) { goto err_ret; } if ( sz != n ) { err = E_IO; goto err_ret; } pfe->upd = FALSE; /* Disk content matches memory content. */ return E_OK;err_ret: /* Record error in PFE. */ pfe->err = TRUE; if ( pfe->dbn_id != PAGEFILE_ID ) { /* Call error handler */ CallErrHdr(pfe, err); } DEBUG_PRINT(("ReadWritePFE err = %d\n", err)); return err;}/* * Read/write pfe page frames linked to pfe_q * cmd = TDC_READ read * cmd = TDC_WRITE write * All page frames must be read/written to/from the * same disk (same pfe->dbn.id). */EXPORT ER ReadWritePFE_IndQue( IndQueTop *pfe_q, W cmd ){ IndQue *q; PFE *pfe; DE *de; DBN dbn, top_dbn, prev_dbn; VB *adr, *end_adr; W blk, cnt, sz; PTH pth; PTE pte; ER err, error = E_OK; q = NextIndQue(pfe_q, NULL); if ( q == NULL ) { return E_OK; /* Queue is empty. */ } pfe = q->ent; if ( pfe->dbn_id == PAGEFILE_ID ) { /* Page file */ de = PageFileDE(); } else { /* Disk map */ de = toDiskEntry(pfe->dbn_id); } /* Map page frames to input/output space. */ InitPTH(&pth, DiskIOSpace, 0); pte.w = PTE_DISKIO; q = NULL; while ( (q = NextIndQue(pfe_q, q)) != NULL ) { pfe = q->ent; err = NextPTE(&pth); if ( err < E_OK ) { EndPTH(&pth, FALSE); goto err_ret1; } pte.c.pfa = PFEtoPFA(pfe); SetPTE(&pth, pte.w, FALSE); } EndPTH(&pth, TRUE); /* Input/output consecutive disk blocks as a whole. */ prev_dbn.id = 0; q = NULL; end_adr = (adr = DiskIOSpace) + (pfe_q->num * PAGESIZE); while ( adr < end_adr ) { q = NextIndQue(pfe_q, q); if ( q != NULL ) { pfe = q->ent; dbn.id = pfe->dbn_id; dbn.no = pfe->dbn_no; if ( dbn.id == PAGEFILE_ID ) { dbn = PageFileDBN(dbn); } if ( prev_dbn.id == 0 ) { /* First */ top_dbn = prev_dbn = dbn; continue; } if ( (prev_dbn.no + de->blkcnt) == dbn.no ) { /* Consecutive */ prev_dbn = dbn; continue; } } blk = top_dbn.no; cnt = prev_dbn.no - top_dbn.no + de->blkcnt; /* Limit to blocks within the real disk. */ if ( blk < 0 ) { adr -= de->info.blocksize * blk; cnt += blk; blk = 0; } if ( (blk + cnt) > de->info.blockcont ) { cnt = de->info.blockcont - blk; } /* Read/write */ if ( cmd == TDC_READ ) { err = tk_srea_dev(de->devid, blk, adr, cnt, &sz); } else { err = tk_swri_dev(de->devid, blk, adr, cnt, &sz); } if ( err < E_OK ) { goto err_ret2; } if ( sz != cnt ) { err = E_IO; goto err_ret2; } cnt = prev_dbn.no - blk + de->blkcnt; adr += cnt * de->info.blocksize; top_dbn = prev_dbn = dbn; } /* Set update flag */ adr = DiskIOSpace; q = NULL; while ( (q = NextIndQue(pfe_q, q)) != NULL ) { pfe = q->ent; pfe->upd = FALSE; /* Disk content matches memory content. */ /* Flush cache */ if ( cmd == TDC_READ ) { WriteBackDCachePage(adr, 0); } else { InvalidateCachePage(adr, 0); } adr += PAGESIZE; } return E_OK;err_ret2: adr = DiskIOSpace; q = NULL; while ( (q = NextIndQue(pfe_q, q)) != NULL ) { if ( cmd == TDC_READ ) { WriteBackDCachePage(adr, 0); } else { InvalidateCachePage(adr, 0); } adr += PAGESIZE; }err_ret1: DEBUG_PRINT(("ReadWritePFE_IndQue err = %d\n", err)); /* Retry page by page */ q = NULL; while ( (q = NextIndQue(pfe_q, q)) != NULL ) { pfe = q->ent; err = ReadWritePFE(pfe, cmd); if ( err < E_OK ) { error = err; } } return error;}/* ------------------------------------------------------------------------ *//* * DiskEntry-related *//* * Obtain free DiskEntry. */LOCAL DE* getDiskEntry( void ){ DE *de; for ( de = &DiskEntryTable[0]; de < &DiskEntryTable[MaxDiskEntry]; de++ ) { if ( de->devid == 0 ) { return de; } } return NULL; /* No free space. */}/* * Check DiskID. */EXPORT DE* checkDiskID( ID diskid ){ DE *de; if ( (diskid < 1) || (diskid > (W)MaxDiskEntry) ) { return NULL; /* Out of range */ } de = toDiskEntry(diskid); if ( de->devid == 0 ) { return NULL; /* Unused entry */ } return de;}/* * Release DiskEntry. */Inline void releaseDiskEntry( DE *de ){ de->devid = 0; /* Indicate unused state. */}/* * Connect to file system * Open (connect) a logical device (disk) specified * by devname[L_DEVNM] in omode-specified mode. * When "pinfo != NULL", check if *pinfo process has a right to access * the devname logical device in omode-specified mode, and open the disk * only if it has the access right. * Return information on the connected disk as diskinfo. * Return diskid (> 0) as a function value. * * (*) Note that page fault may occur when access is made to *devname * or *diskinfo. * (*) The current version does not include checking of access right in omode. */EXPORT WER _AttachFS( TC *devname, UW omode, PINFO *pinfo, DiskInfo *diskinfo ){ UB devnm[L_DEVNM + 1]; DE *de; ID devid; DiskInfo dinfo; VP memadr; W sz; ER err; /* Convert device name: TC -> ASCII */ if ( (tcstoeucs(NULL, devname) > L_DEVNM) || (tcstoeucs(devnm, devname) < 0) ) { err = E_PAR; goto err_ret1; } /* Disk connection */ devid = tk_opn_dev(devnm, TD_UPDATE|TD_WEXCL|TD_NOLOCK); if (( devid == E_RONLY )&&( (omode & D_WRITE) == 0U )) { devid = tk_opn_dev(devnm, TD_READ|TD_WEXCL|TD_NOLOCK); } if ( devid < E_OK ) { err = ERtoERR(devid); goto err_ret1; } /* Obtain disk information */ err = tk_srea_dev(devid, DN_DISKINFO, &dinfo, sizeof(DiskInfo), &sz); if ( err < E_OK ) { err = ERtoERR(err); goto err_ret2; } if ( dinfo.blocksize == 0 ) { /* Unformatted */ err = E_IO; goto err_ret2; } /* Obtain the first address of memory disk area. */ err = tk_srea_dev(devid, DN_DISKMEMADR, &memadr, sizeof(memadr), &sz); if ( err < E_OK ) { /* Not memory disk/not supported */ memadr = INVADR; } else { if ( ((UW)memadr % (UW)PAGESIZE) != 0U ) { /* First address is not located on a page boundary; unable to support. */ memadr = INVADR; } } LockFS(); LockSEG(); /* Obtain free DiskEntry */ de = getDiskEntry(); if ( de == NULL ) { err = E_LIMIT; goto err_ret3; } /* Set disk management information */ de->devid = devid; de->info = dinfo; de->memadr = memadr; de->blkcnt = (UH)(PAGESIZE / dinfo.blocksize); de->lbsz = 0; de->pbadj = 0; if ( de->blkcnt <= 0 ) { err = E_SYS; goto err_ret4; } UnlockSEG(); UnlockFS(); *diskinfo = dinfo; return toDiskID(de);err_ret4: releaseDiskEntry(de);err_ret3: UnlockSEG(); UnlockFS();err_ret2: (void)tk_cls_dev(devid, 0) ;err_ret1: DEBUG_PRINT(("_AttachFS err = %d\n", err)); return err;}/* * Disconnect file system * Close (disconnect) disk specified by diskid. * When "pinfo != NULL", close the disk only if *pinfo process has a right * to access the specified disk. * Unmap all areas mapped for specified disks and perform synchronous * processing of the disks (SyncFS). * If the device is ejectable, eject it when set at "eject = TRUE". * * (*) The current version does not include checking of access right. */EXPORT ER _DetachFS( ID diskid, PINFO *pinfo, BOOL eject ){ DE *de; ID devid; ER err, error = E_OK; LockFS(); LockSEG(); de = checkDiskID(diskid); if ( de == NULL ) { error = E_ID; goto err_ret2; } if ( ((pfinfo.fd > 0) && (pfinfo.de == de))#if USE_PROCESS_MANAGER || (ChkSysProgMap(diskid) != 0)#endif ) { /* Disk cannot be disconnected while page files are * still in use or a system program is mapped. * In such a case, perform disk synchronization only. */ err = SyncDisk(de, 0, SYNCONLY); error = ( err < E_OK )? ERtoERR(err): E_BUSY; goto err_ret2; } /* Synchronize file system and cancel page frame. */ err = SyncDisk(de, 0, FORCEDEL); if ( err < E_OK ) { error = ERtoERR(err); } devid = de->devid; /* Release DiskEntry */ releaseDiskEntry(de); UnlockSEG(); UnlockFS(); /* Disconnect disk */ err = tk_cls_dev(devid, ( eject != 0 )? TD_EJECT: 0); if ( err < E_OK ) { error = ERtoERR(err); } if ( error < E_OK ) { goto err_ret1; } return E_OK;err_ret2: UnlockSEG(); UnlockFS();err_ret1: DEBUG_PRINT(("_DetachFS err = %d\n", error)); return error;}/* * Check right to access file system * Check if *pinfo process has a right to access the devname * logical device in omode-specified mode. */EXPORT ER _CheckFS( TC *devname, UW omode, PINFO *pinfo ){ /* The current version does not include checking of access right. */ return E_OK;}/* * Notify file system information * Notify the file management of information on the file system of * diskid disk. * If mapping is performed to diskid disk, * E_BUSY is returned. * If yet-to-be-written disk blocks remain, write them all to the disk. * Discard all of cached disk blocks. * * (*) Note that page fault may occur when access is made to *spec. */EXPORT ER _InformFS( ID diskid, FsSpec *spec ){ FsSpec fspec; DE *de; ER err; fspec = *spec; LockFS(); LockSEG(); de = checkDiskID(diskid); if ( de == NULL ) { err = E_ID; goto err_ret; } /* Parameter check */ if (( (fspec.lbsz % de->info.blocksize) != 0 ) ||( (fspec.btsz % de->info.blocksize) != 0 )) { err = E_PAR; goto err_ret; } /* Synchronize file system and cancel cache. */ err = SyncDisk(de, 0, DISCARD); if ( err < E_OK ) { err = ERtoERR(err); goto err_ret; } /* Set file system information. * In the case of memory disk, alignment of logical blocks cannot be corrected, * so pbadj is always 0. */ de->lbsz = fspec.lbsz; de->pbadj = ( de->memadr != INVADR )? (H)0: (H)(((W)fspec.lbsz - (W)fspec.btsz) / de->info.blocksize); UnlockSEG(); UnlockFS(); return E_OK;err_ret: UnlockSEG(); UnlockFS(); DEBUG_PRINT(("_InformFS err = %d\n", err)); return err;}/* * Synchronize file system * Write yet-to-be-written data in a file system specified diskid * to the disk. * info == 0: Write all yet-to-be-written data. * info != 0: Write yet-to-be-written data that meets the following conditions: * (mode.info == info || mode.info == 0) * mode.info : Map information specified during mapping */EXPORT ER _SyncFS( ID diskid, VW info ){ DE *de; ER err; LockFS(); LockSEG(); de = checkDiskID(diskid); if ( de == NULL ) { err = E_ID; goto err_ret; } err = SyncDisk(de, info, SYNCONLY); if ( err < E_OK ) { err = ERtoERR(err); goto err_ret; } UnlockSEG(); UnlockFS(); return E_OK;err_ret: UnlockSEG(); UnlockFS(); DEBUG_PRINT(("_SyncFS err = %d\n", err)); return err;}/* ------------------------------------------------------------------------ *//* * Disk I/O related initialization * (Immediately after kernel startup) */EXPORT ER InitSegIO( void ){ W val[TSD_ISI_VAL_5]; VP p; ER err; /* Obtain SYSCONF definition information. */ err = GetSysConf_bms((UB*)"MaxDiskID", val, 1); if ( err < E_OK ) { goto err_ret; } MaxDiskEntry = (UW)val[0]; err = GetSysConf_bms((UB*)"MaxMapEH", val, 1); if ( err < E_OK ) { goto err_ret; } MaxErrHdrEntry = (UW)val[0]; err = GetSysConf_bms((UB*)"MaxPageIO", val, 1); if ( err < E_OK ) { goto err_ret; } MaxPageIO = (UW)val[0]; if ( MaxPageIO <= 0U ) { MaxPageIO = 1; /* At least one page */ } /* Create/initialize disk management information table */ p = Icalloc(MaxDiskEntry, sizeof(DE)); if ( p == NULL ) { err = E_NOMEM; goto err_ret; } DiskEntryTable = p; /* Create/initialize error handler management information table */ p = Icalloc(MaxErrHdrEntry, sizeof(EHE)); if ( p == NULL ) { err = E_NOMEM; goto err_ret; } ErrHdrEntryTable = p; /* Obtain disk I/O space */ p = AllocMemorySpace((W)MaxPageIO, 0); if ( p == NULL ) { err = E_NOMEM; goto err_ret; } err = __MakeSpace(p, (W)MaxPageIO, 0, PTE_DISKIO); if ( err < E_OK ) { goto err_ret; } DiskIOSpace = p; return E_OK;err_ret: BMS_DEBUG_PRINT(("InitSegIO err = %d\n", err)); return err;}/* ======================================================================== *//* * Debug support function */#if DEBUGFUNC_SUPPORT/* * Indicate state of page file */EXPORT void DumpPageFile( void ){ W used; used = ( pfinfo.npage == 0 )? 0: pfinfo.use * TSD_DPF_VAL_100 / pfinfo.npage; printf("PAGE FILE: Total %d Use %d [%d%% used]\n", pfinfo.npage, pfinfo.use, used);}#endif /* DEBUGFUNC_SUPPORT */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -