/** * 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; }
/** * 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; }