📄 dskalloc.c
字号:
return bno; } if ( ++bno >= end ) { return TSD_DB1_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_DB1_RTN_M1; } } while ( (m <<= 1U) != 0U ); } }}/* * Set the width bits from bno th bit of the block bit map bm to 1. * It must be that width > 0. */LOCAL void bitSet( 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_WRITE); m = (UB)(TSD_DAM_BIT_0X80 >> ((UW)bno & TSD_DAM_RSF_7)); do { *b |= m; if ( ++bno >= end ) { return; } } while ( (m >>= 1U) != 0U ); } } else { for ( ;; ) { b = bitMap(bm, (W)((UW)bno >> TSD_DAM_BSU_3), MD_WRITE); m = (UB)(TSD_DAM_BIT_0X01 << ((UW)bno & TSD_DAM_LSF_7)); do { *b |= m; if ( ++bno >= end ) { return; } } while ( (m <<= 1U) != 0U ); } }}/* * Set the width bits from bno th bit of the block bit map bm to 0. * It must be that width > 0. */LOCAL void bitClear( BitMapIO *bm, W bno, W width ){ W end = bno + width; UB *b, m; if ( bm->fsinfo->bigEndian != 0 ) { for ( ;; ) { b = bitMap(bm, (W)((UW)bno >> TSD_DAM_BSU_3), MD_WRITE); m = (UB)(TSD_DAM_BIT_0X80 >> ((UW)bno & TSD_DAM_RSF_7)); do { *b &= ~m; if ( ++bno >= end ) { return; } } while ( (m >>= 1) != 0U ); } } else { for ( ;; ) { b = bitMap(bm, (W)((UW)bno >> TSD_DAM_BSU_3), MD_WRITE); m = (UB)(TSD_DAM_BIT_0X01 << ((UW)bno & TSD_DAM_LSF_7)); do { *b &= ~m; if ( ++bno >= end ) { return; } } while ( (m <<= 1U) != 0U ); } }}/* * Find a contiguous free blocks of between or equal to blkunits and blklimit * in the area from bno th bit to just before end th bit of the block bit map bm, * and return the found blocks to *alloc. * When the free area is not found, return E_NODSK. The *alloc becomes undefined. */LOCAL ER blockSearch( LLogBlk *alloc, BitMapIO *bm, W bno, W end, W blkunits, W blklimit ){ W bsz; W maxcnt; while ( bno < end ) { /* Find a free block. */ bno = bitSearch0(bm, bno, end - bno); if ( bno < 0 ) { break; /* Not found. */ } /* Check how many blocks are free in a row. */ maxcnt = end - bno; if ( maxcnt > blklimit ) { maxcnt = blklimit; } bsz = bitSearch1(bm, bno, maxcnt); bsz = ( bsz < 0 )? (maxcnt): (bsz - bno); if ( bsz >= blkunits ) { /* Found. */ alloc->cnt = (UW)bsz; alloc->adr = (UW)bno; return E_OK; } bno += bsz; } /* Not found. */ return E_NODSK;}/* * Update the total number of used blocks. * Increase/Decrease the total number of used blocks of the file header by diff. * Update the number of free logical blocks of the system header too. */LOCAL ER changeUseBlockCount( W diff, OFCB *ofcb, FsInfo *fsinfo ){ DfFileHeader *fh; DfSystemHeader *sh; W nblk; STIME now; ID mid; ER err; if ( ofcb != NULL ) { /* Map the file header. */ fh = fmpMapDskAdr(ofcb->fhead, sizeof(DfFileHeader), ofcb, &mid, fsinfo); if ( fh == NULL ) { err = (ER)mid; goto err_ret; } /* Update the total number of use blocks. */ nblk = (W)fmpConvEndianW((UW)fh->nblk, fsinfo) + diff; fh->nblk = (W)fmpConvEndianW((UW)nblk, fsinfo); fmpUnmapDisk(mid, MD_WRITE); } /* Map the system header. */ sh = fmpMapDskAdrS(fsinfo->shead, sizeof(DfSystemHeader), MAP_SYS(fsinfo), &mid, fsinfo); if ( sh == NULL ) { err = (ER)mid; goto err_ret; } /* Update the number of free logical blocks. */ nblk = (W)fmpConvEndianW((UW)sh->nflb, fsinfo) - diff; sh->nflb = (W)fmpConvEndianW((UW)nblk, fsinfo); /* Update the date/time of the system block update. */ now = fmGetTime(); sh->mtime = (W)fmpConvEndianW((UW)now, fsinfo); fmpUnmapDisk(mid, MD_WRITE); err = fmpCheckDiskError(ofcb, fsinfo); if ( err < E_OK ) { goto err_ret; } return E_OK;err_ret: DEBUG_PRINT(("changeUseBlockCount err = %d\n", err)); return err;}/* * Reserve a contiguous blocks of up to blksize in steps of blkunits just after or near lblk. * Return the reserved logical blocks to *alloc. */LOCAL ER allocateBlock( LLogBlk *alloc, W blksize, W blkunits, UW lblk, OFCB *ofcb, FsInfo *fsinfo ){ BitMapIO bm; ER err; /* Prepare to access the use block bit map. */ err = openBitMap(&bm, fsinfo->usebm, fsinfo->nbmp, fsinfo); if ( err < E_OK ) { goto err_ret1; } /* Find a free block between lblk + 1 and the end. */ err = blockSearch(alloc, &bm, (W)(lblk + 1U), (W)fsinfo->nlb, blkunits, blksize); if ( err < E_OK ) { /* Find a free block between the start and lblk. */ err = blockSearch(alloc, &bm, 0, (W)(lblk + 1U), blkunits, blksize); } if ( err < E_OK ) { goto err_ret2; } err = fmpCheckDiskError(NULL, fsinfo); if ( err < E_OK ) { goto err_ret2; } if ( (W)alloc->cnt < blksize ) { /* Round down to the blkunits. */ alloc->cnt -= (alloc->cnt % (UW)blkunits); } /* Use bit ON */ bitSet(&bm, (W)alloc->adr, (W)alloc->cnt); err = closeBitMap(&bm); if ( err < E_OK ) { goto err_ret1; } /* Update the total number of use blocks. */ err = changeUseBlockCount((W)+alloc->cnt, ofcb, fsinfo); if ( err < E_OK ) { goto err_ret1; } return E_OK;err_ret2: (void)closeBitMap(&bm);err_ret1: DEBUG_PRINT(("allocateBlock err = %d\n", err)); return err;}/* * Reserve a contiguous logical blocks of size bytes insteps of units bytes * just after or near logical block number lblk. * Register the excess above the size bytes in the fragment table. * Return the reserved logical blocks and the byte count to *alloc and the return value respectively. * ofcb == NULL is not permitted. */EXPORT WER fmpAllocateBlock( LLogBlk *alloc, W size, W units, UW lblk, OFCB *ofcb ){ FsInfo *fsinfo = ofcb->fsinfo; W sblk = (W)fsinfo->sblk; W blksize = (size + sblk - 1) / sblk; W blkunits = (units + sblk - 1) / sblk; W keep; ER err; if ( blkunits > blksize ) { blkunits = blksize; } if ( blkunits < 1 ) { blkunits = 1; } /* Reserve the logical block. */ err = allocateBlock(alloc, blksize, blkunits, lblk, ofcb, fsinfo); if ( err < E_OK ) { goto err_ret; } keep = (W)alloc->cnt * sblk; if ( keep > size ) { /* Register the excess above the size bytes in the fragment table. */ UW blk = alloc->adr + alloc->cnt - 1U; W use = size % sblk; err = fmpAddFragment(blk, use, sblk, ofcb); if ( err < E_OK ) { goto err_ret; } keep = size; } return keep;err_ret: DEBUG_PRINT(("fmpAllocateBlock err = %d\n", err)); return err;}/* * Reserve one block just after or near logical block number lblk. * Return the reserved logical block number. * When ofcb != NULL, reserve it as a block belonging to the file of ofcb. * When ofcb == NULL, reserve it regardless of the file. */EXPORT WER fmpAllocateOneBlock( UW lblk, OFCB *ofcb, FsInfo *fsinfo ){ LLogBlk alloc; ER err; /* Reserve the logical block. */ err = allocateBlock(&alloc, 1, 1, lblk, ofcb, fsinfo); if ( err < E_OK ) { goto err_ret; } return (WER)alloc.adr;err_ret: DEBUG_PRINT(("fmpAllocateOneBlock err = %d\n", err)); return err;}/* * Release cnt logical blocks from lblk. */LOCAL ER freeBlock( UW lblk, W cnt, OFCB *ofcb, FsInfo *fsinfo ){ BitMapIO bm; ER err; /* Prepare to access the use block bit map. */ err = openBitMap(&bm, fsinfo->usebm, fsinfo->nbmp, fsinfo); if ( err < E_OK ) { goto err_ret; } /* Use bit OFF */ bitClear(&bm, (W)lblk, cnt); err = closeBitMap(&bm); if ( err < E_OK ) { goto err_ret; } /* Update the total number of use blocks. */ err = changeUseBlockCount(-cnt, ofcb, fsinfo); if ( err < E_OK ) { goto err_ret; } return E_OK;err_ret: DEBUG_PRINT(("freeBlock err = %d\n", err)); return err;}/* * Release the logical block of free. * If there is an entry corresponding to free in the fragment table, deregister it. * ofcb == NULL is not permitted. */EXPORT ER fmpFreeBlock( LLogBlk free, OFCB *ofcb ){ FsInfo *fsinfo = ofcb->fsinfo; DskAdr top, end; ER err; end = top = fmpLBlkToDAdr(free.adr, fsinfo); end.lblk += free.cnt; /* Deregister from the fragment table. */ err = fmpDeleteFragment(top, end, ofcb); if ( err < E_OK ) { goto err_ret; } /* Release the block. */ err = freeBlock(free.adr, (W)free.cnt, ofcb, fsinfo); if ( err < E_OK ) { goto err_ret; } return E_OK;err_ret: DEBUG_PRINT(("fmpFreeBlock err = %d\n" , err)); return err;}/* * Release one logical block of free. * The fragment table is not changed. * When ofcb != NULL, release it as a block belonging to the file of ofcb. * When ofcb == NULL, release it regardless of the file. */EXPORT ER fmpFreeOneBlock( UW free, OFCB *ofcb, FsInfo *fsinfo ){ ER err; /* Release the block. */ err = freeBlock(free, 1, ofcb, fsinfo); if ( err < E_OK ) { goto err_ret; } return E_OK;err_ret: DEBUG_PRINT(("fmpFreeOneBlock err = %d\n" , err)); return err;}/* * Release the data block. * Release the area from top th byte to just before end th byte of lblk. * When end is not a boundary of the logical block, * it must be at the position of separator code of the fragment. * When top is a boundary of the fragment, topf = TRUE. * In this case, it is merged with the free area located before top. * Return the number of unreleased remaining blocks of lblk * (The number of blocks between the start and top) to the return value. * ofcb == NULL is not permitted. */EXPORT WER fmpFreeDataBlk( LogBlk lblk, W top, W end, BOOL topf, OFCB *ofcb ){ W sblk = (W)ofcb->fsinfo->sblk; W useblk; UW topblk, endblk; W fcnt; ER err; /* The number of blocks to be remained. */ useblk = ( topf != 0 )? 0: ((top + sblk - 1) / sblk); topblk = lblk.adr + (UW)(top / sblk); endblk = lblk.adr + (UW)(end / sblk); top %= sblk; end %= sblk; if ( topblk != endblk ) { if ( end > 0 ) { /* Release up to end of endblk. */ err = fmpMergeFragment(endblk, NULL, 0, end, ofcb); if ( err < E_OK ) { goto err_ret; } } end = sblk; endblk--; } if ( (top == 0) || topf ) { /* Release (Merge) from top to end of topblk. */ err = fmpMergeFragment(topblk, NULL, top, end, ofcb); if ( err < E_OK ) { goto err_ret; } } else { /* Release from top to end of topblk */ err = fmpAddFragment(topblk, top, end, ofcb); if ( err < E_OK ) { goto err_ret; } } topblk++; fcnt = (W)(endblk - topblk + 1U); if ( fcnt > 0 ) { LLogBlk free; /* Release between topblk and endblk. */ free.adr = topblk; free.cnt = (UW)fcnt; err = fmpFreeBlock(free, ofcb); if ( err < E_OK ) { goto err_ret; } } return useblk;err_ret: DEBUG_PRINT(("fmpFreeDataBlk err = %d\n", err)); return err;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -