git: 0096e445c55a - stable/13 - ffs: wait for trims earlier during unmount to avoid panic
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sun, 06 Aug 2023 20:36:39 UTC
The branch stable/13 has been updated by marius:
URL: https://cgit.FreeBSD.org/src/commit/?id=0096e445c55a4a882c213d91eaf33766e27439f4
commit 0096e445c55a4a882c213d91eaf33766e27439f4
Author: Chuck Silvers <chs@FreeBSD.org>
AuthorDate: 2022-04-08 17:19:40 +0000
Commit: Marius Strobl <marius@FreeBSD.org>
CommitDate: 2023-08-06 17:56:42 +0000
ffs: wait for trims earlier during unmount to avoid panic
All softdep processing is supposed to be completed by
softdep_flushfiles() and no more deps are supposed to be created after
that, but if a pending trim completes after softdep_flushfiles() and
before softdep_unmount() then the blkfree that is performed by
ffs_blkfree_trim_task() will create a dep when none should exist, and
if softdep_unmount() is called before that dep is freed then the
kernel will panic. Prevent this by waiting for trims to complete
earlier in the unmount process, in ffs_flushfiles(), so that any deps
will be freed and any modified CG buffers will be flushed by the final
fsync of the devvp in ffs_flushfiles() as intended.
(cherry picked from commit 3dc5f8e19d8c975a5e27752d65f9aa91d67c9c9e)
---
sys/ufs/ffs/ffs_vfsops.c | 18 +++++++++++++++---
1 file changed, 15 insertions(+), 3 deletions(-)
diff --git a/sys/ufs/ffs/ffs_vfsops.c b/sys/ufs/ffs/ffs_vfsops.c
index e77d5e336bf1..23d0c9bc60df 100644
--- a/sys/ufs/ffs/ffs_vfsops.c
+++ b/sys/ufs/ffs/ffs_vfsops.c
@@ -1452,9 +1452,7 @@ ffs_unmount(struct mount *mp, int mntflags)
if (susp)
vfs_write_resume(mp, VR_START_WRITE);
if (ump->um_trim_tq != NULL) {
- while (ump->um_trim_inflight != 0)
- pause("ufsutr", hz);
- taskqueue_drain_all(ump->um_trim_tq);
+ MPASS(ump->um_trim_inflight == 0);
taskqueue_free(ump->um_trim_tq);
free (ump->um_trimhash, M_TRIM);
}
@@ -1564,6 +1562,20 @@ ffs_flushfiles(struct mount *mp, int flags, struct thread *td)
if (qerror == 0 && (error = vflush(mp, 0, flags, td)) != 0)
return (error);
+ /*
+ * If this is a forcible unmount and there were any files that
+ * were unlinked but still open, then vflush() will have
+ * truncated and freed those files, which might have started
+ * some trim work. Wait here for any trims to complete
+ * and process the blkfrees which follow the trims.
+ * This may create more dirty devvp buffers and softdep deps.
+ */
+ if (ump->um_trim_tq != NULL) {
+ while (ump->um_trim_inflight != 0)
+ pause("ufsutr", hz);
+ taskqueue_drain_all(ump->um_trim_tq);
+ }
+
/*
* Flush filesystem metadata.
*/