diff options
author | Todd C. Miller <millert@cvs.openbsd.org> | 2004-12-09 17:41:54 +0000 |
---|---|---|
committer | Todd C. Miller <millert@cvs.openbsd.org> | 2004-12-09 17:41:54 +0000 |
commit | 377b6f07b550256b647183859ee880b5373b2713 (patch) | |
tree | 12fe67a206e2c57bfcea7d6e361d6257883110a4 /sys/ufs/ffs | |
parent | d81532ccce8637bade037c4a614d509e66a5ba7d (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.c | 19 |
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) { |