summaryrefslogtreecommitdiffstats
path: root/sys/fs/ext2fs/ext2_extents.c
diff options
context:
space:
mode:
authorpfg <pfg@FreeBSD.org>2016-01-18 15:39:32 +0000
committerpfg <pfg@FreeBSD.org>2016-01-18 15:39:32 +0000
commite7a4f4fac24004ba950e92768c3874725616b678 (patch)
tree1d065d37db62d43c6e0ae1b4d9d20f38c21f8469 /sys/fs/ext2fs/ext2_extents.c
parent51120efe0753c7fb11ce9dab662dd9542cd41813 (diff)
downloadFreeBSD-src-e7a4f4fac24004ba950e92768c3874725616b678.zip
FreeBSD-src-e7a4f4fac24004ba950e92768c3874725616b678.tar.gz
MFC r293680
ext4: add support for reading sparse files Add support for sparse files in ext4. Also implement read-ahead, which greatly increases the performance when transferring files from ext4. The sparse file support has become very common in ext4. Both features implemented by Damjan Jovanovic. PR: 205816
Diffstat (limited to 'sys/fs/ext2fs/ext2_extents.c')
-rw-r--r--sys/fs/ext2fs/ext2_extents.c26
1 files changed, 23 insertions, 3 deletions
diff --git a/sys/fs/ext2fs/ext2_extents.c b/sys/fs/ext2fs/ext2_extents.c
index 68704bb..1317fdc 100644
--- a/sys/fs/ext2fs/ext2_extents.c
+++ b/sys/fs/ext2fs/ext2_extents.c
@@ -66,13 +66,14 @@ static void
ext4_ext_binsearch(struct inode *ip, struct ext4_extent_path *path, daddr_t lbn)
{
struct ext4_extent_header *ehp = path->ep_header;
- struct ext4_extent *l, *r, *m;
+ struct ext4_extent *first, *l, *r, *m;
if (ehp->eh_ecount == 0)
return;
- l = (struct ext4_extent *)(char *)(ehp + 1);
- r = (struct ext4_extent *)(char *)(ehp + 1) + ehp->eh_ecount - 1;
+ 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)
@@ -81,7 +82,25 @@ ext4_ext_binsearch(struct inode *ip, struct ext4_extent_path *path, daddr_t lbn)
l = m + 1;
}
+ if (l == first) {
+ path->ep_sparse_ext.e_blk = lbn;
+ path->ep_sparse_ext.e_len = first->e_blk - lbn;
+ path->ep_sparse_ext.e_start_hi = 0;
+ path->ep_sparse_ext.e_start_lo = 0;
+ path->ep_is_sparse = 1;
+ return;
+ }
path->ep_ext = l - 1;
+ if (path->ep_ext->e_blk + path->ep_ext->e_len <= lbn) {
+ path->ep_sparse_ext.e_blk = lbn;
+ if (l <= (first + ehp->eh_ecount - 1))
+ path->ep_sparse_ext.e_len = l->e_blk - lbn;
+ else // XXX: where does it end?
+ path->ep_sparse_ext.e_len = 1;
+ path->ep_sparse_ext.e_start_hi = 0;
+ path->ep_sparse_ext.e_start_lo = 0;
+ path->ep_is_sparse = 1;
+ }
}
/*
@@ -169,6 +188,7 @@ ext4_ext_find_extent(struct m_ext2fs *fs, struct inode *ip,
path->ep_depth = i;
path->ep_ext = NULL;
path->ep_index = NULL;
+ path->ep_is_sparse = 0;
ext4_ext_binsearch(ip, path, lbn);
return (path);
OpenPOWER on IntegriCloud