/* Establish the file system and write it to disk */ int fs_format(mem_sblock_t sbp) { blocknum_t inode_bitmap_size; blocknum_t block_bitmap_size; blocknum_t i; sbp->filesys_lock = semaphore_new(1); if (NULL == sbp->filesys_lock) { return -1; } fs_lock(sbp); /* Format super block */ sblock_get(maindisk, sbp); sblock_format(sbp, disk_size); sblock_update(sbp); /* Format inode and block bitmaps */ inode_bitmap_size = sbp->inode_bitmap_last - sbp->inode_bitmap_first + 1; sbp->inode_bitmap = malloc(inode_bitmap_size * DISK_BLOCK_SIZE); block_bitmap_size = sbp->block_bitmap_last - sbp->block_bitmap_first + 1; sbp->block_bitmap = malloc(block_bitmap_size * DISK_BLOCK_SIZE); if (NULL == sbp->block_bitmap || NULL == sbp->inode_bitmap) { semaphore_V(sbp->filesys_lock); return -1; } /* Clear bitmaps */ bitmap_zeroall(sbp->inode_bitmap, inode_bitmap_size * BITS_PER_BLOCK); bitmap_zeroall(sbp->block_bitmap, block_bitmap_size * BITS_PER_BLOCK); /* Set file system blocks to be occupied */ for (i = 0; i <= sbp->block_bitmap_last; ++i) { bitmap_set(sbp->block_bitmap, i); } /* Set inode 0 to be occupied */ bitmap_set(sbp->inode_bitmap, 0); /* Push updates to disk */ for (i = sbp->inode_bitmap_first; i <= sbp->inode_bitmap_last; ++i) { bpush(i, (char*) sbp->inode_bitmap + (i - sbp->inode_bitmap_first) * DISK_BLOCK_SIZE); } for (i = sbp->block_bitmap_first; i <= sbp->block_bitmap_last; ++i) { bpush(i, (char*) sbp->block_bitmap + (i - sbp->block_bitmap_first) * DISK_BLOCK_SIZE); } /* Count free inodes and free blocks */ mainsb->free_inodes = bitmap_count_zero(mainsb->inode_bitmap, mainsb->total_inodes); mainsb->free_blocks = bitmap_count_zero(mainsb->block_bitmap, mainsb->disk_num_blocks); fs_unlock(sbp); return 0; }
void balblk() { BTint val,llink,rlink,cblk; int nkeys,cnkeys,result,diff; char tkey[ZKYLEN]; cblk = btact->cntxt->lf.lfblk; /* get parent block */ btact->cntxt->lf.lfpos = bpull(); btact->cntxt->lf.lfblk = bpull(); nkeys = bgtinf(btact->cntxt->lf.lfblk,ZNKEYS); cnkeys = bgtinf(cblk,ZNKEYS); if (btact->cntxt->lf.lfpos < nkeys) { /* check right sister block */ bsrhbk(btact->cntxt->lf.lfblk,tkey,&btact->cntxt->lf.lfpos,&val, &llink,&rlink,&result); if (result != 0) { bterr("BALBLK",QBALSE,NULL); goto fin; } nkeys = bgtinf(rlink,ZNKEYS); diff = cnkeys-nkeys; if (abs(diff) > (int)(ZMXKEY/2)) { balbk1(cblk,rlink,diff,tkey,val); goto fin; } } if (btact->cntxt->lf.lfpos > 0) { /* check left sister block */ btact->cntxt->lf.lfpos--; bsrhbk(btact->cntxt->lf.lfblk,tkey,&btact->cntxt->lf.lfpos, &val,&llink,&rlink,&result); if (result != 0) { bterr("BALBLK",QBALSE,NULL); goto fin; } nkeys = bgtinf(llink,ZNKEYS); diff = nkeys-cnkeys; if (abs(diff) > (int)(ZMXKEY/2)) { balbk1(llink,cblk,diff,tkey,val); goto fin; } btact->cntxt->lf.lfpos++; } /* no balancing possible; restore original environment */ bpush(btact->cntxt->lf.lfblk); bpush(btact->cntxt->lf.lfpos); btact->cntxt->lf.lfblk = cblk; fin: return; }
/* * Allocate a free inode and return a pointer to free inode * Return NULL if fail. */ inodenum_t ialloc(disk_t* disk) { inodenum_t free_bit = -1; inodenum_t block_offset = -1; fs_lock(mainsb); if (mainsb->free_inodes <= 0) { fs_unlock(mainsb); return -1; } /* Get free inode number */ free_bit = bitmap_next_zero(mainsb->inode_bitmap, mainsb->disk_num_blocks); block_offset = free_bit / BITS_PER_BLOCK; if (free_bit < 0 || block_offset >= mainsb->disk_num_blocks) { fs_unlock(mainsb); return -1; } /* Set the free inode to used */ bitmap_set(mainsb->inode_bitmap, free_bit); bpush(block_offset + mainsb->inode_bitmap_first, (char*) mainsb->inode_bitmap + block_offset * DISK_BLOCK_SIZE); mainsb->free_inodes--; fs_unlock(mainsb); return free_bit; }
/* Set a block to used */ void bset(blocknum_t blocknum) { blocknum_t bit = -1; blocknum_t block_offset; fs_lock(mainsb); if (blocknum <= mainsb->block_bitmap_last || blocknum >=mainsb->disk_num_blocks) { fs_unlock(mainsb); return; } /* Set the block to free */ bit = blocknum; block_offset = bit / BITS_PER_BLOCK; if (bitmap_get(mainsb->block_bitmap, bit) == 0) { bitmap_set(mainsb->block_bitmap, bit); bpush(block_offset + mainsb->block_bitmap_first, (char*) mainsb->block_bitmap + block_offset * DISK_BLOCK_SIZE); mainsb->free_blocks--; } fs_unlock(mainsb); }
/* Get a free block number from the disk and mark the block used */ blocknum_t balloc(disk_t* disk) { blocknum_t free_bit = -1; blocknum_t block_offset = -1; /* Get super block */ fs_lock(mainsb); if (mainsb->free_blocks <= 0) { fs_unlock(mainsb); return -1; } /* Get free block number */ free_bit = bitmap_next_zero(mainsb->block_bitmap, mainsb->disk_num_blocks); block_offset = free_bit / BITS_PER_BLOCK; if (block_offset < 0 || block_offset >= mainsb->disk_num_blocks) { fs_unlock(mainsb); return -1; } /* Set the free block to used */ bitmap_set(mainsb->block_bitmap, free_bit); bpush(block_offset + mainsb->block_bitmap_first, (char*) mainsb->block_bitmap + block_offset * DISK_BLOCK_SIZE); mainsb->free_blocks--; fs_unlock(mainsb); return free_bit; }
/* Add an inode back to free list */ void ifree(inodenum_t inum) { blocknum_t bit = -1; blocknum_t block_offset; fs_lock(mainsb); /* Set the inode to free */ bit = inum; block_offset = bit / BITS_PER_BLOCK; if (bitmap_get(mainsb->inode_bitmap, bit) == 1) { mainsb->free_inodes++; } bitmap_clear(mainsb->inode_bitmap, bit); bpush(block_offset + mainsb->inode_bitmap_first, (char*) mainsb->inode_bitmap + block_offset * DISK_BLOCK_SIZE); fs_unlock(mainsb); }
int bfndky(BTA *b,char *key,BTint *val) { BTint cblk, link1, link2, newblk; int index, result, nkeys, status; char lkey[ZKYLEN]; bterr("",0,NULL); status = QNOKEY; if ((result=bvalap("BFNDKY",b)) != 0) return(result); btact = b; /* set context pointer */ if (btact->shared) { if (!block()) { bterr("BFNDKY",QBUSY,NULL); goto fin; } } /* take local copy of key, truncating if necessary */ strncpy(lkey,key,ZKYLEN); lkey[ZKYLEN-1] = '\0'; /* initialise stack etc */ btact->cntxt->lf.lfexct = FALSE; cblk = btact->cntxt->super.scroot; bstkin(); btact->cntxt->lf.lfblk = -1; btact->cntxt->lf.lfpos = -1; strcpy(btact->cntxt->lf.lfkey,lkey); while (cblk >= 0) { #if DEBUG >= 2 fprintf(stderr,"BFNDKY: searching block " ZINTFMT "\n",cblk); #endif nkeys = bgtinf(cblk,ZNKEYS); if (nkeys == ZMXKEY && btact->cntxt->super.smode == 0) { /* split if block full and updating permitted */ bsptbk(cblk,&newblk); if (newblk < 0) { bterr("BFNDKY",QSPLIT,NULL); break; } /* if split occured, then must re-examine parent */ if (cblk != btact->cntxt->super.scroot) { index = btact->cntxt->lf.lfpos; cblk = btact->cntxt->lf.lfblk; btact->cntxt->lf.lfpos = bpull(); btact->cntxt->lf.lfblk = bpull(); } } else { index = -1; bpush(btact->cntxt->lf.lfblk); bpush(btact->cntxt->lf.lfpos); bsrhbk(cblk,lkey,&index,val,&link1,&link2,&result); btact->cntxt->lf.lfblk = cblk; btact->cntxt->lf.lfpos = index; /* if block is empty, leave lfpos at -1 */ if (result < 0) { /* must examine left block */ cblk = link1; continue; } else if (result > 0) { /* must examine right block */ cblk = link2; /* increment index to indicate this key "visited" */ btact->cntxt->lf.lfpos++; continue; } else { status = 0; btact->cntxt->lf.lfexct = TRUE; break; } } } fin: if (btact->shared) bulock(); /* non-zero status indicates no such key found */ if (status) bterr("BFNDKY",QNOKEY,lkey); return(btgerr()); }