linux-nilfs.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Segment magic number invalid
@ 2010-05-15  0:24 Paul L
       [not found] ` <AANLkTikEfAtM5PdXSFw5pA_8mDW5pcyxes3GTO3kMBPa-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
  0 siblings, 1 reply; 12+ messages in thread
From: Paul L @ 2010-05-15  0:24 UTC (permalink / raw)
  To: linux-nilfs-u79uwXL29TY76Z2rM5mHXA

I have my home directory mounted as a nilfs2 partition. Today what
happened was that first I noticed google-chrome reporting it cannot
load user profile, I initially thought it was a google-chrome error.
At the time I was still able to view and modify my home directory. But
then after rebooting the system, my home partition no longer mounts.
I'm using nilfs-2.0.19 and nilfs-utils-2.0.18 with Linux kernel
2.6.28.

Here is the error message from dmesg (after turning on debugging
message for nilfs2):

NILFS nilfs_fill_super: start(silent=0)
NILFS(recovery) nilfs_search_super_root: looking segment
(seg_start=1607680, seg_end=1609727, segnum=785, seg_seq=307637)
NILFS(recovery) load_segment_summary: checking segment
(pseg_start=1608334, full_check=0)
NILFS(recovery) load_segment_summary: done (ret=3)
NILFS(recovery) nilfs_search_super_root: strayed: scan_newer=0, ret=3
NILFS warning: Segment magic number invalid
NILFS: error searching super root.
NILFS nilfs_fill_super: aborted
NILFS put_nilfs: the_nilfs on bdev mmcblk0p1 was freed

I then dumped the first and last (backup) copy of the nilfs2 super
block, they are identical, and given below:

00000400   02 00 00 00 00 00 34 34  00 01 00 00 A1 6A E9 71  ......44.....j.q
00000410   A3 F1 DD BE 02 00 00 00  AF 07 00 00 00 00 00 00  ................
00000420   00 E0 BF D7 03 00 00 00  01 00 00 00 00 00 00 00  ................
00000430   00 08 00 00 05 00 00 00  7C 3D 0A 00 00 00 00 00  ........|=......
00000440   8E 8A 18 00 00 00 00 00  B5 B1 04 00 00 00 00 00  ................
00000450   00 B8 23 00 00 00 00 00  B9 AF F3 4A 00 00 00 00  ..#........J....
00000460   D9 E1 D6 4B 00 00 00 00  49 8F ED 4B 00 00 00 00  ...K....I..K....
00000470   37 00 32 00 03 00 01 00  B9 AF F3 4A 00 00 00 00  7.2........J....elp
00000480   00 4E ED 00 00 00 00 00  00 00 00 00 0B 00 00 00  .N..............
00000490   80 00 20 00 C0 00 10 00  13 1C FC 11 D7 43 4C 09  .. ..........CL.
000004A0   81 64 93 0A F4 54 CF 5E  48 4F 4D 45 00 00 00 00  .d...T.^HOME....


I wonder if there is a fsck tool to help me recover the file system.
Any help is greatly appreciated!

PS: last time I had a different problem of losing partition info, and
later successfully recovered with the help from people on the list. So
thanks! Now I'm actually backing up my files every two weeks, but
it'll still be great if it can recover and even better if we can trace
the problem.

-- 
Regards,
Paul Liu

Yale Haskell Group
http://www.haskell.org/yale
--
To unsubscribe from this list: send the line "unsubscribe linux-nilfs" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Segment magic number invalid
       [not found] ` <AANLkTikEfAtM5PdXSFw5pA_8mDW5pcyxes3GTO3kMBPa-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
@ 2010-05-16  1:33   ` Ryusuke Konishi
       [not found]     ` <AANLkTinBFQYWRZRmVL69lqxRG1p0cBQ2AxBiFk4SlNE8@mail.gmail.com>
  0 siblings, 1 reply; 12+ messages in thread
From: Ryusuke Konishi @ 2010-05-16  1:33 UTC (permalink / raw)
  To: ninegua-Re5JQEeQqe8AvxtiuMwx3w; +Cc: linux-nilfs-u79uwXL29TY76Z2rM5mHXA

[-- Attachment #1: Type: Text/Plain, Size: 3083 bytes --]

Hi,
On Fri, 14 May 2010 20:24:02 -0400, Paul L wrote:
> I have my home directory mounted as a nilfs2 partition. Today what
> happened was that first I noticed google-chrome reporting it cannot
> load user profile, I initially thought it was a google-chrome error.
> At the time I was still able to view and modify my home directory. But
> then after rebooting the system, my home partition no longer mounts.
> I'm using nilfs-2.0.19 and nilfs-utils-2.0.18 with Linux kernel
> 2.6.28.
> 
> Here is the error message from dmesg (after turning on debugging
> message for nilfs2):
> 
> NILFS nilfs_fill_super: start(silent=0)
> NILFS(recovery) nilfs_search_super_root: looking segment
> (seg_start=1607680, seg_end=1609727, segnum=785, seg_seq=307637)
> NILFS(recovery) load_segment_summary: checking segment
> (pseg_start=1608334, full_check=0)
> NILFS(recovery) load_segment_summary: done (ret=3)
> NILFS(recovery) nilfs_search_super_root: strayed: scan_newer=0, ret=3
> NILFS warning: Segment magic number invalid
> NILFS: error searching super root.
> NILFS nilfs_fill_super: aborted
> NILFS put_nilfs: the_nilfs on bdev mmcblk0p1 was freed
> 
> I then dumped the first and last (backup) copy of the nilfs2 super
> block, they are identical, and given below:
> 
> 00000400   02 00 00 00 00 00 34 34  00 01 00 00 A1 6A E9 71  ......44.....j.q
> 00000410   A3 F1 DD BE 02 00 00 00  AF 07 00 00 00 00 00 00  ................
> 00000420   00 E0 BF D7 03 00 00 00  01 00 00 00 00 00 00 00  ................
> 00000430   00 08 00 00 05 00 00 00  7C 3D 0A 00 00 00 00 00  ........|=......
> 00000440   8E 8A 18 00 00 00 00 00  B5 B1 04 00 00 00 00 00  ................
> 00000450   00 B8 23 00 00 00 00 00  B9 AF F3 4A 00 00 00 00  ..#........J....
> 00000460   D9 E1 D6 4B 00 00 00 00  49 8F ED 4B 00 00 00 00  ...K....I..K....
> 00000470   37 00 32 00 03 00 01 00  B9 AF F3 4A 00 00 00 00  7.2........J....elp
> 00000480   00 4E ED 00 00 00 00 00  00 00 00 00 0B 00 00 00  .N..............
> 00000490   80 00 20 00 C0 00 10 00  13 1C FC 11 D7 43 4C 09  .. ..........CL.
> 000004A0   81 64 93 0A F4 54 CF 5E  48 4F 4D 45 00 00 00 00  .d...T.^HOME....
> 
> 
> I wonder if there is a fsck tool to help me recover the file system.
> Any help is greatly appreciated!
>
> PS: last time I had a different problem of losing partition info, and
> later successfully recovered with the help from people on the list. So
> thanks! Now I'm actually backing up my files every two weeks, but
> it'll still be great if it can recover and even better if we can trace
> the problem.

Your filesystem seems to have lost the latest log according to the
report.

The attached patch may help to recover it.  It is revised scan tool
for nilfs-utils-2.0.18.

After compiling the tool, you can use it like:

 # cd nilfs-utils-2.0.18
 # sbin/fsck/fsck0 <device>

The tool will confirm whether to update super blocks if it finds the
latest log.

You may need to do

 $ aclocal && autoheader && libtoolize -c --foce && automake -a -c && autoconf
 $ ./configure

before build the tool.

With regards,
Ryusuke Konishi

[-- Attachment #2: fsck0-for-2.0.18.patch --]
[-- Type: Text/Plain, Size: 29810 bytes --]

From b1a403ed4a7cb6987052729075255d5d893bebdb Mon Sep 17 00:00:00 2001
From: Ryusuke Konishi <konishi.ryusuke-Zyj7fXuS5i5L9jVzuh4AOg@public.gmane.org>
Date: Sat, 15 May 2010 12:33:27 +0900
Subject: [PATCH] nilfs2-utils: add test tool to correct log pointer in super block

Signed-off-by: Ryusuke Konishi <konishi.ryusuke-Zyj7fXuS5i5L9jVzuh4AOg@public.gmane.org>
---
 configure.ac             |    1 +
 sbin/Makefile.am         |    2 +-
 sbin/fsck/Makefile.am    |    7 +
 sbin/fsck/fsck0.nilfs2.c | 1150 ++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 1159 insertions(+), 1 deletions(-)
 create mode 100644 sbin/fsck/Makefile.am
 create mode 100644 sbin/fsck/fsck0.nilfs2.c

diff --git a/configure.ac b/configure.ac
index 2b2dfd7..30e91eb 100644
--- a/configure.ac
+++ b/configure.ac
@@ -86,6 +86,7 @@ AC_CONFIG_FILES([Makefile
                  man/Makefile
                  sbin/Makefile
                  sbin/cleanerd/Makefile
+		 sbin/fsck/Makefile
                  sbin/mkfs/Makefile
 		 sbin/mount/Makefile])
 AC_OUTPUT
diff --git a/sbin/Makefile.am b/sbin/Makefile.am
index 6038b8f..7f2c6db 100644
--- a/sbin/Makefile.am
+++ b/sbin/Makefile.am
@@ -1,3 +1,3 @@
 ## Makefile.am
 
-SUBDIRS = cleanerd mkfs mount
+SUBDIRS = cleanerd mkfs mount fsck
diff --git a/sbin/fsck/Makefile.am b/sbin/fsck/Makefile.am
new file mode 100644
index 0000000..4a2f380
--- /dev/null
+++ b/sbin/fsck/Makefile.am
@@ -0,0 +1,7 @@
+## Makefile.am
+
+sbin_PROGRAMS = fsck0.nilfs2
+
+fsck0_nilfs2_SOURCES = fsck0.nilfs2.c ../../lib/crc32.c ../mkfs/mkfs.h
+fsck0_nilfs2_CFLAGS = -Wall
+fsck0_nilfs2_CPPFLAGS = -I$(top_srcdir)/include
diff --git a/sbin/fsck/fsck0.nilfs2.c b/sbin/fsck/fsck0.nilfs2.c
new file mode 100644
index 0000000..2d3a435
--- /dev/null
+++ b/sbin/fsck/fsck0.nilfs2.c
@@ -0,0 +1,1150 @@
+/*
+ * fsck0.nilfs2.c - correct inconsistencies of nilfs2 volume
+ *
+ * Licensed under GPLv2: the complete text of the GNU General Public License
+ * can be found in COPYING file of the nilfs-utils package.
+ *
+ * Copyright (C) 2008-2010 Nippon Telegraph and Telephone Corporation.
+ * Written by Ryusuke Konishi <ryusuke-sG5X7nlA6pw@public.gmane.org>
+ */
+#define _LARGEFILE64_SOURCE
+#define _XOPEN_SOURCE 600
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif	/* HAVE_CONFIG_H */
+
+#if HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif	/* HAVE_SYS_TYPES_H */
+
+#if HAVE_LINUX_TYPES_H
+#include <linux/types.h>
+#endif	/* HAVE_LINUX_TYPES_H */
+
+#include <stdio.h>
+
+#if HAVE_STDLIB_H
+#include <stdlib.h>
+#endif	/* HAVE_STDLIB_H */
+
+#if HAVE_FCNTL_H
+#include <fcntl.h>
+#endif	/* HAVE_FCNTL_H */
+
+#include <errno.h>
+
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif	/* HAVE_UNISTD_H */
+
+#include <malloc.h>
+
+#if HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif	/* HAVE_SYS_IOCTL_H */
+
+#if HAVE_STRINGS_H
+#include <strings.h>
+#endif	/* HAVE_SYS_STRINGS_H */
+
+#if HAVE_STRING_H
+#include <string.h>
+#endif	/* HAVE_SYS_STRING_H */
+
+#include <endian.h>
+#include <byteswap.h>
+
+#include <stdarg.h>
+#include <time.h>
+#include <assert.h>
+
+#include "../mkfs/mkfs.h"
+
+#define MOUNTS			"/etc/mtab"
+#define LINE_BUFFER_SIZE	256  /* Line buffer size for reading mtab */
+#define MAX_SCAN_SEGMENT	50   /* Maximum number of segments which are
+					tested for the latest segment search */
+#define SCAN_INDICATOR_SPEED	3    /* Indicator speed (smaller value for
+					higher speed) */
+#define SCAN_SEGMENT_MASK	((1U << SCAN_INDICATOR_SPEED) - 1)
+
+#define NILFS_MAX_SB_SIZE	1024 /* Maximum size of super block in bytes */
+#define NILFS_SB_BLOCK_SIZE_SHIFT	10
+
+/* fsck return codes */
+#define EXIT_OK			0
+#define EXIT_NONDESTRUCT	1
+#define EXIT_DESTRUCT		2
+#define EXIT_UNCORRECTED	4
+#define EXIT_ERROR		8
+#define EXIT_USAGE		16
+#define EXIT_CANCEL		32
+#define EXIT_LIBRARY		128
+
+#define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d))
+
+char *progname = NULL;
+
+struct nilfs_log_ref {
+	__u64 blocknr;   /* start blocknumber */
+	__u64 seqnum;    /* sequence number */
+	__u64 cno;       /* checkpoint number */
+	__u64 ctime;     /* creation time */
+};
+
+static int show_version_only = 0;
+static int force = 0;
+static int verbose = 0;
+
+static int devfd = -1;
+static int blocksize;
+static __u32 crc_seed;
+static __u32 blocks_per_segment;
+static __u64 first_data_block;
+static __u64 nsegments;
+static __u16 checkpoint_size;
+static __u16 sb_bytes;
+
+static int first_checkpoint_offset;
+static int ncheckpoints_per_block;
+
+/*
+ * Generic routines
+ */
+void die(const char *fmt, ...)
+{
+	va_list args;
+
+	va_start(args, fmt);
+	fprintf(stderr, "%s: ", progname);
+	vfprintf(stderr, fmt, args);
+	fprintf(stderr, "\n");
+	va_end(args);
+
+	if (devfd >= 0)
+		close(devfd);
+	exit(EXIT_ERROR);
+}
+
+static void (*nilfs_shrink)(void) = NULL;
+
+void *nilfs_malloc(size_t size)
+{
+	void *p = malloc(size);
+	if (!p) {
+		if (nilfs_shrink)
+			nilfs_shrink();
+		p = malloc(size);
+		if (!p)
+			die("memory allocation failure");
+	}
+	return p;
+}
+
+static inline void *nilfs_zalloc(size_t size)
+{
+	void *p = nilfs_malloc(size);
+	memset(p, 0, size);
+	return p;
+}
+
+/*
+ * Block buffer
+ */
+static void *block_buffer = NULL;
+
+static void destroy_block_buffer(void)
+{
+	if (block_buffer) {
+		free(block_buffer);
+		block_buffer = NULL;
+	}
+}
+
+static void init_block_buffer(void)
+{
+	block_buffer = nilfs_malloc(blocksize);
+	atexit(destroy_block_buffer);
+}
+
+static void read_block(int fd, __u64 blocknr, void *buf,
+		       unsigned long size)
+{
+	if (lseek64(fd, blocknr * blocksize, SEEK_SET) < 0 ||
+	    read(fd, buf, size) < size)
+		die("cannot read block (blocknr = %llu)",
+		    (unsigned long long)blocknr);
+}
+
+static inline __u64 segment_start_blocknr(unsigned long segnum)
+{
+	return segnum > 0 ? blocks_per_segment * segnum : first_data_block;
+}
+
+static int log_is_valid(int fd, __u64 log_start,
+			struct nilfs_segment_summary *ss)
+{
+	__u32 crc, sum;
+	int offset = sizeof(ss->ss_datasum);
+	int nblocks = le32_to_cpu(ss->ss_nblocks);
+	__u64 blocknr = log_start;
+
+	if (le32_to_cpu(ss->ss_magic) != NILFS_SEGSUM_MAGIC)
+		return 0;
+
+	if (nblocks == 0 || nblocks > blocks_per_segment)
+		return 0;
+
+	sum = le32_to_cpu(ss->ss_datasum);
+
+	read_block(fd, blocknr++, block_buffer, blocksize);
+	crc = nilfs_crc32(crc_seed, block_buffer + offset, blocksize - offset);
+	while (--nblocks > 0) {
+		read_block(fd, blocknr++, block_buffer, blocksize);
+		crc = nilfs_crc32(crc, block_buffer, blocksize);
+	}
+	return crc == sum;
+}
+
+/*
+ * Routines to handle log (partial segment) list
+ */
+struct nilfs_list {  /* use struct list_head in kernel land */
+	struct nilfs_list *prev;
+	struct nilfs_list *next;
+};
+
+static inline void nilfs_list_init(struct nilfs_list *list)
+{
+	list->prev = list->next = list;
+}
+
+static inline int nilfs_list_empty(struct nilfs_list *list)
+{
+	return list->next == list;
+}
+
+static inline void nilfs_list_del(struct nilfs_list *list)
+{
+	struct nilfs_list *p = list->prev, *n = list->next;
+
+	p->next = n;
+	n->prev = p;
+	list->prev = list->next = list;
+}
+
+static inline void nilfs_list_add(struct nilfs_list *list,
+				  struct nilfs_list *item)
+{
+	struct nilfs_list *p = list->prev;
+
+	item->prev = p;
+	item->next = list;
+	p->next = list->prev = item;
+}
+
+/* log (partial segment) information */
+struct nilfs_log_info {
+	struct nilfs_list list;
+	__u64 log_start;  /* start blocknr */
+	__u32 nblocks;
+	struct nilfs_segment_summary segsum;  /* on-disk log header */
+	__u16 flags;
+};
+
+static inline struct nilfs_log_info *nilfs_log_list_entry(struct nilfs_list *p)
+{
+	return (void *)p - offsetof(struct nilfs_log_info, list);
+}
+
+struct nilfs_log_info *new_log_info(__u64 blocknr)
+{
+	struct nilfs_log_info *loginfo = nilfs_zalloc(sizeof(*loginfo));
+
+	loginfo->log_start = blocknr;
+	nilfs_list_init(&loginfo->list);
+	return loginfo;
+}
+
+static void dispose_log_list(struct nilfs_list *list)
+{
+	struct nilfs_list *p, *n;
+
+	for (p = list->next; n = p->next, p != list; p = n) {
+		nilfs_list_del(p);
+		free(nilfs_log_list_entry(p));
+	}
+}
+
+/*
+ * Segment information
+ */
+struct nilfs_segment_info {
+	struct nilfs_list list;
+	struct nilfs_list log_list;	/* partial segment list */
+	__u64 seg_start;		/* start blocknr of the segment */
+	__u64 next;			/* pointer to the next segment */
+	__u64 segseq;			/* sequence number of the segment */
+	unsigned long segnum;		/* the number of the segment */
+	int nlogs;			/* number of logs */
+	int refcnt;
+};
+
+static struct nilfs_list segment_cache;
+
+static struct nilfs_segment_info *
+nilfs_segment_list_entry(struct nilfs_list *p)
+{
+	return (void *)p - offsetof(struct nilfs_segment_info, list);
+}
+
+struct nilfs_segment_info *new_segment_info(unsigned long segnum)
+{
+	struct nilfs_segment_info *seginfo;
+
+	seginfo = nilfs_zalloc(sizeof(*seginfo));
+	seginfo->segnum = segnum;
+	seginfo->seg_start = segment_start_blocknr(segnum);
+	seginfo->refcnt = 1;
+
+	nilfs_list_init(&seginfo->log_list);
+	nilfs_list_add(&segment_cache, &seginfo->list);
+	return seginfo;
+}
+
+void destroy_segment_info(struct nilfs_segment_info *seginfo)
+{
+	nilfs_list_del(&seginfo->list);
+	dispose_log_list(&seginfo->log_list);
+	free(seginfo);
+}
+
+static inline struct nilfs_segment_info *
+get_segment_info(struct nilfs_segment_info *seginfo)
+{
+	seginfo->refcnt++;
+	return seginfo;
+}
+
+static inline void put_segment_info(struct nilfs_segment_info *seginfo)
+{
+	assert(seginfo->refcnt > 0);
+	seginfo->refcnt--;
+}
+
+/*
+ * Segment cache
+ */
+void destroy_segment_cache(void)
+{
+	struct nilfs_list *p, *n;
+
+	for (p = segment_cache.next; n = p->next, p != &segment_cache; p = n) {
+		destroy_segment_info(nilfs_segment_list_entry(p));
+	}
+}
+
+void shrink_segment_cache(void)
+{
+	struct nilfs_list *p, *n;
+	struct nilfs_segment_info *seginfo;
+
+	for (p = segment_cache.next; n = p->next, p != &segment_cache; p = n) {
+		seginfo = nilfs_segment_list_entry(p);
+		if (seginfo->refcnt == 0)
+			destroy_segment_info(seginfo);
+	}
+}
+
+void init_segment_cache(void)
+{
+	nilfs_list_init(&segment_cache);
+	nilfs_shrink = shrink_segment_cache;
+	atexit(destroy_segment_cache);
+}
+
+struct nilfs_segment_info *lookup_segment(unsigned long segnum)
+{
+	struct nilfs_segment_info *seginfo;
+	struct nilfs_list *p;
+
+	for (p = segment_cache.next; p != &segment_cache; p = p->next) {
+		seginfo = nilfs_segment_list_entry(p);
+		if (seginfo->segnum == segnum) {
+			get_segment_info(seginfo);
+			return seginfo;
+		}
+	}
+	return NULL;
+}
+
+struct nilfs_segment_info *load_segment(int fd, unsigned long segnum)
+{
+	struct nilfs_segment_info *seginfo;
+	struct nilfs_log_info *loginfo;
+	struct nilfs_segment_summary *ss;
+	__u64 blocknr, end;
+
+	seginfo = lookup_segment(segnum);
+	if (seginfo)
+		return seginfo;
+
+	seginfo = new_segment_info(segnum);
+	blocknr = seginfo->seg_start;
+
+	posix_fadvise(fd, blocknr * blocksize, blocks_per_segment * blocksize,
+		      POSIX_FADV_WILLNEED);
+
+	loginfo = new_log_info(blocknr);
+	nilfs_list_add(&seginfo->log_list, &loginfo->list);
+
+	ss = &loginfo->segsum;
+	read_block(fd, blocknr, ss, sizeof(*ss));
+
+	if (!log_is_valid(fd, blocknr, ss)) {
+		put_segment_info(seginfo);
+		fprintf(stderr, "empty or bad segment: "
+			"segnum = %lu, blocknr = %llu\n", segnum,
+			(unsigned long long)segment_start_blocknr(segnum));
+		return NULL; /* no valid partial segment found */
+	}
+
+	seginfo->segseq = le64_to_cpu(ss->ss_seq);
+	seginfo->next = le64_to_cpu(ss->ss_next);
+
+	end = blocknr + blocks_per_segment;
+	do {
+		seginfo->nlogs++;
+
+		loginfo->nblocks = le32_to_cpu(ss->ss_nblocks);
+		loginfo->flags = le16_to_cpu(ss->ss_flags);
+
+		blocknr += loginfo->nblocks;
+		if (blocknr >= end)
+			return seginfo;
+
+		loginfo = new_log_info(blocknr);
+		nilfs_list_add(&seginfo->log_list, &loginfo->list);
+
+		ss = &loginfo->segsum;
+		read_block(fd, blocknr, ss, sizeof(*ss));
+
+	} while (log_is_valid(fd, blocknr, ss) &&
+		 le64_to_cpu(ss->ss_seq) == seginfo->segseq);
+
+	nilfs_list_del(&loginfo->list);
+	free(loginfo);
+
+	return seginfo;
+}
+
+/*
+ * Operations on segment_info structure
+ */
+struct nilfs_log_info *lookup_log(struct nilfs_segment_info *seginfo,
+				  __u64 blocknr)
+{
+	struct nilfs_log_info *loginfo;
+	struct nilfs_list *p;
+
+	for (p = seginfo->log_list.next; p != &seginfo->log_list;
+	     p = p->next) {
+		loginfo = nilfs_log_list_entry(p);
+		if (loginfo->log_start == blocknr)
+			return loginfo;
+	}
+	return NULL;
+}
+
+struct nilfs_log_info *first_log(struct nilfs_segment_info *seginfo)
+{
+	return nilfs_list_empty(&seginfo->log_list) ? NULL :
+		nilfs_log_list_entry(seginfo->log_list.next);
+}
+
+struct nilfs_log_info *last_log(struct nilfs_segment_info *seginfo)
+{
+	return nilfs_list_empty(&seginfo->log_list) ? NULL :
+		nilfs_log_list_entry(seginfo->log_list.prev);
+}
+
+struct nilfs_log_info *next_log(struct nilfs_segment_info *seginfo,
+				struct nilfs_log_info *loginfo)
+{
+	return loginfo->list.next == &seginfo->log_list ? NULL :
+		nilfs_log_list_entry(loginfo->list.next);
+}
+
+struct nilfs_log_info *prev_log(struct nilfs_segment_info *seginfo,
+				struct nilfs_log_info *loginfo)
+{
+	return loginfo->list.prev == &seginfo->log_list ? NULL :
+		nilfs_log_list_entry(loginfo->list.prev);
+}
+
+struct nilfs_log_info *
+lookup_last_super_root(struct nilfs_segment_info *seginfo)
+{
+	struct nilfs_log_info *loginfo;
+
+	for (loginfo = last_log(seginfo); loginfo != NULL;
+	     loginfo = prev_log(seginfo, loginfo)) {
+		if (loginfo->flags & NILFS_SS_SR)
+			return loginfo;
+	}
+	return NULL;
+}
+
+unsigned long log_length(struct nilfs_segment_info *seginfo)
+{
+	return nilfs_list_empty(&seginfo->log_list) ? 0 :
+		nilfs_log_list_entry(seginfo->log_list.prev)->log_start -
+		seginfo->seg_start +
+		nilfs_log_list_entry(seginfo->log_list.prev)->nblocks;
+}
+
+/*
+ * Routines to get latest checkpoint number
+ */
+static __u64 find_latest_checkpoint(int fd, __u64 cpblocknr, __u64 blkoff)
+{
+	struct nilfs_checkpoint *cp;
+	int i, ncp;
+	__u64 cno = 0;
+
+	read_block(fd, cpblocknr, block_buffer, blocksize);
+	if (blkoff == 0) {
+		cp = block_buffer + first_checkpoint_offset * checkpoint_size;
+		ncp = ncheckpoints_per_block - first_checkpoint_offset;
+	} else {
+		cp = block_buffer;
+		ncp = ncheckpoints_per_block;
+	}
+
+	for (i = 0; i < ncp; i++, cp = (void *)cp + checkpoint_size) {
+		if (!nilfs_checkpoint_invalid(cp) &&
+		    le64_to_cpu(cp->cp_cno) > cno)
+			cno = le64_to_cpu(cp->cp_cno);
+	}
+	return cno;
+}
+
+static void *next_ss_entry(int fd, __u64 *blocknrp,
+			   unsigned *offsetp, unsigned entry_size)
+{
+	void *p;
+
+	if (*offsetp + entry_size > blocksize) {
+		(*blocknrp)++;
+		read_block(fd, *blocknrp, block_buffer, blocksize);
+		*offsetp = 0;
+	}
+	p = block_buffer + *offsetp;
+	(*offsetp) += entry_size;
+	return p;
+}
+
+static __u64 get_latest_cno(int fd, __u64 log_start)
+{
+	struct nilfs_segment_summary *ss;
+	struct nilfs_finfo *finfo;
+	__u32 nfinfo;
+	__u32 nblocks, ndatablk, nnodeblk;
+	__u64 ino;
+	__u64 latest_cno = 0, cno;
+	__u64 blocknr = log_start, fblocknr;
+	unsigned offset;
+	int i, j;
+
+	read_block(fd, blocknr, block_buffer, blocksize);
+	ss = block_buffer;
+	nfinfo = le32_to_cpu(ss->ss_nfinfo);
+	offset = le16_to_cpu(ss->ss_bytes);
+	fblocknr = blocknr + DIV_ROUND_UP(le32_to_cpu(ss->ss_sumbytes),
+					  blocksize);
+
+	for (i = 0; i < nfinfo; i++) {
+		finfo = next_ss_entry(fd, &blocknr, &offset, sizeof(*finfo));
+
+		nblocks = le32_to_cpu(finfo->fi_nblocks);
+		ndatablk = le32_to_cpu(finfo->fi_ndatablk);
+		nnodeblk = nblocks - ndatablk;
+		ino = le64_to_cpu(finfo->fi_ino);
+
+		if (ino == NILFS_DAT_INO) {
+			__le64 *blkoff;
+			struct nilfs_binfo_dat *binfo_dat;
+
+			for (j = 0; j < ndatablk; j++, fblocknr++) {
+				blkoff = next_ss_entry(fd, &blocknr,
+						       &offset,
+						       sizeof(*blkoff));
+			}
+			for (j = 0; j < nnodeblk; j++, fblocknr++) {
+				binfo_dat = next_ss_entry(fd, &blocknr,
+							  &offset,
+							  sizeof(*binfo_dat));
+			}
+		} else {
+			struct nilfs_binfo_v *binfo_v;
+			__le64 *vblocknr;
+
+			for (j = 0; j < ndatablk; j++, fblocknr++) {
+				binfo_v = next_ss_entry(fd, &blocknr,
+							&offset,
+							sizeof(*binfo_v));
+			}
+			if (ino == NILFS_CPFILE_INO && ndatablk > 0) {
+				cno = find_latest_checkpoint(
+					fd, fblocknr - 1,
+					le64_to_cpu(binfo_v->bi_blkoff));
+				if (cno > latest_cno)
+					latest_cno = cno;
+			}
+			for (j = 0; j < nnodeblk; j++, fblocknr++) {
+				vblocknr = next_ss_entry(fd, &blocknr,
+							 &offset,
+							 sizeof(*vblocknr));
+			}
+		}
+	}
+
+	return latest_cno;
+}
+
+__u64 find_latest_cno_in_logical_segment(int fd,
+					 struct nilfs_segment_info *seginfo,
+					 struct nilfs_log_info *start)
+{
+	struct nilfs_log_info *loginfo = start ? : last_log(seginfo);
+	__u64 cno, latest_cno = 0;
+	__u64 seq;
+	int i = 0;
+
+	if (loginfo == NULL)
+		return 0;
+
+	get_segment_info(seginfo);
+	do {
+		cno = get_latest_cno(fd, loginfo->log_start);
+		if (cno > latest_cno)
+			latest_cno = cno;
+
+		if (loginfo->flags & NILFS_SS_LOGBGN)
+			break;
+
+		loginfo = prev_log(seginfo, loginfo);
+		if (loginfo == NULL) {
+			unsigned long segnum = seginfo->segnum;
+
+			if (++i > MAX_SCAN_SEGMENT)
+				break;
+			segnum = (segnum == 0) ? nsegments - 1 : segnum - 1;
+			seq = seginfo->segseq;
+
+			put_segment_info(seginfo);
+			seginfo = load_segment(fd, segnum);
+
+			if (!seginfo || seginfo->segseq != seq - 1)
+				break;
+			loginfo = last_log(seginfo);
+		}
+	} while (loginfo != NULL && !(loginfo->flags & NILFS_SS_LOGEND));
+
+	if (seginfo)
+		put_segment_info(seginfo);
+	return latest_cno;
+}
+
+void print_log_message(const struct nilfs_log_ref *log_ref,
+		       const char *fmt, ...)
+{
+	const char *cp;
+	va_list args;
+
+	va_start(args, fmt);
+	vfprintf(stderr, fmt, args);
+	fprintf(stderr, ": blocknr = %llu\n",
+		(unsigned long long)log_ref->blocknr);
+
+	for (cp = fmt; *cp == ' '; cp++)
+		fputc(' ', stderr);
+	fprintf(stderr, "    segnum = %lu, seq = %llu, cno=%llu\n",
+		(unsigned long)log_ref->blocknr / blocks_per_segment,
+		(unsigned long long)log_ref->seqnum,
+		(unsigned long long)log_ref->cno);
+	if (log_ref->ctime) {
+		char tmbuf[LINE_BUFFER_SIZE];
+		struct tm tm;
+		time_t t = (time_t)le64_to_cpu(log_ref->ctime);
+
+		localtime_r(&t, &tm);
+		strftime(tmbuf, LINE_BUFFER_SIZE, "%F %T", &tm);
+		for (cp = fmt; *cp == ' '; cp++)
+			fputc(' ', stderr);
+		fprintf(stderr, "    creation time = %s\n", tmbuf);
+	}
+	va_end(args);
+}
+
+struct nilfs_log_info *
+find_latest_super_root(int fd, unsigned long segnum, __u64 blocknr,
+		       struct nilfs_segment_info **seginfop)
+{
+	struct nilfs_segment_info *seginfo;
+	struct nilfs_segment_info *seginfo_sr = NULL;
+		/* seginfo which has the last super root */
+	struct nilfs_log_info *log_sr = NULL;
+	int cont = 0, invert = 0;
+	int i;
+
+	seginfo = load_segment(fd, segnum);
+	if (seginfo) {
+		log_sr = lookup_last_super_root(seginfo);
+		if (log_sr)
+			seginfo_sr = get_segment_info(seginfo);
+
+		if (blocknr < seginfo->seg_start + log_length(seginfo))
+			cont = 1;
+	}
+
+	for (i = 0; i < MAX_SCAN_SEGMENT; i++) {
+		struct nilfs_segment_info *seginfo2;
+
+		/*
+		 * Look into the previous segment.
+		 *
+		 * This code depends on the current GC policy; discontinuously
+		 * allocated segments are not supported.
+		 */
+		if (!(i & SCAN_SEGMENT_MASK))
+			fputc('.', stderr);
+		segnum = (segnum == 0) ? nsegments - 1 : segnum - 1;
+
+		seginfo2 = load_segment(fd, segnum);
+		if (!seginfo2) {
+			if (log_sr && cont) {
+				log_sr = NULL;
+				put_segment_info(seginfo_sr);
+				seginfo_sr = NULL;
+			}
+			cont = 0;
+			if (seginfo) {
+				put_segment_info(seginfo);
+				seginfo = NULL;
+			}
+			continue;
+		}
+
+		if (!seginfo) {
+			seginfo = seginfo2;
+			seginfo2 = NULL;
+
+			if (log_sr)
+				put_segment_info(seginfo_sr);
+			log_sr = lookup_last_super_root(seginfo);
+			if (log_sr)
+				seginfo_sr = get_segment_info(seginfo);
+			continue;
+		}
+
+		if (seginfo2->segseq + 1 != seginfo->segseq)
+			cont = 0;
+
+		if (seginfo2->segseq > seginfo->segseq) {
+			invert++;
+			if (log_sr) {
+				log_sr = NULL;
+				put_segment_info(seginfo_sr);
+				seginfo_sr = NULL;
+			}
+		}
+		if (invert && !log_sr) {
+			log_sr = lookup_last_super_root(seginfo2);
+			if (log_sr) {
+				put_segment_info(seginfo);
+				*seginfop = seginfo2;
+				fputc('\n', stderr);
+				return log_sr; /* latest segment was found */
+			}
+		}
+
+		if (!cont && !log_sr) {
+			log_sr = lookup_last_super_root(seginfo2);
+			if (log_sr)
+				seginfo_sr = get_segment_info(seginfo2);
+		}
+
+		put_segment_info(seginfo);
+		seginfo = seginfo2;
+		seginfo2 = NULL;
+	}
+	fputc('\n', stderr);
+	if (seginfo)
+		put_segment_info(seginfo);
+
+	if (log_sr && !cont) {
+		*seginfop = seginfo_sr;
+		return log_sr; /* regard second-ranking candidate
+				   as the latest segment */
+	}
+	if (seginfo_sr)
+		put_segment_info(seginfo_sr);
+	return NULL;
+}
+
+static void check_mount(int fd, const char *device)
+{
+	FILE *fp;
+	char line[LINE_BUFFER_SIZE];
+
+	fp = fopen(MOUNTS, "r");
+	if (fp == NULL)
+		die("cannot open %s!", MOUNTS);
+
+	while (fgets(line, LINE_BUFFER_SIZE, fp) != NULL) {
+		if (strncmp(strtok(line, " "), device, strlen(device)) == 0) {
+			fclose(fp);
+			die("%s is currently mounted.", device);
+		}
+	}
+	fclose(fp);
+}
+
+static int nilfs_sb_is_valid(struct nilfs_super_block *sbp, int check_crc)
+{
+	__le32 sum;
+	__u32 seed, crc;
+
+	if (le16_to_cpu(sbp->s_magic) != NILFS_SUPER_MAGIC)
+		return 0;
+	if (le16_to_cpu(sbp->s_bytes) > NILFS_MAX_SB_SIZE)
+		return 0;
+	if (!check_crc)
+		return 1;
+
+	seed = le32_to_cpu(sbp->s_crc_seed);
+	sum = sbp->s_sum;
+	sbp->s_sum = 0;
+	crc = crc32_le(seed, (unsigned char *)sbp, le16_to_cpu(sbp->s_bytes));
+	sbp->s_sum = sum;
+	return crc == le32_to_cpu(sum);
+}
+
+static struct nilfs_super_block *nilfs_read_super_block(int fd)
+{
+	struct nilfs_super_block *sbp[2];
+	__u64 devsize, sb2_offset;
+
+	sbp[0] = malloc(NILFS_MAX_SB_SIZE);
+	sbp[1] = malloc(NILFS_MAX_SB_SIZE);
+	if (sbp[0] == NULL || sbp[1] == NULL)
+		goto failed;
+
+	if (ioctl(fd, BLKGETSIZE64, &devsize) != 0)
+		goto failed;
+
+	if (lseek64(fd, NILFS_SB_OFFSET_BYTES, SEEK_SET) < 0 ||
+	    read(fd, sbp[0], NILFS_MAX_SB_SIZE) < 0 ||
+	    !nilfs_sb_is_valid(sbp[0], 0)) {
+		free(sbp[0]);
+		sbp[0] = NULL;
+	}
+
+	sb2_offset = NILFS_SB2_OFFSET_BYTES(devsize);
+	if (lseek64(fd, sb2_offset, SEEK_SET) < 0 ||
+	    read(fd, sbp[1], NILFS_MAX_SB_SIZE) < 0 ||
+	    !nilfs_sb_is_valid(sbp[1], 0))
+		goto sb2_failed;
+
+	if (sb2_offset <
+	    (le64_to_cpu(sbp[1]->s_nsegments) *
+	     le32_to_cpu(sbp[1]->s_blocks_per_segment)) <<
+	    (le32_to_cpu(sbp[1]->s_log_block_size) +
+	     NILFS_SB_BLOCK_SIZE_SHIFT))
+		goto sb2_failed;
+
+ sb2_done:
+	if (!sbp[0]) {
+		sbp[0] = sbp[1];
+		sbp[1] = NULL;
+	}
+
+	if (sbp[1] &&
+	    le64_to_cpu(sbp[1]->s_last_cno) > le64_to_cpu(sbp[0]->s_last_cno)) {
+		free(sbp[0]);
+		return sbp[1];
+	} else if (sbp[0]) {
+		free(sbp[1]);
+		return sbp[0];
+	}
+
+ failed:
+	free(sbp[0]);  /* free(NULL) is just ignored */
+	free(sbp[1]);
+	return NULL;
+
+ sb2_failed:
+	free(sbp[1]);
+	sbp[1] = NULL;
+	goto sb2_done;
+}
+
+static void read_sb_info(struct nilfs_super_block *sbp)
+{
+	char tmbuf[LINE_BUFFER_SIZE];
+	struct tm tm;
+	time_t t;
+
+	fprintf(stderr, "Super-block:\n");
+
+	crc_seed = le32_to_cpu(sbp->s_crc_seed);
+
+	fprintf(stderr, "    revision = %d.%d\n",
+		le32_to_cpu(sbp->s_rev_level),
+		le16_to_cpu(sbp->s_minor_rev_level));
+
+	blocksize = 1 << (le32_to_cpu(sbp->s_log_block_size) + 10);
+	blocks_per_segment = le32_to_cpu(sbp->s_blocks_per_segment);
+	first_data_block = le64_to_cpu(sbp->s_first_data_block);
+	nsegments = le64_to_cpu(sbp->s_nsegments);
+	checkpoint_size = le16_to_cpu(sbp->s_checkpoint_size);
+	sb_bytes = le16_to_cpu(sbp->s_bytes);
+
+	first_checkpoint_offset =
+		DIV_ROUND_UP(sizeof(struct nilfs_cpfile_header),
+			     checkpoint_size);
+	ncheckpoints_per_block = blocksize / checkpoint_size;
+
+	t = (time_t)le64_to_cpu(sbp->s_wtime);
+	localtime_r(&t, &tm);
+	strftime(tmbuf, LINE_BUFFER_SIZE, "%F %T", &tm);
+
+	fprintf(stderr, "    blocksize = %d\n", blocksize);
+	fprintf(stderr, "    write time = %s\n", tmbuf);
+}
+
+static void commit_super_block(struct nilfs_super_block *sbp,
+			       const struct nilfs_log_ref *log_ref)
+{
+	__u32 sbsum;
+
+	sbp->s_last_pseg = cpu_to_le64(log_ref->blocknr);
+	sbp->s_last_seq = cpu_to_le64(log_ref->seqnum);
+	sbp->s_last_cno = cpu_to_le64(log_ref->cno);
+
+	sbp->s_wtime = cpu_to_le64(time(NULL));
+	sbp->s_state = cpu_to_le16(le16_to_cpu(sbp->s_state) & ~NILFS_VALID_FS);
+
+	/* fill in crc */
+	sbp->s_sum = 0;
+	sbsum = nilfs_crc32(crc_seed, (unsigned char *)sbp, sb_bytes);
+	sbp->s_sum = cpu_to_le32(sbsum);
+}
+
+static int nilfs_write_super_block(int fd, struct nilfs_super_block *sbp)
+{
+	__u64 devsize, sb2_offset;
+	int ret = -1;
+
+	if (ioctl(fd, BLKGETSIZE64, &devsize) != 0)
+		return -1;
+
+	if (lseek64(fd, NILFS_SB_OFFSET_BYTES, SEEK_SET) < 0 ||
+	    write(fd, sbp, sb_bytes) < sb_bytes ||
+	    fsync(fd) < 0)
+		fprintf(stderr, "failed to write primary super block");
+	else
+		ret = 0;
+
+	sb2_offset = NILFS_SB2_OFFSET_BYTES(devsize);
+	if (sb2_offset < (__u64)nsegments * blocks_per_segment * blocksize)
+		return ret;
+
+	if (lseek64(fd, sb2_offset, SEEK_SET) < 0 ||
+	    write(fd, sbp, sb_bytes) <  sb_bytes ||
+	    fsync(fd) < 0)
+		fprintf(stderr,
+			"failed to write secondary super block");
+	else
+		ret = 0;
+
+	return ret;
+}
+
+static int test_latest_log(int fd, struct nilfs_log_ref *log_ref)
+{
+	struct nilfs_segment_info *seginfo;
+	struct nilfs_log_info *loginfo;
+	unsigned long segnum;
+	int ret = -1;
+
+	/*
+	 * check the log the super block points to
+	 */
+	segnum = log_ref->blocknr / blocks_per_segment;
+	seginfo = load_segment(fd, segnum);
+	if (seginfo) {
+		loginfo = lookup_log(seginfo, log_ref->blocknr);
+		if (loginfo && seginfo->segseq == log_ref->seqnum &&
+		    loginfo->flags & NILFS_SS_SR) {
+			log_ref->ctime =
+				le64_to_cpu(loginfo->segsum.ss_create);
+			print_log_message(log_ref,
+					  "A valid log is pointed to by "
+					  "superblock (No change needed)");
+			ret = 0;
+		}
+	}
+	put_segment_info(seginfo);
+	return ret;
+}
+
+static void nilfs_do_rollback(int fd, struct nilfs_log_ref *log_ref)
+{
+	struct nilfs_segment_info *seginfo;
+	struct nilfs_log_info *loginfo;
+	unsigned long segnum;
+
+	/*
+	 * check logs in the current and prior full segments.
+	 */
+	segnum = log_ref->blocknr / blocks_per_segment;
+	loginfo = find_latest_super_root(fd, segnum, log_ref->blocknr,
+					 &seginfo);
+	if (!loginfo)
+		die("Cannot find super root");
+
+	log_ref->blocknr = loginfo->log_start;
+	log_ref->seqnum = seginfo->segseq;
+	log_ref->ctime = le64_to_cpu(loginfo->segsum.ss_create);
+
+	fprintf(stderr, "Searching the latest checkpoint.\n");
+	log_ref->cno = find_latest_cno_in_logical_segment(fd, seginfo, loginfo);
+	if (log_ref->cno == 0)
+		die("Cannot identify the latest checkpoint");
+
+	print_log_message(log_ref, "Selected log");
+}
+
+static void nilfs_fsck(const char *device)
+{
+	struct nilfs_super_block *sbp;
+	struct nilfs_log_ref log_ref;
+	int clean, ret;
+	int c;
+
+	if ((devfd = open(device, O_RDONLY | O_LARGEFILE)) < 0)
+		die("cannot open device %s", device);
+
+	check_mount(devfd, device);
+
+	sbp = nilfs_read_super_block(devfd);
+	if (!sbp)
+		die("cannot read super block (device=%s)", device);
+
+	read_sb_info(sbp);
+
+	log_ref.blocknr = le64_to_cpu(sbp->s_last_pseg);
+	log_ref.seqnum = le64_to_cpu(sbp->s_last_seq);
+	log_ref.cno = le64_to_cpu(sbp->s_last_cno);
+	log_ref.ctime = 0;
+	print_log_message(&log_ref, "    indicated log");
+	fputc('\n', stderr);
+
+	if (le16_to_cpu(sbp->s_state) & NILFS_VALID_FS) {
+		fprintf(stderr, "Clean FS.\n");
+		clean = 1;
+	} else {
+		fprintf(stderr, "Unclean FS.\n");
+		clean = 0;
+	}
+
+	init_block_buffer();
+	init_segment_cache();
+
+	ret = test_latest_log(devfd, &log_ref);
+	if (ret < 0) {
+		fprintf(stderr, "The latest log is lost. "
+			"Trying rollback recovery..\n");
+		clean = 0;
+		nilfs_do_rollback(devfd, &log_ref);
+	}
+	destroy_segment_cache();
+	destroy_block_buffer();
+
+	if (!ret)
+		goto out;
+
+	/*
+	 * Reopen device to update superblock
+	 */
+	close(devfd);
+	devfd = -1;
+	if ((devfd = open(device, O_RDWR | O_LARGEFILE)) < 0)
+		die("cannot open device %s in read/write mode", device);
+
+	fprintf(stderr, "Do you wish to overwrite super block (y/N)? ");
+	if ((c = getchar()) == 'y' || c == 'Y') {
+		commit_super_block(sbp, &log_ref);
+		if (nilfs_write_super_block(devfd, sbp) < 0)
+			die("couldn't update super block (device=%s)", device);
+	}
+ out:
+	if (!clean)
+		fprintf(stderr, "Recovery will complete on mount.\n");
+	free(sbp);
+	close(devfd);
+}
+
+static void usage(void)
+{
+	fprintf(stderr, "Usage: %s [-fv] device\n", progname);
+	exit(EXIT_USAGE);
+}
+
+static void parse_options(int argc, char *argv[])
+{
+	int c;
+
+	while ((c = getopt(argc, argv, "fvV")) != EOF) {
+		switch (c) {
+		case 'f':
+			force = 1;
+			break;
+		case 'v':
+			verbose = 1;
+			break;
+		case 'V':
+			show_version_only = 1;
+			break;
+		default:
+			usage();
+		}
+	}
+	if (show_version_only)
+		return;
+	if (optind == argc)
+		usage();
+}
+
+int main(int argc, char *argv[])
+{
+	char *device;
+
+	if ((progname = strrchr(argv[0], '/')) != NULL)
+		progname++;
+	else
+		progname = argv[0];
+
+	parse_options(argc, argv);
+	if (show_version_only) {
+		fprintf(stderr, "%s version %s\n", progname, PACKAGE_VERSION);
+		exit(EXIT_OK);
+	}
+	device = argv[optind];
+	nilfs_fsck(device);
+
+	exit(EXIT_OK);
+}
-- 
1.6.3.4


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: Segment magic number invalid
       [not found]       ` <AANLkTinBFQYWRZRmVL69lqxRG1p0cBQ2AxBiFk4SlNE8-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
@ 2010-05-16 18:32         ` Paul L
       [not found]           ` <AANLkTimHvMze3B8fQE383WW8WLbOYcZx0pz0sfjC2DhJ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
  0 siblings, 1 reply; 12+ messages in thread
From: Paul L @ 2010-05-16 18:32 UTC (permalink / raw)
  To: linux-nilfs-u79uwXL29TY76Z2rM5mHXA

Sorry, should have sent it to the list instead.

 Thanks for the patch! I tried it, but seems it still can't find the
 super root. Here is the output. What shall I do now?

 Super-block:
     revision = 2.0
     blocksize = 4096
     write time = 2010-05-14 13:58:33
     indicated log: blocknr = 1608334
         segnum = 785, seq = 307637, cno=671100

 Clean FS.
 The latest log is lost. Trying rollback recovery..
 .......
 fsck0.nilfs2: Cannot find super root


> On 5/15/10, Ryusuke Konishi <ryusuke-sG5X7nlA6pw@public.gmane.org> wrote:
>> Hi,
>> On Fri, 14 May 2010 20:24:02 -0400, Paul L wrote:
>>> I have my home directory mounted as a nilfs2 partition. Today what
>>> happened was that first I noticed google-chrome reporting it cannot
>>> load user profile, I initially thought it was a google-chrome error.
>>> At the time I was still able to view and modify my home directory. But
>>> then after rebooting the system, my home partition no longer mounts.
>>> I'm using nilfs-2.0.19 and nilfs-utils-2.0.18 with Linux kernel
>>> 2.6.28.
>>>
>>> Here is the error message from dmesg (after turning on debugging
>>> message for nilfs2):
>>>
>>> NILFS nilfs_fill_super: start(silent=0)
>>> NILFS(recovery) nilfs_search_super_root: looking segment
>>> (seg_start=1607680, seg_end=1609727, segnum=785, seg_seq=307637)
>>> NILFS(recovery) load_segment_summary: checking segment
>>> (pseg_start=1608334, full_check=0)
>>> NILFS(recovery) load_segment_summary: done (ret=3)
>>> NILFS(recovery) nilfs_search_super_root: strayed: scan_newer=0, ret=3
>>> NILFS warning: Segment magic number invalid
>>> NILFS: error searching super root.
>>> NILFS nilfs_fill_super: aborted
>>> NILFS put_nilfs: the_nilfs on bdev mmcblk0p1 was freed
>>>
>>> I then dumped the first and last (backup) copy of the nilfs2 super
>>> block, they are identical, and given below:
>>>
>>> 00000400   02 00 00 00 00 00 34 34  00 01 00 00 A1 6A E9 71
>>> ......44.....j.q
>>> 00000410   A3 F1 DD BE 02 00 00 00  AF 07 00 00 00 00 00 00
>>> ................
>>> 00000420   00 E0 BF D7 03 00 00 00  01 00 00 00 00 00 00 00
>>> ................
>>> 00000430   00 08 00 00 05 00 00 00  7C 3D 0A 00 00 00 00 00
>>> ........|=......
>>> 00000440   8E 8A 18 00 00 00 00 00  B5 B1 04 00 00 00 00 00
>>> ................
>>> 00000450   00 B8 23 00 00 00 00 00  B9 AF F3 4A 00 00 00 00
>>> ..#........J....
>>> 00000460   D9 E1 D6 4B 00 00 00 00  49 8F ED 4B 00 00 00 00
>>> ...K....I..K....
>>> 00000470   37 00 32 00 03 00 01 00  B9 AF F3 4A 00 00 00 00
>>> 7.2........J....elp
>>> 00000480   00 4E ED 00 00 00 00 00  00 00 00 00 0B 00 00 00
>>> .N..............
>>> 00000490   80 00 20 00 C0 00 10 00  13 1C FC 11 D7 43 4C 09  ..
>>> ..........CL.
>>> 000004A0   81 64 93 0A F4 54 CF 5E  48 4F 4D 45 00 00 00 00
>>> .d...T.^HOME....
>>>
>>>
>>> I wonder if there is a fsck tool to help me recover the file system.
>>> Any help is greatly appreciated!
>>>
>>> PS: last time I had a different problem of losing partition info, and
>>> later successfully recovered with the help from people on the list. So
>>> thanks! Now I'm actually backing up my files every two weeks, but
>>> it'll still be great if it can recover and even better if we can trace
>>> the problem.
>>
>> Your filesystem seems to have lost the latest log according to the
>> report.
>>
>> The attached patch may help to recover it.  It is revised scan tool
>> for nilfs-utils-2.0.18.
>>
>> After compiling the tool, you can use it like:
>>
>>  # cd nilfs-utils-2.0.18
>>  # sbin/fsck/fsck0 <device>
>>
>> The tool will confirm whether to update super blocks if it finds the
>> latest log.
>>
>> You may need to do
>>
>>  $ aclocal && autoheader && libtoolize -c --foce && automake -a -c &&
>> autoconf
>>  $ ./configure
>>
>> before build the tool.
>>
>> With regards,
>> Ryusuke Konishi
>>
>
>
> --
> Regards,
> Paul Liu
>
> Yale Haskell Group
> http://www.haskell.org/yale
>


-- 
Regards,
Paul Liu

Yale Haskell Group
http://www.haskell.org/yale
--
To unsubscribe from this list: send the line "unsubscribe linux-nilfs" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Segment magic number invalid
       [not found]           ` <AANLkTimHvMze3B8fQE383WW8WLbOYcZx0pz0sfjC2DhJ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
@ 2010-05-17  2:46             ` Ryusuke Konishi
       [not found]               ` <20100517.114657.112904526.ryusuke-sG5X7nlA6pw@public.gmane.org>
  0 siblings, 1 reply; 12+ messages in thread
From: Ryusuke Konishi @ 2010-05-17  2:46 UTC (permalink / raw)
  To: ninegua-Re5JQEeQqe8AvxtiuMwx3w; +Cc: linux-nilfs-u79uwXL29TY76Z2rM5mHXA

Hi,
On Sun, 16 May 2010 14:32:05 -0400, Paul L wrote:
> Sorry, should have sent it to the list instead.
> 
>  Thanks for the patch! I tried it, but seems it still can't find the
>  super root. Here is the output. What shall I do now?
> 
>  Super-block:
>      revision = 2.0
>      blocksize = 4096
>      write time = 2010-05-14 13:58:33
>      indicated log: blocknr = 1608334
>          segnum = 785, seq = 307637, cno=671100
> 
>  Clean FS.
>  The latest log is lost. Trying rollback recovery..
>  .......
>  fsck0.nilfs2: Cannot find super root

Can you try increasing the number defined at the following line in
sbin/fsck/fsck0.nilfs2.c ?

 #define  MAX_SCAN_SEGMENT          50

Regards,
Ryusuke Konishi
 
> > On 5/15/10, Ryusuke Konishi <ryusuke-sG5X7nlA6pw@public.gmane.org> wrote:
> >> Hi,
> >> On Fri, 14 May 2010 20:24:02 -0400, Paul L wrote:
> >>> I have my home directory mounted as a nilfs2 partition. Today what
> >>> happened was that first I noticed google-chrome reporting it cannot
> >>> load user profile, I initially thought it was a google-chrome error.
> >>> At the time I was still able to view and modify my home directory. But
> >>> then after rebooting the system, my home partition no longer mounts.
> >>> I'm using nilfs-2.0.19 and nilfs-utils-2.0.18 with Linux kernel
> >>> 2.6.28.
> >>>
> >>> Here is the error message from dmesg (after turning on debugging
> >>> message for nilfs2):
> >>>
> >>> NILFS nilfs_fill_super: start(silent=0)
> >>> NILFS(recovery) nilfs_search_super_root: looking segment
> >>> (seg_start=1607680, seg_end=1609727, segnum=785, seg_seq=307637)
> >>> NILFS(recovery) load_segment_summary: checking segment
> >>> (pseg_start=1608334, full_check=0)
> >>> NILFS(recovery) load_segment_summary: done (ret=3)
> >>> NILFS(recovery) nilfs_search_super_root: strayed: scan_newer=0, ret=3
> >>> NILFS warning: Segment magic number invalid
> >>> NILFS: error searching super root.
> >>> NILFS nilfs_fill_super: aborted
> >>> NILFS put_nilfs: the_nilfs on bdev mmcblk0p1 was freed
> >>>
> >>> I then dumped the first and last (backup) copy of the nilfs2 super
> >>> block, they are identical, and given below:
> >>>
> >>> 00000400   02 00 00 00 00 00 34 34  00 01 00 00 A1 6A E9 71
> >>> ......44.....j.q
> >>> 00000410   A3 F1 DD BE 02 00 00 00  AF 07 00 00 00 00 00 00
> >>> ................
> >>> 00000420   00 E0 BF D7 03 00 00 00  01 00 00 00 00 00 00 00
> >>> ................
> >>> 00000430   00 08 00 00 05 00 00 00  7C 3D 0A 00 00 00 00 00
> >>> ........|=......
> >>> 00000440   8E 8A 18 00 00 00 00 00  B5 B1 04 00 00 00 00 00
> >>> ................
> >>> 00000450   00 B8 23 00 00 00 00 00  B9 AF F3 4A 00 00 00 00
> >>> ..#........J....
> >>> 00000460   D9 E1 D6 4B 00 00 00 00  49 8F ED 4B 00 00 00 00
> >>> ...K....I..K....
> >>> 00000470   37 00 32 00 03 00 01 00  B9 AF F3 4A 00 00 00 00
> >>> 7.2........J....elp
> >>> 00000480   00 4E ED 00 00 00 00 00  00 00 00 00 0B 00 00 00
> >>> .N..............
> >>> 00000490   80 00 20 00 C0 00 10 00  13 1C FC 11 D7 43 4C 09  ..
> >>> ..........CL.
> >>> 000004A0   81 64 93 0A F4 54 CF 5E  48 4F 4D 45 00 00 00 00
> >>> .d...T.^HOME....
> >>>
> >>>
> >>> I wonder if there is a fsck tool to help me recover the file system.
> >>> Any help is greatly appreciated!
> >>>
> >>> PS: last time I had a different problem of losing partition info, and
> >>> later successfully recovered with the help from people on the list. So
> >>> thanks! Now I'm actually backing up my files every two weeks, but
> >>> it'll still be great if it can recover and even better if we can trace
> >>> the problem.
> >>
> >> Your filesystem seems to have lost the latest log according to the
> >> report.
> >>
> >> The attached patch may help to recover it.  It is revised scan tool
> >> for nilfs-utils-2.0.18.
> >>
> >> After compiling the tool, you can use it like:
> >>
> >>  # cd nilfs-utils-2.0.18
> >>  # sbin/fsck/fsck0 <device>
> >>
> >> The tool will confirm whether to update super blocks if it finds the
> >> latest log.
> >>
> >> You may need to do
> >>
> >>  $ aclocal && autoheader && libtoolize -c --foce && automake -a -c &&
> >> autoconf
> >>  $ ./configure
> >>
> >> before build the tool.
> >>
> >> With regards,
> >> Ryusuke Konishi
> >>
> >
> >
> > --
> > Regards,
> > Paul Liu
> >
> > Yale Haskell Group
> > http://www.haskell.org/yale
> >
> 
> 
> -- 
> Regards,
> Paul Liu
> 
> Yale Haskell Group
> http://www.haskell.org/yale
> --
> To unsubscribe from this list: send the line "unsubscribe linux-nilfs" in
> the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe linux-nilfs" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Segment magic number invalid
       [not found]               ` <20100517.114657.112904526.ryusuke-sG5X7nlA6pw@public.gmane.org>
@ 2010-05-17  4:14                 ` Paul L
       [not found]                   ` <AANLkTimfmJU5h4pS23eKpjLNV_c6d4YEBHNmBdcy-r4g-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
  0 siblings, 1 reply; 12+ messages in thread
From: Paul L @ 2010-05-17  4:14 UTC (permalink / raw)
  To: Ryusuke Konishi; +Cc: linux-nilfs-u79uwXL29TY76Z2rM5mHXA

Wow, that does the trick! Here is the output after I change the number to 500.

Super-block:
    revision = 2.0
    blocksize = 4096
    write time = 2010-05-14 13:58:33
    indicated log: blocknr = 1608334
        segnum = 785, seq = 307637, cno=671100

Clean FS.
The latest log is lost. Trying rollback recovery..
...................
Searching the latest checkpoint.
Selected log: blocknr = 1304576
    segnum = 637, seq = 307489, cno=670854
    creation time = 2010-05-14 09:48:18
Do you wish to overwrite super block (y/N)? y
Recovery will complete on mount.

I then mount /home, and things seem to work fine! Can I be sure that
everything will be ok from now on? Or should I backup and reformat?
Thanks!

Actually, I now wonder what could have gone wrong in my case. I wasn't
doing any disk intensive task and the machine wasn't suspended to ram
during the course.

On a separate note, I noticed that Nilfs2 has a higher chance of
corruption when I mount over (a slightly sluggish) network. My backup
plan is also using Nilfs2, as detailed in this web page:

  http://www.thev.net/PaulLiu/backup-plan.html

I rarely had any problem doing it over a USB hard drive, but when I
remotely mount the backup image from a SMBFS over the network, I ran
into problems of dangling nilfs_cleanerd, or just simply corrupted
Nilfs2 partition for quite a few times, till the point that I reverted
back to a local USB drive. Maybe this kind of use case can help you
guys debugging the code and make it more robust. Just a wishful
thought!

Regards,
Paul Liu

On Sun, May 16, 2010 at 10:46 PM, Ryusuke Konishi <ryusuke-sG5X7nlA6pw@public.gmane.org> wrote:
> Hi,
> On Sun, 16 May 2010 14:32:05 -0400, Paul L wrote:
>> Sorry, should have sent it to the list instead.
>>
>>  Thanks for the patch! I tried it, but seems it still can't find the
>>  super root. Here is the output. What shall I do now?
>>
>>  Super-block:
>>      revision = 2.0
>>      blocksize = 4096
>>      write time = 2010-05-14 13:58:33
>>      indicated log: blocknr = 1608334
>>          segnum = 785, seq = 307637, cno=671100
>>
>>  Clean FS.
>>  The latest log is lost. Trying rollback recovery..
>>  .......
>>  fsck0.nilfs2: Cannot find super root
>
> Can you try increasing the number defined at the following line in
> sbin/fsck/fsck0.nilfs2.c ?
>
>  #define  MAX_SCAN_SEGMENT          50
>
> Regards,
> Ryusuke Konishi
>
>> > On 5/15/10, Ryusuke Konishi <ryusuke-sG5X7nlA6pw@public.gmane.org> wrote:
>> >> Hi,
>> >> On Fri, 14 May 2010 20:24:02 -0400, Paul L wrote:
>> >>> I have my home directory mounted as a nilfs2 partition. Today what
>> >>> happened was that first I noticed google-chrome reporting it cannot
>> >>> load user profile, I initially thought it was a google-chrome error.
>> >>> At the time I was still able to view and modify my home directory. But
>> >>> then after rebooting the system, my home partition no longer mounts.
>> >>> I'm using nilfs-2.0.19 and nilfs-utils-2.0.18 with Linux kernel
>> >>> 2.6.28.
>> >>>
>> >>> Here is the error message from dmesg (after turning on debugging
>> >>> message for nilfs2):
>> >>>
>> >>> NILFS nilfs_fill_super: start(silent=0)
>> >>> NILFS(recovery) nilfs_search_super_root: looking segment
>> >>> (seg_start=1607680, seg_end=1609727, segnum=785, seg_seq=307637)
>> >>> NILFS(recovery) load_segment_summary: checking segment
>> >>> (pseg_start=1608334, full_check=0)
>> >>> NILFS(recovery) load_segment_summary: done (ret=3)
>> >>> NILFS(recovery) nilfs_search_super_root: strayed: scan_newer=0, ret=3
>> >>> NILFS warning: Segment magic number invalid
>> >>> NILFS: error searching super root.
>> >>> NILFS nilfs_fill_super: aborted
>> >>> NILFS put_nilfs: the_nilfs on bdev mmcblk0p1 was freed
>> >>>
>> >>> I then dumped the first and last (backup) copy of the nilfs2 super
>> >>> block, they are identical, and given below:
>> >>>
>> >>> 00000400   02 00 00 00 00 00 34 34  00 01 00 00 A1 6A E9 71
>> >>> ......44.....j.q
>> >>> 00000410   A3 F1 DD BE 02 00 00 00  AF 07 00 00 00 00 00 00
>> >>> ................
>> >>> 00000420   00 E0 BF D7 03 00 00 00  01 00 00 00 00 00 00 00
>> >>> ................
>> >>> 00000430   00 08 00 00 05 00 00 00  7C 3D 0A 00 00 00 00 00
>> >>> ........|=......
>> >>> 00000440   8E 8A 18 00 00 00 00 00  B5 B1 04 00 00 00 00 00
>> >>> ................
>> >>> 00000450   00 B8 23 00 00 00 00 00  B9 AF F3 4A 00 00 00 00
>> >>> ..#........J....
>> >>> 00000460   D9 E1 D6 4B 00 00 00 00  49 8F ED 4B 00 00 00 00
>> >>> ...K....I..K....
>> >>> 00000470   37 00 32 00 03 00 01 00  B9 AF F3 4A 00 00 00 00
>> >>> 7.2........J....elp
>> >>> 00000480   00 4E ED 00 00 00 00 00  00 00 00 00 0B 00 00 00
>> >>> .N..............
>> >>> 00000490   80 00 20 00 C0 00 10 00  13 1C FC 11 D7 43 4C 09  ..
>> >>> ..........CL.
>> >>> 000004A0   81 64 93 0A F4 54 CF 5E  48 4F 4D 45 00 00 00 00
>> >>> .d...T.^HOME....
>> >>>
>> >>>
>> >>> I wonder if there is a fsck tool to help me recover the file system.
>> >>> Any help is greatly appreciated!
>> >>>
>> >>> PS: last time I had a different problem of losing partition info, and
>> >>> later successfully recovered with the help from people on the list. So
>> >>> thanks! Now I'm actually backing up my files every two weeks, but
>> >>> it'll still be great if it can recover and even better if we can trace
>> >>> the problem.
>> >>
>> >> Your filesystem seems to have lost the latest log according to the
>> >> report.
>> >>
>> >> The attached patch may help to recover it.  It is revised scan tool
>> >> for nilfs-utils-2.0.18.
>> >>
>> >> After compiling the tool, you can use it like:
>> >>
>> >>  # cd nilfs-utils-2.0.18
>> >>  # sbin/fsck/fsck0 <device>
>> >>
>> >> The tool will confirm whether to update super blocks if it finds the
>> >> latest log.
>> >>
>> >> You may need to do
>> >>
>> >>  $ aclocal && autoheader && libtoolize -c --foce && automake -a -c &&
>> >> autoconf
>> >>  $ ./configure
>> >>
>> >> before build the tool.
>> >>
>> >> With regards,
>> >> Ryusuke Konishi
>> >>
>> >
>> >
>> > --
>> > Regards,
>> > Paul Liu
>> >
>> > Yale Haskell Group
>> > http://www.haskell.org/yale
>> >
>>
>>
>> --
>> Regards,
>> Paul Liu
>>
>> Yale Haskell Group
>> http://www.haskell.org/yale
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-nilfs" in
>> the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>



-- 
Regards,
Paul Liu

Yale Haskell Group
http://www.haskell.org/yale
--
To unsubscribe from this list: send the line "unsubscribe linux-nilfs" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Segment magic number invalid
       [not found]                   ` <AANLkTimfmJU5h4pS23eKpjLNV_c6d4YEBHNmBdcy-r4g-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
@ 2010-05-17  7:26                     ` Ryusuke Konishi
       [not found]                       ` <20100517.162614.107743625.ryusuke-sG5X7nlA6pw@public.gmane.org>
  0 siblings, 1 reply; 12+ messages in thread
From: Ryusuke Konishi @ 2010-05-17  7:26 UTC (permalink / raw)
  To: ninegua-Re5JQEeQqe8AvxtiuMwx3w; +Cc: linux-nilfs-u79uwXL29TY76Z2rM5mHXA

Hi,
On Mon, 17 May 2010 00:14:59 -0400, Paul L wrote:
> Wow, that does the trick! Here is the output after I change the number to 500.
> 
> Super-block:
>     revision = 2.0
>     blocksize = 4096
>     write time = 2010-05-14 13:58:33
>     indicated log: blocknr = 1608334
>         segnum = 785, seq = 307637, cno=671100
> 
> Clean FS.
> The latest log is lost. Trying rollback recovery..
> ...................
> Searching the latest checkpoint.
> Selected log: blocknr = 1304576
>     segnum = 637, seq = 307489, cno=670854
>     creation time = 2010-05-14 09:48:18
> Do you wish to overwrite super block (y/N)? y
> Recovery will complete on mount.
> 
> I then mount /home, and things seem to work fine! Can I be sure that
> everything will be ok from now on? Or should I backup and reformat?
> Thanks!

That was good! 

I recommend you to backup just now and reformat the partition since
the recovered filesystem rewound logs and may contain broken blocks
that GC later overrode.  (If you were suspending GC, the filesystem is
guranteed to be consistent.)

It may be clean, but the fsck tool doesn't yet support sanity check.

> Actually, I now wonder what could have gone wrong in my case. I wasn't
> doing any disk intensive task and the machine wasn't suspended to ram
> during the course.

This problem can happen if the block device doesn't support "write
barrier" properly.  Unfortunately, such devices are not uncommon even
now.

I feel we should do something for it.

> On a separate note, I noticed that Nilfs2 has a higher chance of
> corruption when I mount over (a slightly sluggish) network. My backup
> plan is also using Nilfs2, as detailed in this web page:
> 
>   http://www.thev.net/PaulLiu/backup-plan.html
> 
> I rarely had any problem doing it over a USB hard drive, but when I
> remotely mount the backup image from a SMBFS over the network, I ran
> into problems of dangling nilfs_cleanerd, or just simply corrupted
> Nilfs2 partition for quite a few times, till the point that I reverted
> back to a local USB drive. Maybe this kind of use case can help you
> guys debugging the code and make it more robust. Just a wishful
> thought!

Thanks for the information.  Looks helpful for debugging.

Thanks,
Ryusuke Konishi

> On Sun, May 16, 2010 at 10:46 PM, Ryusuke Konishi <ryusuke-sG5X7nlA6pw@public.gmane.org> wrote:
> > Hi,
> > On Sun, 16 May 2010 14:32:05 -0400, Paul L wrote:
> >> Sorry, should have sent it to the list instead.
> >>
> >>  Thanks for the patch! I tried it, but seems it still can't find the
> >>  super root. Here is the output. What shall I do now?
> >>
> >>  Super-block:
> >>      revision = 2.0
> >>      blocksize = 4096
> >>      write time = 2010-05-14 13:58:33
> >>      indicated log: blocknr = 1608334
> >>          segnum = 785, seq = 307637, cno=671100
> >>
> >>  Clean FS.
> >>  The latest log is lost. Trying rollback recovery..
> >>  .......
> >>  fsck0.nilfs2: Cannot find super root
> >
> > Can you try increasing the number defined at the following line in
> > sbin/fsck/fsck0.nilfs2.c ?
> >
> >  #define  MAX_SCAN_SEGMENT          50
> >
> > Regards,
> > Ryusuke Konishi
> >
> >> > On 5/15/10, Ryusuke Konishi <ryusuke-sG5X7nlA6pw@public.gmane.org> wrote:
> >> >> Hi,
> >> >> On Fri, 14 May 2010 20:24:02 -0400, Paul L wrote:
> >> >>> I have my home directory mounted as a nilfs2 partition. Today what
> >> >>> happened was that first I noticed google-chrome reporting it cannot
> >> >>> load user profile, I initially thought it was a google-chrome error.
> >> >>> At the time I was still able to view and modify my home directory. But
> >> >>> then after rebooting the system, my home partition no longer mounts.
> >> >>> I'm using nilfs-2.0.19 and nilfs-utils-2.0.18 with Linux kernel
> >> >>> 2.6.28.
> >> >>>
> >> >>> Here is the error message from dmesg (after turning on debugging
> >> >>> message for nilfs2):
> >> >>>
> >> >>> NILFS nilfs_fill_super: start(silent=0)
> >> >>> NILFS(recovery) nilfs_search_super_root: looking segment
> >> >>> (seg_start=1607680, seg_end=1609727, segnum=785, seg_seq=307637)
> >> >>> NILFS(recovery) load_segment_summary: checking segment
> >> >>> (pseg_start=1608334, full_check=0)
> >> >>> NILFS(recovery) load_segment_summary: done (ret=3)
> >> >>> NILFS(recovery) nilfs_search_super_root: strayed: scan_newer=0, ret=3
> >> >>> NILFS warning: Segment magic number invalid
> >> >>> NILFS: error searching super root.
> >> >>> NILFS nilfs_fill_super: aborted
> >> >>> NILFS put_nilfs: the_nilfs on bdev mmcblk0p1 was freed
> >> >>>
> >> >>> I then dumped the first and last (backup) copy of the nilfs2 super
> >> >>> block, they are identical, and given below:
> >> >>>
> >> >>> 00000400   02 00 00 00 00 00 34 34  00 01 00 00 A1 6A E9 71
> >> >>> ......44.....j.q
> >> >>> 00000410   A3 F1 DD BE 02 00 00 00  AF 07 00 00 00 00 00 00
> >> >>> ................
> >> >>> 00000420   00 E0 BF D7 03 00 00 00  01 00 00 00 00 00 00 00
> >> >>> ................
> >> >>> 00000430   00 08 00 00 05 00 00 00  7C 3D 0A 00 00 00 00 00
> >> >>> ........|=......
> >> >>> 00000440   8E 8A 18 00 00 00 00 00  B5 B1 04 00 00 00 00 00
> >> >>> ................
> >> >>> 00000450   00 B8 23 00 00 00 00 00  B9 AF F3 4A 00 00 00 00
> >> >>> ..#........J....
> >> >>> 00000460   D9 E1 D6 4B 00 00 00 00  49 8F ED 4B 00 00 00 00
> >> >>> ...K....I..K....
> >> >>> 00000470   37 00 32 00 03 00 01 00  B9 AF F3 4A 00 00 00 00
> >> >>> 7.2........J....elp
> >> >>> 00000480   00 4E ED 00 00 00 00 00  00 00 00 00 0B 00 00 00
> >> >>> .N..............
> >> >>> 00000490   80 00 20 00 C0 00 10 00  13 1C FC 11 D7 43 4C 09  ..
> >> >>> ..........CL.
> >> >>> 000004A0   81 64 93 0A F4 54 CF 5E  48 4F 4D 45 00 00 00 00
> >> >>> .d...T.^HOME....
> >> >>>
> >> >>>
> >> >>> I wonder if there is a fsck tool to help me recover the file system.
> >> >>> Any help is greatly appreciated!
> >> >>>
> >> >>> PS: last time I had a different problem of losing partition info, and
> >> >>> later successfully recovered with the help from people on the list. So
> >> >>> thanks! Now I'm actually backing up my files every two weeks, but
> >> >>> it'll still be great if it can recover and even better if we can trace
> >> >>> the problem.
> >> >>
> >> >> Your filesystem seems to have lost the latest log according to the
> >> >> report.
> >> >>
> >> >> The attached patch may help to recover it.  It is revised scan tool
> >> >> for nilfs-utils-2.0.18.
> >> >>
> >> >> After compiling the tool, you can use it like:
> >> >>
> >> >>  # cd nilfs-utils-2.0.18
> >> >>  # sbin/fsck/fsck0 <device>
> >> >>
> >> >> The tool will confirm whether to update super blocks if it finds the
> >> >> latest log.
> >> >>
> >> >> You may need to do
> >> >>
> >> >>  $ aclocal && autoheader && libtoolize -c --foce && automake -a -c &&
> >> >> autoconf
> >> >>  $ ./configure
> >> >>
> >> >> before build the tool.
> >> >>
> >> >> With regards,
> >> >> Ryusuke Konishi
> >> >>
> >> >
> >> >
> >> > --
> >> > Regards,
> >> > Paul Liu
> >> >
> >> > Yale Haskell Group
> >> > http://www.haskell.org/yale
> >> >
> >>
> >>
> >> --
> >> Regards,
> >> Paul Liu
> >>
> >> Yale Haskell Group
> >> http://www.haskell.org/yale
> >> --
> >> To unsubscribe from this list: send the line "unsubscribe linux-nilfs" in
> >> the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> >> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> >
> 
> 
> 
> -- 
> Regards,
> Paul Liu
> 
> Yale Haskell Group
> http://www.haskell.org/yale
--
To unsubscribe from this list: send the line "unsubscribe linux-nilfs" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Segment magic number invalid
       [not found]                       ` <20100517.162614.107743625.ryusuke-sG5X7nlA6pw@public.gmane.org>
@ 2010-05-19 13:49                         ` Jiro SEKIBA
       [not found]                           ` <871vd8dms5.wl%jir-27yqGEOhnJbQT0dZR+AlfA@public.gmane.org>
  0 siblings, 1 reply; 12+ messages in thread
From: Jiro SEKIBA @ 2010-05-19 13:49 UTC (permalink / raw)
  To: Ryusuke Konishi
  Cc: ninegua-Re5JQEeQqe8AvxtiuMwx3w,
	linux-nilfs-u79uwXL29TY76Z2rM5mHXA

Hi,

At Mon, 17 May 2010 16:26:14 +0900 (JST),
Ryusuke Konishi wrote:
> 
> Hi,
> On Mon, 17 May 2010 00:14:59 -0400, Paul L wrote:
> > Wow, that does the trick! Here is the output after I change the number to 500.
> > 
> > Super-block:
> >     revision = 2.0
> >     blocksize = 4096
> >     write time = 2010-05-14 13:58:33
> >     indicated log: blocknr = 1608334
> >         segnum = 785, seq = 307637, cno=671100
> > 
> > Clean FS.
> > The latest log is lost. Trying rollback recovery..
> > ...................
> > Searching the latest checkpoint.
> > Selected log: blocknr = 1304576
> >     segnum = 637, seq = 307489, cno=670854
> >     creation time = 2010-05-14 09:48:18
> > Do you wish to overwrite super block (y/N)? y
> > Recovery will complete on mount.
> > 
> > I then mount /home, and things seem to work fine! Can I be sure that
> > everything will be ok from now on? Or should I backup and reformat?
> > Thanks!
> 
> That was good! 
> 
> I recommend you to backup just now and reformat the partition since
> the recovered filesystem rewound logs and may contain broken blocks
> that GC later overrode.  (If you were suspending GC, the filesystem is
> guranteed to be consistent.)
> 
> It may be clean, but the fsck tool doesn't yet support sanity check.
> 
> > Actually, I now wonder what could have gone wrong in my case. I wasn't
> > doing any disk intensive task and the machine wasn't suspended to ram
> > during the course.
> 
> This problem can happen if the block device doesn't support "write
> barrier" properly.  Unfortunately, such devices are not uncommon even
> now.
> 
> I feel we should do something for it.

How abou updating one of super blocks when super block update needed?

I'm hoping that even "write barrier" is not supported, back up super block
likely points valid older log.

In case latest super block, which has greater CP, points invalid log,
try to search log from the other super block that has older log and
roll forwad the log until it finds newer super root.

Futher more, because each super block is less frequently updated,
it may address low-end consumer flash super block hot-spot issue.

thanks,

regards

> > On a separate note, I noticed that Nilfs2 has a higher chance of
> > corruption when I mount over (a slightly sluggish) network. My backup
> > plan is also using Nilfs2, as detailed in this web page:
> > 
> >   http://www.thev.net/PaulLiu/backup-plan.html
> > 
> > I rarely had any problem doing it over a USB hard drive, but when I
> > remotely mount the backup image from a SMBFS over the network, I ran
> > into problems of dangling nilfs_cleanerd, or just simply corrupted
> > Nilfs2 partition for quite a few times, till the point that I reverted
> > back to a local USB drive. Maybe this kind of use case can help you
> > guys debugging the code and make it more robust. Just a wishful
> > thought!
> 
> Thanks for the information.  Looks helpful for debugging.
> 
> Thanks,
> Ryusuke Konishi
> 
> > On Sun, May 16, 2010 at 10:46 PM, Ryusuke Konishi <ryusuke-sG5X7nlA6pw@public.gmane.org> wrote:
> > > Hi,
> > > On Sun, 16 May 2010 14:32:05 -0400, Paul L wrote:
> > >> Sorry, should have sent it to the list instead.
> > >>
> > >>  Thanks for the patch! I tried it, but seems it still can't find the
> > >>  super root. Here is the output. What shall I do now?
> > >>
> > >>  Super-block:
> > >>      revision = 2.0
> > >>      blocksize = 4096
> > >>      write time = 2010-05-14 13:58:33
> > >>      indicated log: blocknr = 1608334
> > >>          segnum = 785, seq = 307637, cno=671100
> > >>
> > >>  Clean FS.
> > >>  The latest log is lost. Trying rollback recovery..
> > >>  .......
> > >>  fsck0.nilfs2: Cannot find super root
> > >
> > > Can you try increasing the number defined at the following line in
> > > sbin/fsck/fsck0.nilfs2.c ?
> > >
> > >  #define  MAX_SCAN_SEGMENT          50
> > >
> > > Regards,
> > > Ryusuke Konishi
> > >
> > >> > On 5/15/10, Ryusuke Konishi <ryusuke-sG5X7nlA6pw@public.gmane.org> wrote:
> > >> >> Hi,
> > >> >> On Fri, 14 May 2010 20:24:02 -0400, Paul L wrote:
> > >> >>> I have my home directory mounted as a nilfs2 partition. Today what
> > >> >>> happened was that first I noticed google-chrome reporting it cannot
> > >> >>> load user profile, I initially thought it was a google-chrome error.
> > >> >>> At the time I was still able to view and modify my home directory. But
> > >> >>> then after rebooting the system, my home partition no longer mounts.
> > >> >>> I'm using nilfs-2.0.19 and nilfs-utils-2.0.18 with Linux kernel
> > >> >>> 2.6.28.
> > >> >>>
> > >> >>> Here is the error message from dmesg (after turning on debugging
> > >> >>> message for nilfs2):
> > >> >>>
> > >> >>> NILFS nilfs_fill_super: start(silent=0)
> > >> >>> NILFS(recovery) nilfs_search_super_root: looking segment
> > >> >>> (seg_start=1607680, seg_end=1609727, segnum=785, seg_seq=307637)
> > >> >>> NILFS(recovery) load_segment_summary: checking segment
> > >> >>> (pseg_start=1608334, full_check=0)
> > >> >>> NILFS(recovery) load_segment_summary: done (ret=3)
> > >> >>> NILFS(recovery) nilfs_search_super_root: strayed: scan_newer=0, ret=3
> > >> >>> NILFS warning: Segment magic number invalid
> > >> >>> NILFS: error searching super root.
> > >> >>> NILFS nilfs_fill_super: aborted
> > >> >>> NILFS put_nilfs: the_nilfs on bdev mmcblk0p1 was freed
> > >> >>>
> > >> >>> I then dumped the first and last (backup) copy of the nilfs2 super
> > >> >>> block, they are identical, and given below:
> > >> >>>
> > >> >>> 00000400   02 00 00 00 00 00 34 34  00 01 00 00 A1 6A E9 71
> > >> >>> ......44.....j.q
> > >> >>> 00000410   A3 F1 DD BE 02 00 00 00  AF 07 00 00 00 00 00 00
> > >> >>> ................
> > >> >>> 00000420   00 E0 BF D7 03 00 00 00  01 00 00 00 00 00 00 00
> > >> >>> ................
> > >> >>> 00000430   00 08 00 00 05 00 00 00  7C 3D 0A 00 00 00 00 00
> > >> >>> ........|=......
> > >> >>> 00000440   8E 8A 18 00 00 00 00 00  B5 B1 04 00 00 00 00 00
> > >> >>> ................
> > >> >>> 00000450   00 B8 23 00 00 00 00 00  B9 AF F3 4A 00 00 00 00
> > >> >>> ..#........J....
> > >> >>> 00000460   D9 E1 D6 4B 00 00 00 00  49 8F ED 4B 00 00 00 00
> > >> >>> ...K....I..K....
> > >> >>> 00000470   37 00 32 00 03 00 01 00  B9 AF F3 4A 00 00 00 00
> > >> >>> 7.2........J....elp
> > >> >>> 00000480   00 4E ED 00 00 00 00 00  00 00 00 00 0B 00 00 00
> > >> >>> .N..............
> > >> >>> 00000490   80 00 20 00 C0 00 10 00  13 1C FC 11 D7 43 4C 09  ..
> > >> >>> ..........CL.
> > >> >>> 000004A0   81 64 93 0A F4 54 CF 5E  48 4F 4D 45 00 00 00 00
> > >> >>> .d...T.^HOME....
> > >> >>>
> > >> >>>
> > >> >>> I wonder if there is a fsck tool to help me recover the file system.
> > >> >>> Any help is greatly appreciated!
> > >> >>>
> > >> >>> PS: last time I had a different problem of losing partition info, and
> > >> >>> later successfully recovered with the help from people on the list. So
> > >> >>> thanks! Now I'm actually backing up my files every two weeks, but
> > >> >>> it'll still be great if it can recover and even better if we can trace
> > >> >>> the problem.
> > >> >>
> > >> >> Your filesystem seems to have lost the latest log according to the
> > >> >> report.
> > >> >>
> > >> >> The attached patch may help to recover it.  It is revised scan tool
> > >> >> for nilfs-utils-2.0.18.
> > >> >>
> > >> >> After compiling the tool, you can use it like:
> > >> >>
> > >> >>  # cd nilfs-utils-2.0.18
> > >> >>  # sbin/fsck/fsck0 <device>
> > >> >>
> > >> >> The tool will confirm whether to update super blocks if it finds the
> > >> >> latest log.
> > >> >>
> > >> >> You may need to do
> > >> >>
> > >> >>  $ aclocal && autoheader && libtoolize -c --foce && automake -a -c &&
> > >> >> autoconf
> > >> >>  $ ./configure
> > >> >>
> > >> >> before build the tool.
> > >> >>
> > >> >> With regards,
> > >> >> Ryusuke Konishi
> > >> >>
> > >> >
> > >> >
> > >> > --
> > >> > Regards,
> > >> > Paul Liu
> > >> >
> > >> > Yale Haskell Group
> > >> > http://www.haskell.org/yale
> > >> >
> > >>
> > >>
> > >> --
> > >> Regards,
> > >> Paul Liu
> > >>
> > >> Yale Haskell Group
> > >> http://www.haskell.org/yale
> > >> --
> > >> To unsubscribe from this list: send the line "unsubscribe linux-nilfs" in
> > >> the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> > >> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> > >
> > 
> > 
> > 
> > -- 
> > Regards,
> > Paul Liu
> > 
> > Yale Haskell Group
> > http://www.haskell.org/yale
> --
> To unsubscribe from this list: send the line "unsubscribe linux-nilfs" in
> the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 
> 
> 




-- 
Jiro SEKIBA <jir-hfpbi5WX9J54Eiagz67IpQ@public.gmane.org>
--
To unsubscribe from this list: send the line "unsubscribe linux-nilfs" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Segment magic number invalid
       [not found]                           ` <871vd8dms5.wl%jir-27yqGEOhnJbQT0dZR+AlfA@public.gmane.org>
@ 2010-05-19 16:14                             ` Ryusuke Konishi
       [not found]                               ` <20100520.011455.32954390.ryusuke-sG5X7nlA6pw@public.gmane.org>
  0 siblings, 1 reply; 12+ messages in thread
From: Ryusuke Konishi @ 2010-05-19 16:14 UTC (permalink / raw)
  To: jir-hfpbi5WX9J54Eiagz67IpQ
  Cc: ninegua-Re5JQEeQqe8AvxtiuMwx3w,
	linux-nilfs-u79uwXL29TY76Z2rM5mHXA

On Wed, 19 May 2010 22:49:30 +0900, Jiro SEKIBA wrote:
> > > Actually, I now wonder what could have gone wrong in my case. I wasn't
> > > doing any disk intensive task and the machine wasn't suspended to ram
> > > during the course.
> > 
> > This problem can happen if the block device doesn't support "write
> > barrier" properly.  Unfortunately, such devices are not uncommon even
> > now.
> > 
> > I feel we should do something for it.
> 
> How abou updating one of super blocks when super block update needed?
> 
> I'm hoping that even "write barrier" is not supported, back up super block
> likely points valid older log.
> 
> In case latest super block, which has greater CP, points invalid log,
> try to search log from the other super block that has older log and
> roll forwad the log until it finds newer super root.
> 
> Futher more, because each super block is less frequently updated,
> it may address low-end consumer flash super block hot-spot issue.

Seems a nice solution.

And it looks feasible now since the patch titled "nilfs2: use
checkpoint number instead of timestamp to select super block" made it
easy.

The secondary super block is written to disk along with the primary
one, but less frequently.  So it can be implemented by changing spec
of the dupsb argument of nilfs_commit_super to "other one" from "both
(dupsb)".

Can you make draft patches?

Thanks,
Ryusuke Konishi
--
To unsubscribe from this list: send the line "unsubscribe linux-nilfs" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH] nilfs2: sync super blokcs in turns
       [not found]                               ` <20100520.011455.32954390.ryusuke-sG5X7nlA6pw@public.gmane.org>
@ 2010-05-27  7:27                                 ` Jiro SEKIBA
       [not found]                                   ` <87r5kx6bz9.wl%jir-27yqGEOhnJbQT0dZR+AlfA@public.gmane.org>
  0 siblings, 1 reply; 12+ messages in thread
From: Jiro SEKIBA @ 2010-05-27  7:27 UTC (permalink / raw)
  To: Ryusuke Konishi
  Cc: ninegua-Re5JQEeQqe8AvxtiuMwx3w,
	linux-nilfs-u79uwXL29TY76Z2rM5mHXA

Hi,

This is a proposed patch to sync super blocks by turn.
It still require recovery action when super root is not found,
but it works at least to mount with valid fs with the patch:

 nilfs2: use checkpoint number instead of timestamp to select super block
 9f6c75b4c354939f0a8aefc19eb6a9334ef58a89

This will sync super blocks by turn instead of syncing duplicate
super blocks at the time.  This will help searching valid super root when
super block is written into disk before log is written, which is happen when
barrier-less block devices are unmounted uncleanly.
In the stiation, old super block likely points valid log.

Signed-off-by: Jiro SEKIBA <jir-hfpbi5WX9J54Eiagz67IpQ@public.gmane.org>
---
 fs/nilfs2/nilfs.h     |    2 +-
 fs/nilfs2/segment.c   |    3 +--
 fs/nilfs2/super.c     |   32 ++++++++++++++++----------------
 fs/nilfs2/the_nilfs.c |    2 +-
 4 files changed, 19 insertions(+), 20 deletions(-)

diff --git a/fs/nilfs2/nilfs.h b/fs/nilfs2/nilfs.h
index 8723e5b..ec644c5 100644
--- a/fs/nilfs2/nilfs.h
+++ b/fs/nilfs2/nilfs.h
@@ -270,7 +270,7 @@ extern struct nilfs_super_block *
 nilfs_read_super_block(struct super_block *, u64, int, struct buffer_head **);
 extern int nilfs_store_magic_and_option(struct super_block *,
 					struct nilfs_super_block *, char *);
-extern int nilfs_commit_super(struct nilfs_sb_info *, int);
+extern int nilfs_commit_super(struct nilfs_sb_info *);
 extern int nilfs_attach_checkpoint(struct nilfs_sb_info *, __u64);
 extern void nilfs_detach_checkpoint(struct nilfs_sb_info *);
 
diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c
index 6a7dbd8..b48de1f 100644
--- a/fs/nilfs2/segment.c
+++ b/fs/nilfs2/segment.c
@@ -2490,8 +2490,7 @@ static int nilfs_segctor_construct(struct nilfs_sc_info *sci, int mode)
 		if (test_bit(NILFS_SC_SUPER_ROOT, &sci->sc_flags) &&
 		    nilfs_discontinued(nilfs)) {
 			down_write(&nilfs->ns_sem);
-			err = nilfs_commit_super(
-				sbi, nilfs_altsb_need_update(nilfs));
+			err = nilfs_commit_super(sbi);
 			up_write(&nilfs->ns_sem);
 		}
 	}
diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c
index 48145f5..4894e07 100644
--- a/fs/nilfs2/super.c
+++ b/fs/nilfs2/super.c
@@ -101,7 +101,7 @@ void nilfs_error(struct super_block *sb, const char *function,
 			nilfs->ns_mount_state |= NILFS_ERROR_FS;
 			nilfs->ns_sbp[0]->s_state |=
 				cpu_to_le16(NILFS_ERROR_FS);
-			nilfs_commit_super(sbi, 1);
+			nilfs_commit_super(sbi);
 		}
 		up_write(&nilfs->ns_sem);
 
@@ -200,7 +200,7 @@ static void nilfs_clear_inode(struct inode *inode)
 	nilfs_btnode_cache_clear(&ii->i_btnode_cache);
 }
 
-static int nilfs_sync_super(struct nilfs_sb_info *sbi, int dupsb)
+static int nilfs_sync_super(struct nilfs_sb_info *sbi)
 {
 	struct the_nilfs *nilfs = sbi->s_nilfs;
 	int err;
@@ -226,6 +226,9 @@ static int nilfs_sync_super(struct nilfs_sb_info *sbi, int dupsb)
 		printk(KERN_ERR
 		       "NILFS: unable to write superblock (err=%d)\n", err);
 		if (err == -EIO && nilfs->ns_sbh[1]) {
+			memcpy(nilfs->ns_sbp[1], nilfs->ns_sbp[0],
+			       nilfs->ns_sbsize);
+			nilfs->ns_sbwtime[1] = nilfs->ns_sbwtime[0];
 			nilfs_fall_back_super_block(nilfs);
 			goto retry;
 		}
@@ -240,11 +243,12 @@ static int nilfs_sync_super(struct nilfs_sb_info *sbi, int dupsb)
 
 		/* update GC protection for recent segments */
 		if (nilfs->ns_sbh[1]) {
+			int flip_bits = (nilfs->ns_cno & 0x0FL);
 			sbp = NULL;
-			if (dupsb) {
-				set_buffer_dirty(nilfs->ns_sbh[1]);
-				if (!sync_dirty_buffer(nilfs->ns_sbh[1]))
-					sbp = nilfs->ns_sbp[1];
+			/* flip super block 9 to 7 ratio */
+			if ((flip_bits == 0x08) || flip_bits == 0x0F) {
+				sbp = nilfs->ns_sbp[1];
+				nilfs_swap_super_block(nilfs);
 			}
 		}
 		if (sbp) {
@@ -257,7 +261,7 @@ static int nilfs_sync_super(struct nilfs_sb_info *sbi, int dupsb)
 	return err;
 }
 
-int nilfs_commit_super(struct nilfs_sb_info *sbi, int dupsb)
+int nilfs_commit_super(struct nilfs_sb_info *sbi)
 {
 	struct the_nilfs *nilfs = sbi->s_nilfs;
 	struct nilfs_super_block **sbp = nilfs->ns_sbp;
@@ -294,12 +298,8 @@ int nilfs_commit_super(struct nilfs_sb_info *sbi, int dupsb)
 	sbp[0]->s_sum = cpu_to_le32(crc32_le(nilfs->ns_crc_seed,
 					     (unsigned char *)sbp[0],
 					     nilfs->ns_sbsize));
-	if (dupsb && sbp[1]) {
-		memcpy(sbp[1], sbp[0], nilfs->ns_sbsize);
-		nilfs->ns_sbwtime[1] = t;
-	}
 	clear_nilfs_sb_dirty(nilfs);
-	return nilfs_sync_super(sbi, dupsb);
+	return nilfs_sync_super(sbi);
 }
 
 static void nilfs_put_super(struct super_block *sb)
@@ -314,7 +314,7 @@ static void nilfs_put_super(struct super_block *sb)
 	if (!(sb->s_flags & MS_RDONLY)) {
 		down_write(&nilfs->ns_sem);
 		nilfs->ns_sbp[0]->s_state = cpu_to_le16(nilfs->ns_mount_state);
-		nilfs_commit_super(sbi, 1);
+		nilfs_commit_super(sbi);
 		up_write(&nilfs->ns_sem);
 	}
 	down_write(&nilfs->ns_super_sem);
@@ -343,7 +343,7 @@ static int nilfs_sync_fs(struct super_block *sb, int wait)
 
 	down_write(&nilfs->ns_sem);
 	if (nilfs_sb_dirty(nilfs))
-		nilfs_commit_super(sbi, 1);
+		nilfs_commit_super(sbi);
 	up_write(&nilfs->ns_sem);
 
 	return err;
@@ -657,7 +657,7 @@ static int nilfs_setup_super(struct nilfs_sb_info *sbi)
 	sbp->s_mnt_count = cpu_to_le16(mnt_count + 1);
 	sbp->s_state = cpu_to_le16(le16_to_cpu(sbp->s_state) & ~NILFS_VALID_FS);
 	sbp->s_mtime = cpu_to_le64(get_seconds());
-	return nilfs_commit_super(sbi, 1);
+	return nilfs_commit_super(sbi);
 }
 
 struct nilfs_super_block *nilfs_read_super_block(struct super_block *sb,
@@ -901,7 +901,7 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data)
 		    (nilfs->ns_mount_state & NILFS_VALID_FS))
 			sbp->s_state = cpu_to_le16(nilfs->ns_mount_state);
 		sbp->s_mtime = cpu_to_le64(get_seconds());
-		nilfs_commit_super(sbi, 1);
+		nilfs_commit_super(sbi);
 		up_write(&nilfs->ns_sem);
 	} else {
 		/*
diff --git a/fs/nilfs2/the_nilfs.c b/fs/nilfs2/the_nilfs.c
index a756168..f779363 100644
--- a/fs/nilfs2/the_nilfs.c
+++ b/fs/nilfs2/the_nilfs.c
@@ -327,7 +327,7 @@ int load_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi)
 	down_write(&nilfs->ns_sem);
 	nilfs->ns_mount_state |= NILFS_VALID_FS;
 	nilfs->ns_sbp[0]->s_state = cpu_to_le16(nilfs->ns_mount_state);
-	err = nilfs_commit_super(sbi, 1);
+	err = nilfs_commit_super(sbi);
 	up_write(&nilfs->ns_sem);
 
 	if (err) {
-- 
1.5.6.5

--
To unsubscribe from this list: send the line "unsubscribe linux-nilfs" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [PATCH] nilfs2: sync super blokcs in turns
       [not found]                                   ` <87r5kx6bz9.wl%jir-27yqGEOhnJbQT0dZR+AlfA@public.gmane.org>
@ 2010-05-27 16:59                                     ` Ryusuke Konishi
       [not found]                                       ` <20100528.015959.179492440.ryusuke-sG5X7nlA6pw@public.gmane.org>
  0 siblings, 1 reply; 12+ messages in thread
From: Ryusuke Konishi @ 2010-05-27 16:59 UTC (permalink / raw)
  To: jir-hfpbi5WX9J54Eiagz67IpQ
  Cc: ninegua-Re5JQEeQqe8AvxtiuMwx3w,
	linux-nilfs-u79uwXL29TY76Z2rM5mHXA

Hi,
On Thu, 27 May 2010 16:27:22 +0900, Jiro SEKIBA wrote:
> Hi,
> 
> This is a proposed patch to sync super blocks by turn.
> It still require recovery action when super root is not found,

Arh, right.  We need some extension to retry the search with the older
super block.  It looks a bit complicate.

Ok, I'll take a moment to solve this issue.

> but it works at least to mount with valid fs with the patch:
> 
>  nilfs2: use checkpoint number instead of timestamp to select super block
>  9f6c75b4c354939f0a8aefc19eb6a9334ef58a89
> 
> This will sync super blocks by turn instead of syncing duplicate
> super blocks at the time.  This will help searching valid super root when
> super block is written into disk before log is written, which is happen when
> barrier-less block devices are unmounted uncleanly.
> In the stiation, old super block likely points valid log.
> 
> Signed-off-by: Jiro SEKIBA <jir-hfpbi5WX9J54Eiagz67IpQ@public.gmane.org>
> ---
>  fs/nilfs2/nilfs.h     |    2 +-
>  fs/nilfs2/segment.c   |    3 +--
>  fs/nilfs2/super.c     |   32 ++++++++++++++++----------------
>  fs/nilfs2/the_nilfs.c |    2 +-
>  4 files changed, 19 insertions(+), 20 deletions(-)
> 
> diff --git a/fs/nilfs2/nilfs.h b/fs/nilfs2/nilfs.h
> index 8723e5b..ec644c5 100644
> --- a/fs/nilfs2/nilfs.h
> +++ b/fs/nilfs2/nilfs.h
> @@ -270,7 +270,7 @@ extern struct nilfs_super_block *
>  nilfs_read_super_block(struct super_block *, u64, int, struct buffer_head **);
>  extern int nilfs_store_magic_and_option(struct super_block *,
>  					struct nilfs_super_block *, char *);
> -extern int nilfs_commit_super(struct nilfs_sb_info *, int);
> +extern int nilfs_commit_super(struct nilfs_sb_info *);
>  extern int nilfs_attach_checkpoint(struct nilfs_sb_info *, __u64);
>  extern void nilfs_detach_checkpoint(struct nilfs_sb_info *);
>  
> diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c
> index 6a7dbd8..b48de1f 100644
> --- a/fs/nilfs2/segment.c
> +++ b/fs/nilfs2/segment.c
> @@ -2490,8 +2490,7 @@ static int nilfs_segctor_construct(struct nilfs_sc_info *sci, int mode)
>  		if (test_bit(NILFS_SC_SUPER_ROOT, &sci->sc_flags) &&
>  		    nilfs_discontinued(nilfs)) {
>  			down_write(&nilfs->ns_sem);
> -			err = nilfs_commit_super(
> -				sbi, nilfs_altsb_need_update(nilfs));
> +			err = nilfs_commit_super(sbi);
>  			up_write(&nilfs->ns_sem);
>  		}
>  	}
> diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c
> index 48145f5..4894e07 100644
> --- a/fs/nilfs2/super.c
> +++ b/fs/nilfs2/super.c
> @@ -101,7 +101,7 @@ void nilfs_error(struct super_block *sb, const char *function,
>  			nilfs->ns_mount_state |= NILFS_ERROR_FS;
>  			nilfs->ns_sbp[0]->s_state |=
>  				cpu_to_le16(NILFS_ERROR_FS);
> -			nilfs_commit_super(sbi, 1);
> +			nilfs_commit_super(sbi);
>  		}
>  		up_write(&nilfs->ns_sem);
>  
> @@ -200,7 +200,7 @@ static void nilfs_clear_inode(struct inode *inode)
>  	nilfs_btnode_cache_clear(&ii->i_btnode_cache);
>  }
>  
> -static int nilfs_sync_super(struct nilfs_sb_info *sbi, int dupsb)
> +static int nilfs_sync_super(struct nilfs_sb_info *sbi)
>  {
>  	struct the_nilfs *nilfs = sbi->s_nilfs;
>  	int err;
> @@ -226,6 +226,9 @@ static int nilfs_sync_super(struct nilfs_sb_info *sbi, int dupsb)
>  		printk(KERN_ERR
>  		       "NILFS: unable to write superblock (err=%d)\n", err);
>  		if (err == -EIO && nilfs->ns_sbh[1]) {
> +			memcpy(nilfs->ns_sbp[1], nilfs->ns_sbp[0],
> +			       nilfs->ns_sbsize);
> +			nilfs->ns_sbwtime[1] = nilfs->ns_sbwtime[0];
>  			nilfs_fall_back_super_block(nilfs);
>  			goto retry;
>  		}
> @@ -240,11 +243,12 @@ static int nilfs_sync_super(struct nilfs_sb_info *sbi, int dupsb)
>  
>  		/* update GC protection for recent segments */
>  		if (nilfs->ns_sbh[1]) {
> +			int flip_bits = (nilfs->ns_cno & 0x0FL);
>  			sbp = NULL;
> -			if (dupsb) {
> -				set_buffer_dirty(nilfs->ns_sbh[1]);
> -				if (!sync_dirty_buffer(nilfs->ns_sbh[1]))
> -					sbp = nilfs->ns_sbp[1];
> +			/* flip super block 9 to 7 ratio */
> +			if ((flip_bits == 0x08) || flip_bits == 0x0F) {
> +				sbp = nilfs->ns_sbp[1];
> +				nilfs_swap_super_block(nilfs);
>  			}
>  		}
>  		if (sbp) {
> @@ -257,7 +261,7 @@ static int nilfs_sync_super(struct nilfs_sb_info *sbi, int dupsb)
>  	return err;
>  }
>  
> -int nilfs_commit_super(struct nilfs_sb_info *sbi, int dupsb)
> +int nilfs_commit_super(struct nilfs_sb_info *sbi)
>  {
>  	struct the_nilfs *nilfs = sbi->s_nilfs;
>  	struct nilfs_super_block **sbp = nilfs->ns_sbp;
> @@ -294,12 +298,8 @@ int nilfs_commit_super(struct nilfs_sb_info *sbi, int dupsb)
>  	sbp[0]->s_sum = cpu_to_le32(crc32_le(nilfs->ns_crc_seed,
>  					     (unsigned char *)sbp[0],
>  					     nilfs->ns_sbsize));
> -	if (dupsb && sbp[1]) {
> -		memcpy(sbp[1], sbp[0], nilfs->ns_sbsize);
> -		nilfs->ns_sbwtime[1] = t;
> -	}
>  	clear_nilfs_sb_dirty(nilfs);
> -	return nilfs_sync_super(sbi, dupsb);
> +	return nilfs_sync_super(sbi);
>  }
>  
>  static void nilfs_put_super(struct super_block *sb)
> @@ -314,7 +314,7 @@ static void nilfs_put_super(struct super_block *sb)
>  	if (!(sb->s_flags & MS_RDONLY)) {
>  		down_write(&nilfs->ns_sem);
>  		nilfs->ns_sbp[0]->s_state = cpu_to_le16(nilfs->ns_mount_state);
> -		nilfs_commit_super(sbi, 1);
> +		nilfs_commit_super(sbi);
>  		up_write(&nilfs->ns_sem);
>  	}
>  	down_write(&nilfs->ns_super_sem);
> @@ -343,7 +343,7 @@ static int nilfs_sync_fs(struct super_block *sb, int wait)
>  
>  	down_write(&nilfs->ns_sem);
>  	if (nilfs_sb_dirty(nilfs))
> -		nilfs_commit_super(sbi, 1);
> +		nilfs_commit_super(sbi);
>  	up_write(&nilfs->ns_sem);
>  
>  	return err;
> @@ -657,7 +657,7 @@ static int nilfs_setup_super(struct nilfs_sb_info *sbi)
>  	sbp->s_mnt_count = cpu_to_le16(mnt_count + 1);
>  	sbp->s_state = cpu_to_le16(le16_to_cpu(sbp->s_state) & ~NILFS_VALID_FS);
>  	sbp->s_mtime = cpu_to_le64(get_seconds());
> -	return nilfs_commit_super(sbi, 1);
> +	return nilfs_commit_super(sbi);
>  }
>  
>  struct nilfs_super_block *nilfs_read_super_block(struct super_block *sb,
> @@ -901,7 +901,7 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data)
>  		    (nilfs->ns_mount_state & NILFS_VALID_FS))
>  			sbp->s_state = cpu_to_le16(nilfs->ns_mount_state);
>  		sbp->s_mtime = cpu_to_le64(get_seconds());
> -		nilfs_commit_super(sbi, 1);
> +		nilfs_commit_super(sbi);
>  		up_write(&nilfs->ns_sem);
>  	} else {
>  		/*
> diff --git a/fs/nilfs2/the_nilfs.c b/fs/nilfs2/the_nilfs.c
> index a756168..f779363 100644
> --- a/fs/nilfs2/the_nilfs.c
> +++ b/fs/nilfs2/the_nilfs.c
> @@ -327,7 +327,7 @@ int load_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi)
>  	down_write(&nilfs->ns_sem);
>  	nilfs->ns_mount_state |= NILFS_VALID_FS;
>  	nilfs->ns_sbp[0]->s_state = cpu_to_le16(nilfs->ns_mount_state);
> -	err = nilfs_commit_super(sbi, 1);
> +	err = nilfs_commit_super(sbi);
>  	up_write(&nilfs->ns_sem);
>  
>  	if (err) {
> -- 
> 1.5.6.5


Well, the basic idea looks OK.

But, this patch has an issue.

When the filesystem is mounted, nilfs updates super blocks to drop
their VALID_FS flags, and this state continues until the partition
will be unmounted.

The point is that the checkpoint number does not change when the
VALID_FS flags are set or unset.

If the system goes down while the VALID_FS flag on the secondary super
block is still on, it may prevent roll-forward recovery because the
VALID_FS flag forces to skip the recovery.

So, we still have to drop the VALID_FS flag together from both super
blocks.

Or, we may as well stop using the VALID_FS flag.  Nilfs can know
whether the recovery is needed or not by scanning logs without the
VALID_FS flag.

> +			/* flip super block 9 to 7 ratio */
> +			if ((flip_bits == 0x08) || flip_bits == 0x0F) {
> +				sbp = nilfs->ns_sbp[1];
> +				nilfs_swap_super_block(nilfs);
>  			}

This twist looks well thought out.  But, one comment.  From the coding
style viewpoint, it should be as follows:

> +			if (flip_bits == 0x08 || flip_bits == 0x0F) {

Thanks,
Ryusuke Konishi
--
To unsubscribe from this list: send the line "unsubscribe linux-nilfs" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH] nilfs2: sync super blokcs in turns
       [not found]                                       ` <20100528.015959.179492440.ryusuke-sG5X7nlA6pw@public.gmane.org>
@ 2010-05-28  2:29                                         ` Jiro SEKIBA
       [not found]                                           ` <87zkzkpxn3.wl%jir-27yqGEOhnJbQT0dZR+AlfA@public.gmane.org>
  0 siblings, 1 reply; 12+ messages in thread
From: Jiro SEKIBA @ 2010-05-28  2:29 UTC (permalink / raw)
  To: Ryusuke Konishi
  Cc: ninegua-Re5JQEeQqe8AvxtiuMwx3w,
	linux-nilfs-u79uwXL29TY76Z2rM5mHXA

Hi,

Thank you for the comments!

At Fri, 28 May 2010 01:59:59 +0900 (JST),
Ryusuke Konishi wrote:
> 
> Hi,
> On Thu, 27 May 2010 16:27:22 +0900, Jiro SEKIBA wrote:
> > Hi,
> > 
> > This is a proposed patch to sync super blocks by turn.
> > It still require recovery action when super root is not found,
> 
> Arh, right.  We need some extension to retry the search with the older
> super block.  It looks a bit complicate.
> 
> Ok, I'll take a moment to solve this issue.
> 
> > but it works at least to mount with valid fs with the patch:
> > 
> >  nilfs2: use checkpoint number instead of timestamp to select super block
> >  9f6c75b4c354939f0a8aefc19eb6a9334ef58a89
> > 
> > This will sync super blocks by turn instead of syncing duplicate
> > super blocks at the time.  This will help searching valid super root when
> > super block is written into disk before log is written, which is happen when
> > barrier-less block devices are unmounted uncleanly.
> > In the stiation, old super block likely points valid log.
> > 
> > Signed-off-by: Jiro SEKIBA <jir-hfpbi5WX9J54Eiagz67IpQ@public.gmane.org>
> > ---
> >  fs/nilfs2/nilfs.h     |    2 +-
> >  fs/nilfs2/segment.c   |    3 +--
> >  fs/nilfs2/super.c     |   32 ++++++++++++++++----------------
> >  fs/nilfs2/the_nilfs.c |    2 +-
> >  4 files changed, 19 insertions(+), 20 deletions(-)
> > 
> > diff --git a/fs/nilfs2/nilfs.h b/fs/nilfs2/nilfs.h
> > index 8723e5b..ec644c5 100644
> > --- a/fs/nilfs2/nilfs.h
> > +++ b/fs/nilfs2/nilfs.h
> > @@ -270,7 +270,7 @@ extern struct nilfs_super_block *
> >  nilfs_read_super_block(struct super_block *, u64, int, struct buffer_head **);
> >  extern int nilfs_store_magic_and_option(struct super_block *,
> >  					struct nilfs_super_block *, char *);
> > -extern int nilfs_commit_super(struct nilfs_sb_info *, int);
> > +extern int nilfs_commit_super(struct nilfs_sb_info *);
> >  extern int nilfs_attach_checkpoint(struct nilfs_sb_info *, __u64);
> >  extern void nilfs_detach_checkpoint(struct nilfs_sb_info *);
> >  
> > diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c
> > index 6a7dbd8..b48de1f 100644
> > --- a/fs/nilfs2/segment.c
> > +++ b/fs/nilfs2/segment.c
> > @@ -2490,8 +2490,7 @@ static int nilfs_segctor_construct(struct nilfs_sc_info *sci, int mode)
> >  		if (test_bit(NILFS_SC_SUPER_ROOT, &sci->sc_flags) &&
> >  		    nilfs_discontinued(nilfs)) {
> >  			down_write(&nilfs->ns_sem);
> > -			err = nilfs_commit_super(
> > -				sbi, nilfs_altsb_need_update(nilfs));
> > +			err = nilfs_commit_super(sbi);
> >  			up_write(&nilfs->ns_sem);
> >  		}
> >  	}
> > diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c
> > index 48145f5..4894e07 100644
> > --- a/fs/nilfs2/super.c
> > +++ b/fs/nilfs2/super.c
> > @@ -101,7 +101,7 @@ void nilfs_error(struct super_block *sb, const char *function,
> >  			nilfs->ns_mount_state |= NILFS_ERROR_FS;
> >  			nilfs->ns_sbp[0]->s_state |=
> >  				cpu_to_le16(NILFS_ERROR_FS);
> > -			nilfs_commit_super(sbi, 1);
> > +			nilfs_commit_super(sbi);
> >  		}
> >  		up_write(&nilfs->ns_sem);
> >  
> > @@ -200,7 +200,7 @@ static void nilfs_clear_inode(struct inode *inode)
> >  	nilfs_btnode_cache_clear(&ii->i_btnode_cache);
> >  }
> >  
> > -static int nilfs_sync_super(struct nilfs_sb_info *sbi, int dupsb)
> > +static int nilfs_sync_super(struct nilfs_sb_info *sbi)
> >  {
> >  	struct the_nilfs *nilfs = sbi->s_nilfs;
> >  	int err;
> > @@ -226,6 +226,9 @@ static int nilfs_sync_super(struct nilfs_sb_info *sbi, int dupsb)
> >  		printk(KERN_ERR
> >  		       "NILFS: unable to write superblock (err=%d)\n", err);
> >  		if (err == -EIO && nilfs->ns_sbh[1]) {
> > +			memcpy(nilfs->ns_sbp[1], nilfs->ns_sbp[0],
> > +			       nilfs->ns_sbsize);
> > +			nilfs->ns_sbwtime[1] = nilfs->ns_sbwtime[0];
> >  			nilfs_fall_back_super_block(nilfs);
> >  			goto retry;
> >  		}
> > @@ -240,11 +243,12 @@ static int nilfs_sync_super(struct nilfs_sb_info *sbi, int dupsb)
> >  
> >  		/* update GC protection for recent segments */
> >  		if (nilfs->ns_sbh[1]) {
> > +			int flip_bits = (nilfs->ns_cno & 0x0FL);
> >  			sbp = NULL;
> > -			if (dupsb) {
> > -				set_buffer_dirty(nilfs->ns_sbh[1]);
> > -				if (!sync_dirty_buffer(nilfs->ns_sbh[1]))
> > -					sbp = nilfs->ns_sbp[1];
> > +			/* flip super block 9 to 7 ratio */
> > +			if ((flip_bits == 0x08) || flip_bits == 0x0F) {
> > +				sbp = nilfs->ns_sbp[1];
> > +				nilfs_swap_super_block(nilfs);
> >  			}
> >  		}
> >  		if (sbp) {
> > @@ -257,7 +261,7 @@ static int nilfs_sync_super(struct nilfs_sb_info *sbi, int dupsb)
> >  	return err;
> >  }
> >  
> > -int nilfs_commit_super(struct nilfs_sb_info *sbi, int dupsb)
> > +int nilfs_commit_super(struct nilfs_sb_info *sbi)
> >  {
> >  	struct the_nilfs *nilfs = sbi->s_nilfs;
> >  	struct nilfs_super_block **sbp = nilfs->ns_sbp;
> > @@ -294,12 +298,8 @@ int nilfs_commit_super(struct nilfs_sb_info *sbi, int dupsb)
> >  	sbp[0]->s_sum = cpu_to_le32(crc32_le(nilfs->ns_crc_seed,
> >  					     (unsigned char *)sbp[0],
> >  					     nilfs->ns_sbsize));
> > -	if (dupsb && sbp[1]) {
> > -		memcpy(sbp[1], sbp[0], nilfs->ns_sbsize);
> > -		nilfs->ns_sbwtime[1] = t;
> > -	}
> >  	clear_nilfs_sb_dirty(nilfs);
> > -	return nilfs_sync_super(sbi, dupsb);
> > +	return nilfs_sync_super(sbi);
> >  }
> >  
> >  static void nilfs_put_super(struct super_block *sb)
> > @@ -314,7 +314,7 @@ static void nilfs_put_super(struct super_block *sb)
> >  	if (!(sb->s_flags & MS_RDONLY)) {
> >  		down_write(&nilfs->ns_sem);
> >  		nilfs->ns_sbp[0]->s_state = cpu_to_le16(nilfs->ns_mount_state);
> > -		nilfs_commit_super(sbi, 1);
> > +		nilfs_commit_super(sbi);
> >  		up_write(&nilfs->ns_sem);
> >  	}
> >  	down_write(&nilfs->ns_super_sem);
> > @@ -343,7 +343,7 @@ static int nilfs_sync_fs(struct super_block *sb, int wait)
> >  
> >  	down_write(&nilfs->ns_sem);
> >  	if (nilfs_sb_dirty(nilfs))
> > -		nilfs_commit_super(sbi, 1);
> > +		nilfs_commit_super(sbi);
> >  	up_write(&nilfs->ns_sem);
> >  
> >  	return err;
> > @@ -657,7 +657,7 @@ static int nilfs_setup_super(struct nilfs_sb_info *sbi)
> >  	sbp->s_mnt_count = cpu_to_le16(mnt_count + 1);
> >  	sbp->s_state = cpu_to_le16(le16_to_cpu(sbp->s_state) & ~NILFS_VALID_FS);
> >  	sbp->s_mtime = cpu_to_le64(get_seconds());
> > -	return nilfs_commit_super(sbi, 1);
> > +	return nilfs_commit_super(sbi);
> >  }
> >  
> >  struct nilfs_super_block *nilfs_read_super_block(struct super_block *sb,
> > @@ -901,7 +901,7 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data)
> >  		    (nilfs->ns_mount_state & NILFS_VALID_FS))
> >  			sbp->s_state = cpu_to_le16(nilfs->ns_mount_state);
> >  		sbp->s_mtime = cpu_to_le64(get_seconds());
> > -		nilfs_commit_super(sbi, 1);
> > +		nilfs_commit_super(sbi);
> >  		up_write(&nilfs->ns_sem);
> >  	} else {
> >  		/*
> > diff --git a/fs/nilfs2/the_nilfs.c b/fs/nilfs2/the_nilfs.c
> > index a756168..f779363 100644
> > --- a/fs/nilfs2/the_nilfs.c
> > +++ b/fs/nilfs2/the_nilfs.c
> > @@ -327,7 +327,7 @@ int load_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi)
> >  	down_write(&nilfs->ns_sem);
> >  	nilfs->ns_mount_state |= NILFS_VALID_FS;
> >  	nilfs->ns_sbp[0]->s_state = cpu_to_le16(nilfs->ns_mount_state);
> > -	err = nilfs_commit_super(sbi, 1);
> > +	err = nilfs_commit_super(sbi);
> >  	up_write(&nilfs->ns_sem);
> >  
> >  	if (err) {
> > -- 
> > 1.5.6.5
> 
> 
> Well, the basic idea looks OK.
> 
> But, this patch has an issue.
> 
> When the filesystem is mounted, nilfs updates super blocks to drop
> their VALID_FS flags, and this state continues until the partition
> will be unmounted.
> 
> The point is that the checkpoint number does not change when the
> VALID_FS flags are set or unset.
> 
> If the system goes down while the VALID_FS flag on the secondary super
> block is still on, it may prevent roll-forward recovery because the
> VALID_FS flag forces to skip the recovery.
> 
> So, we still have to drop the VALID_FS flag together from both super
> blocks.

I see the issue.  Actually, VALID_FS flag is never unset for the
older super block on mount time.  Because ns_sbp[0]->s_state is never
propagated to the ns_sbp[1]->s_sate.

There are two way to unset VALID_FS flag on mount time, I came up with:

1. use dupsb flag only in load_nilfs
2. swap super block and commit those separately in load_nilfs

1st case, dupsb flag is examined each time in nilfs_sync_super.
2nd case is a little hacky, for it requires to check checkpoint number
if checkpoint number is the number to swap super blocks to make sure
not to swap twice (in load_nilfs and nilfs_sync_super).

> Or, we may as well stop using the VALID_FS flag.  Nilfs can know
> whether the recovery is needed or not by scanning logs without the
> VALID_FS flag.

Actually, what I've done so far for grub module does not check that flag,
but just try to find the latest log from where super block pointed.
It, as far as I understand, is harmless to try roll forward action
on the clean unmount fs.

I think it may take more time when it's valid but, searching log
instantly fails.  Therefore that differences might be slight.

It would be good to have a "valid" flag for peace of mind, though.

> > +			/* flip super block 9 to 7 ratio */
> > +			if ((flip_bits == 0x08) || flip_bits == 0x0F) {
> > +				sbp = nilfs->ns_sbp[1];
> > +				nilfs_swap_super_block(nilfs);
> >  			}
> 
> This twist looks well thought out.  But, one comment.  From the coding
> style viewpoint, it should be as follows:
> 
> > +			if (flip_bits == 0x08 || flip_bits == 0x0F) {
> 
> Thanks,
> Ryusuke Konishi
> --
> To unsubscribe from this list: send the line "unsubscribe linux-nilfs" in
> the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 
> 
> 


-- 
Jiro SEKIBA <jir-hfpbi5WX9J54Eiagz67IpQ@public.gmane.org>
--
To unsubscribe from this list: send the line "unsubscribe linux-nilfs" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH] nilfs2: sync super blokcs in turns
       [not found]                                           ` <87zkzkpxn3.wl%jir-27yqGEOhnJbQT0dZR+AlfA@public.gmane.org>
@ 2010-06-02 18:26                                             ` Ryusuke Konishi
  0 siblings, 0 replies; 12+ messages in thread
From: Ryusuke Konishi @ 2010-06-02 18:26 UTC (permalink / raw)
  To: jir-hfpbi5WX9J54Eiagz67IpQ
  Cc: ninegua-Re5JQEeQqe8AvxtiuMwx3w,
	linux-nilfs-u79uwXL29TY76Z2rM5mHXA

Hi,

On Fri, 28 May 2010 11:29:04 +0900, Jiro SEKIBA wrote:
> At Fri, 28 May 2010 01:59:59 +0900 (JST),
> Ryusuke Konishi wrote:
> > 
> > Hi,
> > On Thu, 27 May 2010 16:27:22 +0900, Jiro SEKIBA wrote:
> > > Hi,
> > > 
> > > This is a proposed patch to sync super blocks by turn.
> > > It still require recovery action when super root is not found,
> > 
> > Arh, right.  We need some extension to retry the search with the older
> > super block.  It looks a bit complicate.
> > 
> > Ok, I'll take a moment to solve this issue.
> > 
> > > but it works at least to mount with valid fs with the patch:
> > > 
> > >  nilfs2: use checkpoint number instead of timestamp to select super block
> > >  9f6c75b4c354939f0a8aefc19eb6a9334ef58a89
> > > 
> > > This will sync super blocks by turn instead of syncing duplicate
> > > super blocks at the time.  This will help searching valid super root when
> > > super block is written into disk before log is written, which is happen when
> > > barrier-less block devices are unmounted uncleanly.
> > > In the stiation, old super block likely points valid log.
> > > 
> > > Signed-off-by: Jiro SEKIBA <jir-hfpbi5WX9J54Eiagz67IpQ@public.gmane.org>
> > 
> > Well, the basic idea looks OK.
> > 
> > But, this patch has an issue.
> > 
> > When the filesystem is mounted, nilfs updates super blocks to drop
> > their VALID_FS flags, and this state continues until the partition
> > will be unmounted.
> > 
> > The point is that the checkpoint number does not change when the
> > VALID_FS flags are set or unset.
> > 
> > If the system goes down while the VALID_FS flag on the secondary super
> > block is still on, it may prevent roll-forward recovery because the
> > VALID_FS flag forces to skip the recovery.
> > 
> > So, we still have to drop the VALID_FS flag together from both super
> > blocks.
> 
> I see the issue.  Actually, VALID_FS flag is never unset for the
> older super block on mount time.  Because ns_sbp[0]->s_state is never
> propagated to the ns_sbp[1]->s_sate.
> 
> There are two way to unset VALID_FS flag on mount time, I came up with:
> 
> 1. use dupsb flag only in load_nilfs
> 2. swap super block and commit those separately in load_nilfs
> 
> 1st case, dupsb flag is examined each time in nilfs_sync_super.
> 2nd case is a little hacky, for it requires to check checkpoint number
> if checkpoint number is the number to swap super blocks to make sure
> not to swap twice (in load_nilfs and nilfs_sync_super).

Sorry for my late reply.

We can classify these update functions for super blocks into two:

 1. A function to update pointer to the latest log.
    s_last_seq, s_last_pseg, s_last_cno, s_free_blocks_count members
    belong to this category.

 2. A function to update information other than (1).
    The VALID_FS flag and other layout information are included in this
    class.

The class (1) update can be written to the disk alternately.  This
always changes the checkpoint number.

OTOH, the class (2) update should be written to both super blocks.

It would be nice if nilfs_commit_super() is exntended to handle both
classes of updates with a few optional flags.  At present, the above
fields for the class (1) update is set in nilfs_commit_super(), but
this should be moved out to the callers..  We may as well add a new
wrapper function for the periodic writeback of the super blocks.

> > Or, we may as well stop using the VALID_FS flag.  Nilfs can know
> > whether the recovery is needed or not by scanning logs without the
> > VALID_FS flag.
> 
> Actually, what I've done so far for grub module does not check that flag,
> but just try to find the latest log from where super block pointed.
> It, as far as I understand, is harmless to try roll forward action
> on the clean unmount fs.
> 
> I think it may take more time when it's valid but, searching log
> instantly fails.  Therefore that differences might be slight.
> 
> It would be good to have a "valid" flag for peace of mind, though.

Agreed.  Please keep the "valid" flag for now.

Thanks,
Ryusuke Konishi
--
To unsubscribe from this list: send the line "unsubscribe linux-nilfs" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2010-06-02 18:26 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-05-15  0:24 Segment magic number invalid Paul L
     [not found] ` <AANLkTikEfAtM5PdXSFw5pA_8mDW5pcyxes3GTO3kMBPa-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2010-05-16  1:33   ` Ryusuke Konishi
     [not found]     ` <AANLkTinBFQYWRZRmVL69lqxRG1p0cBQ2AxBiFk4SlNE8@mail.gmail.com>
     [not found]       ` <AANLkTinBFQYWRZRmVL69lqxRG1p0cBQ2AxBiFk4SlNE8-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2010-05-16 18:32         ` Paul L
     [not found]           ` <AANLkTimHvMze3B8fQE383WW8WLbOYcZx0pz0sfjC2DhJ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2010-05-17  2:46             ` Ryusuke Konishi
     [not found]               ` <20100517.114657.112904526.ryusuke-sG5X7nlA6pw@public.gmane.org>
2010-05-17  4:14                 ` Paul L
     [not found]                   ` <AANLkTimfmJU5h4pS23eKpjLNV_c6d4YEBHNmBdcy-r4g-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2010-05-17  7:26                     ` Ryusuke Konishi
     [not found]                       ` <20100517.162614.107743625.ryusuke-sG5X7nlA6pw@public.gmane.org>
2010-05-19 13:49                         ` Jiro SEKIBA
     [not found]                           ` <871vd8dms5.wl%jir-27yqGEOhnJbQT0dZR+AlfA@public.gmane.org>
2010-05-19 16:14                             ` Ryusuke Konishi
     [not found]                               ` <20100520.011455.32954390.ryusuke-sG5X7nlA6pw@public.gmane.org>
2010-05-27  7:27                                 ` [PATCH] nilfs2: sync super blokcs in turns Jiro SEKIBA
     [not found]                                   ` <87r5kx6bz9.wl%jir-27yqGEOhnJbQT0dZR+AlfA@public.gmane.org>
2010-05-27 16:59                                     ` Ryusuke Konishi
     [not found]                                       ` <20100528.015959.179492440.ryusuke-sG5X7nlA6pw@public.gmane.org>
2010-05-28  2:29                                         ` Jiro SEKIBA
     [not found]                                           ` <87zkzkpxn3.wl%jir-27yqGEOhnJbQT0dZR+AlfA@public.gmane.org>
2010-06-02 18:26                                             ` Ryusuke Konishi

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).