📄 dskalloc.c
字号:
if ( keep <= TSD_FRF_VAL_2 ) { /* Unable to allocate when there remains only 2 bytes or less of free area at the end of the block. */ return min(keep, size); } bp = fmpMapLogBlk(lblk, ofcb, &mid, fsinfo); if ( bp == NULL ) { err = (ER)mid; goto err_ret1; } /* Obtain the free size. */ free = (W)getBorder((UH*)(bp + use), fsinfo); err = fmpCheckDiskError(ofcb, fsinfo); if ( err < E_OK ) { goto err_ret2; } /* Obtain the size that can be allocated. */ if ( free >= size ) { keep = size; } else { if ( (use + free + TSD_FRF_OF_2) == fsinfo->sblk ) { /* In the case of the end of the block. */ free += TSD_FRF_SZ_2; keep = min(free, size); } else { keep = 0; } } if ( keep > 0 ) { DskAdr oldfrag, newfrag; /* Location of the fragment */ oldfrag = fmpLBlkToDAdr(lblk, fsinfo); oldfrag.offset = (VP)((VB*)oldfrag.offset + use + TSD_FRF_OF_2); newfrag.offset = (VP)((VB*)oldfrag.offset + keep); newfrag.lblk = oldfrag.lblk; use += keep; free -= keep; if ( use <= (fsinfo->sblk - TSD_FRF_VAL_2) ) { W freeEnd = use + free + TSD_FRF_SZ_2; /* Update the separator. */ setBorder((UH*)(bp + use), (UH)free, fsinfo); if ( freeEnd <= (fsinfo->sblk - TSD_FRF_VAL_2) ) { setBorder((UH*)(bp + freeEnd), (UH)free, fsinfo); } mflag = MD_WRITE; } /* Change the fragment size. */ err = fmpChangeFragment(oldfrag, newfrag, free, ofcb); if ( err < E_OK ) { goto err_ret2; } } fmpUnmapDisk(mid, mflag); err = fmpCheckDiskError(ofcb, fsinfo); if ( err < E_OK ) { goto err_ret1; } return keep;err_ret2: fmpUnmapDisk(mid, mflag);err_ret1: DEBUG_PRINT(("fmpResizeFragment err = %d\n", err)); return err;}/* * Merge the free areas. * Define the area from the start th byte to just before the end th byte of the logical block * lblk as a free space, and merge the space with the free areas before and after it. * If lblk is already mapped, set madr to the address. * Otherwise, set madr to NULL. * Return MD_WRITE when writing is performed to lblk. * Otherwise, return MD_RDONLY. * When err < E_OK, it is handled as MD_RDONLY. */EXPORT WER fmpMergeFragment( UW lblk, VP madr, W start, W end, OFCB *ofcb ){ FsInfo *fsinfo = ofcb->fsinfo; DskAdr dadr; VB *mp; DskAdr frag; W freeTop, freeEnd; W free; ID mid; UW mflag = MD_RDONLY; ER err; dadr = fmpLBlkToDAdr(lblk, fsinfo); if ( madr == NULL ) { mp = fmpMapLogBlk(lblk, ofcb, &mid, fsinfo); if ( mp == NULL ) { err = (ER)mid; goto err_ret1; } } else { mp = (VB*)madr; } /* Obtain the range of the merged free area. */ if ( start < TSD_MEF_VAL_2 ) { freeTop = 0; } else { free = (W)getBorder((UH*)(mp + start - TSD_MEF_VAL_2), fsinfo); freeTop = start - free - TSD_MEF_VAL_2; } if ( end > (fsinfo->sblk - TSD_MEF_VAL_2) ) { freeEnd = (W)fsinfo->sblk; } else { free = (W)getBorder((UH*)(mp + end), fsinfo); freeEnd = end + free + TSD_MEF_SZ_2; } free = freeEnd - freeTop; err = fmpCheckDiskError(ofcb, fsinfo); if ( err < E_OK ) { goto err_ret2; } if ( free < fsinfo->sblk ) { /* Change the fragment table. */ if ( (end + TSD_MEF_OF_2) < fsinfo->sblk ) { /* Deregister the lower fragment. */ frag.lblk = dadr.lblk; frag.offset = (VB*)dadr.offset + end + TSD_MEF_OF_2; err = fmpChangeFragment(frag, fmpLBlkToDAdr(0, fsinfo), 0, ofcb); if ( err < E_OK ) { goto err_ret2; } } /* Change the upper fragment. */ frag.lblk = dadr.lblk; frag.offset = (VB*)dadr.offset + freeTop; err = fmpChangeFragment(frag, frag, free, ofcb); if ( err < E_OK ) { goto err_ret2; } /* Set the separator code. */ if ( freeTop >= TSD_MEF_VAL_2 ) { setBorder((UH*)(mp + freeTop - TSD_MEF_VAL_2), (UH)free, fsinfo); mflag = MD_WRITE; } if ( freeEnd <= (fsinfo->sblk - TSD_MEF_VAL_2) ) { setBorder((UH*)(mp + freeEnd), (UH)free, fsinfo); mflag = MD_WRITE; } } else { /* Release whole block. */ LLogBlk fb; fb.cnt = 1; fb.adr = lblk; err = fmpFreeBlock(fb, ofcb); if ( err < E_OK ) { goto err_ret2; } } if ( madr == NULL ) { fmpUnmapDisk(mid, mflag); } return (WER)mflag;err_ret2: if ( madr == NULL ) { fmpUnmapDisk(mid, mflag); }err_ret1: DEBUG_PRINT(("fmpMergeFragment err = %d\n", err)); return err;}/* * Register the free area. * Register the area from use th byte to just before end th byte of blk * in the fragment table as a free area. * When end is not a boundary of the logical block, * it must be a position of separator code of the fragment. */LOCAL ER fmpAddFragment( UW blk, W use, W end, OFCB *ofcb){ FsInfo *fsinfo = ofcb->fsinfo; DskAdr newfrag, oldfrag; W free; VB *bp; ID mid; ER err; oldfrag = fmpLBlkToDAdr(blk, fsinfo); oldfrag.offset = (VP)((VB*)oldfrag.offset + use + TSD_MAF_OF_2); newfrag = oldfrag; bp = fmpMapLogBlk(blk, ofcb, &mid, fsinfo); if ( bp == NULL ) { err = (ER)mid; goto err_ret; } if ( end <= (fsinfo->sblk - TSD_MAF_VAL_2) ) { /* Merge the free spaces after end. */ oldfrag = fmpLBlkToDAdr(blk, fsinfo); oldfrag.offset = (VP)((VB*)oldfrag.offset + end + TSD_MAF_OF_2); end += getBorder((UH*)(bp + end), fsinfo) + TSD_MAF_OF_2; } free = end - use - TSD_MAF_VAL_2; /* Set the separator code. */ if ( use <= (fsinfo->sblk - TSD_MAF_VAL_2) ) { setBorder((UH*)(bp + use), (UH)free, fsinfo); if ( end <= (fsinfo->sblk - TSD_MAF_VAL_2) ) { setBorder((UH*)(bp + end), (UH)free, fsinfo); } } fmpUnmapDisk(mid, MD_WRITE); err = fmpCheckDiskError(ofcb, fsinfo); if ( err < E_OK ) { goto err_ret; } /* Update the fragment table. */ err = fmpChangeFragment(oldfrag, newfrag, free, ofcb); if ( err < E_OK ) { goto err_ret; } return E_OK;err_ret: DEBUG_PRINT(("fmpAddFragment err = %d\n", err)); return err;}/* * Deregister the entry of top <= locate < end from the fragment table. */LOCAL ER fmpDeleteFragment( DskAdr top, DskAdr end, OFCB *ofcb ){ FsInfo *fsinfo = ofcb->fsinfo; DfFileHeaderBlock *fh; Fragment frag; W i, j, nent; ID mid; UW mflag = MD_RDONLY; ER err; /* Map the fragment table (File header). */ fh = fmpMapDskAdr(ofcb->fhead, (W)ofcb->ridxofs, ofcb, &mid, fsinfo); if ( fh == NULL ) { err = (ER)mid; goto err_ret; } /* The number of entries of the fragment table. */ nent = N_FragEnt(ofcb); /* While deleting target entries, close the following entries. */ j = 0; for ( i = 0; i < nent; ++i ) { getFragment(&frag, fh, i, fsinfo); if ( frag.size == 0 ) { break; } if ( i > j ) { setFragment(fh, j, &frag, fsinfo); } if ( (CmpDskAdr(frag.locate, top) < 0) || (CmpDskAdr(frag.locate, end) >= 0) ) { j++; } } if ( j < nent ) { mflag = MD_WRITE; } frag.locate.offset = 0; frag.locate.lblk = 0; frag.size = 0; while ( j < nent ) { setFragment(fh, j++, &frag, fsinfo); } fmpUnmapDisk(mid, mflag); err = fmpCheckDiskError(ofcb, fsinfo); if ( err < E_OK ) { goto err_ret; } return E_OK;err_ret: DEBUG_PRINT(("fmpDeleteFragment err = %d\n", err)); return err;}/* ======================================================================== *//* * Use block bit map related *//* * Start to access the block bit map. * Prepare to access the block bit map that has the size of nbmp bytes * starting from the position bmadr on the disk. * Set bm to the information for access. * The call side must prepare the area for bm and hold the area * until closeBitMap() is executed. */LOCAL ER openBitMap( BitMapIO *bm, DskAdrS bmadr, W nbmp, FsInfo *fsinfo ){ memset(bm, 0, (size_t)sizeof(BitMapIO)); bm->fsinfo = fsinfo; bm->bmadr = bmadr; bm->nbmp = nbmp; bm->idx = N_BM_MAPINFO - 1; return E_OK;}/* * Obtain one byte from the block bit map. * Return the address at offset th byte from the start of the block bit map. * This address is the memory address of the data on the disk being mapped to the memory. * Only the one byte width can be accessed validly. The access to the bytes before and * after it is not permitted. This address is valid until bitMap() is called next time and * can not be accessed after that. * When writing to the returned address, it must be that mflag = MD_WRITE. * Otherwise, mflag = MD_RDONLY. An error is not returned in this call. * If an error occurs, the information is held, and the error is returned * when closeBitMap() is executed. */LOCAL UB* bitMap( BitMapIO *bm, W offset, UW mflag ){ struct bm_mapinfo *mi; W n, nb; DskAdrS mapadr; FsInfo *fsinfo = bm->fsinfo; ER err; /* Find from the ones already mapped. */ for ( mi = bm->mi; mi < &bm->mi[N_BM_MAPINFO]; mi++ ) { if ( mi->mid == 0 ) { continue; } n = offset - mi->offset; if ( (n >= 0) && (n < mi->nbyte) ) { /* Some are already mapped. */ mi->mflag |= mflag; return mi->mapbase + n; } } /* Nothing is mapped. */ bm->idx = (bm->idx + 1) % N_BM_MAPINFO; mi = &bm->mi[bm->idx]; if ( mi->mid != 0 ) { /* Unmap the ones already mapped now. */ fmpUnmapDisk(mi->mid, mi->mflag); mi->mid = 0; } /* Perform a new mapping. */ nb = (W)(fsinfo->sblk - ((UW)bm->bmadr % fsinfo->sblk)); if ( offset < nb ) { /* First logical block */ mapadr = bm->bmadr; } else { /* Logical blocks after the first one */ nb = (W)fsinfo->sblk; mapadr = (UB*)bm->bmadr + offset; mapadr = (DskAdrS)((UB*)mapadr - ((UW)mapadr % fsinfo->sblk)); } mi->offset = (UB*)mapadr - (UB*)bm->bmadr; n = bm->nbmp - mi->offset; if ( nb > n ) { nb = n; } mi->nbyte = nb; mi->mapbase = fmpMapDskAdrS(mapadr, nb, MAP_SYS(fsinfo), &err, fsinfo); if ( mi->mapbase == NULL ) { goto err_ret; } mi->mid = (ID)err; mi->mflag = mflag; return mi->mapbase + (offset - mi->offset);err_ret: bm->error = err; DEBUG_PRINT(("bitMap err = %d\n", err)); return &bm->dummy;}/* * Finish accessing the block bit map. */LOCAL ER closeBitMap( BitMapIO *bm ){ struct bm_mapinfo *mi; ER err; /* Unmap all. */ for ( mi = bm->mi; mi < &bm->mi[N_BM_MAPINFO]; mi++ ) { if ( mi->mid == 0 ) { continue; } fmpUnmapDisk(mi->mid, mi->mflag); } err = fmpCheckDiskError(NULL, bm->fsinfo); if ( err < E_OK ) { bm->error = err; DEBUG_PRINT(("closeBitMap err = %d\n", err)); } return bm->error;}/* * Search the width bits from bno th bit of the block bit map bm, * and return the position where bit 0 is first found. If not found, return -1. * It must be that width > 0. */LOCAL W bitSearch0( BitMapIO *bm, W bno, W width ){ W end = bno + width; UB b, m; if ( bm->fsinfo->bigEndian != 0U ) { for ( ;; ) { b = *bitMap(bm, (W)((UW)bno >> TSD_DAM_BSU_3), MD_RDONLY); m = (UB)(TSD_DAM_BIT_0X80 >> ((UW)bno & TSD_DAM_RSF_7)); do { if ( (b & m) == 0U ) { return bno; } if ( ++bno >= end ) { return TSD_DB0_RTN_M1; } } while ( (m >>= 1U) != 0U ); } } else { for ( ;; ) { b = *bitMap(bm, (W)((UW)bno >> TSD_DAM_BS_3), MD_RDONLY); m = (UB)(TSD_DAM_BIT_0X01 << ((UW)bno & TSD_DAM_LSF_7)); do { if ( (b & m) == 0U ) { return bno; } if ( ++bno >= end ) { return TSD_DB0_RTN_M1; } } while ( (m <<= 1U) != 0U ); } }}/* * Search the width bits from bno th bit of the block bit map bm, * and return the position where bit 1 is first found. If not found, return -1. * It must be that width > 0. */LOCAL W bitSearch1( BitMapIO *bm, W bno, W width ){ W end = bno + width; UB b, m; if ( bm->fsinfo->bigEndian != 0U ) { for ( ;; ) { b = *bitMap(bm, (W)((UW)bno >> TSD_DAM_BS_3), MD_RDONLY); m = (UB)(TSD_DAM_BIT_0X80 >> ((UW)bno & TSD_DAM_RSF_7)); do { if ( (b & m) != 0U ) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -