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.