Changeset View
Changeset View
Standalone View
Standalone View
sys/fs/ext2fs/ext2_bmap.c
Context not available. | |||||
#include <fs/ext2fs/ext2_extern.h> | #include <fs/ext2fs/ext2_extern.h> | ||||
#include <fs/ext2fs/ext2_mount.h> | #include <fs/ext2fs/ext2_mount.h> | ||||
static int ext4_bmapext(struct vnode *, int32_t, int64_t *, int *, int *); | |||||
/* | /* | ||||
* Bmap converts the logical block number of a file to its physical block | * Bmap converts the logical block number of a file to its physical block | ||||
* number on the disk. The conversion is done by using the logical block | * number on the disk. The conversion is done by using the logical block | ||||
Context not available. | |||||
* Convert the logical block number of a file to its physical block number | * Convert the logical block number of a file to its physical block number | ||||
* on the disk within ext4 extents. | * on the disk within ext4 extents. | ||||
*/ | */ | ||||
static int | int | ||||
ext4_bmapext(struct vnode *vp, int32_t bn, int64_t *bnp, int *runp, int *runb) | ext4_bmapext(struct vnode *vp, int32_t bn, int64_t *bnp, int *runp, int *runb) | ||||
{ | { | ||||
struct inode *ip; | struct inode *ip; | ||||
struct m_ext2fs *fs; | struct m_ext2fs *fs; | ||||
struct ext4_extent_header *ehp; | |||||
struct ext4_extent *ep; | struct ext4_extent *ep; | ||||
struct ext4_extent_path path = {.ep_bp = NULL}; | struct ext4_extent_path *path = NULL; | ||||
daddr_t lbn; | daddr_t lbn; | ||||
int error; | int error, depth; | ||||
ip = VTOI(vp); | ip = VTOI(vp); | ||||
fs = ip->i_e2fs; | fs = ip->i_e2fs; | ||||
lbn = bn; | lbn = bn; | ||||
ehp = (struct ext4_extent_header *)ip->i_data; | |||||
depth = ehp->eh_depth; | |||||
*bnp = -1; | |||||
if (runp != NULL) | if (runp != NULL) | ||||
*runp = 0; | *runp = 0; | ||||
if (runb != NULL) | if (runb != NULL) | ||||
*runb = 0; | *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) | error = ext4_ext_find_extent(ip, lbn, &path); | ||||
*bnp = -1; | if (error) | ||||
return (error); | |||||
if (runp != NULL) | ep = path[depth].ep_ext; | ||||
*runp = ep->e_len - (lbn - ep->e_blk) - 1; | if(ep) { | ||||
if (runb != NULL) | if (lbn < ep->e_blk) { | ||||
*runb = lbn - ep->e_blk; | if (runp != NULL) | ||||
*runp = ep->e_blk - lbn - 1; | |||||
} else if (ep->e_blk <= lbn && lbn < ep->e_blk + ep->e_len) { | |||||
*bnp = fsbtodb(fs, lbn - ep->e_blk + | |||||
(ep->e_start_lo | (daddr_t)ep->e_start_hi << 32)); | |||||
if (runp != NULL) | |||||
*runp = ep->e_len - (lbn - ep->e_blk) - 1; | |||||
if (runb != NULL) | |||||
*runb = lbn - ep->e_blk; | |||||
} else { | |||||
if (runb != NULL) | |||||
*runb = ep->e_blk + lbn - ep->e_len; | |||||
} | |||||
} | } | ||||
out: | ext4_ext_path_free(path); | ||||
if (path.ep_bp != NULL) | |||||
brelse(path.ep_bp); | |||||
return (error); | return (error); | ||||
} | } | ||||
Context not available. |