From owner-svn-src-stable@freebsd.org Tue Mar 3 14:58:55 2020 Return-Path: Delivered-To: svn-src-stable@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id 228DA2521E8; Tue, 3 Mar 2020 14:58:55 +0000 (UTC) (envelope-from fsu@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) server-signature RSA-PSS (4096 bits) client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 48X0Wy65Ttz3Q0j; Tue, 3 Mar 2020 14:58:54 +0000 (UTC) (envelope-from fsu@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 mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 78FA46DEC; Tue, 3 Mar 2020 14:58:54 +0000 (UTC) (envelope-from fsu@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id 023EwsxS028216; Tue, 3 Mar 2020 14:58:54 GMT (envelope-from fsu@FreeBSD.org) Received: (from fsu@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id 023Ewr6l028214; Tue, 3 Mar 2020 14:58:53 GMT (envelope-from fsu@FreeBSD.org) Message-Id: <202003031458.023Ewr6l028214@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: fsu set sender to fsu@FreeBSD.org using -f From: Fedor Uporov Date: Tue, 3 Mar 2020 14:58:53 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-12@freebsd.org Subject: svn commit: r358578 - stable/12/sys/fs/ext2fs X-SVN-Group: stable-12 X-SVN-Commit-Author: fsu X-SVN-Commit-Paths: stable/12/sys/fs/ext2fs X-SVN-Commit-Revision: 358578 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-stable@freebsd.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: SVN commit messages for all the -stable branches of the src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 03 Mar 2020 14:58:55 -0000 Author: fsu Date: Tue Mar 3 14:58:53 2020 New Revision: 358578 URL: https://svnweb.freebsd.org/changeset/base/358578 Log: MFC r358073: Add a EXT2FS-specific implementation for lseek(SEEK_DATA). Reviewed by: pfg MFC after: 1 week Differential Revision: https://reviews.freebsd.org/D23605 Modified: stable/12/sys/fs/ext2fs/ext2_bmap.c stable/12/sys/fs/ext2fs/ext2_extern.h stable/12/sys/fs/ext2fs/ext2_vnops.c Modified: stable/12/sys/fs/ext2fs/ext2_bmap.c ============================================================================== --- stable/12/sys/fs/ext2fs/ext2_bmap.c Tue Mar 3 14:15:30 2020 (r358577) +++ stable/12/sys/fs/ext2fs/ext2_bmap.c Tue Mar 3 14:58:53 2020 (r358578) @@ -139,6 +139,47 @@ ext4_bmapext(struct vnode *vp, int32_t bn, int64_t *bn return (error); } +static int +readindir(struct vnode *vp, e2fs_lbn_t lbn, e2fs_daddr_t daddr, struct buf **bpp) +{ + struct buf *bp; + struct mount *mp; + struct ext2mount *ump; + int error; + + mp = vp->v_mount; + ump = VFSTOEXT2(mp); + + bp = getblk(vp, lbn, mp->mnt_stat.f_iosize, 0, 0, 0); + if ((bp->b_flags & B_CACHE) == 0) { + KASSERT(daddr != 0, + ("readindir: indirect block not in cache")); + + bp->b_blkno = blkptrtodb(ump, daddr); + bp->b_iocmd = BIO_READ; + bp->b_flags &= ~B_INVAL; + bp->b_ioflags &= ~BIO_ERROR; + vfs_busy_pages(bp, 0); + bp->b_iooffset = dbtob(bp->b_blkno); + bstrategy(bp); +#ifdef RACCT + if (racct_enable) { + PROC_LOCK(curproc); + racct_add_buf(curproc, bp, 0); + PROC_UNLOCK(curproc); + } +#endif + curthread->td_ru.ru_inblock++; + error = bufwait(bp); + if (error != 0) { + brelse(bp); + return (error); + } + } + *bpp = bp; + return (0); +} + /* * Indirect blocks are now on the vnode for the file. They are given negative * logical block numbers. Indirect blocks are addressed by the negative @@ -228,35 +269,10 @@ ext2_bmaparray(struct vnode *vp, daddr_t bn, daddr_t * */ if (bp) bqrelse(bp); + error = readindir(vp, metalbn, daddr, &bp); + if (error != 0) + return (error); - bp = getblk(vp, metalbn, bsize, 0, 0, 0); - if ((bp->b_flags & B_CACHE) == 0) { -#ifdef INVARIANTS - if (!daddr) - panic("ext2_bmaparray: indirect block not in cache"); -#endif - bp->b_blkno = blkptrtodb(ump, daddr); - bp->b_iocmd = BIO_READ; - bp->b_flags &= ~B_INVAL; - bp->b_ioflags &= ~BIO_ERROR; - vfs_busy_pages(bp, 0); - bp->b_iooffset = dbtob(bp->b_blkno); - bstrategy(bp); -#ifdef RACCT - if (racct_enable) { - PROC_LOCK(curproc); - racct_add_buf(curproc, bp, 0); - PROC_UNLOCK(curproc); - } -#endif - curthread->td_ru.ru_inblock++; - error = bufwait(bp); - if (error) { - brelse(bp); - return (error); - } - } - daddr = ((e2fs_daddr_t *)bp->b_data)[ap->in_off]; if (num == 1 && daddr && runp) { for (bn = ap->in_off + 1; @@ -294,6 +310,107 @@ ext2_bmaparray(struct vnode *vp, daddr_t bn, daddr_t * *bnp = -1; } return (0); +} + +static e2fs_lbn_t +lbn_count(struct ext2mount *ump, int level) + +{ + e2fs_lbn_t blockcnt; + + for (blockcnt = 1; level > 0; level--) + blockcnt *= MNINDIR(ump); + return (blockcnt); +} + +int +ext2_bmap_seekdata(struct vnode *vp, off_t *offp) +{ + struct buf *bp; + struct indir a[EXT2_NIADDR + 1], *ap; + struct inode *ip; + struct mount *mp; + struct ext2mount *ump; + e2fs_daddr_t bn, daddr, nextbn; + uint64_t bsize; + off_t numblks; + int error, num, num1, off; + + bp = NULL; + error = 0; + ip = VTOI(vp); + mp = vp->v_mount; + ump = VFSTOEXT2(mp); + + if (vp->v_type != VREG || (ip->i_flags & SF_SNAPSHOT) != 0) + return (EINVAL); + if (*offp < 0 || *offp >= ip->i_size) + return (ENXIO); + + bsize = mp->mnt_stat.f_iosize; + for (bn = *offp / bsize, numblks = howmany(ip->i_size, bsize); + bn < numblks; bn = nextbn) { + if (bn < EXT2_NDADDR) { + daddr = ip->i_db[bn]; + if (daddr != 0) + break; + nextbn = bn + 1; + continue; + } + + ap = a; + error = ext2_getlbns(vp, bn, ap, &num); + if (error != 0) + break; + MPASS(num >= 2); + daddr = ip->i_ib[ap->in_off]; + ap++, num--; + for (nextbn = EXT2_NDADDR, num1 = num - 1; num1 > 0; num1--) + nextbn += lbn_count(ump, num1); + if (daddr == 0) { + nextbn += lbn_count(ump, num); + continue; + } + + for (; daddr != 0 && num > 0; ap++, num--) { + if (bp != NULL) + bqrelse(bp); + error = readindir(vp, ap->in_lbn, daddr, &bp); + if (error != 0) + return (error); + + /* + * Scan the indirect block until we find a non-zero + * pointer. + */ + off = ap->in_off; + do { + daddr = ((e2fs_daddr_t *)bp->b_data)[off]; + } while (daddr == 0 && ++off < MNINDIR(ump)); + nextbn += off * lbn_count(ump, num - 1); + + /* + * We need to recompute the LBNs of indirect + * blocks, so restart with the updated block offset. + */ + if (off != ap->in_off) + break; + } + if (num == 0) { + /* + * We found a data block. + */ + bn = nextbn; + break; + } + } + if (bp != NULL) + bqrelse(bp); + if (bn >= numblks) + error = ENXIO; + if (error == 0 && *offp < bn * bsize) + *offp = bn * bsize; + return (error); } /* Modified: stable/12/sys/fs/ext2fs/ext2_extern.h ============================================================================== --- stable/12/sys/fs/ext2fs/ext2_extern.h Tue Mar 3 14:15:30 2020 (r358577) +++ stable/12/sys/fs/ext2fs/ext2_extern.h Tue Mar 3 14:58:53 2020 (r358578) @@ -64,6 +64,7 @@ e4fs_daddr_t ext2_blkpref(struct inode *, e2fs_lbn_t, int ext2_bmap(struct vop_bmap_args *); int ext2_bmaparray(struct vnode *, daddr_t, daddr_t *, int *, int *); int ext4_bmapext(struct vnode *, int32_t, int64_t *, int *, int *); +int ext2_bmap_seekdata(struct vnode *, off_t *); void ext2_clusteracct(struct m_ext2fs *, char *, int, e4fs_daddr_t, int); void ext2_dirbad(struct inode *ip, doff_t offset, char *how); int ext2_ei2i(struct ext2fs_dinode *, struct inode *); Modified: stable/12/sys/fs/ext2fs/ext2_vnops.c ============================================================================== --- stable/12/sys/fs/ext2fs/ext2_vnops.c Tue Mar 3 14:15:30 2020 (r358577) +++ stable/12/sys/fs/ext2fs/ext2_vnops.c Tue Mar 3 14:58:53 2020 (r358578) @@ -2155,11 +2155,24 @@ ext2_read(struct vop_read_args *ap) static int ext2_ioctl(struct vop_ioctl_args *ap) { + struct vnode *vp; + int error; + vp = ap->a_vp; switch (ap->a_command) { case FIOSEEKDATA: + if (!(VTOI(vp)->i_flag & IN_E4EXTENTS)) { + error = vn_lock(vp, LK_SHARED); + if (error == 0) { + error = ext2_bmap_seekdata(vp, + (off_t *)ap->a_data); + VOP_UNLOCK(vp, 0); + } else + error = EBADF; + return (error); + } case FIOSEEKHOLE: - return (vn_bmap_seekhole(ap->a_vp, ap->a_command, + return (vn_bmap_seekhole(vp, ap->a_command, (off_t *)ap->a_data, ap->a_cred)); default: return (ENOTTY);