예제 #1
0
void inode_deallocate_data_blocks(struct inode* inode){
	struct inode_disk disk_inode = inode->data;
	int i, size = disk_inode.length;
	if(size<=DIRECT_ACCESS){
		for(i=0; i<DIV_ROUND_UP(size, BLOCK_SECTOR_SIZE); i++){
			free_map_release(disk_inode.direct[i], 1);
		}
		return;
	}
	if(size<= DIRECT_ACCESS+INDIRECT_ACCESS){
		for(i=0; i<N_DIRECT_BLOCKS; i++){
			free_map_release(disk_inode.direct[i], 1);
		}
		size-=DIRECT_ACCESS;
		uint32_t* indirect_block = (uint32_t*)malloc(BLOCK_SECTOR_SIZE);
		cached_read(inode, disk_inode.indirect,indirect_block);
		for(i=0; i<DIV_ROUND_UP(size, BLOCK_SECTOR_SIZE); i++){
			free_map_release(indirect_block[i], 1);
		}
		free_map_release(disk_inode.indirect, 1);
		free(indirect_block);
		return;
	}
	if(size<=DIRECT_ACCESS+INDIRECT_ACCESS+DOUBLE_INDIRECT_ACCESS){
		uint32_t* buff = (uint32_t*)malloc(BLOCK_SECTOR_SIZE);
		for(i=0; i<N_DIRECT_BLOCKS; i++){
			free_map_release(disk_inode.direct[i], 1);
		}
		size-=DIRECT_ACCESS;
		uint32_t* indirect_block = (uint32_t*)malloc(BLOCK_SECTOR_SIZE);
		cached_read(inode, disk_inode.indirect,indirect_block);
		for(i=0; i<N_INDIRECT_POINTERS; i++){
			free_map_release(indirect_block[i], 1);
		}
		free_map_release(disk_inode.indirect, 1);
		free(indirect_block);
		size-=INDIRECT_ACCESS;
		uint32_t* double_indirect_block = (uint32_t*)malloc(BLOCK_SECTOR_SIZE);
		cached_read(inode, disk_inode.double_indirect,double_indirect_block);
		int c_size = size;
		int i,j;
		for(i=0; i<DIV_ROUND_UP(c_size, N_INDIRECT_POINTERS*BLOCK_SECTOR_SIZE); i++){
			cached_read(inode, double_indirect_block[i], buff);
			for(j=0; j<N_INDIRECT_POINTERS && j<DIV_ROUND_UP(size, BLOCK_SECTOR_SIZE); j++){
				free_map_release(buff[j], 1);
				
			}
			size-=BLOCK_SECTOR_SIZE*N_INDIRECT_POINTERS;
			free_map_release(double_indirect_block[i],1);
		}
		free_map_release(disk_inode.double_indirect, 1);
		free(double_indirect_block);
		free(buff);
		return;
	}
}
예제 #2
0
/* Reads SIZE bytes from INODE into BUFFER, starting at position OFFSET.
   Returns the number of bytes actually read, which may be less
   than SIZE if an error occurs or end of file is reached. */
off_t
inode_read_at (struct inode *inode, void *buffer_, off_t size, off_t offset) 
{
  uint8_t *buffer = buffer_;
  off_t bytes_read = 0;
  uint8_t *bounce = NULL;

  while (size > 0) 
    {
      /* Disk sector to read, 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 = 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 copy out of this sector. */
      int chunk_size = size < min_left ? size : min_left;
      if (chunk_size <= 0)
        break;

      if (sector_ofs == 0 && chunk_size == BLOCK_SECTOR_SIZE)
        {
          /* Read full sector directly into caller's buffer. */
          cached_read (inode, sector_idx, buffer + bytes_read);
        }
      else 
        {
          /* Read sector into bounce buffer, then partially copy
             into caller's buffer. */
          if (bounce == NULL) 
            {
              bounce = malloc (BLOCK_SECTOR_SIZE);
              if (bounce == NULL)
                break;
            }
          cached_read (inode, sector_idx, bounce);
          memcpy (buffer + bytes_read, bounce + sector_ofs, chunk_size);
        }
      
      /* Advance. */
      size -= chunk_size;
      offset += chunk_size;
      bytes_read += chunk_size;
    }
  free (bounce);

  return bytes_read;
}
예제 #3
0
파일: little-ro.c 프로젝트: nurpax/sqlite
static
int little_ro_read(sqlite3_file *file, void *buf, int iAmt, sqlite3_int64 iOfst) {
    int filenumber;
    int got = 0;
    int littleAmt;

    little_ro_file *self = (little_ro_file*)file;
    trace("RO %s %llu:%d\n", strstr(self->name,"journal") ? "J" : "D", iOfst, iAmt);

    for (filenumber = iOfst / LITTLE_SECTOR_SIZE,
            iOfst -= filenumber * LITTLE_SECTOR_SIZE
                     ; iAmt > 0
            ; ++filenumber) {

        littleAmt = min(LITTLE_SECTOR_SIZE - iOfst , iAmt);

        got = cached_read(self,filenumber);
        if (got < LITTLE_SECTOR_SIZE) return SQLITE_IOERR_SHORT_READ;
        memcpy(buf,self->lastbuffer + iOfst,littleAmt);

        iAmt -= littleAmt;
        buf  += littleAmt;
        iOfst = 0;
    }
    return SQLITE_OK;
}
예제 #4
0
파일: little.c 프로젝트: GaloisInc/sqlite
static
int little_write(sqlite3_file *file,
                  const void *buf, int iAmt, sqlite3_int64 iOfst) {
  int filenumber, littleAmt, got;

  little_file *self = (little_file*)file;

  for (filenumber = iOfst / LITTLE_SECTOR_SIZE,
       iOfst -= filenumber * LITTLE_SECTOR_SIZE
      ; iAmt > 0
      ; ++filenumber) {

    littleAmt = min(LITTLE_SECTOR_SIZE - iOfst, iAmt);
    if (iOfst == 0 && littleAmt == LITTLE_SECTOR_SIZE) {
      got = write_block(self->name,filenumber,buf, self->version);
      if (got < LITTLE_SECTOR_SIZE) return SQLITE_IOERR_WRITE;
    } else {
      got = cached_read(self,filenumber);
      if (got < 0) return SQLITE_IOERR_WRITE;
      self->dirty = 1;
      self->lastblock = filenumber;
      memcpy(self->lastbuffer + iOfst,buf,littleAmt);
    }

    if (filenumber >= self->nextfreeblock) self->nextfreeblock = filenumber+1;
    iAmt -= littleAmt;
    buf  += littleAmt;
    iOfst = 0;
  }

  return SQLITE_OK;
}
예제 #5
0
파일: iter.c 프로젝트: yunxiaoxiao110/haiku
/* XXX: not the most efficient implementation, but it gets the job done */
status_t csi_read_blocks(struct csi *csi, uint8 *buffer, ssize_t len)
{
    struct csi old_csi;
    uint32 sectors;
    off_t block;
    status_t err;

    ASSERT(len >= csi->vol->bytes_per_sector);

    if (_validate_cs_(csi->vol, csi->cluster, csi->sector) != 0)
        return EINVAL;

    sectors = 1;
    block = _csi_to_block_(csi);

    while (1) {
        old_csi = *csi;
        err = iter_csi(csi, 1);
        if (len < (sectors + 1) * csi->vol->bytes_per_sector)
            break;
        if ((err < B_OK) || (block + sectors != _csi_to_block_(csi)))
            break;
        sectors++;
    }

    err = cached_read(csi->vol->fd, block, buffer, sectors, csi->vol->bytes_per_sector);
    if (err < B_OK)
        return err;

    *csi = old_csi;

    return sectors * csi->vol->bytes_per_sector;
}
예제 #6
0
/* Reads an inode from SECTOR
   and returns a `struct inode' that contains it.
   Returns a null pointer if memory allocation fails. */
struct inode *
inode_open (block_sector_t sector)
{
  printf("inode_open(%u)\n", sector);
  struct list_elem *e;
  struct inode *inode;

  /* Check whether this inode is already open. */
  for (e = list_begin (&open_inodes); e != list_end (&open_inodes);
       e = list_next (e)) 
    {
	  printf("in inode_open()\n");
      inode = list_entry (e, struct inode, elem);
      if (inode->sector == sector) 
        {
		  printf("inode_open(): inode found in open_inodes list\n");
          inode_reopen (inode);
          return inode; 
        }
    }

  /* Allocate memory. */
  inode = malloc (sizeof *inode);
  if (inode == NULL){
	printf("Could not create new inode\n");
    return NULL;
  }

  /* Initialize. */
  list_push_front (&open_inodes, &inode->elem);
  inode->sector = sector;
  inode->open_cnt = 1;
  inode->deny_write_cnt = 0;
  inode->removed = false;
  //inode->type=...
  cached_read (inode, inode->sector, &inode->data); //Assignment 4
  printf("inode_open(): Successfully created new inode\n");
  return inode;
}
예제 #7
0
/* Returns the block device sector that contains byte offset POS
   within INODE.
   Returns -1 if INODE does not contain data for a byte at offset
   POS. */
static block_sector_t
byte_to_sector (struct inode *inode, off_t pos) 
{
  if(INODE_DEBUG) printf("byte_to_sector(%x, %d)\n", inode, pos);
  ASSERT (inode != NULL);
  ASSERT (inode->data.length < MAX_SIZE_INODE_DATA);
  ASSERT (pos < MAX_SIZE_INODE_DATA);
  ASSERT (pos - inode->data.length < BLOCK_SECTOR_SIZE);
  if(pos < DIRECT_ACCESS){
	  int idx = pos/BLOCK_SECTOR_SIZE;
	  block_sector_t b = inode->data.direct[idx];
	  if(b!=0) return b;
	  //printf("byte_to_sector(): pos: %d size: %d\n", pos, inode->data.length);
	  ASSERT(pos-inode->data.length >0);
	  free_map_allocate(1, &b);
	  inode->data.direct[idx]= b;
	  inode->data.length+= pos - inode->data.length;
	  return b;
  }		  
  else if(pos < DIRECT_ACCESS+INDIRECT_ACCESS){
	  uint32_t* indirect_block = (uint32_t*)calloc(BLOCK_SECTOR_SIZE, 1);
	  if(inode->data.indirect ==0){
		ASSERT( pos - inode->data.length >0);
		block_sector_t indir;
		free_map_allocate(1, &indir);
		inode->data.indirect =indir;
	  }
	  cached_read(inode, inode->data.indirect, indirect_block);
	  int idx = (pos-DIRECT_ACCESS)/BLOCK_SECTOR_SIZE;
	  block_sector_t b =  indirect_block[idx];
		if(b==0){
		  ASSERT( pos - inode->data.length >0);
		  free_map_allocate(1, &b);
		  indirect_block[idx]=b;
		  block_write(fs_device, inode->data.indirect, indirect_block);
		  //cache_flush(inode, inode->data.indirect);
		  inode->data.length += pos - inode->data.length;
	  }
	  free(indirect_block);
	  return b;
  }
  else{
	  uint32_t* level_one_block = (uint32_t*)malloc(BLOCK_SECTOR_SIZE);
	  if(inode->data.double_indirect==0){
		  ASSERT(pos-inode->data.length > 0);
		  block_sector_t b;
		  free_map_allocate(1, &b);
		  inode->data.double_indirect = b;
	  }
	  block_read(inode, inode->data.double_indirect, level_one_block);
	  off_t eff = pos-DIRECT_ACCESS-INDIRECT_ACCESS;
	  int idx1 = eff>>(L2_BITS+L3_BITS);
	  block_sector_t level_two_block_no = level_one_block[idx1];
	  if(level_two_block_no ==0){
		  ASSERT(pos- inode->data.length>0);
		  free_map_allocate(1, &level_two_block_no);
		  level_one_block[idx1]=level_two_block_no;
		  block_write(fs_device, inode->data.double_indirect, level_one_block);
		  //cache_flush(inode, inode->data.double_indirect);
	  }
	  uint32_t* level_two_block = (uint32_t*)malloc(BLOCK_SECTOR_SIZE);
	  block_read(inode, level_two_block_no, level_two_block);
	  int idx2 = (eff&L2_MASK)>>L3_BITS;
	  block_sector_t level_three_block_no = level_two_block[idx2];
	  if(level_three_block_no == 0){
		  ASSERT(pos-inode->data.length >0);
		  free_map_allocate(1, &level_three_block_no);
		  level_two_block[idx2]=level_three_block_no;
		  block_write(fs_device, level_two_block_no, level_two_block);
		  //cache_flush(inode, level_two_block_no);
		  inode->data.length += pos - inode->data.length;
	  }
	  free(level_one_block);
	  free(level_two_block);
	  return level_three_block_no;
  }
}
예제 #8
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.
   (Normally a write at end of file would extend the inode, but
   growth is not yet implemented.) */
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;
  uint8_t *bounce = NULL;

  if (inode->deny_write_cnt)
    return 0;

  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 = inode_length (inode) - offset;
      int sector_left = BLOCK_SECTOR_SIZE - sector_ofs;
      //int min_left = inode_left < sector_left ? inode_left : sector_left;
      int min_left = sector_left;
      

      /* Number of bytes to actually write into this sector. */
      int chunk_size = size < min_left ? size : min_left;
      if(offset > inode_length(inode)) inode->data.length += chunk_size;
      if (chunk_size <= 0)
        break;

      if (sector_ofs == 0 && chunk_size == BLOCK_SECTOR_SIZE)
        {
          /* Write full sector directly to disk. */
          cached_write (NULL, sector_idx, buffer + bytes_written);
        }
      else 
        {
          /* We need a bounce buffer. */
          if (bounce == NULL) 
            {
              bounce = malloc (BLOCK_SECTOR_SIZE);
              if (bounce == NULL)
                break;
            }

          /* If the sector contains data before or after the chunk
             we're writing, then we need to read in the sector
             first.  Otherwise we start with a sector of all zeros. */
          if (sector_ofs > 0 || chunk_size < sector_left) 
            cached_read (inode, sector_idx, bounce);
          else
            memset (bounce, 0, BLOCK_SECTOR_SIZE);
          memcpy (bounce + sector_ofs, buffer + bytes_written, chunk_size);
          cached_write (NULL, sector_idx, bounce);
        }

      /* Advance. */
      size -= chunk_size;
      offset += chunk_size;
      bytes_written += chunk_size;
    }
  free (bounce);

  return bytes_written;
}
예제 #9
0
/** Read from an AFS file
 * \par Description:
 * Read from the given file into the given buffer starting at the given offset for
 * the given length.  First, if the start position is not block aligned, read the
 * first block/extant and copy from it into the destination buffer.  Next, loop
 * through the blocks/extants, reading until there are no more full blocks, copying
 * into the destination buffer.  Finally, if there's any data left to read, read the
 * last block/extant and copy the correct data into the destination buffer.
 * \par Note: Directory data does not appear to be cached. This could be a huge slowdown.
 * \par Warning: Does not check for a read past the end of the file.  Use afs_read_pos
 * \param psVolume	AFS filesystem pointer
 * \param psInode	AFS Inode to read from
 * \param pBuffer	Destination buffer for the data
 * \param nPos		Start position in file
 * \param nSize		Number of octets to read
 * \return 0 on success, negative error code on failure
 * \sa
 *****************************************************************************/
static int afs_do_read( AfsVolume_s * psVolume, AfsInode_s * psInode, char *pBuffer, off_t nPos, size_t nSize )
{
	const int nBlockSize = psVolume->av_psSuperBlock->as_nBlockSize;
	off_t nFirstBlock = nPos / nBlockSize;
	off_t nLastBlock =( nPos + nSize + nBlockSize - 1 ) / nBlockSize;
	off_t nNumBlocks = nLastBlock - nFirstBlock + 1;
	int nOffset = nPos % nBlockSize;
	off_t nBlockAddr;
	char *pBlock = NULL;
	int nRunLength;
	int nError;

	if( S_ISDIR( psInode->ai_nMode ) )
	{
		pBlock = afs_alloc_block_buffer( psVolume );
		if( pBlock == NULL )
		{
			printk( "Error: afs_do_read() no memory for data buffer\n" );
			return( -ENOMEM );
		}
	}

	nError = afs_get_stream_blocks( psVolume, &psInode->ai_sData, nFirstBlock, nNumBlocks, &nBlockAddr, &nRunLength );

	if( nError < 0 )
	{
		printk( "Error: afs_do_read() 1 afs_get_stream_blocks() failed with code %d\n", nError );
	}
	if( nError >= 0 && nOffset != 0 )
	{
		if( S_ISDIR( psInode->ai_nMode ) )
		{
			nError = afs_logged_read( psVolume, pBlock, nBlockAddr );
		}
		else
		{
			pBlock =( char * )get_cache_block( psVolume->av_nDevice, nBlockAddr, nBlockSize );
			if( pBlock == NULL )
			{
				nError = -EIO;
			}
		}
		if( nError >= 0 )
		{
			off_t nLen = min( nSize, nBlockSize - nOffset );

			memcpy( pBuffer, pBlock + nOffset, nLen );
			pBuffer += nLen;
			nSize -= nLen;
			if( S_ISDIR( psInode->ai_nMode ) == false )
			{
				release_cache_block( psVolume->av_nDevice, nBlockAddr );
			}
		}
		nBlockAddr++;
		nFirstBlock++;
		nRunLength--;
		nNumBlocks--;
	}

	for( ; nSize >= nBlockSize && nError >= 0; )
	{
		if( nRunLength == 0 )
		{
			nError = afs_get_stream_blocks( psVolume, &psInode->ai_sData, nFirstBlock, nNumBlocks, &nBlockAddr, &nRunLength );
			if( nError < 0 )
			{
				printk( "Error: afs_do_read() 2 afs_get_stream_blocks( %Ld, %Ld ) failed with code %d\n", nFirstBlock, nNumBlocks, nError );
			}
		}
		if( nError >= 0 )
		{
			off_t nLen = min( nSize / nBlockSize, nRunLength );

			if( S_ISDIR( psInode->ai_nMode ) )
			{
				int i;

				nError = 0;
				for( i = 0; i < nLen; ++i )
				{
					nError = afs_logged_read( psVolume, pBuffer, nBlockAddr );
					if( nError < 0 )
					{
						printk( "Error: afs_do_read() failed to read directory data block\n" );
						break;
					}
					nRunLength--;
					nNumBlocks--;
					nFirstBlock++;
					nBlockAddr++;
					nSize -= nBlockSize;
					pBuffer += nBlockSize;
					kassertw( nRunLength >= 0 );
					kassertw( nSize >= 0 );
				}
			}
			else
			{
				nError = cached_read( psVolume->av_nDevice, nBlockAddr, pBuffer, nLen, nBlockSize );
				if( nError >= 0 )
				{
					nRunLength -= nLen;
					nNumBlocks -= nLen;
					nFirstBlock += nLen;
					nBlockAddr += nLen;
					nSize -= nLen * nBlockSize;
					pBuffer += nLen * nBlockSize;

					kassertw( nRunLength >= 0 );
					kassertw( nSize >= 0 );
				}
			}
		}
	}
	if( nSize > 0 && nError >= 0 )
	{
		if( nRunLength == 0 )
		{
			nError = afs_get_stream_blocks( psVolume, &psInode->ai_sData, nFirstBlock, nNumBlocks, &nBlockAddr, &nRunLength );
			if( nError < 0 )
			{
				printk( "Error: afs_do_read() 3 afs_get_stream_blocks() failed with code %d\n", nError );
			}
		}
		if( nError >= 0 )
		{
			if( S_ISDIR( psInode->ai_nMode ) )
			{
				nError = afs_logged_read( psVolume, pBlock, nBlockAddr );
			}
			else
			{
				pBlock =( char * )get_cache_block( psVolume->av_nDevice, nBlockAddr, nBlockSize );

//      printk( "read:3 %d:%d -> %d blocks at %d\n",
//              psInode->ai_sInodeNum.group, psInode->ai_sInodeNum.start, 1, nBlockAddr);

				if( pBlock == NULL )
				{
					nError = -EIO;
				}
			}
			kassertw( nSize < nBlockSize );
			if( nError >= 0 )
			{
				off_t nLen = min( nSize, nBlockSize );

				memcpy( pBuffer, pBlock, nSize );

				pBuffer += nLen;
				nSize -= nLen;
				if( S_ISDIR( psInode->ai_nMode ) == false )
				{
					release_cache_block( psVolume->av_nDevice, nBlockAddr );
				}
			}
		}
		else
		{
			printk( "Error : afs_do_read() Failed to locate last data block\n" );
		}
	}
	if( S_ISDIR( psInode->ai_nMode ) )
	{
		afs_free_block_buffer( psVolume, pBlock );
	}
	return( nError );
}