diff options
author | pfg <pfg@FreeBSD.org> | 2016-01-18 15:39:32 +0000 |
---|---|---|
committer | pfg <pfg@FreeBSD.org> | 2016-01-18 15:39:32 +0000 |
commit | e7a4f4fac24004ba950e92768c3874725616b678 (patch) | |
tree | 1d065d37db62d43c6e0ae1b4d9d20f38c21f8469 /sys/fs/ext2fs/ext2_extents.c | |
parent | 51120efe0753c7fb11ce9dab662dd9542cd41813 (diff) | |
download | FreeBSD-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.c | 26 |
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); |