Example #1
0
/*
 * This function converts the logical block number of a file to
 * its physical block number on the disk within ext4 extents.
 */
static int
ext4_bmapext(struct vnode *vp, int32_t bn, int64_t *bnp, int *runp, int *runb)
{
	struct inode *ip;
	struct m_ext2fs *fs;
	struct ext4_extent *ep;
	struct ext4_extent_path path;
	daddr_t lbn;

	ip = VTOI(vp);
	fs = ip->i_e2fs;
	lbn = bn;

	/*
	 * TODO: need to implement read ahead to improve the performance.
	 */
	if (runp != NULL)
		*runp = 0;

	if (runb != NULL)
		*runb = 0;

	ext4_ext_find_extent(fs, ip, lbn, &path);
	ep = path.ep_ext;
	if (ep == NULL)
		return (EIO);

	*bnp = fsbtodb(fs, lbn - ep->e_blk +
	    (ep->e_start_lo | (daddr_t)ep->e_start_hi << 32));

	if (*bnp == 0)
		*bnp = -1;

	return (0);
}
Example #2
0
/*
 * Logical block number of a file -> physical block number on disk within ext4 extents.
 */
int
ext4_bmapext(struct vnode *vp, daddr_t bn, daddr_t *bnp, struct indir *ap, int *nump, int *runp)
{
	struct inode *ip;
	struct m_ext2fs *fs;
	struct ext4_extent *ep;
	struct ext4_extent_path path;
	daddr_t pos;

	ip = VTOI(vp);
	fs = ip->i_e2fs;

	if (runp != NULL)
		*runp = 0;
	if (nump != NULL)
		*nump = 0;

	ext4_ext_find_extent(fs, ip, bn, &path);
	if ((ep = path.ep_ext) == NULL)
		return (EIO);

	pos = bn - ep->e_blk + (((daddr_t)ep->e_start_hi << 32) | ep->e_start_lo);
	if ((*bnp = fsbtodb(fs, pos)) == 0)
		*bnp = -1;
	return (0);
}
Example #3
0
static int finish_range(handle_t *handle, struct inode *inode,
				struct migrate_struct *lb)

{
	int retval = 0, needed;
	struct ext4_extent newext;
	struct ext4_ext_path *path;
	if (lb->first_pblock == 0)
		return 0;

	/* Add the extent to temp inode*/
	newext.ee_block = cpu_to_le32(lb->first_block);
	newext.ee_len   = cpu_to_le16(lb->last_block - lb->first_block + 1);
	ext4_ext_store_pblock(&newext, lb->first_pblock);
	path = ext4_ext_find_extent(inode, lb->first_block, NULL);

	if (IS_ERR(path)) {
		retval = PTR_ERR(path);
		path = NULL;
		goto err_out;
	}

	/*
	 * Calculate the credit needed to inserting this extent
	 * Since we are doing this in loop we may accumalate extra
	 * credit. But below we try to not accumalate too much
	 * of them by restarting the journal.
	 */
	needed = ext4_ext_calc_credits_for_single_extent(inode,
		    lb->last_block - lb->first_block + 1, path);

	/*
	 * Make sure the credit we accumalated is not really high
	 */
	if (needed && ext4_handle_has_enough_credits(handle,
						EXT4_RESERVE_TRANS_BLOCKS)) {
		retval = ext4_journal_restart(handle, needed);
		if (retval)
			goto err_out;
	} else if (needed) {
		retval = ext4_journal_extend(handle, needed);
		if (retval) {
			/*
			 * IF not able to extend the journal restart the journal
			 */
			retval = ext4_journal_restart(handle, needed);
			if (retval)
				goto err_out;
		}
	}
	retval = ext4_ext_insert_extent(handle, inode, path, &newext, 0);
err_out:
	if (path) {
		ext4_ext_drop_refs(path);
		kfree(path);
	}
	lb->first_pblock = 0;
	return retval;
}
Example #4
0
/*
 * Convert the logical block number of a file to its physical block number
 * on the disk within ext4 extents.
 */
static int
ext4_bmapext(struct vnode *vp, int32_t bn, int64_t *bnp, int *runp, int *runb)
{
	struct inode *ip;
	struct m_ext2fs *fs;
	struct ext4_extent *ep;
	struct ext4_extent_path path = { .ep_bp = NULL };
	daddr_t lbn;
	int error;

	ip = VTOI(vp);
	fs = ip->i_e2fs;
	lbn = bn;

	if (runp != NULL)
		*runp = 0;
	if (runb != NULL)
		*runb = 0;
	error = 0;

	ext4_ext_find_extent(fs, ip, lbn, &path);
	if (path.ep_is_sparse) {
		*bnp = -1;
		if (runp != NULL)
			*runp = path.ep_sparse_ext.e_len -
			    (lbn - path.ep_sparse_ext.e_blk) - 1;
		if (runb != NULL)
			*runb = lbn - path.ep_sparse_ext.e_blk;
	} else {
		if (path.ep_ext == NULL) {
			error = EIO;
			goto out;
		}
		ep = path.ep_ext;
		*bnp = fsbtodb(fs, lbn - ep->e_blk +
		    (ep->e_start_lo | (daddr_t)ep->e_start_hi << 32));

		if (*bnp == 0)
			*bnp = -1;

		if (runp != NULL)
			*runp = ep->e_len - (lbn - ep->e_blk) - 1;
		if (runb != NULL)
			*runb = lbn - ep->e_blk;
	}

out:
	if (path.ep_bp != NULL)
		brelse(path.ep_bp);

	return (error);
}
Example #5
0
/*
 * this function handles ext4 extents block mapping
 */
static int
ext4_ext_read(struct vop_read_args *ap)
{
	struct vnode *vp;
	struct inode *ip;
        struct uio *uio;
	struct m_ext2fs *fs;
        struct buf *bp;
        struct ext4_extent nex, *ep;
        struct ext4_extent_header *ehp;
        struct ext4_extent_path path;
        daddr_t lbn, nextlbn, newblk = 0;
        off_t bytesinfile;
        u_short mode;
        int cache_type;
	int orig_resid;
        int error = 0;
        int depth = 0;
        long size, xfersize, blkoffset;

	vp = ap->a_vp;
	ip = VTOI(vp);
        mode = ip->i_mode;
        uio = ap->a_uio;
        memset(&path, 0, sizeof(path));

	orig_resid = uio->uio_resid;
	KASSERT(orig_resid >= 0, ("ext2_read: uio->uio_resid < 0"));
	if (orig_resid == 0)
		return (0);
	KASSERT(uio->uio_offset >= 0, ("ext2_read: uio->uio_offset < 0"));
	fs = ip->I_FS;
	if (uio->uio_offset < ip->i_size && uio->uio_offset >= fs->e2fs_maxfilesize)
		return (EOVERFLOW);

        for (error = 0, bp = NULL; uio->uio_resid > 0; bp = NULL) {
                if ((bytesinfile = ip->i_size - uio->uio_offset) <= 0)
                        break;
                lbn = lblkno(fs, uio->uio_offset);
                nextlbn = lbn + 1;
                size = BLKSIZE(fs, ip, lbn);
                blkoffset = blkoff(fs, uio->uio_offset);

                xfersize = fs->e2fs_fsize - blkoffset;
                if (uio->uio_resid < xfersize)
                        xfersize = uio->uio_resid;
                if (bytesinfile < xfersize)
                        xfersize = bytesinfile;

                /* get block from ext4 extent cache */
                cache_type = ext4_ext_in_cache(ip, lbn, &nex);
                if (cache_type != 0) {
                        /* block does not be allocated yet */
                        if (cache_type == EXT4_EXT_CACHE_GAP)
                                return (error);
                        else if (cache_type == EXT4_EXT_CACHE_IN)
                                newblk = lbn - nex.e_blk +
                                    (nex.e_start_lo | ((daddr_t)(nex.e_start_hi) << 31) << 1);
                } else {
                        ext4_ext_find_extent(fs, ip, lbn, &path);
                        depth = ((struct ext4_extent_header *)(ip->i_db))->eh_depth;
                        if (path.ep_ext == NULL && depth != 0)
                                return (EIO);

                        ehp = path.ep_header;
                        ep = path.ep_ext;
                        if (ep == NULL)
                                return (EIO);

                        ext4_ext_put_cache(ip, ep, EXT4_EXT_CACHE_IN);

                        newblk = lbn - ep->e_blk +
                            (ep->e_start_lo | ((daddr_t)(ep->e_start_hi) << 31) << 1);

                        if (path.ep_bp != NULL) {
                                brelse(path.ep_bp);
                                path.ep_bp = NULL;
                        }
                }

                error = bread(ip->i_devvp, fsbtodb(fs, newblk), size, NOCRED, &bp);
                if (error) {
                        brelse(bp);
                        bp = NULL;
                        break;
                }

                size -= bp->b_resid;
                if (size < xfersize) {
                        if (size == 0)
                                break;
                        xfersize = size;
                }
                error = uiomove((char *)bp->b_data + blkoffset,
                    (int)xfersize, uio);
                if (error)
                        break;

                bqrelse(bp);
        }

        if (bp != NULL)
                bqrelse(bp);

        return (error);
}