From owner-svn-src-all@freebsd.org Thu Feb 11 00:34:13 2016 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 77FCDAA415F; Thu, 11 Feb 2016 00:34:13 +0000 (UTC) (envelope-from pfg@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 35BE613D0; Thu, 11 Feb 2016 00:34:13 +0000 (UTC) (envelope-from pfg@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id u1B0YCD2052445; Thu, 11 Feb 2016 00:34:12 GMT (envelope-from pfg@FreeBSD.org) Received: (from pfg@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id u1B0YC5t052443; Thu, 11 Feb 2016 00:34:12 GMT (envelope-from pfg@FreeBSD.org) Message-Id: <201602110034.u1B0YC5t052443@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: pfg set sender to pfg@FreeBSD.org using -f From: "Pedro F. Giffuni" Date: Thu, 11 Feb 2016 00:34:12 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r295494 - head/sys/fs/ext2fs X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 11 Feb 2016 00:34:13 -0000 Author: pfg Date: Thu Feb 11 00:34:11 2016 New Revision: 295494 URL: https://svnweb.freebsd.org/changeset/base/295494 Log: Ext4: fix handling of files with sparse blocks before extent's index. This is ongoing work from Damjan Jovanovic to improve ext4 read support with sparse files: Keep track of the first and last block in each extent as it descends down the extent tree, thus being able to work out that some blocks are sparse earlier. This solves an issue on r293680. In ext4_bmapext() start supporting the runb parameter, which appears to be the number of adjacent blocks prior to the block being converted in the same way that runp is the number of blocks after, speding up random access to mmaped files. PR: 206652 Modified: head/sys/fs/ext2fs/ext2_bmap.c head/sys/fs/ext2fs/ext2_extents.c Modified: head/sys/fs/ext2fs/ext2_bmap.c ============================================================================== --- head/sys/fs/ext2fs/ext2_bmap.c Thu Feb 11 00:30:51 2016 (r295493) +++ head/sys/fs/ext2fs/ext2_bmap.c Thu Feb 11 00:34:11 2016 (r295494) @@ -114,6 +114,8 @@ ext4_bmapext(struct vnode *vp, int32_t b 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) @@ -127,6 +129,8 @@ ext4_bmapext(struct vnode *vp, int32_t b if (runp != NULL) *runp = ep->e_len - (lbn - ep->e_blk) - 1; + if (runb != NULL) + *runb = lbn - ep->e_blk; } } Modified: head/sys/fs/ext2fs/ext2_extents.c ============================================================================== --- head/sys/fs/ext2fs/ext2_extents.c Thu Feb 11 00:30:51 2016 (r295493) +++ head/sys/fs/ext2fs/ext2_extents.c Thu Feb 11 00:34:11 2016 (r295494) @@ -43,14 +43,17 @@ #include #include -static void ext4_ext_binsearch_index(struct inode *ip, struct ext4_extent_path - *path, daddr_t lbn) +static int +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 *l, *r, *m; + struct ext4_extent_index *first, *last, *l, *r, *m; - l = (struct ext4_extent_index *)(char *)(ehp + 1); - r = (struct ext4_extent_index *)(char *)(ehp + 1) + ehp->eh_ecount - 1; + 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) @@ -59,11 +62,24 @@ static void ext4_ext_binsearch_index(str 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 = 1; + return (1); + } path->ep_index = l - 1; + *first_lbn = path->ep_index->ei_blk; + if (path->ep_index < last) + *last_lbn = l->ei_blk - 1; + return (0); } static void -ext4_ext_binsearch(struct inode *ip, struct ext4_extent_path *path, daddr_t lbn) +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; @@ -83,8 +99,8 @@ ext4_ext_binsearch(struct inode *ip, str } 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_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 = 1; @@ -92,11 +108,14 @@ ext4_ext_binsearch(struct inode *ip, str } path->ep_ext = l - 1; if (path->ep_ext->e_blk + path->ep_ext->e_len <= lbn) { - path->ep_sparse_ext.e_blk = 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 - lbn; - else // XXX: where does it end? - path->ep_sparse_ext.e_len = 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 = 1; @@ -162,10 +181,16 @@ ext4_ext_find_extent(struct m_ext2fs *fs 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) { - ext4_ext_binsearch_index(ip, path, lbn); - path->ep_depth = 0; + 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; @@ -190,6 +215,6 @@ ext4_ext_find_extent(struct m_ext2fs *fs path->ep_index = NULL; path->ep_is_sparse = 0; - ext4_ext_binsearch(ip, path, lbn); + ext4_ext_binsearch(ip, path, lbn, first_lbn, last_lbn); return (path); }