Date: Fri, 13 Aug 2021 20:36:10 GMT From: Kirk McKusick <mckusick@FreeBSD.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org Subject: git: 654e91791ba3 - stable/13 - Clean up orphaned indirdep dependency structures after disk failure. Message-ID: <202108132036.17DKaAsr021212@gitrepo.freebsd.org>
next in thread | raw e-mail | index | archive | help
The branch stable/13 has been updated by mckusick: URL: https://cgit.FreeBSD.org/src/commit/?id=654e91791ba3230bf26954d3ac1af6848702e4e6 commit 654e91791ba3230bf26954d3ac1af6848702e4e6 Author: Kirk McKusick <mckusick@FreeBSD.org> AuthorDate: 2021-07-29 23:11:58 +0000 Commit: Kirk McKusick <mckusick@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.
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202108132036.17DKaAsr021212>