diff --git a/sys/fs/ext2fs/ext2_extents.h b/sys/fs/ext2fs/ext2_extents.h --- a/sys/fs/ext2fs/ext2_extents.h +++ b/sys/fs/ext2fs/ext2_extents.h @@ -122,15 +122,15 @@ void ext4_ext_tree_init(struct inode *ip); int ext4_ext_in_cache(struct inode *, daddr_t, struct ext4_extent *); void ext4_ext_put_cache(struct inode *, struct ext4_extent *, int); -int ext4_ext_find_extent(struct inode *, daddr_t, struct ext4_extent_path **); -void ext4_ext_path_free(struct ext4_extent_path *path); -int ext4_ext_remove_space(struct inode *ip, off_t length, int flags, +int ext4_ext_find_extent(struct inode *, daddr_t, struct ext4_extent_path **); +void ext4_ext_path_free(struct ext4_extent_path *path); +int ext4_ext_remove_space(struct inode *ip, off_t length, int flags, struct ucred *cred, struct thread *td); -int ext4_ext_get_blocks(struct inode *ip, int64_t iblock, +int ext4_ext_get_blocks(struct inode *ip, int64_t iblock, unsigned long max_blocks, struct ucred *cred, struct buf **bpp, int *allocate, daddr_t *); #ifdef EXT2FS_PRINT_EXTENTS -void ext4_ext_print_extent_tree_status(struct inode *ip); +int ext4_ext_walk(struct inode *ip); #endif #endif /* !_FS_EXT2FS_EXT2_EXTENTS_H_ */ diff --git a/sys/fs/ext2fs/ext2_extents.c b/sys/fs/ext2fs/ext2_extents.c --- a/sys/fs/ext2fs/ext2_extents.c +++ b/sys/fs/ext2fs/ext2_extents.c @@ -59,94 +59,140 @@ static MALLOC_DEFINE(M_EXT2EXTENTS, "ext2_extents", "EXT2 extents"); #ifdef EXT2FS_PRINT_EXTENTS -static void -ext4_ext_print_extent(struct ext4_extent *ep) +static const bool print_extents_walk = true; + +static int ext4_ext_check_header(struct inode *, struct ext4_extent_header *); +static int ext4_ext_walk_header(struct inode *, struct ext4_extent_header *); +static inline e4fs_daddr_t ext4_ext_index_pblock(struct ext4_extent_index *); +static inline e4fs_daddr_t ext4_ext_extent_pblock(struct ext4_extent *); + +static int +ext4_ext_blk_check(struct inode *ip, e4fs_daddr_t blk) { + struct m_ext2fs *fs; - printf(" ext %p => (blk %u len %u start %ju)\n", - ep, le32toh(ep->e_blk), le16toh(ep->e_len), - (uint64_t)le16toh(ep->e_start_hi) << 32 | le32toh(ep->e_start_lo)); -} + fs = ip->i_e2fs; -static void ext4_ext_print_header(struct inode *ip, struct ext4_extent_header *ehp); + if (blk < fs->e2fs->e2fs_first_dblock || blk >= fs->e2fs_bcount) + return (EIO); -static void -ext4_ext_print_index(struct inode *ip, struct ext4_extent_index *ex, int do_walk) + return (0); +} + +static int +ext4_ext_walk_index(struct inode *ip, struct ext4_extent_index *ex, bool do_walk) { struct m_ext2fs *fs; struct buf *bp; + e4fs_daddr_t blk; int error; fs = ip->i_e2fs; - printf(" index %p => (blk %u pblk %ju)\n", - ex, le32toh(ex->ei_blk), (uint64_t)le16toh(ex->ei_leaf_hi) << 32 | - le32toh(ex->ei_leaf_lo)); + if (print_extents_walk) + printf(" index %p => (blk %u pblk %ju)\n", ex, + le32toh(ex->ei_blk), (uint64_t)le16toh(ex->ei_leaf_hi) << 32 | + le32toh(ex->ei_leaf_lo)); if(!do_walk) - return; + return (0); + + blk = ext4_ext_index_pblock(ex); + error = ext4_ext_blk_check(ip, blk); + if (error) + return (error); if ((error = bread(ip->i_devvp, - fsbtodb(fs, ((uint64_t)le16toh(ex->ei_leaf_hi) << 32 | - le32toh(ex->ei_leaf_lo))), (int)fs->e2fs_bsize, NOCRED, &bp)) != 0) { + fsbtodb(fs, blk), (int)fs->e2fs_bsize, NOCRED, &bp)) != 0) { brelse(bp); - return; + return (error); } - ext4_ext_print_header(ip, (struct ext4_extent_header *)bp->b_data); + error = ext4_ext_walk_header(ip, (struct ext4_extent_header *)bp->b_data); brelse(bp); + return (error); } -static void -ext4_ext_print_header(struct inode *ip, struct ext4_extent_header *ehp) +static int +ext4_ext_walk_extent(struct inode *ip, struct ext4_extent *ep) +{ + e4fs_daddr_t blk; + int error; + + blk = ext4_ext_extent_pblock(ep); + error = ext4_ext_blk_check(ip, blk); + if (error) + return (error); + + if (print_extents_walk) + printf(" ext %p => (blk %u len %u start %ju)\n", + ep, le32toh(ep->e_blk), le16toh(ep->e_len), + (uint64_t)blk); + + return (0); +} + +static int +ext4_ext_walk_header(struct inode *ip, struct ext4_extent_header *eh) { - int i; + int i, error = 0; - printf("header %p => (magic 0x%x entries %d max %d depth %d gen %d)\n", - ehp, le16toh(ehp->eh_magic), le16toh(ehp->eh_ecount), - le16toh(ehp->eh_max), le16toh(ehp->eh_depth), le32toh(ehp->eh_gen)); + error = ext4_ext_check_header(ip, eh); + if (error) + return (error); + + if (print_extents_walk) + printf("header %p => (entries %d max %d depth %d gen %d)\n", + eh, le16toh(eh->eh_ecount), + le16toh(eh->eh_max), le16toh(eh->eh_depth), le32toh(eh->eh_gen)); - for (i = 0; i < le16toh(ehp->eh_ecount); i++) - if (ehp->eh_depth != 0) - ext4_ext_print_index(ip, - (struct ext4_extent_index *)(ehp + 1 + i), 1); + for (i = 0; i < le16toh(eh->eh_ecount) && error == 0; i++) + if (eh->eh_depth != 0) + error = ext4_ext_walk_index(ip, + (struct ext4_extent_index *)(eh + 1 + i), true); else - ext4_ext_print_extent((struct ext4_extent *)(ehp + 1 + i)); + error = ext4_ext_walk_extent(ip, (struct ext4_extent *)(eh + 1 + i)); + + return (error); } -static void +static int ext4_ext_print_path(struct inode *ip, struct ext4_extent_path *path) { - int k, l; + int k, l, error = 0; l = path->ep_depth; - printf("ip=%ju, Path:\n", ip->i_number); - for (k = 0; k <= l; k++, path++) { + if (print_extents_walk) + printf("ip=%ju, Path:\n", ip->i_number); + + for (k = 0; k <= l && error == 0; k++, path++) { if (path->ep_index) { - ext4_ext_print_index(ip, path->ep_index, 0); + error = ext4_ext_walk_index(ip, path->ep_index, false); } else if (path->ep_ext) { - ext4_ext_print_extent(path->ep_ext); + error = ext4_ext_walk_extent(ip, path->ep_ext); } } + + return (error); } -void -ext4_ext_print_extent_tree_status(struct inode *ip) +int +ext4_ext_walk(struct inode *ip) { struct ext4_extent_header *ehp; - ehp = (struct ext4_extent_header *)(char *)ip->i_db; + ehp = (struct ext4_extent_header *)ip->i_db; - printf("Extent status:ip=%ju\n", ip->i_number); - if (!(ip->i_flag & IN_E4EXTENTS)) - return; + if (print_extents_walk) + printf("Extent status:ip=%ju\n", ip->i_number); - ext4_ext_print_header(ip, ehp); + if (!(ip->i_flag & IN_E4EXTENTS)) + return (0); - return; + return (ext4_ext_walk_header(ip, ehp)); } #endif diff --git a/sys/fs/ext2fs/ext2_inode_cnv.c b/sys/fs/ext2fs/ext2_inode_cnv.c --- a/sys/fs/ext2fs/ext2_inode_cnv.c +++ b/sys/fs/ext2fs/ext2_inode_cnv.c @@ -86,7 +86,7 @@ le16toh(ep->e_start_hi)); printf("\n"); } else { - printf("BLOCKS:"); + printf("Blocks:"); for (i = 0; i < (in->i_blocks <= 24 ? (in->i_blocks + 1) / 2 : 12); i++) printf(" %d", in->i_db[i]); printf("\n"); diff --git a/sys/fs/ext2fs/ext2_vfsops.c b/sys/fs/ext2fs/ext2_vfsops.c --- a/sys/fs/ext2fs/ext2_vfsops.c +++ b/sys/fs/ext2fs/ext2_vfsops.c @@ -1283,11 +1283,18 @@ for (i = used_blocks; i < EXT2_NDIR_BLOCKS; i++) ip->i_db[i] = 0; } + + bqrelse(bp); + #ifdef EXT2FS_PRINT_EXTENTS ext2_print_inode(ip); - ext4_ext_print_extent_tree_status(ip); + error = ext4_ext_walk(ip); + if (error) { + vput(vp); + *vpp = NULL; + return (error); + } #endif - bqrelse(bp); /* * Initialize the vnode from the inode, check for aliases. diff --git a/sys/fs/ext2fs/fs.h b/sys/fs/ext2fs/fs.h --- a/sys/fs/ext2fs/fs.h +++ b/sys/fs/ext2fs/fs.h @@ -164,6 +164,6 @@ /* * Use if additional debug logging is required. */ -/* #define EXT2FS_PRINT_EXTENTS */ +/* #define EXT2FS_PRINT_EXTENTS */ #endif /* !_FS_EXT2FS_FS_H_ */