Пример #1
0
static void *cramfs_read_nand(struct super_block *sb, unsigned int offset, unsigned int len)
{
	unsigned i, blocknr, buffer;
	char *data;
	struct cramfs_sb_info *sbi = sb->s_fs_info;
	struct mtd_info *mtd = sbi->mtd;
	unsigned mblock, moffset, pblock, maddr;
	int retv;
	size_t dummy;

	if (!len)
		return NULL;
	blocknr = offset >> PAGE_CACHE_SHIFT;

	/* Check if an existing buffer already has the data.. */
	for (i = 0; i < READ_BUFFERS; i++) {
		unsigned int blk_offset;

		if (buffer_dev[i] != sb) 
			continue;
		if (blocknr < buffer_blocknr[i])
			continue;
		blk_offset = (blocknr - buffer_blocknr[i]) << PAGE_CACHE_SHIFT;
		blk_offset += (offset & (PAGE_CACHE_SIZE - 1));
		if (blk_offset + len > BUFFER_SIZE)
			continue;
		return read_buffers[i] + blk_offset;
	}

	buffer = next_buffer;
	next_buffer = NEXT_BUFFER(buffer);
	buffer_blocknr[buffer] = blocknr;
	buffer_dev[buffer] = sb;

	mblock = offset / mtd->erasesize;
	moffset = (offset & (mtd->erasesize - 1)) & (~(PAGE_CACHE_SIZE - 1));
	offset &= (PAGE_CACHE_SIZE - 1);

	pblock = get_block_map(sb, mblock);
	maddr = pblock * mtd->erasesize + moffset;

	data = read_buffers[buffer];
	if (moffset + BUFFER_SIZE <= mtd->erasesize) {
		retv = mtd->read(mtd, maddr, BUFFER_SIZE, &dummy, data);
	} else {
		int read_size;
		read_size = mtd->erasesize - moffset;
		retv = mtd->read(mtd, maddr, read_size, &dummy, data);
		pblock = get_block_map(sb, mblock + 1);
		maddr = pblock * mtd->erasesize;
		retv = mtd->read(mtd, maddr, (BUFFER_SIZE - read_size), &dummy, data + read_size);
	}

	return read_buffers[buffer] + offset;
}
Пример #2
0
/*===========================================================================*
 *                             fs_rdlink                                     *
 *===========================================================================*/
int fs_rdlink()
{
  struct buf *bp = NULL;       /* buffer containing link text */
  char* link_text;             /* either bp->b_data or rip->i_block */
  register struct inode *rip;  /* target inode */
  register int r;              /* return value */
  size_t copylen;

  copylen = min( (size_t) fs_m_in.REQ_MEM_SIZE, UMAX_FILE_POS);

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

  if (rip->i_size >= MAX_FAST_SYMLINK_LENGTH) {
  /* normal symlink */
       	if(!(bp = get_block_map(rip, 0))) {
		r = EIO;
	} else {
		link_text = b_data(bp);
		r = OK;
	}
  } else {
        /* fast symlink, stored in inode */
        link_text = (char*) rip->i_block;
	r = OK;
  }
  if (r == OK) {
  /* Passed all checks */
  /* We can safely cast to unsigned, because copylen is guaranteed to be
     below max file size */
	copylen = min( copylen, (unsigned) rip->i_size);
	r = sys_safecopyto(VFS_PROC_NR, (cp_grant_id_t) fs_m_in.REQ_GRANT,
	                   (vir_bytes) 0, (vir_bytes) link_text,
			   (size_t) copylen);
	put_block(bp, DIRECTORY_BLOCK);
	if (r == OK)
		fs_m_out.RES_NBYTES = copylen;
  }

  put_inode(rip);
  return(r);
}
Пример #3
0
/*===========================================================================*
 *                             fs_rdlink                                     *
 *===========================================================================*/
ssize_t fs_rdlink(ino_t ino_nr, struct fsdriver_data *data, size_t bytes)
{
    struct buf *bp = NULL;       /* buffer containing link text */
    char* link_text;             /* either bp->b_data or rip->i_block */
    register struct inode *rip;  /* target inode */
    register int r;              /* return value */

    /* Temporarily open the file. */
    if( (rip = get_inode(fs_dev, ino_nr)) == NULL)
        return(EINVAL);

    if (rip->i_size >= MAX_FAST_SYMLINK_LENGTH) {
        /* normal symlink */
        if(!(bp = get_block_map(rip, 0))) {
            r = EIO;
        } else {
            link_text = b_data(bp);
            r = OK;
        }
    } else {
        /* fast symlink, stored in inode */
        link_text = (char*) rip->i_block;
        r = OK;
    }
    if (r == OK) {
        /* Passed all checks */
        if (bytes > rip->i_size)
            bytes = rip->i_size;
        r = fsdriver_copyout(data, 0, link_text, bytes);
        put_block(bp, DIRECTORY_BLOCK);
        if (r == OK)
            r = bytes;
    }

    put_inode(rip);
    return(r);
}