コード例 #1
0
ファイル: file.c プロジェクト: HarryR/sanos
int dfs_write(struct file *filp, void *data, size_t size)
{
  struct inode *inode;
  size_t written;
  size_t count;
  char *p;
  unsigned int iblock;
  unsigned int start;
  vfs_blkno_t blk;
  struct buf *buf;

  inode = (struct inode *) filp->data;
  written = 0;
  p = (char *) data;
  while (size > 0)
  {
    iblock = filp->pos / inode->fs->blocksize;
    start = filp->pos % inode->fs->blocksize;

    count = inode->fs->blocksize - start;
    if (count > size) count = size;

    if (iblock < inode->desc->blocks)
      blk = get_inode_block(inode, iblock);
    else if (iblock == inode->desc->blocks)
      blk = expand_inode(inode);
    else
      return written;

    if (blk == -1) return written;

    if (count == inode->fs->blocksize)
      buf = alloc_buffer(inode->fs->cache, blk);
    else
      buf = get_buffer(inode->fs->cache, blk);

    if (!buf) return written;

    memcpy(buf->data + start, p, count);
    filp->flags |= F_MODIFIED;

    mark_buffer_updated(buf);
    release_buffer(inode->fs->cache, buf);

    filp->pos += count;
    p += count;
    written += count;
    size -= count;

    if (filp->pos > inode->desc->size)
    {
      inode->desc->size = filp->pos;
      mark_inode_dirty(inode);
    }
  }

  return written;
}
コード例 #2
0
ファイル: write_ext2.c プロジェクト: caltry/Bikeshed
/*
 * Add a number of blocks to an inode.
 */
Uint32
increase_inode_size
	(struct ext2_filesystem_context *context,
	struct ext2_inode *fp,
	Uint32 nbytes)
{
	Uint32 block_size = get_block_size( context->sb );
	Uint32 initial_size = fp->size;
	Uint32 logical_block_idx = initial_size / block_size;

	Uint32 blocks_allocated = 0;
	Uint32 total_bytes_to_alloc = nbytes;

	// Account for unused space in the last block.
	if( initial_size % block_size )
	{
		nbytes -= block_size - (initial_size % block_size);
	}

	// Allocate at least nbytes worth of blocks. Because it needs to be
	// aligned, we'll always round up.
	Uint32 num_blocks_to_alloc = nbytes / block_size;
	if( nbytes % block_size )
	{
		num_blocks_to_alloc += 1;
	}

	BlockNumber last_block_allocked = 0;
	for( Uint i = 0; i < num_blocks_to_alloc; ++i )
	{
		last_block_allocked = block_alloc( context );

		// Was the alloc successful?
		if( last_block_allocked )
		{
			blocks_allocated++;
			Uint32 *inode_block = get_inode_block( fp, logical_block_idx );
			*inode_block = last_block_allocked;
		} else {
			break;
		}
	}

	// Record the new size of the inode
	if( blocks_allocated == num_blocks_to_alloc )
	{
		fp->size += total_bytes_to_alloc;
	} else {
		fp->size += total_bytes_to_alloc -
			((num_blocks_to_alloc - blocks_allocated) * block_size);
	}

	return blocks_allocated;
}
コード例 #3
0
ファイル: inode.c プロジェクト: Arseny-N/fgfs
static int gfs_zero_inode(struct gfs_inode_info *inode)
{
	struct gfs_super_info *sb = (struct gfs_super_info *)inode->vfs_inode.i_sb->s_fs_info;
	int nblocks = sb->s_chunk_size, i;
	
	for( i = 0;i<nblocks; ++i ) {
		struct buffer_head *bh = get_inode_block(inode, i, 1);
		if(!bh)
			return -ENOMEM;
		memset(bh->b_data, 0, bh->b_size);
		put_inode_block(inode,1);
	}
	return 0;
}
コード例 #4
0
ファイル: file.c プロジェクト: HarryR/sanos
int dfs_read(struct file *filp, void *data, size_t size, off64_t pos) {
  struct inode *inode;
  size_t read;
  size_t count;
  off64_t left;
  char *p;
  unsigned int iblock;
  unsigned int start;
  blkno_t blk;
  struct buf *buf;

  inode = (struct inode *) filp->data;
  read = 0;
  p = (char *) data;
  while (pos < inode->desc->size && size > 0) {
    if (filp->flags & F_CLOSED) return -EINTR;

    iblock = (unsigned int) (pos / inode->fs->blocksize);
    start = (unsigned int) (pos % inode->fs->blocksize);

    count = inode->fs->blocksize - start;
    if (count > size) count = size;

    left = inode->desc->size - (size_t) pos;
    if (count > left) count = (size_t) left;
    if (count <= 0) break;

    blk = get_inode_block(inode, iblock);
    if (blk == NOBLOCK) return -EIO;

    if (filp->flags & O_DIRECT) {
      if (start != 0 || count != inode->fs->blocksize) return read;
      if (dev_read(inode->fs->devno, p, count, blk, 0) != (int) count) return read;
    } else {
      buf = get_buffer(inode->fs->cache, blk);
      if (!buf) return -EIO;
      memcpy(p, buf->data + start, count);
      release_buffer(inode->fs->cache, buf);
    }

    pos += count;
    p += count;
    read += count;
    size -= count;
  }

  return read;
}
コード例 #5
0
ファイル: filesystem.c プロジェクト: alamgird/UnixFileSystem
//pass 2 pointers by ref. and inode number, returns 0 on success, updates pointers by ref.
int get_inode(struct inode_block **inode_block, struct inode **inode, int inode_num)
{
    int offset = inode_num % 8;

    if(inode_num < 0)
        return -1;

    *inode_block = get_inode_block(inode_num);

    if(!inode_block)
    {
        return -1;
    }

    *inode = &(**inode_block).inodes[offset];

    return 0;
}
コード例 #6
0
ファイル: file.c プロジェクト: HarryR/sanos
int dfs_read(struct file *filp, void *data, size_t size)
{
  struct inode *inode;
  size_t read;
  size_t count;
  size_t left;
  char *p;
  unsigned int iblock;
  unsigned int start;
  vfs_blkno_t blk;
  struct buf *buf;

  inode = (struct inode *) filp->data;
  read = 0;
  p = (char *) data;
  while (filp->pos < inode->desc->size && size > 0)
  {
    iblock = filp->pos / inode->fs->blocksize;
    start = filp->pos % inode->fs->blocksize;

    count = inode->fs->blocksize - start;
    if (count > size) count = size;

    left = (int) inode->desc->size - filp->pos;
    if (count > left) count = left;

    blk = get_inode_block(inode, iblock);
    if (blk == -1) return read;

    buf = get_buffer(inode->fs->cache, blk);
    if (!buf) return read;

    memcpy(p, buf->data + start, count);

    release_buffer(inode->fs->cache, buf);

    filp->pos += count;
    p += count;
    read += count;
    size -= count;
  }

  return read;
}
コード例 #7
0
ファイル: dir.c プロジェクト: HarryR/sanos
int dfs_readdir(struct file *filp, struct vfs_dirent *dirp, int count)
{
  unsigned int iblock;
  unsigned int start;
  struct inode *inode;
  vfs_blkno_t blk;
  struct buf *buf;
  struct dentry *de;

  inode = (struct inode *) filp->data;
  if (count != 1) return -1;
  if (filp->pos == inode->desc->size) return 0;
  if (filp->pos > inode->desc->size) return -1;

  iblock = filp->pos / inode->fs->blocksize;
  start = filp->pos % inode->fs->blocksize;

  blk = get_inode_block(inode, iblock);
  if (blk == -1) return -1;

  buf = get_buffer(inode->fs->cache, blk);
  if (!buf) return -1;

  de = (struct dentry *) (buf->data + start);
  if (de->reclen + start > inode->fs->blocksize || de->namelen <= 0 || de->namelen >= MAXPATH)
  {
    release_buffer(inode->fs->cache, buf);
    return -1;
  }

  dirp->ino = de->ino;
  dirp->reclen = de->reclen;
  dirp->namelen = de->namelen;
  memcpy(dirp->name, de->name, de->namelen);
  dirp->name[de->namelen] = 0;
  
  filp->pos += de->reclen;

  release_buffer(inode->fs->cache, buf);
  return 1;
}
コード例 #8
0
ファイル: dir.c プロジェクト: HarryR/sanos
vfs_ino_t modify_dir_entry(struct inode *dir, char *name, int len, vfs_ino_t ino)
{
  unsigned int block;
  vfs_blkno_t blk;
  struct buf *buf;
  char *p;
  struct dentry *de;
  vfs_ino_t oldino;

  if (len <= 0 || len >= MAXPATH) return -1;
  if (!VFS_S_ISDIR(dir->desc->mode)) return -1;

  for (block = 0; block < dir->desc->blocks; block++)
  {
    blk = get_inode_block(dir, block);
    buf = get_buffer(dir->fs->cache, blk);
    if (!buf) return -1;

    p = buf->data;
    while (p < buf->data + dir->fs->blocksize)
    {
      de = (struct dentry *) p;

      if (fnmatch(name, len, de->name, de->namelen))
      {
        oldino = de->ino;
        de->ino = ino;
        mark_buffer_updated(buf);
        release_buffer(dir->fs->cache, buf);
        return oldino;
      }

      p += de->reclen;
    }

    release_buffer(dir->fs->cache, buf);
  }

  return -1;
}
コード例 #9
0
ファイル: dir.c プロジェクト: HarryR/sanos
int read_dir(struct inode *dir, filldir_t filldir, void *data)
{
  unsigned int block;
  vfs_blkno_t blk;
  struct buf *buf;
  char *p;
  struct dentry *de;
  int rc;

  if (!VFS_S_ISDIR(dir->desc->mode)) return -1;

  for (block = 0; block < dir->desc->blocks; block++)
  {
    blk = get_inode_block(dir, block);
    buf = get_buffer(dir->fs->cache, blk);
    if (!buf) return -1;

    p = buf->data;
    while (p < buf->data + dir->fs->blocksize)
    {
      de = (struct dentry *) p;

      rc = filldir(de->name, de->namelen, de->ino, data);
      if (rc != 0)
      {
        release_buffer(dir->fs->cache, buf);
        return rc;
      }

      p += de->reclen;
    }

    release_buffer(dir->fs->cache, buf);
  }

  return 0;
}
コード例 #10
0
ファイル: dir.c プロジェクト: HarryR/sanos
int delete_dir_entry(struct inode *dir, char *name, int len)
{
  unsigned int block;
  vfs_blkno_t blk;
  vfs_blkno_t lastblk;
  struct buf *buf;
  char *p;
  struct dentry *de;
  struct dentry *prevde;
  struct dentry *nextde;

  if (len <= 0 || len >= MAXPATH) return -1;
  if (!VFS_S_ISDIR(dir->desc->mode)) return -1;

  for (block = 0; block < dir->desc->blocks; block++)
  {
    blk = get_inode_block(dir, block);
    buf = get_buffer(dir->fs->cache, blk);
    if (!buf) return -1;

    p = buf->data;
    prevde = NULL;
    while (p < buf->data + dir->fs->blocksize)
    {
      de = (struct dentry *) p;

      if (fnmatch(name, len, de->name, de->namelen))
      {
        if (prevde)
        {
          // Merge entry with previous entry
          prevde->reclen += de->reclen;
          memset(de, 0, sizeof(struct dentry) + NAME_ALIGN_LEN(de->namelen));
          mark_buffer_updated(buf);
        }
        else if (de->reclen == dir->fs->blocksize)
        {
          // Block is empty, swap this block with last block and truncate
          if (block != dir->desc->blocks - 1)
          {
            lastblk = get_inode_block(dir, dir->desc->blocks - 1);
            set_inode_block(dir, block, lastblk);
            set_inode_block(dir, dir->desc->blocks - 1, buf->blkno);
          }

          truncate_inode(dir, dir->desc->blocks - 1);
          dir->desc->size -= dir->fs->blocksize;
          mark_buffer_invalid(buf);
        }
        else
        {
          // Merge with next entry
          nextde = (struct dentry *) (p + de->reclen);
          de->ino = nextde->ino;
          de->reclen += nextde->reclen;
          de->namelen = nextde->namelen;
          memcpy(de->name, nextde->name, nextde->namelen); // TODO: should be memmove?
          mark_buffer_updated(buf);
        }

        release_buffer(dir->fs->cache, buf);

        dir->desc->mtime = time(NULL);
        mark_inode_dirty(dir);

        return 0;
      }

      prevde = de;
      p += de->reclen;
    }

    release_buffer(dir->fs->cache, buf);
  }

  return -1;
}
コード例 #11
0
ファイル: dir.c プロジェクト: HarryR/sanos
int add_dir_entry(struct inode *dir, char *name, int len, vfs_ino_t ino)
{
  unsigned int block;
  vfs_blkno_t blk;
  struct buf *buf;
  char *p;
  struct dentry *de;
  struct dentry *newde;
  int minlen;

  if (len <= 0 || len >= MAXPATH) return -1;
  if (!VFS_S_ISDIR(dir->desc->mode)) return -1;

  for (block = 0; block < dir->desc->blocks; block++)
  {
    blk = get_inode_block(dir, block);
    buf = get_buffer(dir->fs->cache, blk);
    if (!buf) return -1;

    p = buf->data;
    while (p < buf->data + dir->fs->blocksize)
    {
      de = (struct dentry *) p;
      minlen = sizeof(struct dentry) + NAME_ALIGN_LEN(de->namelen);

      if (de->reclen >= minlen + sizeof(struct dentry) + NAME_ALIGN_LEN(de->namelen))
      {
        newde = (struct dentry *) (p + minlen);

        newde->ino = ino;
        newde->reclen = de->reclen - minlen;
        newde->namelen = len;
        memcpy(newde->name, name, len);

        de->reclen = minlen;

        mark_buffer_updated(buf);
        release_buffer(dir->fs->cache, buf);

        dir->desc->mtime = time(NULL);
        mark_inode_dirty(dir);

        return 0;
      }

      p += de->reclen;
    }

    release_buffer(dir->fs->cache, buf);
  }

  blk = expand_inode(dir);
  if (blk == -1) return -1;

  buf = alloc_buffer(dir->fs->cache, blk);
  if (!buf) return -1;

  dir->desc->size += dir->fs->blocksize;
  dir->desc->mtime = time(NULL);
  mark_inode_dirty(dir);

  newde = (struct dentry *) (buf->data);
  newde->ino = ino;
  newde->reclen = dir->fs->blocksize;
  newde->namelen = len;
  memcpy(newde->name, name, len);

  mark_buffer_updated(buf);
  release_buffer(dir->fs->cache, buf);

  return 0;
}
コード例 #12
0
ファイル: dir.c プロジェクト: nvtkhanh/uoafiles
int ext2_lookup(inode *ino, const char *name, uint32_t *out)
{
	//printf("OPEN\n");

	ext2_filesystem *fs = (ino->fs);
	ext2_dirent *dir_entry;
	buffer *buff;

	// get number of block in total
	ext2_inode *in = &ino->in;
	uint32_t inodeSize = in->size;
	uint32_t blockSize = fs->blocksize;
	uint32_t numOfBlock = inodeSize / blockSize;


	
	//uint32_t inodenum;

	
	

	uint32_t currentBlock = 0;
	//used to report error
	int r, direntoffset;


	// for each block, get all the directory entries   
	for (currentBlock=0; currentBlock<numOfBlock; currentBlock++)
	{
		// get the content of the block
		if(0 > (r = get_inode_block(ino, currentBlock, 0, &buff)))
		{
			return r;
		}
       

		//bufcache_release(fs->bc,buffer,0);
		
		for (direntoffset = 0; direntoffset < blockSize; direntoffset += dir_entry->rec_len)
		{
			// get the current directory entry
			dir_entry = (ext2_dirent*)&buff->data[direntoffset];
			uint8_t nameLen = dir_entry->name_len;
			// compare with name
			if (dir_entry->inode!=0)  // if valid entry
			{
				//compare the name
		        if ( (nameLen == strlen(name)) &&  !strncmp(dir_entry->name,name,nameLen) )
				{
					*out = dir_entry->inode;
					bufcache_release(fs->bc,buff,buff->dirty);
					//printf("RETURN\n");
					return 0;
				}
			}
           
		}
		bufcache_release(fs->bc,buff,buff->dirty);
	}
	bufcache_release(fs->bc,buff,buff->dirty);	
	//printf("RETURN\n");
	return -ENOENT;
}
コード例 #13
0
ファイル: blockmap-test.c プロジェクト: nvtkhanh/uoafiles
int main(int argc, char **argv)
{
  /* Create a test filesystem to work with. This is a "fake" filesystem with
     a 16-byte block size that resides entirely in memory. It only contains
     the subset of the data structures necessary for the test (i.e. no
     superblock, block group descriptors, or i-node cache are present). */
  ext2_filesystem *fs = test_init();
  int max_blocks = 12 + RPB + RPB*RPB + RPB*RPB*RPB;
  uint32_t map[max_blocks];
  printf("Max # blocks per inode = %d\n",max_blocks);

  /* Create an i-node with the maximum file size */
  inode *ino = create_test_inode(fs,max_blocks*BLOCKSIZE,map);

  /* Print out the block numbers of data and indirect blocks */
  array *out = array_new();
  print_inode_blocks(ino,out);
  printf("%s",out->data);
  array_free(out);

  int r;
  int failures = 0;

  printf("\n");
  printf("Logical to physical block map\n");
  printf("---------------------------------\n");
  printf("%-10s %-10s %-10s %-10s\n","Logical","Physical","Physical","Result");
  printf("%-10s %-10s %-10s %-10s\n","","(expected)","(actual)","");

  /* For each logical block number, call get_inode_block to see if it returns
     the correct block. Since the test code stores all buffer objects in a
     single array, we can work out the physical block number simpy by
     subtracting the address of the first buffer from the address of the one
     returned by get_inode_block. */
  int i;
  for (i = 0; i < max_blocks; i++) {
    buffer *buf;
    if (0 > (r = get_inode_block(ino,i,0,&buf))) {
      printf("%-10d %-10d %-10s FAIL\n",i,map[i],"ERROR");
      failures++;
    }
    else {
      int blockno = ((char*)buf - buffermem)/(BLOCKSIZE+sizeof(buffer));
      if (blockno == map[i]) {
        printf("%-10d %-10d %-10d PASS\n",i,map[i],blockno);
      }
      else {
        printf("%-10d %-10d %-10d FAIL\n",i,map[i],blockno);
        failures++;
      }
    }
  }

  if (0 < failures) {
    printf("One or more tests failed\n");
    r = 1;
  }
  else {
    printf("All tests passed successfully\n");
    r = 0;
  }

  /* Cleanup */
  free(ino);
  test_cleanup();
  return r;
}
コード例 #14
0
ファイル: file.c プロジェクト: HarryR/sanos
int dfs_write(struct file *filp, void *data, size_t size, off64_t pos) {
  struct inode *inode;
  size_t written;
  size_t count;
  char *p;
  unsigned int iblock;
  unsigned int start;
  blkno_t blk;
  struct buf *buf;
  int rc;

  inode = (struct inode *) filp->data;

  if (filp->flags & O_APPEND) pos = inode->desc->size;
  if (pos + size > DFS_MAXFILESIZE) return -EFBIG;
  if (S_ISDIR(inode->desc->mode)) return -EISDIR;

  if (pos > inode->desc->size) {
    rc = dfs_ftruncate(filp, pos);
    if (rc < 0) return rc;
  }

  written = 0;
  p = (char *) data;
  while (size > 0) {
    if (filp->flags & F_CLOSED) return -EINTR;

    iblock = (unsigned int) pos / inode->fs->blocksize;
    start = (unsigned int) pos % inode->fs->blocksize;

    count = inode->fs->blocksize - start;
    if (count > size) count = size;

    if (iblock < inode->desc->blocks) {
      blk = get_inode_block(inode, iblock);
      if (blk == NOBLOCK) return -EIO;
    } else if (iblock == inode->desc->blocks) {
      blk = expand_inode(inode);
      if (blk == NOBLOCK) return -ENOSPC;
    } else {
      return written;
    }

    if (filp->flags & O_DIRECT) {
      if (start != 0 || count != inode->fs->blocksize) return written;
      if (dev_write(inode->fs->devno, p, count, blk, 0) != (int) count) return written;
    } else {
      if (count == inode->fs->blocksize) {
        buf = alloc_buffer(inode->fs->cache, blk);
      } else {
        buf = get_buffer(inode->fs->cache, blk);
      }
      if (!buf) return -EIO;

      memcpy(buf->data + start, p, count);

      mark_buffer_updated(inode->fs->cache, buf);
      release_buffer(inode->fs->cache, buf);
    }

    filp->flags |= F_MODIFIED;
    pos += count;
    p += count;
    written += count;
    size -= count;

    if (pos > inode->desc->size) {
      inode->desc->size = pos;
      mark_inode_dirty(inode);
    }
  }

  return written;
}