Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/ufs Disentangle buffer-cached I/O from page-cached I/O i...



details:   https://anonhg.NetBSD.org/src/rev/5eaca9eb781a
branches:  trunk
changeset: 336927:5eaca9eb781a
user:      riastradh <riastradh%NetBSD.org@localhost>
date:      Fri Mar 27 17:27:55 2015 +0000

description:
Disentangle buffer-cached I/O from page-cached I/O in UFS.

Page-cached I/O is used for regular files, and is initiated by VFS
users such as userland and NFS.

Buffer-cached I/O is used for directories and symlinks, and is issued
only internally by UFS.

New UFS routine ufs_bufio replaces vn_rdwr for internal use.
ufs_bufio is implemented by new UFS operations uo_bufrd/uo_bufwr,
which sit in ufs_readwrite.c alongside the VOP_READ/VOP_WRITE
implementations.

I preserved the code as much as possible and will leave further
simplification for future commits.  I kept the ulfs_readwrite.c
copypasta close to ufs_readwrite.c in case we ever want to merge them
back; likewise ext2fs_readwrite.c.

No externally visible semantic change.  All atf fs tests still pass.

diffstat:

 sys/ufs/chfs/chfs_vnops.c         |    9 +-
 sys/ufs/ext2fs/ext2fs_extern.h    |    4 +-
 sys/ufs/ext2fs/ext2fs_lookup.c    |   10 +-
 sys/ufs/ext2fs/ext2fs_readwrite.c |  257 ++++++++++++++++++++++++++-----------
 sys/ufs/ext2fs/ext2fs_rename.c    |   16 +-
 sys/ufs/ext2fs/ext2fs_vfsops.c    |    6 +-
 sys/ufs/ext2fs/ext2fs_vnops.c     |   17 +-
 sys/ufs/ffs/ffs_extern.h          |    6 +-
 sys/ufs/ffs/ffs_vfsops.c          |    6 +-
 sys/ufs/lfs/lfs_extern.h          |    5 +-
 sys/ufs/lfs/lfs_rename.c          |    8 +-
 sys/ufs/lfs/lfs_vnops.c           |   10 +-
 sys/ufs/lfs/ulfs_extern.h         |    4 +-
 sys/ufs/lfs/ulfs_lookup.c         |    8 +-
 sys/ufs/lfs/ulfs_readwrite.c      |  250 +++++++++++++++++++++++++++--------
 sys/ufs/lfs/ulfs_vnops.c          |   52 +++++++-
 sys/ufs/ufs/ufs_extern.h          |    4 +-
 sys/ufs/ufs/ufs_lookup.c          |    8 +-
 sys/ufs/ufs/ufs_readwrite.c       |  258 +++++++++++++++++++++++++++++--------
 sys/ufs/ufs/ufs_rename.c          |    8 +-
 sys/ufs/ufs/ufs_vnops.c           |   60 +++++++-
 sys/ufs/ufs/ufsmount.h            |    8 +-
 22 files changed, 749 insertions(+), 265 deletions(-)

diffs (truncated from 1808 to 300 lines):

diff -r 51ef6af9df11 -r 5eaca9eb781a sys/ufs/chfs/chfs_vnops.c
--- a/sys/ufs/chfs/chfs_vnops.c Fri Mar 27 12:46:51 2015 +0000
+++ b/sys/ufs/chfs/chfs_vnops.c Fri Mar 27 17:27:55 2015 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: chfs_vnops.c,v 1.24 2015/01/11 17:29:57 hannken Exp $  */
+/*     $NetBSD: chfs_vnops.c,v 1.25 2015/03/27 17:27:55 riastradh Exp $        */
 
 /*-
  * Copyright (c) 2010 Department of Software Engineering,
@@ -1310,9 +1310,8 @@
 
                uvm_vnp_setsize(vp, len);
        } else {
-               err = vn_rdwr(UIO_WRITE, vp, target, len, (off_t)0,
-                   UIO_SYSSPACE, IO_NODELOCKED, cnp->cn_cred,
-                   (size_t *)0, NULL);
+               err = ufs_bufio(UIO_WRITE, vp, target, len, (off_t)0,
+                   IO_NODELOCKED, cnp->cn_cred, (size_t *)0, NULL);
        }
 
 out:
@@ -1454,7 +1453,7 @@
                return (0);
        }
 
-       return (VOP_READ(vp, uio, 0, cred));
+       return (UFS_BUFRD(vp, uio, 0, cred));
 }
 
 /* --------------------------------------------------------------------- */
diff -r 51ef6af9df11 -r 5eaca9eb781a sys/ufs/ext2fs/ext2fs_extern.h
--- a/sys/ufs/ext2fs/ext2fs_extern.h    Fri Mar 27 12:46:51 2015 +0000
+++ b/sys/ufs/ext2fs/ext2fs_extern.h    Fri Mar 27 17:27:55 2015 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ext2fs_extern.h,v 1.47 2014/05/25 14:07:19 hannken Exp $       */
+/*     $NetBSD: ext2fs_extern.h,v 1.48 2015/03/27 17:27:56 riastradh Exp $     */
 
 /*-
  * Copyright (c) 1991, 1993, 1994
@@ -147,6 +147,8 @@
 /* ext2fs_readwrite.c */
 int ext2fs_read(void *);
 int ext2fs_write(void *);
+int ext2fs_bufrd(struct vnode *, struct uio *, int, kauth_cred_t);
+int ext2fs_bufwr(struct vnode *, struct uio *, int, kauth_cred_t);
 
 /* ext2fs_vnops.c */
 int ext2fs_create(void *);
diff -r 51ef6af9df11 -r 5eaca9eb781a sys/ufs/ext2fs/ext2fs_lookup.c
--- a/sys/ufs/ext2fs/ext2fs_lookup.c    Fri Mar 27 12:46:51 2015 +0000
+++ b/sys/ufs/ext2fs/ext2fs_lookup.c    Fri Mar 27 17:27:55 2015 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ext2fs_lookup.c,v 1.77 2014/06/03 19:30:29 joerg Exp $ */
+/*     $NetBSD: ext2fs_lookup.c,v 1.78 2015/03/27 17:27:56 riastradh Exp $     */
 
 /*
  * Modified for NetBSD 1.2E
@@ -48,7 +48,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ext2fs_lookup.c,v 1.77 2014/06/03 19:30:29 joerg Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ext2fs_lookup.c,v 1.78 2015/03/27 17:27:56 riastradh Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -180,7 +180,7 @@
        }
        aiov.iov_base = dirbuf;
 
-       error = VOP_READ(ap->a_vp, &auio, 0, ap->a_cred);
+       error = UFS_BUFRD(ap->a_vp, &auio, 0, ap->a_cred);
        if (error == 0) {
                readcnt = e2fs_count - auio.uio_resid;
                for (dp = (struct ext2fs_direct *)dirbuf;
@@ -952,8 +952,8 @@
 #define        MINDIRSIZ (sizeof (struct ext2fs_dirtemplate) / 2)
 
        for (off = 0; off < ext2fs_size(ip); off += fs2h16(dp->e2d_reclen)) {
-               error = vn_rdwr(UIO_READ, ITOV(ip), (void *)dp, MINDIRSIZ, off,
-                  UIO_SYSSPACE, IO_NODELOCKED, cred, &count, NULL);
+               error = ufs_bufio(UIO_READ, ITOV(ip), (void *)dp, MINDIRSIZ,
+                   off, IO_NODELOCKED, cred, &count, NULL);
                /*
                 * Since we read MINDIRSIZ, residual must
                 * be 0 unless we're at end of file.
diff -r 51ef6af9df11 -r 5eaca9eb781a sys/ufs/ext2fs/ext2fs_readwrite.c
--- a/sys/ufs/ext2fs/ext2fs_readwrite.c Fri Mar 27 12:46:51 2015 +0000
+++ b/sys/ufs/ext2fs/ext2fs_readwrite.c Fri Mar 27 17:27:55 2015 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ext2fs_readwrite.c,v 1.66 2014/11/09 18:23:28 maxv Exp $       */
+/*     $NetBSD: ext2fs_readwrite.c,v 1.67 2015/03/27 17:27:56 riastradh Exp $  */
 
 /*-
  * Copyright (c) 1993
@@ -60,7 +60,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ext2fs_readwrite.c,v 1.66 2014/11/09 18:23:28 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ext2fs_readwrite.c,v 1.67 2015/03/27 17:27:56 riastradh Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -97,13 +97,9 @@
        struct vnode *vp;
        struct inode *ip;
        struct uio *uio;
-       struct m_ext2fs *fs;
-       struct buf *bp;
        struct ufsmount *ump;
        vsize_t bytelen;
-       daddr_t lbn, nextlbn;
-       off_t bytesinfile;
-       long size, xfersize, blkoffset;
+       int advice;
        int error;
 
        vp = ap->a_vp;
@@ -123,7 +119,10 @@
        } else if (vp->v_type != VREG && vp->v_type != VDIR)
                panic("%s: type %d", "ext2fs_read", vp->v_type);
 #endif
-       fs = ip->i_e2fs;
+       /* XXX Eliminate me by refusing directory reads from userland.  */
+       if (vp->v_type == VDIR)
+               return ext2fs_bufrd(vp, uio, ap->a_ioflag, ap->a_cred);
+
        if ((uint64_t)uio->uio_offset > ump->um_maxfilesize)
                return (EFBIG);
        if (uio->uio_resid == 0)
@@ -131,22 +130,64 @@
        if (uio->uio_offset >= ext2fs_size(ip))
                goto out;
 
-       if (vp->v_type == VREG) {
-               const int advice = IO_ADV_DECODE(ap->a_ioflag);
-
-               while (uio->uio_resid > 0) {
-                       bytelen = MIN(ext2fs_size(ip) - uio->uio_offset,
+       KASSERT(vp->v_type == VREG);
+       advice = IO_ADV_DECODE(ap->a_ioflag);
+       while (uio->uio_resid > 0) {
+               bytelen = MIN(ext2fs_size(ip) - uio->uio_offset,
                            uio->uio_resid);
-                       if (bytelen == 0)
-                               break;
+               if (bytelen == 0)
+                       break;
+
+               error = ubc_uiomove(&vp->v_uobj, uio, bytelen, advice,
+                   UBC_READ | UBC_PARTIALOK | UBC_UNMAP_FLAG(vp));
+               if (error)
+                       break;
+       }
+
+out:
+       if (!(vp->v_mount->mnt_flag & MNT_NOATIME)) {
+               ip->i_flag |= IN_ACCESS;
+               if ((ap->a_ioflag & IO_SYNC) == IO_SYNC)
+                       error = ext2fs_update(vp, NULL, NULL, UPDATE_WAIT);
+       }
+       return (error);
+}
 
-                       error = ubc_uiomove(&vp->v_uobj, uio, bytelen, advice,
-                           UBC_READ | UBC_PARTIALOK | UBC_UNMAP_FLAG(vp));
-                       if (error)
-                               break;
-               }
+/*
+ * UFS op for reading via the buffer cache
+ */
+int
+ext2fs_bufrd(struct vnode *vp, struct uio *uio, int ioflag, kauth_cred_t cred)
+{
+       struct inode *ip;
+       struct ufsmount *ump;
+       struct m_ext2fs *fs;
+       struct buf *bp;
+       off_t bytesinfile;
+       daddr_t lbn, nextlbn;
+       long size, xfersize, blkoffset;
+       int error;
+
+       KASSERT(uio->uio_rw == UIO_READ);
+       KASSERT(VOP_ISLOCKED(vp));
+       KASSERT(vp->v_type == VDIR || vp->v_type == VLNK);
+
+       ip = VTOI(vp);
+       ump = ip->i_ump;
+       fs = ip->i_e2fs;
+       error = 0;
+
+       KASSERT(vp->v_type != VLNK ||
+           ext2fs_size(ip) >= ump->um_maxsymlinklen);
+       KASSERT(vp->v_type != VLNK || ump->um_maxsymlinklen != 0 ||
+           ext2fs_nblock(ip) != 0);
+
+       if (uio->uio_offset > ump->um_maxfilesize)
+               return EFBIG;
+       if (uio->uio_resid == 0)
+               return 0;
+       if (uio->uio_offset >= ext2fs_size(ip))
                goto out;
-       }
 
        for (error = 0, bp = NULL; uio->uio_resid > 0; bp = NULL) {
                bytesinfile = ext2fs_size(ip) - uio->uio_offset;
@@ -196,7 +237,7 @@
 out:
        if (!(vp->v_mount->mnt_flag & MNT_NOATIME)) {
                ip->i_flag |= IN_ACCESS;
-               if ((ap->a_ioflag & IO_SYNC) == IO_SYNC)
+               if ((ioflag & IO_SYNC) == IO_SYNC)
                        error = ext2fs_update(vp, NULL, NULL, UPDATE_WAIT);
        }
        return (error);
@@ -218,11 +259,9 @@
        struct uio *uio;
        struct inode *ip;
        struct m_ext2fs *fs;
-       struct buf *bp;
        struct ufsmount *ump;
-       daddr_t lbn;
        off_t osize;
-       int blkoffset, error, flags, ioflag, resid, xfersize;
+       int blkoffset, error, ioflag, resid;
        vsize_t bytelen;
        off_t oldoff = 0;                                       /* XXX */
        bool async;
@@ -271,58 +310,124 @@
        resid = uio->uio_resid;
        osize = ext2fs_size(ip);
 
-       if (vp->v_type == VREG) {
-               while (uio->uio_resid > 0) {
-                       oldoff = uio->uio_offset;
-                       blkoffset = ext2_blkoff(fs, uio->uio_offset);
-                       bytelen = MIN(fs->e2fs_bsize - blkoffset,
-                           uio->uio_resid);
-
-                       if (vp->v_size < oldoff + bytelen) {
-                               uvm_vnp_setwritesize(vp, oldoff + bytelen);
-                       }
-                       error = ufs_balloc_range(vp, uio->uio_offset,
-                           bytelen, ap->a_cred, 0);
-                       if (error)
-                               break;
-                       error = ubc_uiomove(&vp->v_uobj, uio, bytelen, advice,
-                           UBC_WRITE | UBC_UNMAP_FLAG(vp));
-                       if (error)
-                               break;
+       KASSERT(vp->v_type == VREG);
+       while (uio->uio_resid > 0) {
+               oldoff = uio->uio_offset;
+               blkoffset = ext2_blkoff(fs, uio->uio_offset);
+               bytelen = MIN(fs->e2fs_bsize - blkoffset, uio->uio_resid);
 
-                       /*
-                        * update UVM's notion of the size now that we've
-                        * copied the data into the vnode's pages.
-                        */
-
-                       if (vp->v_size < uio->uio_offset) {
-                               uvm_vnp_setsize(vp, uio->uio_offset);
-                               extended = 1;
-                       }
+               if (vp->v_size < oldoff + bytelen) {
+                       uvm_vnp_setwritesize(vp, oldoff + bytelen);
+               }
+               error = ufs_balloc_range(vp, uio->uio_offset, bytelen,
+                   ap->a_cred, 0);
+               if (error)
+                       break;
+               error = ubc_uiomove(&vp->v_uobj, uio, bytelen, advice,
+                   UBC_WRITE | UBC_UNMAP_FLAG(vp));
+               if (error)
+                       break;
 
-                       /*
-                        * flush what we just wrote if necessary.
-                        * XXXUBC simplistic async flushing.
-                        */
+               /*
+                * update UVM's notion of the size now that we've
+                * copied the data into the vnode's pages.
+                */
 
-                       if (!async && oldoff >> 16 != uio->uio_offset >> 16) {
-                               mutex_enter(vp->v_interlock);
-                               error = VOP_PUTPAGES(vp, (oldoff >> 16) << 16,
-                                   (uio->uio_offset >> 16) << 16,
-                                   PGO_CLEANIT | PGO_LAZY);
-                       }
-               }
-               if (error == 0 && ioflag & IO_SYNC) {
-                       mutex_enter(vp->v_interlock);
-                       error = VOP_PUTPAGES(vp, trunc_page(oldoff),
-                           round_page(ext2_blkroundup(fs, uio->uio_offset)),



Home | Main Index | Thread Index | Old Index