Module Name: src
Committed By: maya
Date: Thu Jun 15 14:37:31 UTC 2017
Modified Files:
src/sys/ufs/lfs: lfs_segment.c
Log Message:
It isn't safe to drain dirops with seglock held, it'll deadlock if there
are any dirops. drain before grabbing seglock.
lfs_dirops == 0 is always true (as we already drained dirops), so omit
that part of the comparison.
Fixes a lot of LFS deadlocks. PR kern/52301
Many thanks to dholland for help analyzing coredumps
To generate a diff of this commit:
cvs rdiff -u -r1.271 -r1.272 src/sys/ufs/lfs/lfs_segment.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/ufs/lfs/lfs_segment.c
diff -u src/sys/ufs/lfs/lfs_segment.c:1.271 src/sys/ufs/lfs/lfs_segment.c:1.272
--- src/sys/ufs/lfs/lfs_segment.c:1.271 Mon Jun 12 15:02:32 2017
+++ src/sys/ufs/lfs/lfs_segment.c Thu Jun 15 14:37:30 2017
@@ -1,4 +1,4 @@
-/* $NetBSD: lfs_segment.c,v 1.271 2017/06/12 15:02:32 maya Exp $ */
+/* $NetBSD: lfs_segment.c,v 1.272 2017/06/15 14:37:30 maya Exp $ */
/*-
* Copyright (c) 1999, 2000, 2001, 2002, 2003 The NetBSD Foundation, Inc.
@@ -60,7 +60,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: lfs_segment.c,v 1.271 2017/06/12 15:02:32 maya Exp $");
+__KERNEL_RCSID(0, "$NetBSD: lfs_segment.c,v 1.272 2017/06/15 14:37:30 maya Exp $");
#ifdef DEBUG
# define vndebug(vp, str) do { \
@@ -603,7 +603,6 @@ lfs_segwrite(struct mount *mp, int flags
SEGUSE *segusep;
int do_ckp, did_ckp, error;
unsigned n, segleft, maxseg, sn, i, curseg;
- int writer_set = 0;
int dirty;
int redo;
SEGSUM *ssp;
@@ -628,6 +627,8 @@ lfs_segwrite(struct mount *mp, int flags
if (do_ckp)
flags &= ~SEGM_SINGLE;
+ lfs_writer_enter(fs, "lfs segwrite");
+
lfs_seglock(fs, flags | (do_ckp ? SEGM_CKP : 0));
sp = fs->lfs_sp;
if (sp->seg_flags & (SEGM_CLEAN | SEGM_CKP))
@@ -653,11 +654,7 @@ lfs_segwrite(struct mount *mp, int flags
break;
}
- if (do_ckp || fs->lfs_dirops == 0) {
- if (!writer_set) {
- lfs_writer_enter(fs, "lfs writer");
- writer_set = 1;
- }
+ if (do_ckp) {
error = lfs_writevnodes(fs, mp, sp, VN_DIROP);
if (um_error == 0)
um_error = error;
@@ -806,8 +803,7 @@ lfs_segwrite(struct mount *mp, int flags
/* Note Ifile no longer needs to be written */
fs->lfs_doifile = 0;
- if (writer_set)
- lfs_writer_leave(fs);
+ lfs_writer_leave(fs);
/*
* If we didn't write the Ifile, we didn't really do anything.