/* * blk_alloc() * Request an existing file have its allocation increased * * Returns 0 on success, 1 on failure. */ int blk_alloc(struct inode *i, uint newsize) { /* * If the start is 0, it's "truncated" or new, so we update * it to the current place our free blocks start, and put it into * the block allocation list. */ if (i->i_start == 0) { ASSERT_DEBUG(i->i_fsize == 0, "blk_alloc: trunc with length"); i->i_start = spc_inode->i_start + BLOCKS(spc_inode->i_fsize); ino_addblklist(i); } /* * We now decide what alterations need to be made to the block * allocations within the inode. First we check that we have enough * space available to allocate the required data */ if (BLOCKS(newsize) > i->i_blocks) { /* * We really ought to be far more intelligent about what * we do here - my ideas so far are to first try and * grab some space from a near neighbour - if one has some. * Next we try moving the file (or if a neighbour's smaller * and freeing the space will be enough we move the * neighbour) to the largest free slot available (if that's * big enough) and finally if all else fails we'll compact * the whole fs down! */ return 1; } /* * OK, so there's enough space to allocate the required blocks. * Now we juggle the block details within the inode to reflect the * changes */ i->i_fsize = newsize; /* * Mark the inode dirty. Superblock probably also dirty; mark it so. */ ino_dirty(i); bdirty(shandle); return 0; }
void block_free(byte *block, size_t size) { unsigned int space_nr = SPACE(block); unsigned int block_nr = BLOCK_NR(block); size_t blocks = BLOCKS(size); byte *block_map = SPACE_MAP(space_nr); int i; int ok = 1; for(i=0; i<blocks; ++i) block_map[block_nr+i] = TYPE_FREE; /* See if we can free the entire space */ for (i=0; i<BLOCKS_PER_SPACE; i++) { if (block_map[i] != TYPE_FREE) { ok = 0; break; } } unmap(block, GRAINROUND(page_size, size)); if (ok) { /* Free the entire space */ release_arena_space(space_nr); } }
int memory_read(stream_t* stream, void* m, size_t n) { int i = 0; for(; i < BLOCKS(stream, n); i++) block_read(stream, MEMORY_BLOCK(stream, m, i)); return 0; }
int memory_write(stream_t* stream, void* m, size_t n) { int i = 0; printf("Memory: 0x%X\n", (unsigned int)m); for(; i < BLOCKS(stream, n); i++) block_write(stream, MEMORY_BLOCK(stream, m, i)); return 0; }
byte *block_alloc(byte type, size_t size) { int s, b, found = 0, blocks = BLOCKS(size); byte *block_map; byte *space; if (arena_state != INITIALIZED) arena_init(); if (blocks > BLOCKS_PER_SPACE) error("Trying to allocate too many contiguous blocks."); for(s=0; s<SPACES_IN_ARENA; ++s) { if (space_type[s] == TYPE_BLOCKS) { block_map = SPACE_MAP(s); for (b=0; b<BLOCKS_PER_SPACE; b++) { if (block_map[b] == TYPE_FREE) { found ++; if(found >= blocks) { int start = b+1-found, k; for(k=start; k<=b; ++k) block_map[k] = type; map(BLOCK_BASE(s,start), GRAINROUND(page_size, size)); return(BLOCK_BASE(s,start)); } } else found = 0; } found = 0; } } /* None of the existing block spaces have room; let's make a new one */ space = space_alloc(TYPE_BLOCKS,0); /* allocate the new space */ s = SPACE(space); block_map = SPACE_MAP(s) = block_maps + s*BLOCKS_PER_SPACE; /* This is where the map is */ for(b=0; b< blocks; ++b) block_map[b] = type; for (b=blocks; b < BLOCKS_PER_SPACE; b++) block_map[b] = TYPE_FREE; /* ... and initialize it */ map(space, GRAINROUND(page_size, size)); return(space); }
static secno hpfs_bmap(struct inode *inode, unsigned file_secno) { struct hpfs_inode_info *hpfs_inode = hpfs_i(inode); unsigned n, disk_secno; struct fnode *fnode; struct buffer_head *bh; if (BLOCKS(hpfs_i(inode)->mmu_private) <= file_secno) return 0; n = file_secno - hpfs_inode->i_file_sec; if (n < hpfs_inode->i_n_secs) return hpfs_inode->i_disk_sec + n; if (!(fnode = hpfs_map_fnode(inode->i_sb, inode->i_ino, &bh))) return 0; disk_secno = hpfs_bplus_lookup(inode->i_sb, inode, &fnode->btree, file_secno, bh); if (disk_secno == -1) return 0; if (hpfs_chk_sectors(inode->i_sb, disk_secno, 1, "bmap")) return 0; return disk_secno; }
/* * blk_trunc() * Remove the blocks from under the named file * * The freed blocks are allocated back onto the previous inode's managed * list. Note that we don't mark the inode dirty. This is because the * caller will often *further* dirty the inode, so no need to do it twice. */ void blk_trunc(struct inode *i) { int blocks; /* * Add blocks worth of storage back onto free count */ blocks = BLOCKS(i->i_fsize); sblock->s_free += blocks; /* * Flag start/len as 0. blk_alloc() will notice this * and update where the free blocks start. */ i->i_start = i->i_fsize = 0; bdirty(shandle); /* * Sort out all references to our former block neighbours */ if (i->i_prev != I_FREE) { ilist[i->i_prev]->i_next = i->i_next; ilist[i->i_prev]->i_blocks += i->i_blocks; if (i == spc_inode) { spc_inode = ilist[i->i_prev]; } } if (i->i_next != I_FREE ) { ilist[i->i_next]->i_prev = i->i_prev; } /* * Finally remove references to our former neighbours */ i->i_next = I_FREE; i->i_prev = I_FREE; }
int LinnCreate::create(Size blockSize, Size blockNum, Size inodeNum) { LinnGroup *group; BitArray map(128); assert(image != ZERO); assert(prog != ZERO); assert(blockNum >= 2); assert(inodeNum > 0); /* Allocate blocks. */ blocks = new u8[blockSize * blockNum]; memset(blocks, 0, blockSize * blockNum); /* Create a superblock. */ super = (LinnSuperBlock *) (blocks + LINN_SUPER_OFFSET); super->magic0 = LINN_SUPER_MAGIC0; super->magic1 = LINN_SUPER_MAGIC1; super->majorRevision = LINN_SUPER_MAJOR; super->minorRevision = LINN_SUPER_MINOR; super->state = LINN_SUPER_VALID; super->blockSize = blockSize; super->blocksPerGroup = LINN_CREATE_BLOCKS_PER_GROUP; super->inodesCount = inodeNum; super->blocksCount = blockNum; super->inodesPerGroup = super->inodesCount / LINN_GROUP_COUNT(super); super->freeInodesCount = super->inodesCount; super->freeBlocksCount = blockNum - 3; super->creationTime = time(ZERO); super->mountTime = ZERO; super->mountCount = ZERO; super->lastCheck = ZERO; super->groupsTable = 2; /* Allocate LinnGroups. */ for (Size i = 0; i < LINN_GROUP_COUNT(super); i++) { /* Point to the correct LinnGroup. */ group = BLOCKPTR(LinnGroup, 2) + i; /* Fill the group. */ group->freeBlocksCount = super->blocksPerGroup; group->freeInodesCount = super->inodesPerGroup; group->blockMap = BLOCKS(super, LINN_GROUP_NUM_BLOCKMAP(super)); group->inodeMap = BLOCKS(super, LINN_GROUP_NUM_INODEMAP(super)); group->inodeTable = BLOCKS(super, LINN_GROUP_NUM_INODETAB(super)); } /* Create special inodes. */ createInode(LINN_INODE_ROOT, DirectoryFile, OwnerRWX | GroupRX | OtherRX); createInode(LINN_INODE_LOADER, RegularFile, OwnerRWX | GroupRX | OtherRX); createInode(LINN_INODE_BAD, RegularFile, OwnerRW | GroupR | OtherR); createInode(LINN_INODE_JOURNAL, RegularFile, OwnerRW | GroupR | OtherR); /* Insert into directory contents, if set. */ if (input) { insertDirectory(input, LINN_INODE_ROOT, LINN_INODE_ROOT); } /* Mark blocks used. */ for (le32 block = 0; block < super->freeBlocksCount; block++) { /* Point to group. */ group = BLOCKPTR(LinnGroup, super->groupsTable) + (block / super->blocksPerGroup); group->freeBlocksCount--; /* Mark the block used. */ map.setArray(BLOCKPTR(u8, group->blockMap), super->blocksPerGroup); map.set(block % super->blocksPerGroup); } /* Write the final image. */ return writeImage(); }