summaryrefslogtreecommitdiffstats
path: root/fs/ubifs/super.c
diff options
context:
space:
mode:
authorArtem Bityutskiy <Artem.Bityutskiy@nokia.com>2009-01-23 14:17:36 +0200
committerArtem Bityutskiy <Artem.Bityutskiy@nokia.com>2009-01-26 12:54:11 +0200
commite4d9b6cbfc98d696a28d2c24a3d49768695811ee (patch)
tree5d76848d68add2830efa29b16425e2f07b4f1967 /fs/ubifs/super.c
parent82c1593cad3dfc97661764c8bc62aa1a416e9ea8 (diff)
UBIFS: fix LEB list freeing
When freeing the c->idx_lebs list, we have to release the LEBs as well, because we might be called from mount to read-only mode code. Otherwise the LEBs stay taken forever, which may cause problems when we re-mount back ro RW mode. Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
Diffstat (limited to 'fs/ubifs/super.c')
-rw-r--r--fs/ubifs/super.c42
1 files changed, 27 insertions, 15 deletions
diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c
index da99da098ef..807bbd3c8b4 100644
--- a/fs/ubifs/super.c
+++ b/fs/ubifs/super.c
@@ -1469,9 +1469,6 @@ static int ubifs_remount_rw(struct ubifs_info *c)
{
int err, lnum;
- if (c->ro_media)
- return -EINVAL;
-
mutex_lock(&c->umount_mutex);
c->remounting_rw = 1;
c->always_chk_crc = 1;
@@ -1605,9 +1602,13 @@ out:
*/
static void commit_on_unmount(struct ubifs_info *c)
{
- struct super_block *sb = c->vfs_sb;
long long bud_bytes;
+ if (!c->fast_unmount) {
+ dbg_gen("skip committing - fast unmount enabled");
+ return;
+ }
+
/*
* This function is called before the background thread is stopped, so
* we may race with ongoing commit, which means we have to take
@@ -1617,8 +1618,11 @@ static void commit_on_unmount(struct ubifs_info *c)
bud_bytes = c->bud_bytes;
spin_unlock(&c->buds_lock);
- if (!c->fast_unmount && !(sb->s_flags & MS_RDONLY) && bud_bytes)
+ if (bud_bytes) {
+ dbg_gen("run commit");
ubifs_run_commit(c);
+ } else
+ dbg_gen("journal is empty, do not run commit");
}
/**
@@ -1633,6 +1637,8 @@ static void ubifs_remount_ro(struct ubifs_info *c)
int i, err;
ubifs_assert(!c->need_recovery);
+ ubifs_assert(!c->ro_media);
+
commit_on_unmount(c);
mutex_lock(&c->umount_mutex);
@@ -1646,16 +1652,17 @@ static void ubifs_remount_ro(struct ubifs_info *c)
del_timer_sync(&c->jheads[i].wbuf.timer);
}
- if (!c->ro_media) {
- c->mst_node->flags &= ~cpu_to_le32(UBIFS_MST_DIRTY);
- c->mst_node->flags |= cpu_to_le32(UBIFS_MST_NO_ORPHS);
- c->mst_node->gc_lnum = cpu_to_le32(c->gc_lnum);
- err = ubifs_write_master(c);
- if (err)
- ubifs_ro_mode(c, err);
- }
+ c->mst_node->flags &= ~cpu_to_le32(UBIFS_MST_DIRTY);
+ c->mst_node->flags |= cpu_to_le32(UBIFS_MST_NO_ORPHS);
+ c->mst_node->gc_lnum = cpu_to_le32(c->gc_lnum);
+ err = ubifs_write_master(c);
+ if (err)
+ ubifs_ro_mode(c, err);
+
+ err = ubifs_destroy_idx_gc(c);
+ if (err)
+ ubifs_ro_mode(c, err);
- ubifs_destroy_idx_gc(c);
free_wbufs(c);
vfree(c->orph_buf);
c->orph_buf = NULL;
@@ -1754,6 +1761,11 @@ static int ubifs_remount_fs(struct super_block *sb, int *flags, char *data)
}
if ((sb->s_flags & MS_RDONLY) && !(*flags & MS_RDONLY)) {
+ if (c->ro_media) {
+ ubifs_msg("cannot re-mount R/W, UBIFS is working in "
+ "R/O mode");
+ return -EINVAL;
+ }
err = ubifs_remount_rw(c);
if (err)
return err;
@@ -2044,7 +2056,7 @@ static void ubifs_kill_sb(struct super_block *sb)
* We do 'commit_on_unmount()' here instead of 'ubifs_put_super()'
* in order to be outside BKL.
*/
- if (sb->s_root)
+ if (sb->s_root && !(sb->s_flags & MS_RDONLY))
commit_on_unmount(c);
/* The un-mount routine is actually done in put_super() */
generic_shutdown_super(sb);