Module Name:    src
Committed By:   dholland
Date:           Sun Aug  2 18:10:55 UTC 2015

Modified Files:
        src/sys/ufs/lfs: lfs_segment.c

Log Message:
Fix catastrophic bug in lfs_rewind() that changed segment numbers
(lfs_curseg/lfs_nextseg in the superblock) using the wrong units.
These fields are for whatever reason the start addresses of segments
(measured in frags) rather than the segment numbers 0..n.

This only apparently affects dumping from a mounted fs; however, it
trashes the fs.

I would really, really like to have a static analysis tool that can
keep track of the units things are measured in, since fs code is full
of conversion macros and the macros are named inscrutable things like
"sntod" whose letters don't necessarily even correspond to the units
they convert. It is surprising that more of these are not wrong.


To generate a diff of this commit:
cvs rdiff -u -r1.246 -r1.247 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.246 src/sys/ufs/lfs/lfs_segment.c:1.247
--- src/sys/ufs/lfs/lfs_segment.c:1.246	Sun Aug  2 18:10:08 2015
+++ src/sys/ufs/lfs/lfs_segment.c	Sun Aug  2 18:10:55 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: lfs_segment.c,v 1.246 2015/08/02 18:10:08 dholland Exp $	*/
+/*	$NetBSD: lfs_segment.c,v 1.247 2015/08/02 18:10:55 dholland 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.246 2015/08/02 18:10:08 dholland Exp $");
+__KERNEL_RCSID(0, "$NetBSD: lfs_segment.c,v 1.247 2015/08/02 18:10:55 dholland Exp $");
 
 #define _VFS_VNODE_PRIVATE	/* XXX: check for VI_MARKER, this has to go */
 
@@ -1699,7 +1699,7 @@ lfs_updatemeta(struct segment *sp)
 }
 
 /*
- * Move lfs_offset to a segment earlier than sn.
+ * Move lfs_offset to a segment earlier than newsn.
  */
 int
 lfs_rewind(struct lfs *fs, int newsn)
@@ -1730,7 +1730,7 @@ lfs_rewind(struct lfs *fs, int newsn)
 		panic("lfs_rewind: no clean segments");
 	if (newsn >= 0 && sn >= newsn)
 		return ENOENT;
-	lfs_sb_setnextseg(fs, sn);
+	lfs_sb_setnextseg(fs, lfs_sntod(fs, sn));
 	lfs_newseg(fs);
 	lfs_sb_setoffset(fs, lfs_sb_getcurseg(fs));
 

Reply via email to