diff options
author | Thordur I. Bjornsson <thib@cvs.openbsd.org> | 2009-08-27 23:26:57 +0000 |
---|---|---|
committer | Thordur I. Bjornsson <thib@cvs.openbsd.org> | 2009-08-27 23:26:57 +0000 |
commit | eb829b5161018a1760bb5cb088700543403224b6 (patch) | |
tree | 06cb2a704361e67f76d4232bdf714cb25f563f37 | |
parent | d20caf5343ab03fcbcba9d39918f0d99bedd9205 (diff) |
introduce a flag member to struct nfs_aiod, and use flags instead of the exit
and worked members. nad_worked becomes NFSAIOD_WAKEUP, which is set after if
an aiod was removed from the idle list and woken up by nfs_asyncio().
don't rely on tsleep wchans being unique, that is keep going back to sleep if
woken up unless the NFSAIOD_WAKEUP flag is set.
fix a divide by zero crash if nfs.vfs.iothreads is set to 0, as that can happen
when we recalculate the maximum buf's to queue up for each aiod.
in nfs_asyncio() set the nad_mnt to NULL before returning the aiod back to the
idle list in the case where we have already queued up to many bufs, otherwise
we trip an assertion.
minimize the time we are holding the nfs_aiodl_mtx to only when we are inserting
or removing from the lists, with the exception of nfs_set_naiod() as it would
make the loops more complicated and its uncommon in any case.
tested by myself and deraadt@
"fine with me" deraadt@
-rw-r--r-- | sys/nfs/nfs_aiod.c | 38 | ||||
-rw-r--r-- | sys/nfs/nfs_bio.c | 9 | ||||
-rw-r--r-- | sys/nfs/nfsnode.h | 12 |
3 files changed, 34 insertions, 25 deletions
diff --git a/sys/nfs/nfs_aiod.c b/sys/nfs/nfs_aiod.c index 3c0b269182d..937fa44d36d 100644 --- a/sys/nfs/nfs_aiod.c +++ b/sys/nfs/nfs_aiod.c @@ -1,4 +1,4 @@ -/* $OpenBSD: nfs_aiod.c,v 1.2 2009/08/26 12:08:10 thib Exp $ */ +/* $OpenBSD: nfs_aiod.c,v 1.3 2009/08/27 23:26:56 thib Exp $ */ /* * Copyright (c) 1989, 1993 * The Regents of the University of California. All rights reserved. @@ -102,12 +102,13 @@ nfs_aiod(void *arg) loop: /* Loop around until SIGKILL */ - mtx_enter(&nfs_aiodl_mtx); - if (aiod->nad_worked) { + + if (aiod->nad_flags & NFSAIOD_WAKEUP) { + mtx_enter(&nfs_aiodl_mtx); LIST_INSERT_HEAD(&nfs_aiods_idle, aiod, nad_idle); - aiod->nad_worked = 0; + mtx_leave(&nfs_aiodl_mtx); + aiod->nad_flags &= ~NFSAIOD_WAKEUP; } - mtx_leave(&nfs_aiodl_mtx); while (1) { nmp = aiod->nad_mnt; @@ -116,9 +117,8 @@ loop: /* Loop around until SIGKILL */ break; } - error = tsleep(aiod, PWAIT, "nioidle", 0); - if (error) - goto out; + while (!(aiod->nad_flags & NFSAIOD_WAKEUP)) + tsleep(aiod, PWAIT, "aiodidle", 0); /* * Wakeup for this aiod happens in one of the following @@ -130,7 +130,7 @@ loop: /* Loop around until SIGKILL */ * found some work for this thread, and if so, ignore it until * later. */ - if (aiod->nad_exiting) { + if (aiod->nad_flags & NFSAIOD_EXIT) { if (aiod->nad_mnt == NULL) goto out1; else @@ -147,20 +147,20 @@ loop: /* Loop around until SIGKILL */ KASSERT(nmp->nm_naiods > 0); nmp->nm_naiods--; - if (aiod->nad_exiting) + if (aiod->nad_flags & NFSAIOD_EXIT) goto out1; goto loop; -out: - mtx_enter(&nfs_aiodl_mtx); - LIST_REMOVE(aiod, nad_idle); - mtx_leave(&nfs_aiodl_mtx); out1: free(aiod, M_TEMP); nfs_numaiods--; + KASSERT(nfs_numaiods >= 0); /* Rejust the limit of bufs to queue. See comment above. */ - nfs_aiodbufqmax = max((bcstats.numbufs / 4) / nfs_numaiods, 64); + if (nfs_numaiods > 0) + nfs_aiodbufqmax = max((bcstats.numbufs / 4) / nfs_numaiods, 64); + else + nfs_aiodbufqmax = 0; kthread_exit(error); } @@ -201,16 +201,16 @@ nfs_set_naiod(int howmany) aiod = LIST_FIRST(&nfs_aiods_idle); LIST_REMOVE(aiod, nad_idle); LIST_REMOVE(aiod, nad_all); /* Yuck. */ - aiod->nad_exiting = 1; - wakeup(aiod); + aiod->nad_flags |= NFSAIOD_QUIT; + wakeup_one(aiod); want--; } while (!LIST_EMPTY(&nfs_aiods_all) && want > 0) { aiod = LIST_FIRST(&nfs_aiods_all); LIST_REMOVE(aiod, nad_all); - aiod->nad_exiting = 1; - wakeup(aiod); + aiod->nad_flags |= NFSAIOD_QUIT; + wakeup_one(aiod); want--; } mtx_leave(&nfs_aiodl_mtx); diff --git a/sys/nfs/nfs_bio.c b/sys/nfs/nfs_bio.c index 7350481ea41..c39ff82666c 100644 --- a/sys/nfs/nfs_bio.c +++ b/sys/nfs/nfs_bio.c @@ -1,4 +1,4 @@ -/* $OpenBSD: nfs_bio.c,v 1.64 2009/08/26 12:08:10 thib Exp $ */ +/* $OpenBSD: nfs_bio.c,v 1.65 2009/08/27 23:26:56 thib Exp $ */ /* $NetBSD: nfs_bio.c,v 1.25.4.2 1996/07/08 20:47:04 jtc Exp $ */ /* @@ -521,13 +521,14 @@ nfs_asyncio(struct buf *bp) * it to work on this mount. */ LIST_REMOVE(aiod, nad_idle); - aiod->nad_worked = 1; mtx_leave(&nfs_aiodl_mtx); + + aiod->nad_flags |= NFSAIOD_WAKEUP; gotone = 1; KASSERT(aiod->nad_mnt == NULL); aiod->nad_mnt = nmp; nmp->nm_naiods++; - wakeup(aiod); + wakeup_one(aiod); } else { mtx_leave(&nfs_aiodl_mtx); } @@ -554,6 +555,8 @@ nfs_asyncio(struct buf *bp) */ if (nmp->nm_bufqlen >= nfs_aiodbufqmax) { if (aiod != NULL) { + aiod->nad_flags &= ~NFSAIOD_WAKEUP; + aiod->nad_mnt = NULL; mtx_enter(&nfs_aiodl_mtx); LIST_INSERT_HEAD(&nfs_aiods_idle, aiod, nad_idle); mtx_leave(&nfs_aiodl_mtx); diff --git a/sys/nfs/nfsnode.h b/sys/nfs/nfsnode.h index 890323078f1..b0f00b77b73 100644 --- a/sys/nfs/nfsnode.h +++ b/sys/nfs/nfsnode.h @@ -1,4 +1,4 @@ -/* $OpenBSD: nfsnode.h,v 1.36 2009/08/26 12:08:10 thib Exp $ */ +/* $OpenBSD: nfsnode.h,v 1.37 2009/08/27 23:26:56 thib Exp $ */ /* $NetBSD: nfsnode.h,v 1.16 1996/02/18 11:54:04 fvdl Exp $ */ /* @@ -142,10 +142,16 @@ struct nfs_aiod { LIST_ENTRY(nfs_aiod) nad_all; LIST_ENTRY(nfs_aiod) nad_idle; struct nfsmount *nad_mnt; - int nad_exiting; - int nad_worked; /* Was removed from idle list. */ + int nad_flags; }; +/* Flags for nad_flags. */ +#define NFSAIOD_EXIT 0x0001 /* aiod being asked to exit. */ +#define NFSAIOD_WAKEUP 0x0002 /* aiod being asked to wakeup. */ +/* used by nfs_set_naiod(), for convience. */ +#define NFSAIOD_QUIT (NFSAIOD_EXIT|NFSAIOD_WAKEUP) /* aiod must quit. */ + + LIST_HEAD(nfs_aiodhead, nfs_aiod); extern struct mutex nfs_aiodl_mtx; |