Пример #1
0
/* Initializes an inode with LENGTH bytes of data and
   writes the new inode to sector SECTOR on the file system
   disk.
   Returns true if successful.
   Returns false if memory or disk allocation fails. */
bool
inode_create (disk_sector_t sector, off_t length, bool is_dir)
{
  struct inode_disk *disk_inode = NULL;
  struct inode *inode;
  bool success = false;

  ASSERT (length >= 0);

  /* If this assertion fails, the inode structure is not exactly
     one sector in size, and you should fix that. */
  ASSERT (sizeof *disk_inode == DISK_SECTOR_SIZE);

  disk_inode = calloc (1, sizeof *disk_inode);
  if (disk_inode != NULL)
    {
      disk_inode->length = 0;
      disk_inode->sector_count = 0;
      disk_inode->is_dir = is_dir;
      disk_inode->parent = dir_get_inode (thread_current ()->dir)->sector;
      disk_inode->magic = INODE_MAGIC;

      cache_write (sector, disk_inode, 0, DISK_SECTOR_SIZE);
      inode = inode_open (sector);
      success = inode_extend (inode, length);
      free (disk_inode);
    }
  return success;
}
Пример #2
0
/* Writes SIZE bytes from BUFFER into INODE, starting at OFFSET.
   Returns the number of bytes actually written, which may be
   less than SIZE if an error occurs. */
off_t
inode_write_at (struct inode *inode, const void *buffer_, off_t size,
                off_t offset) 
{
	if(INODE_DEBUG) printf("INODE: writing inode %u @ offset %i from buffer %x. Size: %i bytes\n", inode->sector, offset, (unsigned) buffer_, size);

	const void *buffer = buffer_;
	off_t bytes_written = 0;

	if (inode->deny_write_cnt)
		return 0;

	/* current inode size */
	off_t length = inode_length (inode);

	/* space left in last sector */
	off_t space_left = BLOCK_SECTOR_SIZE - length % BLOCK_SECTOR_SIZE;
	if(space_left == BLOCK_SECTOR_SIZE)
		space_left = 0;

	/* add block sectors if needed */
	if(offset + size > length)
	{
		/* extend file */
		ASSERT(inode_extend (inode, offset + size - length));
	
		/* update length */
		length += offset + size;
	}

	/* write to file */
	while (size > 0)
	{
		/* Sector to write, starting byte offset within sector. */
		block_sector_t sector_idx = byte_to_sector (inode, offset);
		int sector_ofs = offset % BLOCK_SECTOR_SIZE;
		
		/* Bytes left in inode, bytes left in sector, lesser of the two. */
		off_t inode_left = length - offset;
		int sector_left = BLOCK_SECTOR_SIZE - sector_ofs;
		int min_left = inode_left < sector_left ? inode_left : sector_left;

		/* Number of bytes to actually write into this sector. */
		int chunk_size = size < min_left ? size : min_left;
		if (chunk_size <= 0)
			break;

		/* write chunk to cache */
		cache_write(sector_idx, buffer + bytes_written, sector_ofs, chunk_size);
	
		/* Advance. */
		size -= chunk_size;
		offset += chunk_size;
		bytes_written += chunk_size;
    }

	return bytes_written;
}
Пример #3
0
/* Initializes an inode with LENGTH bytes of data and
   writes the new inode to sector SECTOR on the file system
   device.
   Returns true if successful.
   Returns false if memory or disk allocation fails. */
bool
inode_create (block_sector_t sector, off_t length, enum file_t file_type)
{
	if(INODE_DEBUG || FILE_DEBUG) printf("INODE: creating inode for sector %u with inital size %i\n", sector, length);

	struct inode_disk *disk_inode = NULL;
	bool success = false;

	ASSERT (length >= 0);

	/* If this assertion fails, the inode structure is not exactly
	 one sector in size, and you should fix that. */
	ASSERT (sizeof *disk_inode == BLOCK_SECTOR_SIZE);

	disk_inode = calloc (1, sizeof *disk_inode);
	if (disk_inode != NULL)
	{

		disk_inode->length = 0;
		disk_inode->sector_count = 0;
		disk_inode->magic = INODE_MAGIC;
		disk_inode->type = file_type;

		/* create empty file */
		cache_write(sector, disk_inode, 0, BLOCK_SECTOR_SIZE);

		/* open the file */
		struct inode* inode = inode_open(sector);

		/* extend file by length bytes */
		inode_extend(inode, length);
	
		/* close file */
		inode_close(inode);

		/* free space */
		free (disk_inode);

		success = true;
    }

	return success;
}
Пример #4
0
/* Writes SIZE bytes from BUFFER into INODE, starting at OFFSET.
   Returns the number of bytes actually written, which may be
   less than SIZE if an error occurs. */
off_t
inode_write_at (struct inode *inode, const void *buffer_, off_t size,
                off_t offset)
{
  const uint8_t *buffer = buffer_;
  off_t bytes_written = 0;
  off_t length;

  if (inode->deny_write_cnt)
    return 0;

  /* Extend file. */
  length = inode_length (inode);
  if (offset + size > length)
    inode_extend (inode, offset + size - length);

  while (size > 0)
    {
      /* Sector to write, starting byte offset within sector. */
      disk_sector_t sector_idx = byte_to_sector (inode, offset);
      int sector_ofs = offset % DISK_SECTOR_SIZE;

      /* Bytes left in inode, bytes left in sector, lesser of the two. */
      off_t inode_left = inode_length (inode) - offset;
      int sector_left = DISK_SECTOR_SIZE - sector_ofs;
      int min_left = inode_left < sector_left ? inode_left : sector_left;

      /* Number of bytes to actually write into this sector. */
      int chunk_size = size < min_left ? size : min_left;
      if (chunk_size <= 0)
        break;

      /* Write sector through buffer cache. */
      cache_write (sector_idx, buffer + bytes_written, sector_ofs, chunk_size);

      /* Advance. */
      size -= chunk_size;
      offset += chunk_size;
      bytes_written += chunk_size;
    }

  return bytes_written;
}
Пример #5
0
/* Initializes an inode with LENGTH bytes of data and
   writes the new inode to sector SECTOR on the file system
   device.
   Returns true if successful.
   Returns false if memory or disk allocation fails. */
bool
inode_create (block_sector_t sector_, off_t length, bool is_dir)
{
  uint8_t buf[BLOCK_SECTOR_SIZE];
  bool success = false;

  ASSERT (length >= 0);
  struct inode *inode = malloc (sizeof (struct inode));
  if (inode != NULL)
  {
    inode->sector = sector_;
    inode->length = 0;
    inode->magic = INODE_MAGIC;
    inode->open_cnt = 0;
    inode->removed = 0;
    inode->deny_write_cnt = 0;
    inode->indirect_block = 0;
    inode->doubly_indirect_block = 0;
    inode->is_dir = is_dir;
    memset (inode->direct_blocks, 0, sizeof inode->direct_blocks);

    success = inode_extend (inode, bytes_to_sectors(length));

    if (success)
    {
      inode->length = length;
      inode->max_read_length = inode->length;
      memset (buf, 0, BLOCK_SECTOR_SIZE);
      memcpy (buf, inode, sizeof (*inode));
      block_write (fs_device, inode->sector, buf);
    }

    free (inode);
  }
  return success;
}
Пример #6
0
/* Writes SIZE bytes from BUFFER into INODE, starting at OFFSET.
   Returns the number of bytes actually written, which may be
   less than SIZE if end of file is reached or an error occurs. */
off_t
inode_write_at (struct inode *inode, const void *buffer_, off_t size,
                off_t offset) 
{
  const uint8_t *buffer = buffer_;
  off_t bytes_written = 0;
  struct cached_block *cached_block;
  block_sector_t sector_idx = -1;
  bool extending = false;

  if (inode->deny_write_cnt)
    return 0;

  //grow inode if necessary
  
  if (offset + size > inode->max_read_length)
  {

    extending = true;
    lock_acquire (&inode->extend_lock);
    if (offset + size > inode->max_read_length)
    {
      int num_blocks_to_add = bytes_to_sectors (offset + size ) - bytes_to_sectors (inode_length (inode));
      if (num_blocks_to_add > 0)
      {
        if (!inode_extend(inode, num_blocks_to_add))
        {
          lock_release (&inode->extend_lock);
          return 0;
        }
      }
      inode->length = offset + size ;
    }
    else
    {
      extending = false;
      lock_release (&inode->extend_lock);
    }
  }

  while (size > 0) 
  {
    /* Sector to write, starting byte offset within sector. */
    sector_idx = byte_to_sector (inode, offset);
    int sector_ofs = offset % BLOCK_SECTOR_SIZE;

    /* Bytes left in inode, bytes left in sector, lesser of the two. */
    off_t inode_left = inode_length (inode) - offset;
    int sector_left = BLOCK_SECTOR_SIZE - sector_ofs;
    int min_left = inode_left < sector_left ? inode_left : sector_left;

    /* Number of bytes to actually write into this sector. */
    int chunk_size = size < min_left ? size : min_left;
    if (chunk_size <= 0)
      break;

    cached_block = cache_insert (sector_idx);

    cached_block->active_r_w ++ ;
    lock_release (&cached_block->lock);


    thread_current ()->cache_block_being_accessed = cached_block;
    memcpy (cached_block->data + sector_ofs, buffer + bytes_written, chunk_size);
    cached_block->dirty = true;

    thread_current ()->cache_block_being_accessed = NULL;

    lock_acquire (&cached_block->lock);
    cached_block->active_r_w --;
    if (cached_block->active_r_w == 0)
      cond_broadcast (&cached_block->r_w_done, &cached_block->lock);
    lock_release (&cached_block->lock);


    /* Advance. */
    size -= chunk_size;
    offset += chunk_size;
    bytes_written += chunk_size;

  }

  if (((int)sector_idx != -1) && (bytes_to_sectors (inode->max_read_length) > sector_idx))
  {
    block_sector_t next_sector = byte_to_sector (inode, offset + BLOCK_SECTOR_SIZE);
    cache_read_ahead (next_sector);
  }

  if (extending)
  {
    inode->max_read_length = inode->length;
    uint8_t buf[BLOCK_SECTOR_SIZE];
    memset (buf, 0, BLOCK_SECTOR_SIZE);
    memcpy (buf, inode, sizeof (*inode));
    block_write (fs_device, inode->sector, buf);
    lock_release (&inode->extend_lock);
  }

  return bytes_written;
}