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-all
mailing list