git: 654e91791ba3 - stable/13 - Clean up orphaned indirdep dependency structures after disk failure.

Kirk McKusick mckusick at FreeBSD.org
Fri Aug 13 20:36:10 UTC 2021


The branch stable/13 has been updated by mckusick:

URL: https://cgit.FreeBSD.org/src/commit/?id=654e91791ba3230bf26954d3ac1af6848702e4e6

commit 654e91791ba3230bf26954d3ac1af6848702e4e6
Author:     Kirk McKusick <mckusick at FreeBSD.org>
AuthorDate: 2021-07-29 23:11:58 +0000
Commit:     Kirk McKusick <mckusick at FreeBSD.org>
CommitDate: 2021-08-13 17:37:26 +0000

    Clean up orphaned indirdep dependency structures after disk failure.
    
    (cherry picked from commit 412b5e40a721430adba1b4abae210641f733f976)
    (cherry picked from commit a91716efeb684c50289c0e1136f5432f880dc873)
---
 sys/ufs/ffs/ffs_softdep.c | 54 +++++++++++++++++++++++++++++++++++++++++------
 sys/ufs/ffs/softdep.h     |  4 +---
 2 files changed, 49 insertions(+), 9 deletions(-)

diff --git a/sys/ufs/ffs/ffs_softdep.c b/sys/ufs/ffs/ffs_softdep.c
index 446fc69a6a32..c53ba7c70d2f 100644
--- a/sys/ufs/ffs/ffs_softdep.c
+++ b/sys/ufs/ffs/ffs_softdep.c
@@ -1233,9 +1233,7 @@ workitem_free(item, type)
 	    ump->um_fs->fs_fsmnt, TYPENAME(item->wk_type)));
 	atomic_subtract_long(&dep_current[item->wk_type], 1);
 	ump->softdep_curdeps[item->wk_type] -= 1;
-#ifdef INVARIANTS
 	LIST_REMOVE(item, wk_all);
-#endif
 	free(item, DtoM(type));
 }
 
@@ -1262,9 +1260,7 @@ workitem_alloc(item, type, mp)
 	ump->softdep_curdeps[type] += 1;
 	ump->softdep_deps++;
 	ump->softdep_accdeps++;
-#ifdef INVARIANTS
 	LIST_INSERT_HEAD(&ump->softdep_alldeps[type], item, wk_all);
-#endif
 	FREE_LOCK(ump);
 }
 
@@ -1293,6 +1289,8 @@ workitem_reassign(item, newtype)
 	dep_total[newtype]++;
 	FREE_GBLLOCK(&lk);
 	item->wk_type = newtype;
+	LIST_REMOVE(item, wk_all);
+	LIST_INSERT_HEAD(&ump->softdep_alldeps[newtype], item, wk_all);
 }
 
 /*
@@ -2710,10 +2708,8 @@ softdep_mount(devvp, mp, fs, cred)
 	ump->indir_hash_size = i - 1;
 	for (i = 0; i <= ump->indir_hash_size; i++)
 		TAILQ_INIT(&ump->indir_hashtbl[i]);
-#ifdef INVARIANTS
 	for (i = 0; i <= D_LAST; i++)
 		LIST_INIT(&ump->softdep_alldeps[i]);
-#endif
 	ACQUIRE_GBLLOCK(&lk);
 	TAILQ_INSERT_TAIL(&softdepmounts, sdp, sd_next);
 	FREE_GBLLOCK(&lk);
@@ -14765,9 +14761,12 @@ softdep_check_suspend(struct mount *mp,
 		      int secondary_writes,
 		      int secondary_accwrites)
 {
+	struct buf *bp;
 	struct bufobj *bo;
 	struct ufsmount *ump;
 	struct inodedep *inodedep;
+	struct indirdep *indirdep;
+	struct worklist *wk, *nextwk;
 	int error, unlinked;
 
 	bo = &devvp->v_bufobj;
@@ -14843,9 +14842,52 @@ softdep_check_suspend(struct mount *mp,
 		}
 	}
 
+	/*
+	 * XXX Check for orphaned indirdep dependency structures.
+	 *
+	 * During forcible unmount after a disk failure there is a
+	 * bug that causes one or more indirdep dependency structures
+	 * to fail to be deallocated. We check for them here and clean
+	 * them up so that the unmount can succeed.
+	 */
+	if ((ump->um_flags & UM_FSFAIL_CLEANUP) != 0 && ump->softdep_deps > 0 &&
+	    ump->softdep_deps == ump->softdep_curdeps[D_INDIRDEP]) {
+		LIST_FOREACH_SAFE(wk, &ump->softdep_alldeps[D_INDIRDEP],
+		    wk_all, nextwk) {
+			indirdep = WK_INDIRDEP(wk);
+			if ((indirdep->ir_state & (GOINGAWAY | DEPCOMPLETE)) !=
+			    (GOINGAWAY | DEPCOMPLETE) ||
+			    !TAILQ_EMPTY(&indirdep->ir_trunc) ||
+			    !LIST_EMPTY(&indirdep->ir_completehd) ||
+			    !LIST_EMPTY(&indirdep->ir_writehd) ||
+			    !LIST_EMPTY(&indirdep->ir_donehd) ||
+			    !LIST_EMPTY(&indirdep->ir_deplisthd) ||
+			    indirdep->ir_saveddata != NULL ||
+			    indirdep->ir_savebp == NULL) {
+				printf("%s: skipping orphaned indirdep %p\n",
+				    __FUNCTION__, indirdep);
+				continue;
+			}
+			printf("%s: freeing orphaned indirdep %p\n",
+			    __FUNCTION__, indirdep);
+			bp = indirdep->ir_savebp;
+			indirdep->ir_savebp = NULL;
+			free_indirdep(indirdep);
+			FREE_LOCK(ump);
+			brelse(bp);
+			while (!TRY_ACQUIRE_LOCK(ump)) {
+				BO_UNLOCK(bo);
+				ACQUIRE_LOCK(ump);
+				FREE_LOCK(ump);
+				BO_LOCK(bo);
+			}
+		}
+	}
+
 	/*
 	 * Reasons for needing more work before suspend:
 	 * - Dirty buffers on devvp.
+	 * - Dependency structures still exist
 	 * - Softdep activity occurred after start of vnode sync loop
 	 * - Secondary writes occurred after start of vnode sync loop
 	 */
diff --git a/sys/ufs/ffs/softdep.h b/sys/ufs/ffs/softdep.h
index 3493aadafc98..41728be3ec0f 100644
--- a/sys/ufs/ffs/softdep.h
+++ b/sys/ufs/ffs/softdep.h
@@ -213,10 +213,10 @@ struct worklist {
 	struct mount		*wk_mp;		/* Mount we live in */
 	unsigned int		wk_type:8,	/* type of request */
 				wk_state:24;	/* state flags */
+	LIST_ENTRY(worklist)	wk_all;		/* list of deps of this type */
 #ifdef INVARIANTS
 	const char		*wk_func;	/* func where added / removed */
 	int			wk_line;	/* line where added / removed */
-	LIST_ENTRY(worklist)	wk_all;		/* list of deps of this type */
 #endif
 };
 #define	WK_DATA(wk) ((void *)(wk))
@@ -1075,9 +1075,7 @@ struct mount_softdeps {
 	TAILQ_ENTRY(mount_softdeps) sd_next;	/* List of softdep filesystem */
 	struct	ufsmount *sd_ump;		/* our ufsmount structure */
 	u_long	sd_curdeps[D_LAST + 1];		/* count of current deps */
-#ifdef INVARIANTS
 	struct	workhead sd_alldeps[D_LAST + 1];/* Lists of all deps */
-#endif
 };
 /*
  * Flags for communicating with the syncer thread.


More information about the dev-commits-src-branches mailing list