svn commit: r348429 - stable/12/sys/ufs/ufs
Mark Johnston
markj at FreeBSD.org
Thu May 30 15:23:45 UTC 2019
Author: markj
Date: Thu May 30 15:23:43 2019
New Revision: 348429
URL: https://svnweb.freebsd.org/changeset/base/348429
Log:
MFC r346932, r347159:
Optimize lseek(SEEK_DATA) on UFS.
Modified:
stable/12/sys/ufs/ufs/ufs_bmap.c
stable/12/sys/ufs/ufs/ufs_extern.h
stable/12/sys/ufs/ufs/ufs_vnops.c
Directory Properties:
stable/12/ (props changed)
Modified: stable/12/sys/ufs/ufs/ufs_bmap.c
==============================================================================
--- stable/12/sys/ufs/ufs/ufs_bmap.c Thu May 30 15:20:20 2019 (r348428)
+++ stable/12/sys/ufs/ufs/ufs_bmap.c Thu May 30 15:23:43 2019 (r348429)
@@ -56,6 +56,9 @@ __FBSDID("$FreeBSD$");
#include <ufs/ufs/ufsmount.h>
#include <ufs/ufs/ufs_extern.h>
+static ufs_lbn_t lbn_count(struct ufsmount *, int);
+static int readindir(struct vnode *, ufs_lbn_t, ufs2_daddr_t, struct buf **);
+
/*
* Bmap converts the logical block number of a file to its physical block
* number on the disk. The conversion is done by using the logical block
@@ -90,6 +93,51 @@ ufs_bmap(ap)
return (error);
}
+static int
+readindir(vp, lbn, daddr, bpp)
+ struct vnode *vp;
+ ufs_lbn_t lbn;
+ ufs2_daddr_t daddr;
+ struct buf **bpp;
+{
+ struct buf *bp;
+ struct mount *mp;
+ struct ufsmount *ump;
+ int error;
+
+ mp = vp->v_mount;
+ ump = VFSTOUFS(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
@@ -212,35 +260,10 @@ ufs_bmaparray(vp, bn, bnp, nbp, runp, runb)
*/
if (bp)
bqrelse(bp);
+ error = readindir(vp, metalbn, daddr, &bp);
+ if (error != 0)
+ return (error);
- bp = getblk(vp, metalbn, mp->mnt_stat.f_iosize, 0, 0, 0);
- if ((bp->b_flags & B_CACHE) == 0) {
-#ifdef INVARIANTS
- if (!daddr)
- panic("ufs_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 /* RACCT */
- curthread->td_ru.ru_inblock++;
- error = bufwait(bp);
- if (error) {
- brelse(bp);
- return (error);
- }
- }
-
if (I_IS_UFS1(ip)) {
daddr = ((ufs1_daddr_t *)bp->b_data)[ap->in_off];
if (num == 1 && daddr && runp) {
@@ -301,6 +324,112 @@ ufs_bmaparray(vp, bn, bnp, nbp, runp, runb)
*bnp = -1;
}
return (0);
+}
+
+static ufs_lbn_t
+lbn_count(ump, level)
+ struct ufsmount *ump;
+ int level;
+{
+ ufs_lbn_t blockcnt;
+
+ for (blockcnt = 1; level > 0; level--)
+ blockcnt *= MNINDIR(ump);
+ return (blockcnt);
+}
+
+int
+ufs_bmap_seekdata(vp, offp)
+ struct vnode *vp;
+ off_t *offp;
+{
+ struct buf *bp;
+ struct indir a[UFS_NIADDR + 1], *ap;
+ struct inode *ip;
+ struct mount *mp;
+ struct ufsmount *ump;
+ ufs2_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 = VFSTOUFS(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 < UFS_NDADDR) {
+ daddr = DIP(ip, i_db[bn]);
+ if (daddr != 0)
+ break;
+ nextbn = bn + 1;
+ continue;
+ }
+
+ ap = a;
+ error = ufs_getlbns(vp, bn, ap, &num);
+ if (error != 0)
+ break;
+ MPASS(num >= 2);
+ daddr = DIP(ip, i_ib[ap->in_off]);
+ ap++, num--;
+ for (nextbn = UFS_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 = I_IS_UFS1(ip) ?
+ ((ufs1_daddr_t *)bp->b_data)[off] :
+ ((ufs2_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/ufs/ufs/ufs_extern.h
==============================================================================
--- stable/12/sys/ufs/ufs/ufs_extern.h Thu May 30 15:20:20 2019 (r348428)
+++ stable/12/sys/ufs/ufs/ufs_extern.h Thu May 30 15:23:43 2019 (r348429)
@@ -58,6 +58,7 @@ extern struct vop_vector ufs_vnodeops;
int ufs_bmap(struct vop_bmap_args *);
int ufs_bmaparray(struct vnode *, ufs2_daddr_t, ufs2_daddr_t *,
struct buf *, int *, int *);
+int ufs_bmap_seekdata(struct vnode *, off_t *);
int ufs_fhtovp(struct mount *, struct ufid *, int, struct vnode **);
int ufs_checkpath(ino_t, ino_t, struct inode *, struct ucred *, ino_t *);
void ufs_dirbad(struct inode *, doff_t, char *);
Modified: stable/12/sys/ufs/ufs/ufs_vnops.c
==============================================================================
--- stable/12/sys/ufs/ufs/ufs_vnops.c Thu May 30 15:20:20 2019 (r348428)
+++ stable/12/sys/ufs/ufs/ufs_vnops.c Thu May 30 15:23:43 2019 (r348429)
@@ -2694,12 +2694,15 @@ bad:
static int
ufs_ioctl(struct vop_ioctl_args *ap)
{
+ struct vnode *vp;
+ vp = ap->a_vp;
switch (ap->a_command) {
case FIOSEEKDATA:
+ return (ufs_bmap_seekdata(vp, (off_t *)ap->a_data));
case FIOSEEKHOLE:
- return (vn_bmap_seekhole(ap->a_vp, ap->a_command,
- (off_t *)ap->a_data, ap->a_cred));
+ return (vn_bmap_seekhole(vp, ap->a_command, (off_t *)ap->a_data,
+ ap->a_cred));
default:
return (ENOTTY);
}
More information about the svn-src-all
mailing list