Source-Changes-HG archive

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

[src/trunk]: src/sys/ufs/ffs for softdep vnodes, always write together the pa...



details:   https://anonhg.NetBSD.org/src/rev/9ecc94daebba
branches:  trunk
changeset: 526541:9ecc94daebba
user:      chs <chs%NetBSD.org@localhost>
date:      Sun May 05 17:00:06 2002 +0000

description:
for softdep vnodes, always write together the pages for any block that
might have a dependency , since the accounting doesn't work otherwise.
fixes PRs 15364 16336 16448.

diffstat:

 sys/ufs/ffs/ffs_extern.h |   3 +-
 sys/ufs/ffs/ffs_vnops.c  |  62 +++++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 61 insertions(+), 4 deletions(-)

diffs (114 lines):

diff -r b21d568a954b -r 9ecc94daebba sys/ufs/ffs/ffs_extern.h
--- a/sys/ufs/ffs/ffs_extern.h  Sun May 05 16:26:30 2002 +0000
+++ b/sys/ufs/ffs/ffs_extern.h  Sun May 05 17:00:06 2002 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ffs_extern.h,v 1.21 2001/09/15 20:36:42 chs Exp $      */
+/*     $NetBSD: ffs_extern.h,v 1.22 2002/05/05 17:00:06 chs Exp $      */
 
 /*-
  * Copyright (c) 1991, 1993, 1994
@@ -140,6 +140,7 @@
 int ffs_fsync __P((void *));
 int ffs_reclaim __P((void *));
 int ffs_getpages __P((void *));
+int ffs_putpages __P((void *));
 void ffs_gop_size __P((struct vnode *, off_t, off_t *));
 __END_DECLS
 
diff -r b21d568a954b -r 9ecc94daebba sys/ufs/ffs/ffs_vnops.c
--- a/sys/ufs/ffs/ffs_vnops.c   Sun May 05 16:26:30 2002 +0000
+++ b/sys/ufs/ffs/ffs_vnops.c   Sun May 05 17:00:06 2002 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ffs_vnops.c,v 1.48 2001/12/31 21:37:22 thorpej Exp $   */
+/*     $NetBSD: ffs_vnops.c,v 1.49 2002/05/05 17:00:06 chs Exp $       */
 
 /*
  * Copyright (c) 1982, 1986, 1989, 1993
@@ -36,7 +36,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ffs_vnops.c,v 1.48 2001/12/31 21:37:22 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ffs_vnops.c,v 1.49 2002/05/05 17:00:06 chs Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -63,6 +63,8 @@
 #include <ufs/ffs/fs.h>
 #include <ufs/ffs/ffs_extern.h>
 
+#include <uvm/uvm.h>
+
 static int ffs_full_fsync __P((void *));
 
 /* Global vfs data structures for ufs. */
@@ -116,7 +118,7 @@
        { &vop_update_desc, ffs_update },               /* update */
        { &vop_bwrite_desc, vn_bwrite },                /* bwrite */
        { &vop_getpages_desc, ffs_getpages },           /* getpages */
-       { &vop_putpages_desc, genfs_putpages },         /* putpages */
+       { &vop_putpages_desc, ffs_putpages },           /* putpages */
        { NULL, NULL }
 };
 const struct vnodeopv_desc ffs_vnodeop_opv_desc =
@@ -501,6 +503,60 @@
        return genfs_getpages(v);
 }
 
+int
+ffs_putpages(void *v)
+{
+       struct vop_putpages_args /* {
+               struct vnode *a_vp;
+               voff_t a_offlo;
+               voff_t a_offhi;
+               int a_flags;
+       } */ *ap = v;
+       struct vnode *vp = ap->a_vp;
+       struct uvm_object *uobj = &vp->v_uobj;
+       struct inode *ip = VTOI(vp);
+       struct fs *fs = ip->i_fs;
+       struct vm_page *pg;
+       off_t off;
+       ufs_lbn_t lbn;
+
+       if (!DOINGSOFTDEP(vp) || (ap->a_flags & PGO_CLEANIT) == 0) {
+               return genfs_putpages(v);
+       }
+
+       /*
+        * for softdep files, force the pages in a block to be written together.
+        * if we're the pagedaemon and we would have to wait for other pages,
+        * just fail the request.  the pagedaemon will pick a different page.
+        */
+
+       ap->a_offlo &= ~fs->fs_qbmask;
+       lbn = lblkno(fs, ap->a_offhi);
+       ap->a_offhi = blkroundup(fs, ap->a_offhi);
+       if (curproc == uvm.pagedaemon_proc) {
+               for (off = ap->a_offlo; off < ap->a_offhi; off += PAGE_SIZE) {
+                       pg = uvm_pagelookup(uobj, off);
+
+                       /*
+                        * we only have missing pages here because the
+                        * calculation of offhi above doesn't account for
+                        * fragments.  so once we see one missing page,
+                        * the rest should be missing as well, but we'll
+                        * check for the rest just to be paranoid.
+                        */
+
+                       if (pg == NULL) {
+                               continue;
+                       }
+                       if (pg->flags & PG_BUSY) {
+                               simple_unlock(&uobj->vmobjlock);
+                               return EBUSY;
+                       }
+               }
+       }
+       return genfs_putpages(v);
+}
+
 /*
  * Return the last logical file offset that should be written for this file
  * if we're doing a write that ends at "size".



Home | Main Index | Thread Index | Old Index