summaryrefslogtreecommitdiff
path: root/fs/logfs
diff options
context:
space:
mode:
authorJoern Engel <joern@logfs.org>2010-03-04 21:36:19 +0100
committerJoern Engel <joern@logfs.org>2010-03-04 21:36:19 +0100
commitc6d3830140f1d56b07d8ab56a6e14ca3c492a39a (patch)
tree8dd9923b4217f6f7dc2735356d112fdcfa277852 /fs/logfs
parent9421502b4fc894cc477be8fc49776830e37ca157 (diff)
downloadkernel-common-c6d3830140f1d56b07d8ab56a6e14ca3c492a39a.tar.gz
kernel-common-c6d3830140f1d56b07d8ab56a6e14ca3c492a39a.tar.bz2
kernel-common-c6d3830140f1d56b07d8ab56a6e14ca3c492a39a.zip
[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.
Diffstat (limited to 'fs/logfs')
-rw-r--r--fs/logfs/gc.c6
-rw-r--r--fs/logfs/journal.c11
-rw-r--r--fs/logfs/logfs.h4
-rw-r--r--fs/logfs/readwrite.c2
-rw-r--r--fs/logfs/segment.c7
-rw-r--r--fs/logfs/super.c2
6 files changed, 19 insertions, 13 deletions
diff --git a/fs/logfs/gc.c b/fs/logfs/gc.c
index b3656c44190e..92949f95a901 100644
--- a/fs/logfs/gc.c
+++ b/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);
}
diff --git a/fs/logfs/journal.c b/fs/logfs/journal.c
index c0e7d63221d4..57eb4fb444a9 100644
--- a/fs/logfs/journal.c
+++ b/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);
diff --git a/fs/logfs/logfs.h b/fs/logfs/logfs.h
index 72592114a28f..129779431373 100644
--- a/fs/logfs/logfs.h
+++ b/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,
diff --git a/fs/logfs/readwrite.c b/fs/logfs/readwrite.c
index 1dbe6e8cccec..7a23b3e7c0a7 100644
--- a/fs/logfs/readwrite.c
+++ b/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 */
diff --git a/fs/logfs/segment.c b/fs/logfs/segment.c
index 664cd0dd3576..1a14f9910d55 100644
--- a/fs/logfs/segment.c
+++ b/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;
diff --git a/fs/logfs/super.c b/fs/logfs/super.c
index 94d80f7ee7c2..1d081b7ede5a 100644
--- a/fs/logfs/super.c
+++ b/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