📄 maprec.c
字号:
/* *---------------------------------------------------------------------- * T-Kernel / Standard Extension * * Copyright (C) 2006 by Ken Sakamura. All rights reserved. * T-Kernel / Standard Extension is distributed * under the T-License for T-Kernel / Standard Extension. *---------------------------------------------------------------------- * * Version: 1.00.00 * Released by T-Engine Forum(http://www.t-engine.org) at 2006/8/11. * *---------------------------------------------------------------------- *//* * maprec.c (file) * * File management * Record map */#include "fileio.h"#include "mcb.h"#include "diskio.h"LOCAL MCB* fmpNewMCB( FD *fd, RCB *rcb );LOCAL void fmpDeleteMCB( MCB *mcb );LOCAL VP mapLBlks( LBlks *lb, W mode, PINFO *pinfo, OFCB *ofcb, ID_ERR *mid );LOCAL WER mapRecord( FD *fd, RCB *rcb, OFCB *ofcb, FM_MAP_REC_PARA *cmdPara );#define TSD_MLB_VAL_M1 (-1)/* * Newly generate MCB. * Generate MCB to map the record of rcb that is opened with fd. */LOCAL MCB* fmpNewMCB( FD *fd, RCB *rcb ){ MCB *mcb; /* Reserve a memory. */ mcb = Vmalloc(sizeof(MCB)); if ( mcb == NULL ) { return NULL; } /* Link to fd and rcb. */ QueInsert(&mcb->fdq, &fd->mcbq); QueInsert(&mcb->rcbq, &rcb->mcbq); return mcb;}/* * Delete MCB */LOCAL void fmpDeleteMCB( MCB *mcb ){ /* Delete the links from fd and rcb. */ QueRemove(&mcb->fdq); QueRemove(&mcb->rcbq); /* Release the memory. */ Vfree(mcb);}/* ------------------------------------------------------------------------ *//* * Perform mapping according to the block list. */LOCAL VP mapLBlks( LBlks *lb, W mode, PINFO *pinfo, OFCB *ofcb, ID_ERR *mid ){ PhyBlk *blks, *p; LogBlk *lblk; W nlblk; W prev; MapMode mapmode; FsInfo *fsinfo = ofcb->fsinfo; W blkRatio = (W)fsinfo->blkRatio; ER err;#ifdef CanNotMapRecord /* When the record map can not be performed at all. */ err = E_NOSPT; goto err_ret1;#endif#ifdef MappableBlockSize /* When the logical block size that can be mapped is restricted. */ if ( (fsinfo->sblk % MappableBlockSize) != 0 ) { err = E_NOSPT; goto err_ret1; }#endif /* The number of entries of the logical block list */ nlblk = fmpNLBlks(lb); if ( nlblk <= 0 ) { err = E_SYS; goto err_ret1; } /* Reserve the storing area of the physical block list. */ blks = (PhyBlk*)Kmalloc((UW)(nlblk + 1) * sizeof(PhyBlk)); if ( blks == NULL ) { err = E_SYSMEM; goto err_ret1; } /* Convert from the logical block list into physical block list. */ p = blks; lblk = NULL; prev = TSD_MLB_VAL_M1; while ( fmNextLBlks(lb, &lblk) != 0 ) { if ( lblk->adr == prev ) { /* It is continued from the previous block. */ (p - 1)->len += (UW)(lblk->cnt * blkRatio); } else { p->blk = (UW)((lblk->adr * blkRatio) + fsinfo->pbadj); p->len = (UW)(lblk->cnt * blkRatio); p++; } prev = lblk->adr + lblk->cnt; } p->len = 0; /* Map mode */ mapmode.resv = 0; mapmode.rank = MapRankFM3; mapmode.real = 0; mapmode.clear = MapNoClr; mapmode.addr = INVADR; mapmode.info = (VW)ofcb; switch ( (UW)mode & (UW)F_SYSTEM ) { case F_SYSTEM: /* System space */ mapmode.level = MapSystem; mapmode.space = 0; break; case F_COMMON: /* Shared space */ mapmode.level = MapUser; mapmode.space = 0; break; default: /* Local space */ mapmode.level = MapUser; mapmode.space = GetLSID(pinfo); break; } if ( ((UW)mode & F_READ ) != 0U ) { mapmode.level |= MapRead; } if ( ((UW)mode & F_WRITE ) != 0U ) { mapmode.level |= MapWrite; } if ( ((UW)mode & F_EXCUTE) != 0U ) { mapmode.level |= MapExecute; } /* Mapping */ err = MapDisk(fsinfo->dskid, blks, &mapmode); if ( err < E_OK ) { goto err_ret2; } *mid = (ID)err; Kfree(blks); return mapmode.addr;err_ret2: fmpResetDiskError(err, ofcb, fsinfo); if ( err == E_TMOUT ) { err = E_SYSMEM; } Kfree(blks);err_ret1: DEBUG_PRINT(("mapLBlks err = %d\n", err)); *mid = err; return NULL;}/* * Map the data record. */LOCAL WER mapRecord( FD *fd, RCB *rcb, OFCB *ofcb, FM_MAP_REC_PARA *cmdPara ){ MCB *mcb; LBlks lb; W offset; VB *mp; ID mid; ER err; /* Obtain MCB. */ mcb = fmpNewMCB(fd, rcb); if ( mcb == NULL ) { err = E_SYSMEM; goto err_ret1; } /* Prepare the block list. */ err = fmNewLBlks(&lb); if ( err < E_OK ) { goto err_ret2; } /* Create the block list of record. */ offset = fmpMakeLBlks(&lb, rcb, cmdPara->offset, cmdPara->size, ofcb); if ( offset < 0 ) { err = (ER)offset; goto err_ret2; } /* Map the record */ mp = mapLBlks(&lb, cmdPara->mode, fd->pinfo, ofcb, &mid); if ( mp == NULL ) { err = (ER)mid; goto err_ret3; } mp += offset; /* Release the block list. */ fmDeleteLBlks(&lb); /* Set MCB. */ mcb->mid = mid; mcb->mode = cmdPara->mode; *cmdPara->addr = mp; return mid;err_ret3: fmDeleteLBlks(&lb);err_ret2: fmpDeleteMCB(mcb);err_ret1: DEBUG_PRINT(("mapRecord err = %d\n", err)); return err;}/* * Record map */EXPORT void fmpMapRecord( FmCmdPkt *pkt ){ FM_MAP_REC_PARA *cmdPara = (FM_MAP_REC_PARA*)pkt->cmd.para; FD *fd; OFCB *ofcb; RCB *rcb; UW chkmode; ER err; /* Obtain FD and OFCB. */ fd = getFDp(cmdPara->fd); ofcb = fd->ofcb; /* Parameter check */ if ( (((UW)cmdPara->mode & ~(UW)(F_READ|F_WRITE|F_EXCUTE|F_SYSTEM)) != 0) || (((UW)cmdPara->mode & (F_READ|F_WRITE|F_EXCUTE)) == 0U) || (cmdPara->offset < 0) || (cmdPara->size <= 0) ) { err = E_PAR; goto err_ret; } err = CheckSpaceRW(cmdPara->addr, sizeof(B*)); if ( err < E_OK ) { goto err_ret; } /* Removal disks can not be mapped. Mapping can not be performed in the disk recovery mode. */ if ( ofcb->fsinfo->dskInfo.removable || _isFsrcvMode() ) { err = E_NOSPT; goto err_ret; } /* Check the open mode. */ chkmode = 0; if ( ((UW)cmdPara->mode & F_WRITE) != 0U ) { chkmode |= F_WRITE; } if ( ((UW)cmdPara->mode & (F_READ|F_EXCUTE)) != 0U ) { chkmode |= F_READ; } err = fmpCheckFileOpenMode(fd, chkmode); if ( err < E_OK ) { goto err_ret; } /* Obtain the current record. */ err = fmpSetRCB(rcb = fd->crcb, ofcb); if ( err < E_OK ) { goto err_ret; } /* Link record can not be mapped. */ if ( isLinkRecord(rcb->rtype) != 0 ) { err = E_REC; goto err_ret; } /* The current record size must not be exceeded. */ if ( ((UW)cmdPara->offset + (UW)cmdPara->size) > (UW)rcb->rsize ) { err = E_PAR; goto err_ret; } /* Record map */ err = mapRecord(fd, rcb, ofcb, cmdPara); if ( err < E_OK ) { goto err_ret; } pkt->cmd.ret = err; /* Map ID */ return;err_ret: DEBUG_PRINT(("fmpMapRecord err = %d\n", err)); pkt->cmd.ret = err; return;}/* * Release the record map. */EXPORT void fmpUnmapRecord( FmCmdPkt *pkt ){ FM_UMP_REC_PARA *cmdPara = (FM_UMP_REC_PARA*)pkt->cmd.para; FD *fd; MCB *mcb; OFCB *ofcb; ER err, error = E_OK; /* Obtain FD and OFCB. */ fd = getFDp(cmdPara->fd); ofcb = fd->ofcb; /* Retrieve MCB. */ mcb = (MCB*)QueSearch(&fd->mcbq, &fd->mcbq, cmdPara->mapid, (W)offsetof(MCB, mid)); if ( mcb == (MCB*)&fd->mcbq ) { error = E_NOEXS; goto err_ret; } /* Release the map. */ fmpUnmapDisk(mcb->mid, (((UW)mcb->mode & F_WRITE) != 0U )? MD_WRITE: MD_RDONLY); err = fmpCheckDiskError(ofcb, ofcb->fsinfo); if ( err < E_OK ) { error = err; } /* Update the time stamp. */ err = fmpSetTimeStamp(ofcb, (UW)mcb->mode); if ( err < E_OK ) { error = err; } /* Delete MCB. */ fmpDeleteMCB(mcb);err_ret:DO_DEBUG( if ( error < E_OK ) { DEBUG_PRINT(("fmpUnmapRecord err = %d\n", error)); }) pkt->cmd.ret = error; setSyncAtExit(SAE_OPENF, ofcb->fsinfo); return;}/* * Release the map of all records of fd. */EXPORT ER fmpUnmapAllRecord( FD *fd, OFCB *ofcb ){ MCB *mcb; UW mode = 0; ER err, error = E_OK; while ( !isQueEmpty(&fd->mcbq) ) { mcb = (MCB*)fd->mcbq.next; /* Release the map. */ fmpUnmapDisk(mcb->mid, (((UW)mcb->mode & F_WRITE) != 0U )? MD_WRITE: MD_RDONLY); mode |= (UW)mcb->mode; /* Delete MCB. */ fmpDeleteMCB(mcb); } err = fmpCheckDiskError(ofcb, ofcb->fsinfo); if ( err < E_OK ) { error = err; } /* Update the time stamp. */ err = fmpSetTimeStamp(ofcb, mode); if ( err < E_OK ) { error = err; }DO_DEBUG( if ( error < E_OK ) { DEBUG_PRINT(("fmpUnmapAllRecord err = %d\n", error)); }) return error;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -