Module Name:    src
Committed By:   christos
Date:           Fri Jun  3 15:35:48 UTC 2016

Modified Files:
        src/sys/ufs/ext2fs: ext2fs.h ext2fs_bmap.c
Added Files:
        src/sys/ufs/ext2fs: ext2fs_extents.c ext2fs_extents.h

Log Message:
Add ext4 extent support from GSoC 2016 (Hrishikesh Goyal), from the FreeBSD
ext2 code.


To generate a diff of this commit:
cvs rdiff -u -r1.36 -r1.37 src/sys/ufs/ext2fs/ext2fs.h
cvs rdiff -u -r1.26 -r1.27 src/sys/ufs/ext2fs/ext2fs_bmap.c
cvs rdiff -u -r0 -r1.1 src/sys/ufs/ext2fs/ext2fs_extents.c \
    src/sys/ufs/ext2fs/ext2fs_extents.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/ufs/ext2fs/ext2fs.h
diff -u src/sys/ufs/ext2fs/ext2fs.h:1.36 src/sys/ufs/ext2fs/ext2fs.h:1.37
--- src/sys/ufs/ext2fs/ext2fs.h:1.36	Sun Jun 23 03:28:37 2013
+++ src/sys/ufs/ext2fs/ext2fs.h	Fri Jun  3 11:35:48 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: ext2fs.h,v 1.36 2013/06/23 07:28:37 dholland Exp $	*/
+/*	$NetBSD: ext2fs.h,v 1.37 2016/06/03 15:35:48 christos Exp $	*/
 
 /*
  * Copyright (c) 1982, 1986, 1993
@@ -86,6 +86,11 @@
 #define	BBLOCK		((daddr_t)(0))
 #define	SBLOCK		((daddr_t)(BBLOCK + BBSIZE / DEV_BSIZE))
 
+#define	fsbtodb(fs, b)  ((daddr_t)(b) << (fs)->e2fs_fsbtodb)
+/* calculates (loc / fs->fs_bsize) */
+#define	lblkno(fs, loc) ((loc) >> (fs->e2fs_bshift))
+#define	blksize(fs, ip, lbn) ((fs)->e2fs_bsize)
+
 /*
  * Addresses stored in inodes are capable of addressing blocks
  * XXX
@@ -132,7 +137,7 @@ struct ext2fs {
 	uint32_t  e2fs_fbcount;		/* free blocks count */
 	uint32_t  e2fs_ficount;		/* free inodes count */
 	uint32_t  e2fs_first_dblock;	/* first data block */
-	uint32_t  e2fs_log_bsize;	/* block size = 1024*(2^e2fs_log_bsize) */
+	uint32_t  e2fs_log_bsize;	/* bsize = 1024*(2^e2fs_log_bsize) */
 	uint32_t  e2fs_fsize;		/* fragment size */
 	uint32_t  e2fs_bpg;		/* blocks per group */
 	uint32_t  e2fs_fpg;		/* frags per group */
@@ -165,7 +170,62 @@ struct ext2fs {
 	uint8_t   e2fs_prealloc;	/* # of blocks to preallocate */
 	uint8_t   e2fs_dir_prealloc;	/* # of blocks to preallocate for dir */
 	uint16_t  e2fs_reserved_ngdb;	/* # of reserved gd blocks for resize */
-	uint32_t  reserved2[204];
+	
+	/* Additional fields */
+	char      e3fs_journal_uuid[16];/* uuid of journal superblock */
+	uint32_t  e3fs_journal_inum;	/* inode number of journal file */
+	uint32_t  e3fs_journal_dev;	/* device number of journal file */
+	uint32_t  e3fs_last_orphan;	/* start of list of inodes to delete */
+	uint32_t  e3fs_hash_seed[4];	/* HTREE hash seed */
+	char      e3fs_def_hash_version;/* Default hash version to use */
+	char      e3fs_jnl_backup_type;
+	uint16_t  e3fs_desc_size;	/* size of group descriptor */
+	uint32_t  e3fs_default_mount_opts;
+	uint32_t  e3fs_first_meta_bg;	/* First metablock block group */
+	uint32_t  e3fs_mkfs_time;	/* when the fs was created */
+	uint32_t  e3fs_jnl_blks[17];	/* backup of the journal inode */
+	uint32_t  e4fs_bcount_hi;	/* high bits of blocks count */
+	uint32_t  e4fs_rbcount_hi;	/* high bits of reserved blocks count */
+	uint32_t  e4fs_fbcount_hi;	/* high bits of free blocks count */
+	uint16_t  e4fs_min_extra_isize; /* all inodes have some bytes */
+	uint16_t  e4fs_want_extra_isize;/* inodes must reserve some bytes */
+	uint32_t  e4fs_flags;		/* miscellaneous flags */
+	uint16_t  e4fs_raid_stride;	/* RAID stride */
+	uint16_t  e4fs_mmpintv;		/* seconds to wait in MMP checking */
+	uint64_t  e4fs_mmpblk;		/* block for multi-mount protection */
+	uint32_t  e4fs_raid_stripe_wid; /* blocks on data disks (N * stride) */
+	uint8_t   e4fs_log_gpf;		/* FLEX_BG group size */
+	uint8_t   e4fs_chksum_type;	/* metadata checksum algorithm used */
+	uint8_t   e4fs_encrypt;		/* versioning level for encryption */
+	uint8_t   e4fs_reserved_pad;
+	uint64_t  e4fs_kbytes_written;	/* number of lifetime kilobytes */
+	uint32_t  e4fs_snapinum;	/* inode number of active snapshot */
+	uint32_t  e4fs_snapid;		/* sequential ID of active snapshot */
+	uint64_t  e4fs_snaprbcount;	/* rsvd blocks for active snapshot */
+	uint32_t  e4fs_snaplist;	/* inode number for on-disk snapshot */
+	uint32_t  e4fs_errcount;	/* number of file system errors */
+	uint32_t  e4fs_first_errtime;	/* first time an error happened */
+	uint32_t  e4fs_first_errino;	/* inode involved in first error */
+	uint64_t  e4fs_first_errblk;	/* block involved of first error */
+	uint8_t   e4fs_first_errfunc[32];/* function where error happened */
+	uint32_t  e4fs_first_errline;	/* line number where error happened */
+	uint32_t  e4fs_last_errtime;	/* most recent time of an error */
+	uint32_t  e4fs_last_errino;	/* inode involved in last error */
+	uint32_t  e4fs_last_errline;	/* line number where error happened */
+	uint64_t  e4fs_last_errblk;	/* block involved of last error */
+	uint8_t   e4fs_last_errfunc[32];/* function where error happened */
+	uint8_t   e4fs_mount_opts[64];
+	uint32_t  e4fs_usrquota_inum;	/* inode for tracking user quota */
+	uint32_t  e4fs_grpquota_inum;	/* inode for tracking group quota */
+	uint32_t  e4fs_overhead_clusters;/* overhead blocks/clusters */
+	uint32_t  e4fs_backup_bgs[2];	/* groups with sparse_super2 SBs */
+	uint8_t   e4fs_encrypt_algos[4];/* encryption algorithms in use */
+	uint8_t   e4fs_encrypt_pw_salt[16];/* salt used for string2key */
+	uint32_t  e4fs_lpf_ino;		/* location of the lost+found inode */
+	uint32_t  e4fs_proj_quota_inum;	/* inode for tracking project quota */
+	uint32_t  e4fs_chksum_seed;	/* checksum seed */
+	uint32_t  e4fs_reserved[98];	/* padding to the end of the block */
+	uint32_t  e4fs_sbchksum;	/* superblock checksum */
 };
 
 
@@ -267,7 +327,8 @@ struct m_ext2fs {
 #define EXT2F_ROCOMPAT_SUPP		(EXT2F_ROCOMPAT_SPARSESUPER \
 					 | EXT2F_ROCOMPAT_LARGEFILE \
 					 | EXT2F_ROCOMPAT_HUGE_FILE)
-#define EXT2F_INCOMPAT_SUPP		EXT2F_INCOMPAT_FTYPE
+#define EXT2F_INCOMPAT_SUPP		(EXT2F_INCOMPAT_FTYPE \
+					 | EXT2F_INCOMPAT_EXTENTS)
 
 /*
  * Definitions of behavior on errors

Index: src/sys/ufs/ext2fs/ext2fs_bmap.c
diff -u src/sys/ufs/ext2fs/ext2fs_bmap.c:1.26 src/sys/ufs/ext2fs/ext2fs_bmap.c:1.27
--- src/sys/ufs/ext2fs/ext2fs_bmap.c:1.26	Tue Jan 22 04:39:15 2013
+++ src/sys/ufs/ext2fs/ext2fs_bmap.c	Fri Jun  3 11:35:48 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: ext2fs_bmap.c,v 1.26 2013/01/22 09:39:15 dholland Exp $	*/
+/*	$NetBSD: ext2fs_bmap.c,v 1.27 2016/06/03 15:35:48 christos Exp $	*/
 
 /*
  * Copyright (c) 1989, 1991, 1993
@@ -65,7 +65,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ext2fs_bmap.c,v 1.26 2013/01/22 09:39:15 dholland Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ext2fs_bmap.c,v 1.27 2016/06/03 15:35:48 christos Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -84,8 +84,10 @@ __KERNEL_RCSID(0, "$NetBSD: ext2fs_bmap.
 #include <ufs/ext2fs/ext2fs.h>
 #include <ufs/ext2fs/ext2fs_extern.h>
 
-static int ext2fs_bmaparray(struct vnode *, daddr_t, daddr_t *,
-				struct indir *, int *, int *);
+
+static int ext4_bmapext(struct vnode *, int32_t, int64_t *, int *, int *);
+static int ext2fs_bmaparray(struct vnode *, daddr_t, daddr_t *, struct indir *,
+    int *, int *);
 
 #define	is_sequential(ump, a, b)	((b) == (a) + ump->um_seqinc)
 
@@ -112,11 +114,79 @@ ext2fs_bmap(void *v)
 		*ap->a_vpp = VTOI(ap->a_vp)->i_devvp;
 	if (ap->a_bnp == NULL)
 		return (0);
+	
+	
+	if (VTOI(ap->a_vp)->i_din.e2fs_din->e2di_flags & IN_E4EXTENTS)
+		return ext4_bmapext(ap->a_vp, ap->a_bn, ap->a_bnp,
+		    ap->a_runp, NULL);
+	else
+		return ext2fs_bmaparray(ap->a_vp, ap->a_bn, ap->a_bnp, NULL,
+		    NULL, ap->a_runp);
+	
+		
+}
+
+/*
+ * 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 = 0;
+
+	ip = VTOI(vp);
+	fs = ip->i_e2fs;
+	lbn = bn;
+
+	/* XXX: Should not initialize on error? */
+	if (runp != NULL)
+		*runp = 0;
+
+	if (runb != NULL)
+		*runb = 0;
 
-	return (ext2fs_bmaparray(ap->a_vp, ap->a_bn, ap->a_bnp, NULL, NULL,
-		ap->a_runp));
+	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, 0);
+	}
+
+	return error;
 }
 
+
+
 /*
  * Indirect blocks are now on the vnode for the file.  They are given negative
  * logical block numbers.  Indirect blocks are addressed by the negative

Added files:

Index: src/sys/ufs/ext2fs/ext2fs_extents.c
diff -u /dev/null src/sys/ufs/ext2fs/ext2fs_extents.c:1.1
--- /dev/null	Fri Jun  3 11:35:48 2016
+++ src/sys/ufs/ext2fs/ext2fs_extents.c	Fri Jun  3 11:35:48 2016
@@ -0,0 +1,232 @@
+/*	$NetBSD: ext2fs_extents.c,v 1.1 2016/06/03 15:35:48 christos Exp $	*/
+
+/*-
+ * Copyright (c) 2010 Zheng Liu <[email protected]>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: head/sys/fs/ext2fs/ext2_extents.c 295523 2016-02-11 15:27:14Z pfg $
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: ext2fs_extents.c,v 1.1 2016/06/03 15:35:48 christos Exp $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/resourcevar.h>
+#include <sys/kernel.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <sys/buf.h>
+#include <sys/proc.h>
+#include <sys/mount.h>
+#include <sys/vnode.h>
+#include <sys/signalvar.h>
+#include <sys/kauth.h>
+
+#include <ufs/ufs/inode.h>
+#include <ufs/ufs/ufsmount.h>
+#include <ufs/ufs/ufs_extern.h>
+
+
+#include <ufs/ext2fs/ext2fs.h>
+#include <ufs/ext2fs/ext2fs_extents.h>
+#include <ufs/ext2fs/ext2fs_extern.h>
+
+
+
+static bool
+ext4_ext_binsearch_index(struct inode *ip, struct ext4_extent_path *path,
+		daddr_t lbn, daddr_t *first_lbn, daddr_t *last_lbn)
+{
+	struct ext4_extent_header *ehp = path->ep_header;
+	struct ext4_extent_index *first, *last, *l, *r, *m;
+
+	first = (struct ext4_extent_index *)(char *)(ehp + 1);
+	last = first + ehp->eh_ecount - 1;
+	l = first;
+	r = last;
+	while (l <= r) {
+		m = l + (r - l) / 2;
+		if (lbn < m->ei_blk)
+			r = m - 1;
+		else
+			l = m + 1;
+	}
+
+	if (l == first) {
+		path->ep_sparse_ext.e_blk = *first_lbn;
+		path->ep_sparse_ext.e_len = first->ei_blk - *first_lbn;
+		path->ep_sparse_ext.e_start_hi = 0;
+		path->ep_sparse_ext.e_start_lo = 0;
+		path->ep_is_sparse = true;
+		return (true);
+	}
+	path->ep_index = l - 1;
+	*first_lbn = path->ep_index->ei_blk;
+	if (path->ep_index < last)
+		*last_lbn = l->ei_blk - 1;
+	return (false);
+}
+
+static void
+ext4_ext_binsearch(struct inode *ip, struct ext4_extent_path *path, daddr_t lbn,
+		daddr_t first_lbn, daddr_t last_lbn)
+{
+	struct ext4_extent_header *ehp = path->ep_header;
+	struct ext4_extent *first, *l, *r, *m;
+
+	if (ehp->eh_ecount == 0)
+		return;
+
+	first = (struct ext4_extent *)(char *)(ehp + 1);
+	l = first;
+	r = first + ehp->eh_ecount - 1;
+	while (l <= r) {
+		m = l + (r - l) / 2;
+		if (lbn < m->e_blk)
+			r = m - 1;
+		else
+			l = m + 1;
+	}
+
+	if (l == first) {
+		path->ep_sparse_ext.e_blk = first_lbn;
+		path->ep_sparse_ext.e_len = first->e_blk - first_lbn;
+		path->ep_sparse_ext.e_start_hi = 0;
+		path->ep_sparse_ext.e_start_lo = 0;
+		path->ep_is_sparse = true;
+		return;
+	}
+	path->ep_ext = l - 1;
+	if (path->ep_ext->e_blk + path->ep_ext->e_len <= lbn) {
+		path->ep_sparse_ext.e_blk = path->ep_ext->e_blk +
+		    path->ep_ext->e_len;
+		if (l <= (first + ehp->eh_ecount - 1))
+			path->ep_sparse_ext.e_len = l->e_blk -
+			    path->ep_sparse_ext.e_blk;
+		else
+			path->ep_sparse_ext.e_len = last_lbn -
+			    path->ep_sparse_ext.e_blk + 1;
+		path->ep_sparse_ext.e_start_hi = 0;
+		path->ep_sparse_ext.e_start_lo = 0;
+		path->ep_is_sparse = true;
+	}
+}
+
+/*
+ * Find a block in ext4 extent cache.
+ */
+int
+ext4_ext_in_cache(struct inode *ip, daddr_t lbn, struct ext4_extent *ep)
+{
+	struct ext4_extent_cache *ecp;
+	int ret = EXT4_EXT_CACHE_NO;
+
+	ecp = &ip->inode_ext.e2fs.i_ext_cache;
+
+	/* cache is invalid */
+	if (ecp->ec_type == EXT4_EXT_CACHE_NO)
+		return (ret);
+
+	if (lbn >= ecp->ec_blk && lbn < ecp->ec_blk + ecp->ec_len) {
+		ep->e_blk = ecp->ec_blk;
+		ep->e_start_lo = ecp->ec_start & 0xffffffff;
+		ep->e_start_hi = ecp->ec_start >> 32 & 0xffff;
+		ep->e_len = ecp->ec_len;
+		ret = ecp->ec_type;
+	}
+	return (ret);
+}
+
+/*
+ * Put an ext4_extent structure in ext4 cache.
+ */
+void
+ext4_ext_put_cache(struct inode *ip, struct ext4_extent *ep, int type)
+{
+	struct ext4_extent_cache *ecp;
+
+	ecp = &ip->inode_ext.e2fs.i_ext_cache;
+	ecp->ec_type = type;
+	ecp->ec_blk = ep->e_blk;
+	ecp->ec_len = ep->e_len;
+	ecp->ec_start = (daddr_t)ep->e_start_hi << 32 | ep->e_start_lo;
+}
+
+/*
+ * Find an extent.
+ */
+struct ext4_extent_path *
+ext4_ext_find_extent(struct m_ext2fs *fs, struct inode *ip,
+		     daddr_t lbn, struct ext4_extent_path *path)
+{
+	struct ext4_extent_header *ehp;
+	uint16_t i;
+	int error, size;
+	daddr_t nblk;
+
+	ehp = (struct ext4_extent_header *)ip->i_din.e2fs_din->e2di_blocks;
+
+	if (ehp->eh_magic != EXT4_EXT_MAGIC)
+		return (NULL);
+
+	path->ep_header = ehp;
+
+	daddr_t first_lbn = 0;
+	daddr_t last_lbn = lblkno(ip->i_e2fs, ip->i_size);
+
+	for (i = ehp->eh_depth; i != 0; --i) {
+		path->ep_depth = i;
+		path->ep_ext = NULL;
+		if (ext4_ext_binsearch_index(ip, path, lbn, &first_lbn,
+		    &last_lbn)) {
+			return (path);
+		}
+
+		nblk = (daddr_t)path->ep_index->ei_leaf_hi << 32 |
+		    path->ep_index->ei_leaf_lo;
+		size = blksize(fs, ip, nblk);
+		if (path->ep_bp != NULL) {
+			brelse(path->ep_bp, 0);
+			path->ep_bp = NULL;
+		}
+		error = bread(ip->i_devvp, fsbtodb(fs, nblk), size, 0,
+			    &path->ep_bp);
+		if (error) {
+			brelse(path->ep_bp, 0);
+			path->ep_bp = NULL;
+			return (NULL);
+		}
+		ehp = (struct ext4_extent_header *)path->ep_bp->b_data;
+		path->ep_header = ehp;
+	}
+
+	path->ep_depth = i;
+	path->ep_ext = NULL;
+	path->ep_index = NULL;
+	path->ep_is_sparse = false;
+
+	ext4_ext_binsearch(ip, path, lbn, first_lbn, last_lbn);
+	return (path);
+}
Index: src/sys/ufs/ext2fs/ext2fs_extents.h
diff -u /dev/null src/sys/ufs/ext2fs/ext2fs_extents.h:1.1
--- /dev/null	Fri Jun  3 11:35:48 2016
+++ src/sys/ufs/ext2fs/ext2fs_extents.h	Fri Jun  3 11:35:48 2016
@@ -0,0 +1,107 @@
+/*	$NetBSD: ext2fs_extents.h,v 1.1 2016/06/03 15:35:48 christos Exp $	*/
+
+/*-
+ * Copyright (c) 2012, 2010 Zheng Liu <[email protected]>
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * $FreeBSD: head/sys/fs/ext2fs/ext2_extents.h 295523 2016-02-11 15:27:14Z pfg $
+ */     
+
+#ifndef _UFS_EXT2FS_EXT2FS_EXTENTS_H_
+#define	_UFS_EXT2FS_EXT2FS_EXTENTS_H_
+
+#include <sys/types.h>
+#include <ufs/ufs/inode.h>
+#define	EXT4_EXT_MAGIC  0xf30a
+
+#define	EXT4_EXT_CACHE_NO	0
+#define	EXT4_EXT_CACHE_GAP	1
+#define	EXT4_EXT_CACHE_IN	2
+
+/*
+ * Ext4 file system extent on disk.
+ */
+struct ext4_extent {
+	uint32_t e_blk;		/* first logical block */
+	uint16_t e_len;		/* number of blocks */
+	uint16_t e_start_hi;	/* high 16 bits of physical block */
+	uint32_t e_start_lo;	/* low 32 bits of physical block */
+};
+
+/*
+ * Extent index on disk.
+ */
+struct ext4_extent_index {
+	uint32_t ei_blk;	/* indexes logical blocks */
+	uint32_t ei_leaf_lo;	/* points to physical block of the
+				 * next level */
+	uint16_t ei_leaf_hi;	/* high 16 bits of physical block */
+	uint16_t ei_unused;
+};
+
+/*
+ * Extent tree header.
+ */
+struct ext4_extent_header {
+	uint16_t eh_magic;	/* magic number: 0xf30a */
+	uint16_t eh_ecount;	/* number of valid entries */
+	uint16_t eh_max;	/* capacity of store in entries */
+	uint16_t eh_depth;	/* the depth of extent tree */
+	uint32_t eh_gen;	/* generation of extent tree */
+};
+
+/*
+ * Save cached extent.
+ */
+struct ext4_extent_cache {
+	daddr_t	ec_start;	/* extent start */
+	uint32_t ec_blk;	/* logical block */
+	uint32_t ec_len;
+	uint32_t ec_type;
+};
+
+/*
+ * Save path to some extent.
+ */
+struct ext4_extent_path {
+	uint16_t ep_depth;
+	struct buf *ep_bp;
+	bool ep_is_sparse;
+	union {
+		struct ext4_extent ep_sparse_ext;
+		struct ext4_extent *ep_ext;
+	};
+	struct ext4_extent_index *ep_index;
+	struct ext4_extent_header *ep_header;
+};
+
+struct inode;
+struct m_ext2fs;
+
+int	ext4_ext_in_cache(struct inode *, daddr_t, struct ext4_extent *);
+void	ext4_ext_put_cache(struct inode *, struct ext4_extent *, int);
+struct ext4_extent_path *ext4_ext_find_extent(struct m_ext2fs *fs,
+    struct inode *, daddr_t, struct ext4_extent_path *);
+
+#endif /* !_UFS_EXT2FS_EXT2FS_EXTENTS_H_ */

Reply via email to