Here is a minimal fix that only addresses the tight CPU loop in
softdep_process_worklist(). It will exit the loop if we cannot
make progress instead of spinning.
process_worklist_item() now returns 1 if it processed an item or 0
if it could not. The existing semantics of matchcnt have been
preserved.
- todd
Index: ffs_softdep.c
===================================================================
RCS file: /cvs/src/sys/ufs/ffs/ffs_softdep.c,v
retrieving revision 1.148
diff -u -p -u -r1.148 ffs_softdep.c
--- ffs_softdep.c 4 Feb 2020 04:09:11 -0000 1.148
+++ ffs_softdep.c 3 Mar 2020 15:34:31 -0000
@@ -163,7 +163,7 @@ STATIC int inodedep_lookup(struct fs *,
STATIC int pagedep_lookup(struct inode *, daddr_t, int, struct pagedep **);
STATIC void pause_timer(void *);
STATIC int request_cleanup(int, int);
-STATIC int process_worklist_item(struct mount *, int);
+STATIC int process_worklist_item(struct mount *, int *, int);
STATIC void add_to_worklist(struct worklist *);
/*
@@ -639,7 +639,8 @@ softdep_process_worklist(struct mount *m
loopcount = 1;
getmicrouptime(&starttime);
while (num_on_worklist > 0) {
- matchcnt += process_worklist_item(matchmnt, LK_NOWAIT);
+ if (process_worklist_item(matchmnt, &matchcnt, LK_NOWAIT) == 0)
+ break;
/*
* If a umount operation wants to run the worklist
@@ -707,13 +708,12 @@ softdep_process_worklist(struct mount *m
* Process one item on the worklist.
*/
STATIC int
-process_worklist_item(struct mount *matchmnt, int flags)
+process_worklist_item(struct mount *matchmnt, int *matchcnt, int flags)
{
struct worklist *wk, *wkend;
struct dirrem *dirrem;
struct mount *mp;
struct vnode *vp;
- int matchcnt = 0;
ACQUIRE_LOCK(&lk);
/*
@@ -761,8 +761,8 @@ process_worklist_item(struct mount *matc
panic("%s: dirrem on suspended filesystem",
"process_worklist_item");
#endif
- if (mp == matchmnt)
- matchcnt += 1;
+ if (matchmnt != NULL && mp == matchmnt)
+ *matchcnt += 1;
handle_workitem_remove(WK_DIRREM(wk));
break;
@@ -774,8 +774,8 @@ process_worklist_item(struct mount *matc
panic("%s: freeblks on suspended filesystem",
"process_worklist_item");
#endif
- if (mp == matchmnt)
- matchcnt += 1;
+ if (matchmnt != NULL && mp == matchmnt)
+ *matchcnt += 1;
handle_workitem_freeblocks(WK_FREEBLKS(wk));
break;
@@ -787,8 +787,8 @@ process_worklist_item(struct mount *matc
panic("%s: freefrag on suspended filesystem",
"process_worklist_item");
#endif
- if (mp == matchmnt)
- matchcnt += 1;
+ if (matchmnt != NULL && mp == matchmnt)
+ *matchcnt += 1;
handle_workitem_freefrag(WK_FREEFRAG(wk));
break;
@@ -800,8 +800,8 @@ process_worklist_item(struct mount *matc
panic("%s: freefile on suspended filesystem",
"process_worklist_item");
#endif
- if (mp == matchmnt)
- matchcnt += 1;
+ if (matchmnt != NULL && mp == matchmnt)
+ *matchcnt += 1;
handle_workitem_freefile(WK_FREEFILE(wk));
break;
@@ -810,7 +810,7 @@ process_worklist_item(struct mount *matc
"softdep", TYPENAME(wk->wk_type));
/* NOTREACHED */
}
- return (matchcnt);
+ return (1);
}
/*
@@ -5253,8 +5253,8 @@ request_cleanup(int resource, int islock
atomic_setbits_int(&p->p_flag, P_SOFTDEP);
if (islocked)
FREE_LOCK(&lk);
- process_worklist_item(NULL, LK_NOWAIT);
- process_worklist_item(NULL, LK_NOWAIT);
+ process_worklist_item(NULL, NULL, LK_NOWAIT);
+ process_worklist_item(NULL, NULL, LK_NOWAIT);
atomic_clearbits_int(&p->p_flag, P_SOFTDEP);
stat_worklist_push += 2;
if (islocked)