On Fri, 22 Jan 2010, Rick Macklem wrote:


There should probably be some sort of 3 way handshake between
the code in nfs_asyncio() after calling nfs_nfsnewiod() and the
code near the beginning of nfssvc_iod(), but I think the following
somewhat cheesy fix might do the trick:

[stuff deleted]
I know it's a little weird to reply to my own posting, but I think
this might be a reasonable patch (I have only tested it for a few
minutes at this point).

I basically redefined nfs_iodwant[] as a tri-state variable (although
it was a struct proc *, it was only tested NULL/non-NULL).
0 - was NULL
1 - was non-NULL
-1 - just created by nfs_asyncio() and will be used by it

I'll keep testing it, but hopefully someone else can test and/or
review it... rick
ps: Mikolaj, I'm a sysadmin so I understand the problems with
    production systems, but if you do get a chance to test it somehow,
    that would be great.
pss: This is against -current, but hopefully stable/7 can be patched
    about the same.

--- patch for nfsiod race against -current ---
--- nfsclient/nfs.h.sav 2010-01-22 16:21:53.000000000 -0500
+++ nfsclient/nfs.h     2010-01-22 16:22:04.000000000 -0500
@@ -252,7 +252,7 @@
 int    nfs_commit(struct vnode *vp, u_quad_t offset, int cnt,
            struct ucred *cred, struct thread *td);
 int    nfs_readdirrpc(struct vnode *, struct uio *, struct ucred *);
-int    nfs_nfsiodnew(void);
+int    nfs_nfsiodnew(int);
 int    nfs_asyncio(struct nfsmount *, struct buf *, struct ucred *, struct 
thread *);
 int    nfs_doio(struct vnode *, struct buf *, struct ucred *, struct thread *);
 void   nfs_doio_directwrite (struct buf *);
--- nfsclient/nfsnode.h.sav     2010-01-22 14:56:34.000000000 -0500
+++ nfsclient/nfsnode.h 2010-01-22 14:56:52.000000000 -0500
@@ -180,7 +180,7 @@
  * Queue head for nfsiod's
  */
 extern TAILQ_HEAD(nfs_bufq, buf) nfs_bufq;
-extern struct proc *nfs_iodwant[NFS_MAXASYNCDAEMON];
+extern int nfs_iodwant[NFS_MAXASYNCDAEMON];
 extern struct nfsmount *nfs_iodmount[NFS_MAXASYNCDAEMON];

 #if defined(_KERNEL)
--- nfsclient/nfs_bio.c.sav     2010-01-22 14:57:28.000000000 -0500
+++ nfsclient/nfs_bio.c 2010-01-22 16:17:24.000000000 -0500
@@ -1377,7 +1377,7 @@
         * Find a free iod to process this request.
         */
        for (iod = 0; iod < nfs_numasync; iod++)
-               if (nfs_iodwant[iod]) {
+               if (nfs_iodwant[iod] > 0) {
                        gotiod = TRUE;
                        break;
                }
@@ -1386,7 +1386,7 @@
         * Try to create one if none are free.
         */
        if (!gotiod) {
-               iod = nfs_nfsiodnew();
+               iod = nfs_nfsiodnew(1);
                if (iod != -1)
                        gotiod = TRUE;
        }
@@ -1398,7 +1398,7 @@
                 */
                NFS_DPF(ASYNCIO, ("nfs_asyncio: waking iod %d for mount %p\n",
                    iod, nmp));
-               nfs_iodwant[iod] = NULL;
+               nfs_iodwant[iod] = 0;
                nfs_iodmount[iod] = nmp;
                nmp->nm_bufqiods++;
                wakeup(&nfs_iodwant[iod]);
--- nfsclient/nfs_nfsiod.c.sav  2010-01-22 14:57:28.000000000 -0500
+++ nfsclient/nfs_nfsiod.c      2010-01-22 16:32:31.000000000 -0500
@@ -113,7 +113,7 @@
         * than the new minimum, create some more.
         */
        for (i = nfs_iodmin - nfs_numasync; i > 0; i--)
-               nfs_nfsiodnew();
+               nfs_nfsiodnew(0);
 out:
        mtx_unlock(&nfs_iod_mtx);
        return (0);
@@ -147,7 +147,7 @@
         */
        iod = nfs_numasync - 1;
        for (i = 0; i < nfs_numasync - nfs_iodmax; i++) {
-               if (nfs_iodwant[iod])
+               if (nfs_iodwant[iod] > 0)
                        wakeup(&nfs_iodwant[iod]);
                iod--;
        }
@@ -160,7 +160,7 @@
     "Max number of nfsiod kthreads");

 int
-nfs_nfsiodnew(void)
+nfs_nfsiodnew(int set_iodwant)
 {
        int error, i;
        int newiod;
@@ -176,12 +176,17 @@
                }
        if (newiod == -1)
                return (-1);
+       if (set_iodwant > 0)
+               nfs_iodwant[i] = -1;
        mtx_unlock(&nfs_iod_mtx);
        error = kproc_create(nfssvc_iod, nfs_asyncdaemon + i, NULL, RFHIGHPID,
            0, "nfsiod %d", newiod);
        mtx_lock(&nfs_iod_mtx);
-       if (error)
+       if (error) {
+               if (set_iodwant > 0)
+                       nfs_iodwant[i] = 0;
                return (-1);
+       }
        nfs_numasync++;
        return (newiod);
 }
@@ -199,7 +204,7 @@
                nfs_iodmin = NFS_MAXASYNCDAEMON;

        for (i = 0; i < nfs_iodmin; i++) {
-               error = nfs_nfsiodnew();
+               error = nfs_nfsiodnew(0);
                if (error == -1)
                        panic("nfsiod_setup: nfs_nfsiodnew failed");
        }
@@ -236,7 +241,8 @@
                        goto finish;
                if (nmp)
                        nmp->nm_bufqiods--;
-               nfs_iodwant[myiod] = curthread->td_proc;
+               if (nfs_iodwant[myiod] == 0)
+                       nfs_iodwant[myiod] = 1;
                nfs_iodmount[myiod] = NULL;
                /*
                 * Always keep at least nfs_iodmin kthreads.
@@ -303,7 +309,7 @@
        nfs_asyncdaemon[myiod] = 0;
        if (nmp)
            nmp->nm_bufqiods--;
-       nfs_iodwant[myiod] = NULL;
+       nfs_iodwant[myiod] = 0;
        nfs_iodmount[myiod] = NULL;
        /* Someone may be waiting for the last nfsiod to terminate. */
        if (--nfs_numasync == 0)
--- nfsclient/nfs_subs.c.sav    2010-01-22 14:57:28.000000000 -0500
+++ nfsclient/nfs_subs.c        2010-01-22 16:35:10.000000000 -0500
@@ -347,7 +347,7 @@
                nfs_ticks = 1;
        /* Ensure async daemons disabled */
        for (i = 0; i < NFS_MAXASYNCDAEMON; i++) {
-               nfs_iodwant[i] = NULL;
+               nfs_iodwant[i] = 0;
                nfs_iodmount[i] = NULL;
        }
        nfs_nhinit();                   /* Init the nfsnode table */
@@ -375,7 +375,7 @@
        mtx_lock(&nfs_iod_mtx);
        nfs_iodmax = 0;
        for (i = 0; i < nfs_numasync; i++)
-               if (nfs_iodwant[i])
+               if (nfs_iodwant[i] > 0)
                        wakeup(&nfs_iodwant[i]);
        /* The last nfsiod to exit will wake us up when nfs_numasync hits 0 */
        while (nfs_numasync)
--- nfsclient/nfs_vnops.c.sav   2010-01-22 14:57:28.000000000 -0500
+++ nfsclient/nfs_vnops.c       2010-01-22 15:01:38.000000000 -0500
@@ -212,7 +212,7 @@
  * Global variables
  */
 struct mtx     nfs_iod_mtx;
-struct proc    *nfs_iodwant[NFS_MAXASYNCDAEMON];
+int            nfs_iodwant[NFS_MAXASYNCDAEMON];
 struct nfsmount *nfs_iodmount[NFS_MAXASYNCDAEMON];
 int             nfs_numasync = 0;
 vop_advlock_t  *nfs_advlock_p = nfs_dolock;
_______________________________________________
freebsd-stable@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-stable
To unsubscribe, send any mail to "freebsd-stable-unsubscr...@freebsd.org"

Reply via email to