Source-Changes-HG archive

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

[src/trunk]: src/sys/nfs The per nfsnode n_commitlock is a sleep lock, but we...



details:   https://anonhg.NetBSD.org/src/rev/e8abd6598187
branches:  trunk
changeset: 526554:e8abd6598187
user:      enami <enami%NetBSD.org@localhost>
date:      Mon May 06 00:07:51 2002 +0000

description:
The per nfsnode n_commitlock is a sleep lock, but we can't sleep if
PGO_LOCKED getpages request.  So, just make the lock fail and tell
the caller that there is no pages available if we can't acquire it.
The caller will call us again soon without PGO_LOCKED.  Reviewed by chuq.

diffstat:

 sys/nfs/nfs_bio.c |  59 +++++++++++++++++++++++++++++++++++++++++++-----------
 1 files changed, 47 insertions(+), 12 deletions(-)

diffs (122 lines):

diff -r fc1f8259b4cb -r e8abd6598187 sys/nfs/nfs_bio.c
--- a/sys/nfs/nfs_bio.c Sun May 05 22:55:49 2002 +0000
+++ b/sys/nfs/nfs_bio.c Mon May 06 00:07:51 2002 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: nfs_bio.c,v 1.79 2002/04/10 03:06:57 chs Exp $ */
+/*     $NetBSD: nfs_bio.c,v 1.80 2002/05/06 00:07:51 enami Exp $       */
 
 /*
  * Copyright (c) 1989, 1993
@@ -39,7 +39,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: nfs_bio.c,v 1.79 2002/04/10 03:06:57 chs Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nfs_bio.c,v 1.80 2002/05/06 00:07:51 enami Exp $");
 
 #include "opt_nfs.h"
 #include "opt_ddb.h"
@@ -1109,9 +1109,10 @@
        struct vnode *vp = ap->a_vp;
        struct uvm_object *uobj = &vp->v_uobj;
        struct nfsnode *np = VTONFS(vp);
-       struct vm_page *pg, **pgs;
+       const int npages = *ap->a_count;
+       struct vm_page *pg, **pgs, *opgs[npages];
        off_t origoffset, len;
-       int i, error, npages;
+       int i, error;
        boolean_t v3 = NFS_ISV3(vp);
        boolean_t write = (ap->a_access_type & VM_PROT_WRITE) != 0;
        boolean_t locked = (ap->a_flags & PGO_LOCKED) != 0;
@@ -1127,13 +1128,29 @@
        crhold(np->n_rcred);
 
        /*
-        * call the genfs code to get the pages.
+        * call the genfs code to get the pages.  `pgs' may be NULL
+        * when doing read-ahead.
         */
 
-       npages = *ap->a_count;
+       pgs = ap->a_m;
+       if (locked && v3) {
+               KASSERT(write);
+               KASSERT(pgs != NULL);
+#ifdef DEBUG
+
+               /*
+                * If PGO_LOCKED is set, real pages shouldn't exists
+                * in the array.
+                */
+
+               for (i = 0; i < npages; i++)
+                       KDASSERT(pgs[i] == NULL || pgs[i] == PGO_DONTCARE);
+#endif
+               memcpy(opgs, pgs, npages * sizeof(struct vm_pages *));
+       }
        error = genfs_getpages(v);
        if (error) {
-               return error;
+               return (error);
        }
 
        /*
@@ -1143,7 +1160,6 @@
         * this fault.
         */
 
-       pgs = ap->a_m;
        if (!write && (np->n_flag & NMODIFIED) == 0 && pgs != NULL) {
                if (!locked) {
                        simple_lock(&uobj->vmobjlock);
@@ -1160,7 +1176,7 @@
                }
        }
        if (!write) {
-               return error;
+               return (0);
        }
 
        /*
@@ -1170,12 +1186,31 @@
        origoffset = ap->a_offset;
        len = npages << PAGE_SHIFT;
 
-       np->n_flag |= NMODIFIED;
        if (v3) {
-               lockmgr(&np->n_commitlock, LK_EXCLUSIVE, NULL);
+               error = lockmgr(&np->n_commitlock,
+                   LK_EXCLUSIVE | (locked ? LK_NOWAIT : 0), NULL);
+               if (error) {
+                       KASSERT(locked != 0);
+
+                       /*
+                        * Since PGO_LOCKED is set, we need to unbusy
+                        * all pages fetched by genfs_getpages() above,
+                        * tell the caller that there are no pages
+                        * available and put back original pgs array.
+                        */
+
+                       uvm_lock_pageq();
+                       uvm_page_unbusy(pgs, npages);
+                       uvm_unlock_pageq();
+                       *ap->a_count = 0;
+                       memcpy(pgs, opgs,
+                           npages * sizeof(struct vm_pages *));
+                       return (error);
+               }
                nfs_del_committed_range(vp, origoffset, len);
                nfs_del_tobecommitted_range(vp, origoffset, len);
        }
+       np->n_flag |= NMODIFIED;
        if (!locked) {
                simple_lock(&uobj->vmobjlock);
        }
@@ -1192,5 +1227,5 @@
        if (v3) {
                lockmgr(&np->n_commitlock, LK_RELEASE, NULL);
        }
-       return 0;
+       return (0);
 }



Home | Main Index | Thread Index | Old Index