Skip to content

Commit

Permalink
added ext4 extents
Browse files Browse the repository at this point in the history
  • Loading branch information
hrishikeshgoyal committed May 31, 2016
1 parent b5aa23f commit 9252f8f
Show file tree
Hide file tree
Showing 9 changed files with 38,062 additions and 8 deletions.
37,621 changes: 37,621 additions & 0 deletions cscope.out

Large diffs are not rendered by default.

69 changes: 67 additions & 2 deletions ext2fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,11 @@
* Modified for ext2fs by Manuel Bouyer.
*/

#define fsbtodb(fs, b) ((daddr_t)(b) << (fs)->e2fs_fsbtodb)
#define lblkno(fs, loc) /* calculates (loc / fs->fs_bsize) */ \
((loc) >> (fs->e2fs_bshift))
#define blksize(fs, ip, lbn) ((fs)->e2fs_bsize)

#ifndef _UFS_EXT2FS_EXT2FS_H_
#define _UFS_EXT2FS_EXT2FS_H_

Expand Down Expand Up @@ -165,7 +170,63 @@ 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];
//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 at least 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; /* number of seconds to wait in MMP checking */
uint64_t e4fs_mmpblk; /* block for multi-mount protection */
uint32_t e4fs_raid_stripe_wid; /* blocks on all 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; /* reserved 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 */
};


Expand Down Expand Up @@ -267,7 +328,11 @@ 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 )

//#define EXT4F_RO_INCOMPAT_SUPP

/*
* Definitions of behavior on errors
Expand Down
72 changes: 71 additions & 1 deletion ext2fs_bmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,9 @@ __KERNEL_RCSID(0, "$NetBSD: ext2fs_bmap.c,v 1.26 2013/01/22 09:39:15 dholland Ex
#include <ufs/ext2fs/ext2fs.h>
#include <ufs/ext2fs/ext2fs_extern.h>


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 *);

Expand All @@ -105,6 +108,7 @@ ext2fs_bmap(void *v)
daddr_t *a_bnp;
int *a_runp;
} */ *ap = v;

/*
* Check for underlying vnode requests and ensure that logical
* to physical mapping is requested.
Expand All @@ -114,10 +118,76 @@ ext2fs_bmap(void *v)
if (ap->a_bnp == NULL)
return (0);

return (ext2fs_bmaparray(ap->a_vp, ap->a_bn, ap->a_bnp, NULL, NULL,
if (VTOI(ap->a_vp)->i_flag & 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));

}


/*
* 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)
{
printf ("inside ext4_bmapext\n");
struct inode *ip;
struct m_ext2fs *fs;
struct ext4_extent *ep;
struct ext4_extent_path path = { .ep_bp = NULL };
daddr_t lbn;
int ret = 0;

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

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

if (runb != NULL)
*runb = 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 {
ep = path.ep_ext;
if (ep == NULL)
ret = EIO;
else {
*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;
}
}

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

return (ret);
}



/*
* Indirect blocks are now on the vnode for the file. They are given negative
* logical block numbers. Indirect blocks are addressed by the negative
Expand Down
204 changes: 204 additions & 0 deletions ext2fs_extents.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
#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)
{
printf("ext4_ext_binsearch_index\n");
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)
{
printf("ext4_ext_binsearch\n");
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)
{
printf("ext4_ext_in_cache\n");
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)
{
printf("ext4_ext_put_cache\n");
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)
{
printf("inside ext4_ext_find_extent\n");
struct ext4_extent_header *ehp;
uint16_t i;
int error, size;
daddr_t nblk;

ehp = (struct ext4_extent_header *)(char *)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);
}
Loading

0 comments on commit 9252f8f

Please sign in to comment.