* ubifs_destroy_idx_gc - destroy idx_gc list.
* @c: UBIFS file-system description object
*
- * This function destroys the idx_gc list. It is called when unmounting or
- * remounting read-only so locks are not needed.
+ * This function destroys the @c->idx_gc list. It is called when unmounting or
+ * remounting read-only so locks are not needed. Returns zero in case of
+ * success and a negative error code in case of failure.
*/
-void ubifs_destroy_idx_gc(struct ubifs_info *c)
+int ubifs_destroy_idx_gc(struct ubifs_info *c)
{
+ int ret = 0;
+
while (!list_empty(&c->idx_gc)) {
+ int err;
struct ubifs_gced_idx_leb *idx_gc;
idx_gc = list_entry(c->idx_gc.next, struct ubifs_gced_idx_leb,
list);
- c->idx_gc_cnt -= 1;
+ err = ubifs_change_one_lp(c, idx_gc->lnum, LPROPS_NC,
+ LPROPS_NC, 0, LPROPS_TAKEN, -1);
+ if (err && !ret)
+ ret = err;
list_del(&idx_gc->list);
kfree(idx_gc);
}
+ return ret;
}
/**
out:
ubifs_release_lprops(c);
+ if (err)
+ ubifs_err("cannot change properties of LEB %d, error %d",
+ lnum, err);
return err;
}
out:
ubifs_release_lprops(c);
+ if (err)
+ ubifs_err("cannot update properties of LEB %d, error %d",
+ lnum, err);
return err;
}
lpp = ubifs_lpt_lookup(c, lnum);
if (IS_ERR(lpp)) {
err = PTR_ERR(lpp);
+ ubifs_err("cannot read properties of LEB %d, error %d",
+ lnum, err);
goto out;
}
{
int err, lnum;
- if (c->ro_media)
- return -EINVAL;
-
mutex_lock(&c->umount_mutex);
c->remounting_rw = 1;
c->always_chk_crc = 1;
*/
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
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");
}
/**
int i, err;
ubifs_assert(!c->need_recovery);
+ ubifs_assert(!c->ro_media);
+
commit_on_unmount(c);
mutex_lock(&c->umount_mutex);
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;
}
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;
* 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);
int ubifs_garbage_collect(struct ubifs_info *c, int anyway);
int ubifs_gc_start_commit(struct ubifs_info *c);
int ubifs_gc_end_commit(struct ubifs_info *c);
-void ubifs_destroy_idx_gc(struct ubifs_info *c);
+int ubifs_destroy_idx_gc(struct ubifs_info *c);
int ubifs_get_idx_gc_leb(struct ubifs_info *c);
int ubifs_garbage_collect_leb(struct ubifs_info *c, struct ubifs_lprops *lp);