From owner-dev-commits-src-main@freebsd.org Thu Jul 29 23:32:17 2021 Return-Path: Delivered-To: dev-commits-src-main@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id 29BDD656639; Thu, 29 Jul 2021 23:32:17 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4GbRdY0Y0fz4rWZ; Thu, 29 Jul 2021 23:32:17 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id EF0621AA1F; Thu, 29 Jul 2021 23:32:16 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 16TNWGwl063358; Thu, 29 Jul 2021 23:32:16 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 16TNWGk2063357; Thu, 29 Jul 2021 23:32:16 GMT (envelope-from git) Date: Thu, 29 Jul 2021 23:32:16 GMT Message-Id: <202107292332.16TNWGk2063357@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Kirk McKusick Subject: git: a91716efeb68 - main - Clean up orphaned indirdep dependency structures after disk failure. MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: mckusick X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: a91716efeb684c50289c0e1136f5432f880dc873 Auto-Submitted: auto-generated X-BeenThere: dev-commits-src-main@freebsd.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Commit messages for the main branch of the src repository List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 29 Jul 2021 23:32:17 -0000 The branch main has been updated by mckusick: URL: https://cgit.FreeBSD.org/src/commit/?id=a91716efeb684c50289c0e1136f5432f880dc873 commit a91716efeb684c50289c0e1136f5432f880dc873 Author: Kirk McKusick AuthorDate: 2021-07-29 23:31:16 +0000 Commit: Kirk McKusick CommitDate: 2021-07-29 23:31:16 +0000 Clean up orphaned indirdep dependency structures after disk failure. During forcible unmount after a disk failure there is a bug that causes one or more indirdep dependency structures to fail to be deallocated. Until we manage to track down why they fail to get cleaned up, this code tracks them down and eliminates them so that the unmount can succeed. Reported by: Peter Holm Help from: kib Reviewed by: Chuck Silvers Tested by: Peter Holm MFC after: 7 days Sponsored by: Netflix --- sys/ufs/ffs/ffs_softdep.c | 54 ++++++++++++++++++++++++++++++++++++++++------- sys/ufs/ffs/softdep.h | 4 +--- 2 files changed, 47 insertions(+), 11 deletions(-) diff --git a/sys/ufs/ffs/ffs_softdep.c b/sys/ufs/ffs/ffs_softdep.c index da80f28bc814..e518cc5c5deb 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,10 +1289,8 @@ workitem_reassign(item, newtype) dep_total[newtype]++; FREE_GBLLOCK(&lk); item->wk_type = newtype; -#ifdef INVARIANTS LIST_REMOVE(item, wk_all); LIST_INSERT_HEAD(&ump->softdep_alldeps[newtype], item, wk_all); -#endif } /* @@ -2713,10 +2707,8 @@ softdep_mount(devvp, mp, fs, cred) sdp->sd_indirhashsize = i - 1; for (i = 0; i <= sdp->sd_indirhashsize; i++) TAILQ_INIT(&sdp->sd_indirhash[i]); -#ifdef INVARIANTS for (i = 0; i <= D_LAST; i++) LIST_INIT(&sdp->sd_alldeps[i]); -#endif ACQUIRE_GBLLOCK(&lk); TAILQ_INSERT_TAIL(&softdepmounts, sdp, sd_next); FREE_GBLLOCK(&lk); @@ -14793,9 +14785,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; @@ -14871,9 +14866,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.