Exemplo n.º 1
0
/**
 * Finds first free physical page and marks it reserved.
 *
 * @return Address of first free physical page, zero if no free pages
 * are available.
 */
physaddr_t physmem_allocblock(void)
{
  interrupt_status_t intr_status;
  int i;

  intr_status = _interrupt_disable();
  spinlock_acquire(&physmem_slock);

  if (physmem_num_free_pages > 0) {
    i = bitmap_findnset(physmem_free_pages,physmem_num_pages);
    physmem_num_free_pages--;

    /* There should have been a free page. Check that the physmem
       internal variables are in synch. */
    KERNEL_ASSERT(i >= 0 && physmem_num_free_pages >= 0);
  } else {
    i = 0;
  }

  spinlock_release(&physmem_slock);
  _interrupt_set_state(intr_status);
  return i*PAGE_SIZE;
}
Exemplo n.º 2
0
Arquivo: tfs.c Projeto: ArvoX/osm
/**
 * Creates file of given size. Implements fs.create(). Checks that
 * file name doesn't allready exist in directory block.Allocates
 * enough blocks from the allocation block for the file (1 for inode
 * and then enough for the file of given size). Reserved blocks are zeroed.
 *
 * @param fs Pointer to fs data structure of the device.
 * @param filename File name of the file to be created
 * @param size Size of the file to be created
 *
 * @return If file allready exists or not enough space return VFS_ERROR,
 * otherwise return VFS_OK.
 */
int tfs_create(fs_t *fs, char *filename, int size) 
{
    tfs_t *tfs = (tfs_t *)fs->internal;
    gbd_request_t req;
    uint32_t i;
    uint32_t numblocks = (size + TFS_BLOCK_SIZE - 1)/TFS_BLOCK_SIZE; 
    int index = -1;
    int r;
	
    semaphore_P(tfs->lock);
	
    if(numblocks > (TFS_BLOCK_SIZE / 4 - 1)) {
        semaphore_V(tfs->lock);
        return VFS_ERROR;
    }
    
    /* Read directory block. Check that file doesn't allready exist and
	 there is space left for the file in directory block. */
    req.block = TFS_DIRECTORY_BLOCK;
    req.buf = ADDR_KERNEL_TO_PHYS((uint32_t)tfs->buffer_md);
    req.sem = NULL;
    r = tfs->disk->read_block(tfs->disk, &req);
    if(r == 0) {
        /* An error occured. */
        semaphore_V(tfs->lock);
        return VFS_ERROR;
    }
	
    for(i=0;i<TFS_MAX_FILES;i++) {
        if(stringcmp(tfs->buffer_md[i].name, filename) == 0) {
            semaphore_V(tfs->lock);
            return VFS_ERROR;
        }

        if(tfs->buffer_md[i].inode == 0) {
            /* found free slot from directory */
            index = i;
        }
    }
	
    if(index == -1) {
        /* there was no space in directory, because index is not set */
        semaphore_V(tfs->lock);
        return VFS_ERROR;
    }
	
    stringcopy(tfs->buffer_md[index].name,filename, TFS_FILENAME_MAX);
	
    /* Read allocation block and... */
    req.block = TFS_ALLOCATION_BLOCK;
    req.buf = ADDR_KERNEL_TO_PHYS((uint32_t)tfs->buffer_bat);
    req.sem = NULL;
    r = tfs->disk->read_block(tfs->disk, &req);
    if(r==0) {
        /* An error occured. */
        semaphore_V(tfs->lock);
        return VFS_ERROR;
    }
	
	
    /* ...find space for inode... */
    tfs->buffer_md[index].inode = bitmap_findnset(tfs->buffer_bat,
                                                  tfs->totalblocks);
    if((int)tfs->buffer_md[index].inode == -1) {
        semaphore_V(tfs->lock);
        return VFS_ERROR;
    }
	
    /* ...and the rest of the blocks. Mark found block numbers in
	 inode.*/
    tfs->buffer_inode->filesize = size;
    for(i=0; i<numblocks; i++) {
        tfs->buffer_inode->block[i] = bitmap_findnset(tfs->buffer_bat,
                                                      tfs->totalblocks);
        if((int)tfs->buffer_inode->block[i] == -1) {
            /* Disk full. No free block found. */
            semaphore_V(tfs->lock);
            return VFS_ERROR;
        }
    }
    
    /* Mark rest of the blocks in inode as unused. */
    while(i < (TFS_BLOCK_SIZE / 4 - 1))
        tfs->buffer_inode->block[i++] = 0;

    req.block = TFS_ALLOCATION_BLOCK;
    req.buf   = ADDR_KERNEL_TO_PHYS((uint32_t)tfs->buffer_bat);
    req.sem   = NULL;
    r = tfs->disk->write_block(tfs->disk, &req);
    if(r==0) {
        /* An error occured. */
        semaphore_V(tfs->lock);
        return VFS_ERROR;
    }
	
    req.block = TFS_DIRECTORY_BLOCK;
    req.buf   = ADDR_KERNEL_TO_PHYS((uint32_t)tfs->buffer_md);
    req.sem   = NULL;
    r = tfs->disk->write_block(tfs->disk, &req);
    if(r==0) {
        /* An error occured. */
        semaphore_V(tfs->lock);
        return VFS_ERROR;
    }
	
    req.block = tfs->buffer_md[index].inode;
    req.buf   = ADDR_KERNEL_TO_PHYS((uint32_t)tfs->buffer_inode);
    req.sem   = NULL;
    r = tfs->disk->write_block(tfs->disk, &req);
    if(r==0) {
        /* An error occured. */
        semaphore_V(tfs->lock);
        return VFS_ERROR;
    }
	
    /* Write zeros to the reserved blocks. Buffer for allocation block
	 is no longer needed, so lets use it as zero buffer. */ 
    memoryset(tfs->buffer_bat, 0, TFS_BLOCK_SIZE);
    for(i=0;i<numblocks;i++) {
        req.block = tfs->buffer_inode->block[i];
        req.buf   = ADDR_KERNEL_TO_PHYS((uint32_t)tfs->buffer_bat);
        req.sem   = NULL;
        r = tfs->disk->write_block(tfs->disk, &req);
        if(r==0) {
            /* An error occured. */
            semaphore_V(tfs->lock);
            return VFS_ERROR;
        }
       
    }
	
    semaphore_V(tfs->lock);
    return VFS_OK;
}