Patchwork Regular ext4 error warning with HD in USB dock

login
register
mail settings
Submitter Amir Goldstein
Date Jan. 8, 2011, 8:06 p.m.
Message ID <AANLkTintasUFQFfTbLOVG1bA+6FtwoVdKP7XN5Zrhemf@mail.gmail.com>
Download mbox | patch
Permalink /patch/77984/
State New
Headers show

Comments

Amir Goldstein - Jan. 8, 2011, 8:06 p.m.
On Sat, Jan 8, 2011 at 10:05 AM, Rogier Wolff <R.E.Wolff@bitwizard.nl> wrote:
> On Fri, Jan 07, 2011 at 11:07:23PM +0200, Amir Goldstein wrote:
>> On Fri, Jan 7, 2011 at 9:41 PM, Amir Goldstein <amir73il@gmail.com> wrote:
>> > On Fri, Jan 7, 2011 at 7:26 AM, Ted Ts'o <tytso@mit.edu> wrote:
>> >> Am I missing something?  The kernel stores up to 3k worth of data, on
>> >> a 4k block file system.  Whereas e2fsck patch blindly assume 2k worhth
>> >> of data regardless of the block size.  The kernel patch looks ok, but
>> >> the e2fsprogs patch seems badly broken....
>>
>> So it's not badly broken, it copies blocksize-2K, which is clumsily
>> written like this:
>> +     int len = ctx->fs->blocksize - 2*SUPERBLOCK_OFFSET;
>
> So this should be:
>
>  int len = ctx->fs->blocksize - SUPERBLOCK_OFFSET - sizeof (<superblock>);
>
> Although those two numbers are equal right now, there is no reason to
> assume that they will remain so in the future. So if the superblock
> size (or the offset) changes in the future, it's much better to have
> programmed this so that it will keep on working as opposed to getting
> to deal with ugly bugs in code that hasn't changed in years...
>

Very well, here is a less ugly version of the e2fsck patch:

e2fsck: display recorded error messages

Ext4 error messages are recorded in a message buffer after the
journal super block.  After journal recovery, the journal message buffer
is copied to the file system message buffer.  On fsck, if the message
buffer is not empty, the recorded messages are printed to stdout and
the buffer is cleared.

Signed-off-by: Amir Goldstein <amir73il@users.sf.net>

Patch

diff --git a/e2fsck/journal.c b/e2fsck/journal.c
index 93f685c..00d4d8f 100644
--- a/e2fsck/journal.c
+++ b/e2fsck/journal.c
@@ -837,6 +837,22 @@  static errcode_t recover_ext3_journal(e2fsck_t ctx)


 	if (journal->j_superblock->s_errno) {
+		/* journal message buffer at journal super block + 1K */
+		char *buf = ((char *) journal->j_superblock) +
+			SUPERBLOCK_OFFSET;
+		int n, len = ctx->fs->blocksize - MSGBUF_OFFSET;
+
+		if (len >= MSGBUF_OFFSET && *buf) {
+			/* keep it simple - write in MSGBUF_OFFSET blocksize */
+			io_channel_set_blksize(ctx->fs->io, MSGBUF_OFFSET);
+			n = len / MSGBUF_OFFSET;
+			/* write journal message buffer to super block + 2K */
+			retval = io_channel_write_blk(ctx->fs->io, 1, n, buf);
+			io_channel_set_blksize(ctx->fs->io, ctx->fs->blocksize);
+			/* clear journal message buffer */
+			memset(buf, 0, len);
+		}
+
 		ctx->fs->super->s_state |= EXT2_ERROR_FS;
 		ext2fs_mark_super_dirty(ctx->fs);
 		journal->j_superblock->s_errno = 0;
diff --git a/e2fsck/super.c b/e2fsck/super.c
index b6923c6..f3274df 100644
--- a/e2fsck/super.c
+++ b/e2fsck/super.c
@@ -452,6 +452,45 @@  static void e2fsck_fix_dirhash_hint(e2fsck_t ctx)
 	}
 }

+/*
+ * This function prints the message buffer at the end of super block.
+ */
+static void e2fsck_print_message_buffer(e2fsck_t ctx)
+{
+	char *buf;
+	int n, len = ctx->fs->blocksize - MSGBUF_OFFSET;
+	unsigned offset = 0;
+	int retval;
+
+	if (len < MSGBUF_OFFSET)
+		/* 1K or 2K fs->blocksize */
+		return;
+
+	buf = (char *) e2fsck_allocate_memory(ctx, len, "message buffer");
+
+	/* keep it simple - write in MSGBUF_OFFSET blocksize */
+	io_channel_set_blksize(ctx->fs->io, MSGBUF_OFFSET);
+	n = len / MSGBUF_OFFSET;
+	/* read message buffer from super block + 2K */
+	retval = io_channel_read_blk(ctx->fs->io, 1, n, buf);
+	if (retval || !*buf)
+		goto out;
+
+	/* print messages in buffer */
+	puts("Error messages recorded in message buffer:");
+	while (offset < len && buf[offset]) {
+		puts(buf+offset);
+		offset += MSGBUF_RECLEN;
+	}
+	/* clear message buffer */
+	memset(buf, 0, len);
+	retval = io_channel_write_blk(ctx->fs->io, 2, 2, buf);
+	puts("End of message buffer.");
+out:
+	io_channel_set_blksize(ctx->fs->io, ctx->fs->blocksize);
+	ext2fs_free_mem(&buf);
+}
+

 void check_super_block(e2fsck_t ctx)
 {
@@ -874,6 +913,11 @@  void check_super_block(e2fsck_t ctx)
 	 */
 	e2fsck_fix_dirhash_hint(ctx);

+	/*
+	 * Print message buffer if necessary
+	 */
+	e2fsck_print_message_buffer(ctx);
+
 	return;
 }

diff --git a/lib/ext2fs/ext2fs.h b/lib/ext2fs/ext2fs.h
index a204eb7..5b73c2a 100644
--- a/lib/ext2fs/ext2fs.h
+++ b/lib/ext2fs/ext2fs.h
@@ -38,6 +38,12 @@  extern "C" {
  */
 #define SUPERBLOCK_OFFSET	1024
 #define SUPERBLOCK_SIZE 	1024
+/*
+ * When blocksize > 2K, the space after the superblock is used as
+ * a buffer to record error messages (in 256 bytes records).
+ */
+#define MSGBUF_OFFSET 		(SUPERBLOCK_OFFSET+SUPERBLOCK_SIZE)
+#define MSGBUF_RECLEN		256

 /*
  * The last ext2fs revision level that this version of the library is