summaryrefslogtreecommitdiff
path: root/sys/ufs/ffs
diff options
context:
space:
mode:
authorTodd C. Miller <millert@cvs.openbsd.org>2004-12-09 17:41:54 +0000
committerTodd C. Miller <millert@cvs.openbsd.org>2004-12-09 17:41:54 +0000
commit377b6f07b550256b647183859ee880b5373b2713 (patch)
tree12fe67a206e2c57bfcea7d6e361d6257883110a4 /sys/ufs/ffs
parentd81532ccce8637bade037c4a614d509e66a5ba7d (diff)
When removing the last item from a non-empty worklist, the worklist
tail pointer must be updated; from FreeBSD (mckusick). Appears to fix problems I was seeing with processes stuck with WCHAN=inode in rev 1.50. OK pedro@ and tedu@.
Diffstat (limited to 'sys/ufs/ffs')
-rw-r--r--sys/ufs/ffs/ffs_softdep.c19
1 files changed, 16 insertions, 3 deletions
diff --git a/sys/ufs/ffs/ffs_softdep.c b/sys/ufs/ffs/ffs_softdep.c
index 65c6b19c8c6..232a8fc5f3e 100644
--- a/sys/ufs/ffs/ffs_softdep.c
+++ b/sys/ufs/ffs/ffs_softdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ffs_softdep.c,v 1.54 2004/12/08 16:17:52 millert Exp $ */
+/* $OpenBSD: ffs_softdep.c,v 1.55 2004/12/09 17:41:53 millert Exp $ */
/*
* Copyright 1998, 2000 Marshall Kirk McKusick. All Rights Reserved.
*
@@ -533,6 +533,7 @@ workitem_free(item)
* Workitem queue management
*/
STATIC struct workhead softdep_workitem_pending;
+STATIC struct worklist *worklist_tail;
STATIC int num_on_worklist; /* number of worklist items to be processed */
STATIC int softdep_worklist_busy; /* 1 => trying to do unmount */
STATIC int softdep_worklist_req; /* serialized waiters */
@@ -571,7 +572,6 @@ STATIC void
add_to_worklist(wk)
struct worklist *wk;
{
- static struct worklist *worklist_tail;
if (wk->wk_state & ONWORKLIST) {
#ifdef DEBUG
@@ -723,7 +723,7 @@ process_worklist_item(matchmnt, flags)
struct mount *matchmnt;
int flags;
{
- struct worklist *wk;
+ struct worklist *wk, *wkend;
struct dirrem *dirrem;
struct mount *mp;
struct vnode *vp;
@@ -749,7 +749,20 @@ process_worklist_item(matchmnt, flags)
FREE_LOCK(&lk);
return (0);
}
+ /*
+ * Remove the item to be processed. If we are removing the last
+ * item on the list, we need to recalculate the tail pointer.
+ * As this happens rarely and usually when the list is short,
+ * we just run down the list to find it rather than tracking it
+ * in the above loop.
+ */
WORKLIST_REMOVE(wk);
+ if (wk == worklist_tail) {
+ LIST_FOREACH(wkend, &softdep_workitem_pending, wk_list)
+ if (LIST_NEXT(wkend, wk_list) == NULL)
+ break;
+ worklist_tail = wkend;
+ }
num_on_worklist -= 1;
FREE_LOCK(&lk);
switch (wk->wk_type) {