Example #1
0
/*===========================================================================*
 *				read_block				     *
 *===========================================================================*/
static void read_block(
  struct buf *bp	/* buffer pointer */
)
{
/* Read or write a disk block. This is the only routine in which actual disk
 * I/O is invoked. If an error occurs, a message is printed here, but the error
 * is not reported to the caller.  If the error occurred while purging a block
 * from the cache, it is not clear what the caller could do about it anyway.
 */
  int r, op_failed;
  off_t pos;
  dev_t dev = bp->lmfs_dev;

  op_failed = 0;

  assert(dev != NO_DEV);

  ASSERT(bp->lmfs_bytes == fs_block_size);
  ASSERT(fs_block_size > 0);

  pos = (off_t)bp->lmfs_blocknr * fs_block_size;
  if(fs_block_size > PAGE_SIZE) {
#define MAXPAGES 20
	vir_bytes blockrem, vaddr = (vir_bytes) bp->data;
	int p = 0;
  	static iovec_t iovec[MAXPAGES];
	blockrem = fs_block_size;
	while(blockrem > 0) {
		vir_bytes chunk = blockrem >= PAGE_SIZE ? PAGE_SIZE : blockrem;
		iovec[p].iov_addr = vaddr;
		iovec[p].iov_size = chunk;
		vaddr += chunk;
		blockrem -= chunk;
		p++;
	}
  	r = bdev_gather(dev, pos, iovec, p, BDEV_NOFLAGS);
  } else {
  	r = bdev_read(dev, pos, bp->data, fs_block_size,
  		BDEV_NOFLAGS);
  }
  if (r < 0) {
  	printf("fs cache: I/O error on device %d/%d, block %u\n",
  	major(dev), minor(dev), bp->lmfs_blocknr);
  	op_failed = 1;
  } else if (r != (ssize_t) fs_block_size) {
  	r = END_OF_FILE;
  	op_failed = 1;
  }

  if (op_failed) {
  	bp->lmfs_dev = NO_DEV;	/* invalidate block */

  	/* Report read errors to interested parties. */
  	rdwt_err = r;
  }

}
/*===========================================================================*
 *				read_block				     *
 *===========================================================================*/
static int read_block(struct buf *bp, size_t block_size)
{
/* Read a disk block of 'size' bytes.  The given size is always the FS block
 * size, except for the last block of a device.  If an I/O error occurs,
 * invalidate the block and return an error code.
 */
  ssize_t r;
  off_t pos;
  dev_t dev = bp->lmfs_dev;

  assert(dev != NO_DEV);

  ASSERT(bp->lmfs_bytes == block_size);
  ASSERT(fs_block_size > 0);

  pos = (off_t)bp->lmfs_blocknr * fs_block_size;
  if (block_size > PAGE_SIZE) {
#define MAXPAGES 20
	vir_bytes blockrem, vaddr = (vir_bytes) bp->data;
	int p = 0;
  	static iovec_t iovec[MAXPAGES];
	blockrem = block_size;
	while(blockrem > 0) {
		vir_bytes chunk = blockrem >= PAGE_SIZE ? PAGE_SIZE : blockrem;
		iovec[p].iov_addr = vaddr;
		iovec[p].iov_size = chunk;
		vaddr += chunk;
		blockrem -= chunk;
		p++;
	}
  	r = bdev_gather(dev, pos, iovec, p, BDEV_NOFLAGS);
  } else {
	r = bdev_read(dev, pos, bp->data, block_size, BDEV_NOFLAGS);
  }
  if (r != (ssize_t)block_size) {
	/* Aesthetics: do not report EOF errors on superblock reads, because
	 * this is a fairly common occurrence, e.g. during system installation.
	 */
	if (bp->lmfs_blocknr != 0 /*first block*/ || r != 0 /*EOF*/)
		printf("fs cache: I/O error on device %d/%d, block %"PRIu64
		    " (%zd)\n", major(dev), minor(dev), bp->lmfs_blocknr, r);

	if (r >= 0)
		r = EIO; /* TODO: retry retrieving (just) the remaining part */

	bp->lmfs_dev = NO_DEV;	/* invalidate block */

	return r;
  }

  return OK;
}
Example #3
0
/*===========================================================================*
 *				rw_block				     *
 *===========================================================================*/
static void rw_block(
  register struct buf *bp,	/* buffer pointer */
  int rw_flag 			/* READING or WRITING */
)
{
/* Read or write a disk block. This is the only routine in which actual disk
 * I/O is invoked. If an error occurs, a message is printed here, but the error
 * is not reported to the caller.  If the error occurred while purging a block
 * from the cache, it is not clear what the caller could do about it anyway.
 */
  int r, op_failed = 0;
  u64_t pos;
  dev_t dev;

  if ( (dev = bp->b_dev) != NO_DEV) {
	pos = mul64u(bp->b_blocknr, fs_block_size);
	if (rw_flag == READING)
		r = bdev_read(dev, pos, bp->b_data, fs_block_size,
			BDEV_NOFLAGS);
	else
		r = bdev_write(dev, pos, bp->b_data, fs_block_size,
			BDEV_NOFLAGS);
	if (r < 0) {
		printf("Ext2(%d) I/O error on device %d/%d, block %u\n",
			SELF_E, major(dev), minor(dev), bp->b_blocknr);
		op_failed = 1;
	} else if (r != (ssize_t) fs_block_size) {
		r = END_OF_FILE;
		op_failed = 1;
	}

	if (op_failed) {
		bp->b_dev = NO_DEV;     /* invalidate block */

		/* Report read errors to interested parties. */
		if (rw_flag == READING) rdwt_err = r;

	}
  }

  bp->b_dirt = CLEAN;
}
Example #4
0
/*
 * Reads from a file.
 */
PUBLIC ssize_t sys_read(int fd, void *buf, size_t n)
{
	dev_t dev;       /* Device number.       */
	struct file *f;  /* File.                */
	struct inode *i; /* Inode.               */
	ssize_t count;   /* Bytes actually read. */
	
	/* Invalid file descriptor. */
	if ((fd < 0) || (fd >= OPEN_MAX) || ((f = curr_proc->ofiles[fd]) == NULL))
		return (-EBADF);
	
	/* File not opened for reading. */
	if (ACCMODE(f->oflag) == O_WRONLY)
		return (-EBADF);

#if (EDUCATIONAL_KERNEL == 0)
	
	/* Invalid buffer. */	
	if (!chkmem(buf, n, MAY_WRITE))
		return (-EINVAL);

#endif

	/* Nothing to do. */
	if (n == 0)
		return (0);
	
	 i = f->inode;
	
	/* Character special file. */
	if (S_ISCHR(i->mode))
	{		
		dev = i->blocks[0];
		count = cdev_read(dev, buf, n);
		return (count);
	}
	
	/* Block special file. */
	else if (S_ISBLK(i->mode))
	{
		dev = i->blocks[0];
		count = bdev_read(dev, buf, n, f->pos);
	}
	
	/* Pipe file. */
	else if (S_ISFIFO(i->mode))
	{
		kprintf("read from pipe");
		count = pipe_read(i, buf, n);
	}
	
	/* Regular file/directory. */
	else if ((S_ISDIR(i->mode)) || (S_ISREG(i->mode)))
		count = file_read(i, buf, n, f->pos);
	
	/* Unknown file type. */
	else
		return (-EINVAL);
	
	/* Failed to read. */
	if (count < 0)
		return (curr_proc->errno);

	inode_touch(i);
	f->pos += count;

	return (count);
}