예제 #1
0
파일: test72.c 프로젝트: Hooman3/minix
int
dowriteblock(int b, int blocksize, u32_t seed, char *data)
{
	struct buf *bp;

	assert(blocksize == curblocksize);

	if(!(bp = lmfs_get_block(MYDEV, b, NORMAL))) {
		e(30);
		return 0;
	}

	memcpy(bp->data, data, blocksize);

	lmfs_markdirty(bp);

	lmfs_put_block(bp, FULL_DATA_BLOCK);

	return blocksize;
}
int
dowriteblock(int b, int blocksize, u32_t seed, char *data)
{
	struct buf *bp;
	int r;

	assert(blocksize == curblocksize);

	if ((r = lmfs_get_block(&bp, MYDEV, b, NORMAL)) != 0) {
		e(30);
		return 0;
	}

	memcpy(bp->data, data, blocksize);

	lmfs_markdirty(bp);

	lmfs_put_block(bp);

	return blocksize;
}
예제 #3
0
파일: bio.c 프로젝트: Hooman3/minix
/*
 * Perform block I/O, on "dev", starting from offset "pos", for a total of
 * "bytes" bytes.  Reading, writing, and peeking are highly similar, and thus,
 * this function implements all of them.  The "call" parameter indicates the
 * call type (one of FSC_READ, FSC_WRITE, FSC_PEEK).  For read and write calls,
 * "data" will identify the user buffer to use; for peek calls, "data" is set
 * to NULL.  In all cases, this function returns the number of bytes
 * successfully transferred, 0 on end-of-file conditions, and a negative error
 * code if no bytes could be transferred due to an error.  Dirty data is not
 * flushed immediately, and thus, a successful write only indicates that the
 * data have been taken in by the cache (for immediate I/O, a character device
 * would have to be used, but MINIX3 no longer supports this), which may be
 * follwed later by silent failures, including undetected end-of-file cases.
 * In particular, write requests may or may not return 0 (EOF) immediately when
 * writing at or beyond the block device's size. i Since block I/O takes place
 * at block granularity, block-unaligned writes have to read a block from disk
 * before updating it, and that is the only possible source of actual I/O
 * errors for write calls.
 * TODO: reconsider the buffering-only approach, or see if we can at least
 * somehow throw accurate EOF errors without reading in each block first.
 */
ssize_t
lmfs_bio(dev_t dev, struct fsdriver_data * data, size_t bytes, off_t pos,
	int call)
{
	block_t block, blocks_left;
	size_t block_size, off, block_off, chunk;
	struct buf *bp;
	int r, write, how;

	if (dev == NO_DEV)
		return EINVAL;

	block_size = lmfs_fs_block_size();
	write = (call == FSC_WRITE);

	assert(block_size > 0);

	/* FIXME: block_t is 32-bit, so we have to impose a limit here. */
	if (pos < 0 || pos / block_size > UINT32_MAX || bytes > SSIZE_MAX)
		return EINVAL;

	off = 0;
	block = pos / block_size;
	block_off = (size_t)(pos % block_size);
	blocks_left = howmany(block_off + bytes, block_size);

	lmfs_reset_rdwt_err();
	r = OK;

	for (off = 0; off < bytes; off += chunk) {
		chunk = block_size - block_off;
		if (chunk > bytes - off)
			chunk = bytes - off;

		/*
		 * For read requests, help the block driver form larger I/O
		 * requests.
		 */
		if (!write)
			block_prefetch(dev, block, blocks_left);

		/*
		 * Do not read the block from disk if we will end up
		 * overwriting all of its contents.
		 */
		how = (write && chunk == block_size) ? NO_READ : NORMAL;

		bp = lmfs_get_block(dev, block, how);
		assert(bp);

		r = lmfs_rdwt_err();

		if (r == OK && data != NULL) {
			assert(lmfs_dev(bp) != NO_DEV);

			if (write) {
				r = fsdriver_copyin(data, off,
				    (char *)bp->data + block_off, chunk);

				/*
				 * Mark the block as dirty even if the copy
				 * failed, since the copy may in fact have
				 * succeeded partially.  This is an interface
				 * issue that should be resolved at some point,
				 * but for now we do not want the cache to be
				 * desynchronized from the disk contents.
				 */
				lmfs_markdirty(bp);
			} else
				r = fsdriver_copyout(data, off,
				    (char *)bp->data + block_off, chunk);
		}

		lmfs_put_block(bp, FULL_DATA_BLOCK);

		if (r != OK)
			break;

		block++;
		block_off = 0;
		blocks_left--;
	}

	/*
	 * If we were not able to do any I/O, return the error (or EOF, even
	 * for writes).  Otherwise, return how many bytes we did manage to
	 * transfer.
	 */
	if (r != OK && off == 0)
		return (r == END_OF_FILE) ? 0 : r;

	return off;
}
예제 #4
0
파일: open.c 프로젝트: bdeepak77/minix3
/*===========================================================================*
 *                             fs_slink 				     *
 *===========================================================================*/
int fs_slink()
{
  phys_bytes len;
  struct inode *sip;           /* inode containing symbolic link */
  struct inode *ldirp;         /* directory containing link */
  register int r;              /* error code */
  char string[NAME_MAX];       /* last component of the new dir's path name */
  char* link_target_buf = NULL;       /* either sip->i_block or bp->b_data */
  struct buf *bp = NULL;    /* disk buffer for link */

  caller_uid = (uid_t) fs_m_in.REQ_UID;
  caller_gid = (gid_t) fs_m_in.REQ_GID;

  /* Copy the link name's last component */
  len = fs_m_in.REQ_PATH_LEN;
  if (len > NAME_MAX || len > EXT2_NAME_MAX)
	return(ENAMETOOLONG);

  r = sys_safecopyfrom(VFS_PROC_NR, (cp_grant_id_t) fs_m_in.REQ_GRANT,
		       (vir_bytes) 0, (vir_bytes) string, (size_t) len);
  if (r != OK) return(r);
  NUL(string, len, sizeof(string));

  /* Temporarily open the dir. */
  if( (ldirp = get_inode(fs_dev, (ino_t) fs_m_in.REQ_INODE_NR)) == NULL)
	  return(EINVAL);

  /* Create the inode for the symlink. */
  sip = new_node(ldirp, string, (mode_t) (I_SYMBOLIC_LINK | RWX_MODES),
		   (block_t) 0);

  /* If we can then create fast symlink (store it in inode),
   * Otherwise allocate a disk block for the contents of the symlink and
   * copy contents of symlink (the name pointed to) into first disk block. */
  if( (r = err_code) == OK) {
	if ( (fs_m_in.REQ_MEM_SIZE + 1) > sip->i_sp->s_block_size) {
		r = ENAMETOOLONG;
	} else if ((fs_m_in.REQ_MEM_SIZE + 1) <= MAX_FAST_SYMLINK_LENGTH) {
		r = sys_safecopyfrom(VFS_PROC_NR,
				     (cp_grant_id_t) fs_m_in.REQ_GRANT3,
				     (vir_bytes) 0, (vir_bytes) sip->i_block,
                                     (vir_bytes) fs_m_in.REQ_MEM_SIZE);
		sip->i_dirt = IN_DIRTY;
		link_target_buf = (char*) sip->i_block;
        } else {
		if ((bp = new_block(sip, (off_t) 0)) != NULL) {
			sys_safecopyfrom(VFS_PROC_NR,
					 (cp_grant_id_t) fs_m_in.REQ_GRANT3,
					 (vir_bytes) 0, (vir_bytes) b_data(bp),
					 (vir_bytes) fs_m_in.REQ_MEM_SIZE);
			lmfs_markdirty(bp);
			link_target_buf = b_data(bp);
		} else {
			r = err_code;
		}
	}
	if (r == OK) {
		assert(link_target_buf);
		link_target_buf[fs_m_in.REQ_MEM_SIZE] = '\0';
		sip->i_size = (off_t) strlen(link_target_buf);
		if (sip->i_size != fs_m_in.REQ_MEM_SIZE) {
			  /* This can happen if the user provides a buffer
			   * with a \0 in it. This can cause a lot of trouble
			   * when the symlink is used later. We could just use
			   * the strlen() value, but we want to let the user
			   * know he did something wrong. ENAMETOOLONG doesn't
			   * exactly describe the error, but there is no
			   * ENAMETOOWRONG.
			   */
			  r = ENAMETOOLONG;
		  }
	}

	put_block(bp, DIRECTORY_BLOCK); /* put_block() accepts NULL. */

	if(r != OK) {
		sip->i_links_count = NO_LINK;
		if (search_dir(ldirp, string, NULL, DELETE, IGN_PERM, 0) != OK)
			panic("Symbolic link vanished");
	}
  }

  /* put_inode() accepts NULL as a noop, so the below are safe. */
  put_inode(sip);
  put_inode(ldirp);

  return(r);
}