[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

Re: Ext3 filesystem modified while mounted read-only



Hi,

On Mon, 2003-11-03 at 16:48, Graham Bleach wrote:
> I noticed that ext3 filesystems are modified if mounted read-only:
> 
> # mke2fs -j /dev/hdb1
> 
> [...]
> 
> # md5sum /dev/hdb1 > MD5SUM
> # mount -t ext3 -o ro /dev/hdb1 /mnt/test1
> # umount /mnt/test1
> # md5sum -c MD5SUM 
> md5sum: MD5 check failed for '/dev/hdb1'

Yep, it's an unusual case deep in the journal logic that is causing
this.  I think there's a simple fix, but I'm nervous about it because it
adds a conditional to the journal updates, and the consequences of
failing to complete a necessary update the journal superblock are
catastrophic on recovery.

Proposed patch is attached: does this help for you?  I've been trying it
out on LVM snapshots here.

Cheers,
 Stephen

--- linux-2.4-ext3merge/fs/jbd/journal.c.=K0003=.orig
+++ linux-2.4-ext3merge/fs/jbd/journal.c
@@ -946,6 +946,22 @@ void journal_update_superblock(journal_t
 	journal_superblock_t *sb = journal->j_superblock;
 	struct buffer_head *bh = journal->j_sb_buffer;
 
+	/* As a special case, if the on-disk copy is already marked as
+        * needing no recovery (s_start == 0) and there are no
+        * outstanding transactions in the filesystem, then we can safely
+        * defer the superblock update until the next commit by setting
+        * JFS_FLUSHED.  This avoids attempting a write to a
+        * potential-readonly device. */
+
+	if (sb->s_start == 0 && 
+	    journal->j_tail_sequence == journal->j_transaction_sequence) {
+		jbd_debug(1,"JBD: Skipping superblock update on recovered sb "
+			  "(start %ld, seq %d, errno %d)\n",
+			  journal->j_tail, journal->j_tail_sequence, 
+			  journal->j_errno);
+		goto out;
+	}
+	
 	jbd_debug(1,"JBD: updating superblock (start %ld, seq %d, errno %d)\n",
 		  journal->j_tail, journal->j_tail_sequence, journal->j_errno);
 
@@ -959,6 +975,7 @@ void journal_update_superblock(journal_t
 	if (wait)
 		wait_on_buffer(bh);
 
+out:
 	/* If we have just flushed the log (by marking s_start==0), then
 	 * any future commit will have to be careful to update the
 	 * superblock again to re-record the true start of the log. */

[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]