Browse Source

[LogFS] Only write journal if dirty

This prevents unnecessary journal writes.  More importantly it prevents
an oops due to a journal write on failed mount.
Joern Engel 15 years ago
parent
commit
c6d3830140
6 changed files with 19 additions and 13 deletions
  1. 3 3
      fs/logfs/gc.c
  2. 7 4
      fs/logfs/journal.c
  3. 2 2
      fs/logfs/logfs.h
  4. 1 1
      fs/logfs/readwrite.c
  5. 5 2
      fs/logfs/segment.c
  6. 1 1
      fs/logfs/super.c

+ 3 - 3
fs/logfs/gc.c

@@ -469,7 +469,7 @@ static void __logfs_gc_pass(struct super_block *sb, int target)
 
 		/* Sync in-memory state with on-medium state in case they
 		 * diverged */
-		logfs_write_anchor(super->s_master_inode);
+		logfs_write_anchor(sb);
 		round += logfs_scan_some(sb);
 		if (no_free_segments(sb) >= target)
 			goto write_alias;
@@ -613,8 +613,8 @@ void logfs_gc_pass(struct super_block *sb)
 	 */
 	if (super->s_dirty_used_bytes + super->s_dirty_free_bytes
 			+ LOGFS_MAX_OBJECTSIZE >= super->s_free_bytes)
-		logfs_write_anchor(super->s_master_inode);
-	__logfs_gc_pass(sb, logfs_super(sb)->s_total_levels);
+		logfs_write_anchor(sb);
+	__logfs_gc_pass(sb, super->s_total_levels);
 	logfs_wl_pass(sb);
 	logfs_journal_wl_pass(sb);
 }

+ 7 - 4
fs/logfs/journal.c

@@ -724,14 +724,17 @@ static int logfs_write_obj_aliases(struct super_block *sb)
  * bit wasteful, but robustness is more important.  With this we can *always*
  * erase all journal segments except the one containing the most recent commit.
  */
-void logfs_write_anchor(struct inode *inode)
+void logfs_write_anchor(struct super_block *sb)
 {
-	struct super_block *sb = inode->i_sb;
 	struct logfs_super *super = logfs_super(sb);
 	struct logfs_area *area = super->s_journal_area;
 	int i, err;
 
-	BUG_ON(logfs_super(sb)->s_flags & LOGFS_SB_FLAG_SHUTDOWN);
+	if (!(super->s_flags & LOGFS_SB_FLAG_DIRTY))
+		return;
+	super->s_flags &= ~LOGFS_SB_FLAG_DIRTY;
+
+	BUG_ON(super->s_flags & LOGFS_SB_FLAG_SHUTDOWN);
 	mutex_lock(&super->s_journal_mutex);
 
 	/* Do this first or suffer corruption */
@@ -821,7 +824,7 @@ void do_logfs_journal_wl_pass(struct super_block *sb)
 	area->a_is_open = 0;
 	area->a_used_bytes = 0;
 	/* Write journal */
-	logfs_write_anchor(super->s_master_inode);
+	logfs_write_anchor(sb);
 	/* Write superblocks */
 	err = logfs_write_sb(sb);
 	BUG_ON(err);

+ 2 - 2
fs/logfs/logfs.h

@@ -82,7 +82,7 @@
 
 /* Read-only filesystem */
 #define LOGFS_SB_FLAG_RO	0x0001
-#define LOGFS_SB_FLAG_SEG_ALIAS	0x0002
+#define LOGFS_SB_FLAG_DIRTY	0x0002
 #define LOGFS_SB_FLAG_OBJ_ALIAS	0x0004
 #define LOGFS_SB_FLAG_SHUTDOWN	0x0008
 
@@ -526,7 +526,7 @@ void logfs_delete_inode(struct inode *inode);
 void logfs_clear_inode(struct inode *inode);
 
 /* journal.c */
-void logfs_write_anchor(struct inode *inode);
+void logfs_write_anchor(struct super_block *sb);
 int logfs_init_journal(struct super_block *sb);
 void logfs_cleanup_journal(struct super_block *sb);
 int write_alias_journal(struct super_block *sb, u64 ino, u64 bix,

+ 1 - 1
fs/logfs/readwrite.c

@@ -421,7 +421,7 @@ static void inode_write_block(struct logfs_block *block)
 
 	inode = block->inode;
 	if (inode->i_ino == LOGFS_INO_MASTER)
-		logfs_write_anchor(inode);
+		logfs_write_anchor(inode->i_sb);
 	else {
 		ret = __logfs_write_inode(inode, 0);
 		/* see indirect_write_block comment */

+ 5 - 2
fs/logfs/segment.c

@@ -352,7 +352,8 @@ int logfs_segment_write(struct inode *inode, struct page *page,
 	int ret;
 	void *buf;
 
-	BUG_ON(logfs_super(sb)->s_flags & LOGFS_SB_FLAG_SHUTDOWN);
+	super->s_flags |= LOGFS_SB_FLAG_DIRTY;
+	BUG_ON(super->s_flags & LOGFS_SB_FLAG_SHUTDOWN);
 	do_compress = logfs_inode(inode)->li_flags & LOGFS_IF_COMPRESSED;
 	if (shadow->gc_level != 0) {
 		/* temporarily disable compression for indirect blocks */
@@ -653,11 +654,13 @@ int logfs_segment_read(struct inode *inode, struct page *page,
 int logfs_segment_delete(struct inode *inode, struct logfs_shadow *shadow)
 {
 	struct super_block *sb = inode->i_sb;
+	struct logfs_super *super = logfs_super(sb);
 	struct logfs_object_header h;
 	u16 len;
 	int err;
 
-	BUG_ON(logfs_super(sb)->s_flags & LOGFS_SB_FLAG_SHUTDOWN);
+	super->s_flags |= LOGFS_SB_FLAG_DIRTY;
+	BUG_ON(super->s_flags & LOGFS_SB_FLAG_SHUTDOWN);
 	BUG_ON(shadow->old_ofs & LOGFS_FULLY_POPULATED);
 	if (!shadow->old_ofs)
 		return 0;

+ 1 - 1
fs/logfs/super.c

@@ -490,7 +490,7 @@ static void logfs_kill_sb(struct super_block *sb)
 	log_super("LogFS: Start unmounting\n");
 	/* Alias entries slow down mount, so evict as many as possible */
 	sync_filesystem(sb);
-	logfs_write_anchor(super->s_master_inode);
+	logfs_write_anchor(sb);
 
 	/*
 	 * From this point on alias entries are simply dropped - and any