示例#1
0
/**
 * ubifs_log_end_commit - end commit.
 * @c: UBIFS file-system description object
 * @ltail_lnum: new log tail LEB number
 *
 * This function is called on when the commit operation was finished. It
 * moves log tail to new position and updates the master node so that it stores
 * the new log tail LEB number. Returns zero in case of success and a negative
 * error code in case of failure.
 */
int ubifs_log_end_commit(struct ubifs_info *c, int ltail_lnum)
{
	int err;

	/*
	 * At this phase we have to lock 'c->log_mutex' because UBIFS allows FS
	 * writes during commit. Its only short "commit" start phase when
	 * writers are blocked.
	 */
	mutex_lock(&c->log_mutex);

	dbg_log("old tail was LEB %d:0, new tail is LEB %d:0",
		c->ltail_lnum, ltail_lnum);

	c->ltail_lnum = ltail_lnum;
	/*
	 * The commit is finished and from now on it must be guaranteed that
	 * there is always enough space for the next commit.
	 */
	c->min_log_bytes = c->leb_size;

	spin_lock(&c->buds_lock);
	c->bud_bytes -= c->cmt_bud_bytes;
	spin_unlock(&c->buds_lock);

	err = dbg_check_bud_bytes(c);
	if (err)
		goto out;

	err = ubifs_write_master(c);

out:
	mutex_unlock(&c->log_mutex);
	return err;
}
示例#2
0
/**
 * do_commit - commit the journal.
 * @c: UBIFS file-system description object
 *
 * This function implements UBIFS commit. It has to be called with commit lock
 * locked. Returns zero in case of success and a negative error code in case of
 * failure.
 */
static int do_commit(struct ubifs_info *c)
{
	int err, new_ltail_lnum, old_ltail_lnum, i;
	struct ubifs_zbranch zroot;
	struct ubifs_lp_stats lst;

	dbg_cmt("start");
	if (c->ro_media) {
		err = -EROFS;
		goto out_up;
	}

	/* Sync all write buffers (necessary for recovery) */
	for (i = 0; i < c->jhead_cnt; i++) {
		err = ubifs_wbuf_sync(&c->jheads[i].wbuf);
		if (err)
			goto out_up;
	}

	c->cmt_no += 1;
	err = ubifs_gc_start_commit(c);
	if (err)
		goto out_up;
	err = dbg_check_lprops(c);
	if (err)
		goto out_up;
	err = ubifs_log_start_commit(c, &new_ltail_lnum);
	if (err)
		goto out_up;
	err = ubifs_tnc_start_commit(c, &zroot);
	if (err)
		goto out_up;
	err = ubifs_lpt_start_commit(c);
	if (err)
		goto out_up;
	err = ubifs_orphan_start_commit(c);
	if (err)
		goto out_up;

	ubifs_get_lp_stats(c, &lst);

	up_write(&c->commit_sem);

	err = ubifs_tnc_end_commit(c);
	if (err)
		goto out;
	err = ubifs_lpt_end_commit(c);
	if (err)
		goto out;
	err = ubifs_orphan_end_commit(c);
	if (err)
		goto out;
	old_ltail_lnum = c->ltail_lnum;
	err = ubifs_log_end_commit(c, new_ltail_lnum);
	if (err)
		goto out;
	err = dbg_check_old_index(c, &zroot);
	if (err)
		goto out;

	mutex_lock(&c->mst_mutex);
	c->mst_node->cmt_no      = cpu_to_le64(c->cmt_no);
	c->mst_node->log_lnum    = cpu_to_le32(new_ltail_lnum);
	c->mst_node->root_lnum   = cpu_to_le32(zroot.lnum);
	c->mst_node->root_offs   = cpu_to_le32(zroot.offs);
	c->mst_node->root_len    = cpu_to_le32(zroot.len);
	c->mst_node->ihead_lnum  = cpu_to_le32(c->ihead_lnum);
	c->mst_node->ihead_offs  = cpu_to_le32(c->ihead_offs);
	c->mst_node->index_size  = cpu_to_le64(c->old_idx_sz);
	c->mst_node->lpt_lnum    = cpu_to_le32(c->lpt_lnum);
	c->mst_node->lpt_offs    = cpu_to_le32(c->lpt_offs);
	c->mst_node->nhead_lnum  = cpu_to_le32(c->nhead_lnum);
	c->mst_node->nhead_offs  = cpu_to_le32(c->nhead_offs);
	c->mst_node->ltab_lnum   = cpu_to_le32(c->ltab_lnum);
	c->mst_node->ltab_offs   = cpu_to_le32(c->ltab_offs);
	c->mst_node->lsave_lnum  = cpu_to_le32(c->lsave_lnum);
	c->mst_node->lsave_offs  = cpu_to_le32(c->lsave_offs);
	c->mst_node->lscan_lnum  = cpu_to_le32(c->lscan_lnum);
	c->mst_node->empty_lebs  = cpu_to_le32(lst.empty_lebs);
	c->mst_node->idx_lebs    = cpu_to_le32(lst.idx_lebs);
	c->mst_node->total_free  = cpu_to_le64(lst.total_free);
	c->mst_node->total_dirty = cpu_to_le64(lst.total_dirty);
	c->mst_node->total_used  = cpu_to_le64(lst.total_used);
	c->mst_node->total_dead  = cpu_to_le64(lst.total_dead);
	c->mst_node->total_dark  = cpu_to_le64(lst.total_dark);
	if (c->no_orphs)
		c->mst_node->flags |= cpu_to_le32(UBIFS_MST_NO_ORPHS);
	else
		c->mst_node->flags &= ~cpu_to_le32(UBIFS_MST_NO_ORPHS);
	err = ubifs_write_master(c);
	mutex_unlock(&c->mst_mutex);
	if (err)
		goto out;

	err = ubifs_log_post_commit(c, old_ltail_lnum);
	if (err)
		goto out;
	err = ubifs_gc_end_commit(c);
	if (err)
		goto out;
	err = ubifs_lpt_post_commit(c);
	if (err)
		goto out;

	spin_lock(&c->cs_lock);
	c->cmt_state = COMMIT_RESTING;
	wake_up(&c->cmt_wq);
	dbg_cmt("commit end");
	spin_unlock(&c->cs_lock);

	return 0;

out_up:
	up_write(&c->commit_sem);
out:
	ubifs_err("commit failed, error %d", err);
	spin_lock(&c->cs_lock);
	c->cmt_state = COMMIT_BROKEN;
	wake_up(&c->cmt_wq);
	spin_unlock(&c->cs_lock);
	ubifs_ro_mode(c, err);
	return err;
}