diff options
Diffstat (limited to 'sys/fs/ext2fs/ext2_subr.c')
-rw-r--r-- | sys/fs/ext2fs/ext2_subr.c | 51 |
1 files changed, 47 insertions, 4 deletions
diff --git a/sys/fs/ext2fs/ext2_subr.c b/sys/fs/ext2fs/ext2_subr.c index df6e430..cd4a06b 100644 --- a/sys/fs/ext2fs/ext2_subr.c +++ b/sys/fs/ext2fs/ext2_subr.c @@ -50,10 +50,11 @@ #include <fs/ext2fs/ext2_extern.h> #include <fs/ext2fs/ext2fs.h> #include <fs/ext2fs/fs.h> - -#ifdef KDB +#include <fs/ext2fs/ext2_extents.h> #include <fs/ext2fs/ext2_mount.h> +#include <fs/ext2fs/ext2_dinode.h> +#ifdef KDB void ext2_checkoverlap(struct buf *, struct inode *); #endif @@ -70,21 +71,63 @@ ext2_blkatoff(struct vnode *vp, off_t offset, char **res, struct buf **bpp) struct buf *bp; e2fs_lbn_t lbn; int bsize, error; + daddr_t newblk; + struct ext4_extent *ep; + struct ext4_extent_path path; ip = VTOI(vp); fs = ip->i_e2fs; lbn = lblkno(fs, offset); bsize = blksize(fs, ip, lbn); - *bpp = NULL; - if ((error = bread(vp, lbn, bsize, NOCRED, &bp)) != 0) { + + /* + * The EXT4_EXTENTS requires special treatment, otherwise we can + * fall back to the normal path. + */ + if (!(ip->i_flags & EXT4_EXTENTS)) + goto normal; + + memset(&path, 0, sizeof(path)); + if (ext4_ext_find_extent(fs, ip, lbn, &path) == NULL) + goto normal; + ep = path.ep_ext; + if (ep == NULL) + goto normal; + + newblk = lbn - ep->e_blk + + (ep->e_start_lo | (daddr_t)ep->e_start_hi << 32); + + if (path.ep_bp != NULL) { + brelse(path.ep_bp); + path.ep_bp = NULL; + } + error = bread(ip->i_devvp, fsbtodb(fs, newblk), bsize, NOCRED, &bp); + if (error != 0) { brelse(bp); return (error); } if (res) *res = (char *)bp->b_data + blkoff(fs, offset); + /* + * If EXT4_EXTENTS is enabled we would get a wrong offset so + * reset b_offset here. + */ + bp->b_offset = lbn * bsize; *bpp = bp; return (0); + +normal: + if (*bpp == NULL) { + if ((error = bread(vp, lbn, bsize, NOCRED, &bp)) != 0) { + brelse(bp); + return (error); + } + if (res) + *res = (char *)bp->b_data + blkoff(fs, offset); + *bpp = bp; + } + return (0); } #ifdef KDB |