162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * This file is part of UBIFS. 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2006-2008 Nokia Corporation. 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Authors: Adrian Hunter 862306a36Sopenharmony_ci * Artem Bityutskiy (Битюцкий Артём) 962306a36Sopenharmony_ci */ 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci/* 1262306a36Sopenharmony_ci * This file implements functions that manage the running of the commit process. 1362306a36Sopenharmony_ci * Each affected module has its own functions to accomplish their part in the 1462306a36Sopenharmony_ci * commit and those functions are called here. 1562306a36Sopenharmony_ci * 1662306a36Sopenharmony_ci * The commit is the process whereby all updates to the index and LEB properties 1762306a36Sopenharmony_ci * are written out together and the journal becomes empty. This keeps the 1862306a36Sopenharmony_ci * file system consistent - at all times the state can be recreated by reading 1962306a36Sopenharmony_ci * the index and LEB properties and then replaying the journal. 2062306a36Sopenharmony_ci * 2162306a36Sopenharmony_ci * The commit is split into two parts named "commit start" and "commit end". 2262306a36Sopenharmony_ci * During commit start, the commit process has exclusive access to the journal 2362306a36Sopenharmony_ci * by holding the commit semaphore down for writing. As few I/O operations as 2462306a36Sopenharmony_ci * possible are performed during commit start, instead the nodes that are to be 2562306a36Sopenharmony_ci * written are merely identified. During commit end, the commit semaphore is no 2662306a36Sopenharmony_ci * longer held and the journal is again in operation, allowing users to continue 2762306a36Sopenharmony_ci * to use the file system while the bulk of the commit I/O is performed. The 2862306a36Sopenharmony_ci * purpose of this two-step approach is to prevent the commit from causing any 2962306a36Sopenharmony_ci * latency blips. Note that in any case, the commit does not prevent lookups 3062306a36Sopenharmony_ci * (as permitted by the TNC mutex), or access to VFS data structures e.g. page 3162306a36Sopenharmony_ci * cache. 3262306a36Sopenharmony_ci */ 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci#include <linux/freezer.h> 3562306a36Sopenharmony_ci#include <linux/kthread.h> 3662306a36Sopenharmony_ci#include <linux/slab.h> 3762306a36Sopenharmony_ci#include "ubifs.h" 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci/* 4062306a36Sopenharmony_ci * nothing_to_commit - check if there is nothing to commit. 4162306a36Sopenharmony_ci * @c: UBIFS file-system description object 4262306a36Sopenharmony_ci * 4362306a36Sopenharmony_ci * This is a helper function which checks if there is anything to commit. It is 4462306a36Sopenharmony_ci * used as an optimization to avoid starting the commit if it is not really 4562306a36Sopenharmony_ci * necessary. Indeed, the commit operation always assumes flash I/O (e.g., 4662306a36Sopenharmony_ci * writing the commit start node to the log), and it is better to avoid doing 4762306a36Sopenharmony_ci * this unnecessarily. E.g., 'ubifs_sync_fs()' runs the commit, but if there is 4862306a36Sopenharmony_ci * nothing to commit, it is more optimal to avoid any flash I/O. 4962306a36Sopenharmony_ci * 5062306a36Sopenharmony_ci * This function has to be called with @c->commit_sem locked for writing - 5162306a36Sopenharmony_ci * this function does not take LPT/TNC locks because the @c->commit_sem 5262306a36Sopenharmony_ci * guarantees that we have exclusive access to the TNC and LPT data structures. 5362306a36Sopenharmony_ci * 5462306a36Sopenharmony_ci * This function returns %1 if there is nothing to commit and %0 otherwise. 5562306a36Sopenharmony_ci */ 5662306a36Sopenharmony_cistatic int nothing_to_commit(struct ubifs_info *c) 5762306a36Sopenharmony_ci{ 5862306a36Sopenharmony_ci /* 5962306a36Sopenharmony_ci * During mounting or remounting from R/O mode to R/W mode we may 6062306a36Sopenharmony_ci * commit for various recovery-related reasons. 6162306a36Sopenharmony_ci */ 6262306a36Sopenharmony_ci if (c->mounting || c->remounting_rw) 6362306a36Sopenharmony_ci return 0; 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci /* 6662306a36Sopenharmony_ci * If the root TNC node is dirty, we definitely have something to 6762306a36Sopenharmony_ci * commit. 6862306a36Sopenharmony_ci */ 6962306a36Sopenharmony_ci if (c->zroot.znode && ubifs_zn_dirty(c->zroot.znode)) 7062306a36Sopenharmony_ci return 0; 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci /* 7362306a36Sopenharmony_ci * Even though the TNC is clean, the LPT tree may have dirty nodes. For 7462306a36Sopenharmony_ci * example, this may happen if the budgeting subsystem invoked GC to 7562306a36Sopenharmony_ci * make some free space, and the GC found an LEB with only dirty and 7662306a36Sopenharmony_ci * free space. In this case GC would just change the lprops of this 7762306a36Sopenharmony_ci * LEB (by turning all space into free space) and unmap it. 7862306a36Sopenharmony_ci */ 7962306a36Sopenharmony_ci if (c->nroot && test_bit(DIRTY_CNODE, &c->nroot->flags)) 8062306a36Sopenharmony_ci return 0; 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci ubifs_assert(c, atomic_long_read(&c->dirty_zn_cnt) == 0); 8362306a36Sopenharmony_ci ubifs_assert(c, c->dirty_pn_cnt == 0); 8462306a36Sopenharmony_ci ubifs_assert(c, c->dirty_nn_cnt == 0); 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci return 1; 8762306a36Sopenharmony_ci} 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci/** 9062306a36Sopenharmony_ci * do_commit - commit the journal. 9162306a36Sopenharmony_ci * @c: UBIFS file-system description object 9262306a36Sopenharmony_ci * 9362306a36Sopenharmony_ci * This function implements UBIFS commit. It has to be called with commit lock 9462306a36Sopenharmony_ci * locked. Returns zero in case of success and a negative error code in case of 9562306a36Sopenharmony_ci * failure. 9662306a36Sopenharmony_ci */ 9762306a36Sopenharmony_cistatic int do_commit(struct ubifs_info *c) 9862306a36Sopenharmony_ci{ 9962306a36Sopenharmony_ci int err, new_ltail_lnum, old_ltail_lnum, i; 10062306a36Sopenharmony_ci struct ubifs_zbranch zroot; 10162306a36Sopenharmony_ci struct ubifs_lp_stats lst; 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci dbg_cmt("start"); 10462306a36Sopenharmony_ci ubifs_assert(c, !c->ro_media && !c->ro_mount); 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_ci if (c->ro_error) { 10762306a36Sopenharmony_ci err = -EROFS; 10862306a36Sopenharmony_ci goto out_up; 10962306a36Sopenharmony_ci } 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci if (nothing_to_commit(c)) { 11262306a36Sopenharmony_ci up_write(&c->commit_sem); 11362306a36Sopenharmony_ci err = 0; 11462306a36Sopenharmony_ci goto out_cancel; 11562306a36Sopenharmony_ci } 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci /* Sync all write buffers (necessary for recovery) */ 11862306a36Sopenharmony_ci for (i = 0; i < c->jhead_cnt; i++) { 11962306a36Sopenharmony_ci err = ubifs_wbuf_sync(&c->jheads[i].wbuf); 12062306a36Sopenharmony_ci if (err) 12162306a36Sopenharmony_ci goto out_up; 12262306a36Sopenharmony_ci } 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci c->cmt_no += 1; 12562306a36Sopenharmony_ci err = ubifs_gc_start_commit(c); 12662306a36Sopenharmony_ci if (err) 12762306a36Sopenharmony_ci goto out_up; 12862306a36Sopenharmony_ci err = dbg_check_lprops(c); 12962306a36Sopenharmony_ci if (err) 13062306a36Sopenharmony_ci goto out_up; 13162306a36Sopenharmony_ci err = ubifs_log_start_commit(c, &new_ltail_lnum); 13262306a36Sopenharmony_ci if (err) 13362306a36Sopenharmony_ci goto out_up; 13462306a36Sopenharmony_ci err = ubifs_tnc_start_commit(c, &zroot); 13562306a36Sopenharmony_ci if (err) 13662306a36Sopenharmony_ci goto out_up; 13762306a36Sopenharmony_ci err = ubifs_lpt_start_commit(c); 13862306a36Sopenharmony_ci if (err) 13962306a36Sopenharmony_ci goto out_up; 14062306a36Sopenharmony_ci err = ubifs_orphan_start_commit(c); 14162306a36Sopenharmony_ci if (err) 14262306a36Sopenharmony_ci goto out_up; 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_ci ubifs_get_lp_stats(c, &lst); 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci up_write(&c->commit_sem); 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci err = ubifs_tnc_end_commit(c); 14962306a36Sopenharmony_ci if (err) 15062306a36Sopenharmony_ci goto out; 15162306a36Sopenharmony_ci err = ubifs_lpt_end_commit(c); 15262306a36Sopenharmony_ci if (err) 15362306a36Sopenharmony_ci goto out; 15462306a36Sopenharmony_ci err = ubifs_orphan_end_commit(c); 15562306a36Sopenharmony_ci if (err) 15662306a36Sopenharmony_ci goto out; 15762306a36Sopenharmony_ci err = dbg_check_old_index(c, &zroot); 15862306a36Sopenharmony_ci if (err) 15962306a36Sopenharmony_ci goto out; 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ci c->mst_node->cmt_no = cpu_to_le64(c->cmt_no); 16262306a36Sopenharmony_ci c->mst_node->log_lnum = cpu_to_le32(new_ltail_lnum); 16362306a36Sopenharmony_ci c->mst_node->root_lnum = cpu_to_le32(zroot.lnum); 16462306a36Sopenharmony_ci c->mst_node->root_offs = cpu_to_le32(zroot.offs); 16562306a36Sopenharmony_ci c->mst_node->root_len = cpu_to_le32(zroot.len); 16662306a36Sopenharmony_ci c->mst_node->ihead_lnum = cpu_to_le32(c->ihead_lnum); 16762306a36Sopenharmony_ci c->mst_node->ihead_offs = cpu_to_le32(c->ihead_offs); 16862306a36Sopenharmony_ci c->mst_node->index_size = cpu_to_le64(c->bi.old_idx_sz); 16962306a36Sopenharmony_ci c->mst_node->lpt_lnum = cpu_to_le32(c->lpt_lnum); 17062306a36Sopenharmony_ci c->mst_node->lpt_offs = cpu_to_le32(c->lpt_offs); 17162306a36Sopenharmony_ci c->mst_node->nhead_lnum = cpu_to_le32(c->nhead_lnum); 17262306a36Sopenharmony_ci c->mst_node->nhead_offs = cpu_to_le32(c->nhead_offs); 17362306a36Sopenharmony_ci c->mst_node->ltab_lnum = cpu_to_le32(c->ltab_lnum); 17462306a36Sopenharmony_ci c->mst_node->ltab_offs = cpu_to_le32(c->ltab_offs); 17562306a36Sopenharmony_ci c->mst_node->lsave_lnum = cpu_to_le32(c->lsave_lnum); 17662306a36Sopenharmony_ci c->mst_node->lsave_offs = cpu_to_le32(c->lsave_offs); 17762306a36Sopenharmony_ci c->mst_node->lscan_lnum = cpu_to_le32(c->lscan_lnum); 17862306a36Sopenharmony_ci c->mst_node->empty_lebs = cpu_to_le32(lst.empty_lebs); 17962306a36Sopenharmony_ci c->mst_node->idx_lebs = cpu_to_le32(lst.idx_lebs); 18062306a36Sopenharmony_ci c->mst_node->total_free = cpu_to_le64(lst.total_free); 18162306a36Sopenharmony_ci c->mst_node->total_dirty = cpu_to_le64(lst.total_dirty); 18262306a36Sopenharmony_ci c->mst_node->total_used = cpu_to_le64(lst.total_used); 18362306a36Sopenharmony_ci c->mst_node->total_dead = cpu_to_le64(lst.total_dead); 18462306a36Sopenharmony_ci c->mst_node->total_dark = cpu_to_le64(lst.total_dark); 18562306a36Sopenharmony_ci if (c->no_orphs) 18662306a36Sopenharmony_ci c->mst_node->flags |= cpu_to_le32(UBIFS_MST_NO_ORPHS); 18762306a36Sopenharmony_ci else 18862306a36Sopenharmony_ci c->mst_node->flags &= ~cpu_to_le32(UBIFS_MST_NO_ORPHS); 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ci old_ltail_lnum = c->ltail_lnum; 19162306a36Sopenharmony_ci err = ubifs_log_end_commit(c, new_ltail_lnum); 19262306a36Sopenharmony_ci if (err) 19362306a36Sopenharmony_ci goto out; 19462306a36Sopenharmony_ci 19562306a36Sopenharmony_ci err = ubifs_log_post_commit(c, old_ltail_lnum); 19662306a36Sopenharmony_ci if (err) 19762306a36Sopenharmony_ci goto out; 19862306a36Sopenharmony_ci err = ubifs_gc_end_commit(c); 19962306a36Sopenharmony_ci if (err) 20062306a36Sopenharmony_ci goto out; 20162306a36Sopenharmony_ci err = ubifs_lpt_post_commit(c); 20262306a36Sopenharmony_ci if (err) 20362306a36Sopenharmony_ci goto out; 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ciout_cancel: 20662306a36Sopenharmony_ci spin_lock(&c->cs_lock); 20762306a36Sopenharmony_ci c->cmt_state = COMMIT_RESTING; 20862306a36Sopenharmony_ci wake_up(&c->cmt_wq); 20962306a36Sopenharmony_ci dbg_cmt("commit end"); 21062306a36Sopenharmony_ci spin_unlock(&c->cs_lock); 21162306a36Sopenharmony_ci return 0; 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_ciout_up: 21462306a36Sopenharmony_ci up_write(&c->commit_sem); 21562306a36Sopenharmony_ciout: 21662306a36Sopenharmony_ci ubifs_err(c, "commit failed, error %d", err); 21762306a36Sopenharmony_ci spin_lock(&c->cs_lock); 21862306a36Sopenharmony_ci c->cmt_state = COMMIT_BROKEN; 21962306a36Sopenharmony_ci wake_up(&c->cmt_wq); 22062306a36Sopenharmony_ci spin_unlock(&c->cs_lock); 22162306a36Sopenharmony_ci ubifs_ro_mode(c, err); 22262306a36Sopenharmony_ci return err; 22362306a36Sopenharmony_ci} 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_ci/** 22662306a36Sopenharmony_ci * run_bg_commit - run background commit if it is needed. 22762306a36Sopenharmony_ci * @c: UBIFS file-system description object 22862306a36Sopenharmony_ci * 22962306a36Sopenharmony_ci * This function runs background commit if it is needed. Returns zero in case 23062306a36Sopenharmony_ci * of success and a negative error code in case of failure. 23162306a36Sopenharmony_ci */ 23262306a36Sopenharmony_cistatic int run_bg_commit(struct ubifs_info *c) 23362306a36Sopenharmony_ci{ 23462306a36Sopenharmony_ci spin_lock(&c->cs_lock); 23562306a36Sopenharmony_ci /* 23662306a36Sopenharmony_ci * Run background commit only if background commit was requested or if 23762306a36Sopenharmony_ci * commit is required. 23862306a36Sopenharmony_ci */ 23962306a36Sopenharmony_ci if (c->cmt_state != COMMIT_BACKGROUND && 24062306a36Sopenharmony_ci c->cmt_state != COMMIT_REQUIRED) 24162306a36Sopenharmony_ci goto out; 24262306a36Sopenharmony_ci spin_unlock(&c->cs_lock); 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ci down_write(&c->commit_sem); 24562306a36Sopenharmony_ci spin_lock(&c->cs_lock); 24662306a36Sopenharmony_ci if (c->cmt_state == COMMIT_REQUIRED) 24762306a36Sopenharmony_ci c->cmt_state = COMMIT_RUNNING_REQUIRED; 24862306a36Sopenharmony_ci else if (c->cmt_state == COMMIT_BACKGROUND) 24962306a36Sopenharmony_ci c->cmt_state = COMMIT_RUNNING_BACKGROUND; 25062306a36Sopenharmony_ci else 25162306a36Sopenharmony_ci goto out_cmt_unlock; 25262306a36Sopenharmony_ci spin_unlock(&c->cs_lock); 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_ci return do_commit(c); 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ciout_cmt_unlock: 25762306a36Sopenharmony_ci up_write(&c->commit_sem); 25862306a36Sopenharmony_ciout: 25962306a36Sopenharmony_ci spin_unlock(&c->cs_lock); 26062306a36Sopenharmony_ci return 0; 26162306a36Sopenharmony_ci} 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_ci/** 26462306a36Sopenharmony_ci * ubifs_bg_thread - UBIFS background thread function. 26562306a36Sopenharmony_ci * @info: points to the file-system description object 26662306a36Sopenharmony_ci * 26762306a36Sopenharmony_ci * This function implements various file-system background activities: 26862306a36Sopenharmony_ci * o when a write-buffer timer expires it synchronizes the appropriate 26962306a36Sopenharmony_ci * write-buffer; 27062306a36Sopenharmony_ci * o when the journal is about to be full, it starts in-advance commit. 27162306a36Sopenharmony_ci * 27262306a36Sopenharmony_ci * Note, other stuff like background garbage collection may be added here in 27362306a36Sopenharmony_ci * future. 27462306a36Sopenharmony_ci */ 27562306a36Sopenharmony_ciint ubifs_bg_thread(void *info) 27662306a36Sopenharmony_ci{ 27762306a36Sopenharmony_ci int err; 27862306a36Sopenharmony_ci struct ubifs_info *c = info; 27962306a36Sopenharmony_ci 28062306a36Sopenharmony_ci ubifs_msg(c, "background thread \"%s\" started, PID %d", 28162306a36Sopenharmony_ci c->bgt_name, current->pid); 28262306a36Sopenharmony_ci set_freezable(); 28362306a36Sopenharmony_ci 28462306a36Sopenharmony_ci while (1) { 28562306a36Sopenharmony_ci if (kthread_should_stop()) 28662306a36Sopenharmony_ci break; 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ci if (try_to_freeze()) 28962306a36Sopenharmony_ci continue; 29062306a36Sopenharmony_ci 29162306a36Sopenharmony_ci set_current_state(TASK_INTERRUPTIBLE); 29262306a36Sopenharmony_ci /* Check if there is something to do */ 29362306a36Sopenharmony_ci if (!c->need_bgt) { 29462306a36Sopenharmony_ci /* 29562306a36Sopenharmony_ci * Nothing prevents us from going sleep now and 29662306a36Sopenharmony_ci * be never woken up and block the task which 29762306a36Sopenharmony_ci * could wait in 'kthread_stop()' forever. 29862306a36Sopenharmony_ci */ 29962306a36Sopenharmony_ci if (kthread_should_stop()) 30062306a36Sopenharmony_ci break; 30162306a36Sopenharmony_ci schedule(); 30262306a36Sopenharmony_ci continue; 30362306a36Sopenharmony_ci } else 30462306a36Sopenharmony_ci __set_current_state(TASK_RUNNING); 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_ci c->need_bgt = 0; 30762306a36Sopenharmony_ci err = ubifs_bg_wbufs_sync(c); 30862306a36Sopenharmony_ci if (err) 30962306a36Sopenharmony_ci ubifs_ro_mode(c, err); 31062306a36Sopenharmony_ci 31162306a36Sopenharmony_ci run_bg_commit(c); 31262306a36Sopenharmony_ci cond_resched(); 31362306a36Sopenharmony_ci } 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_ci ubifs_msg(c, "background thread \"%s\" stops", c->bgt_name); 31662306a36Sopenharmony_ci return 0; 31762306a36Sopenharmony_ci} 31862306a36Sopenharmony_ci 31962306a36Sopenharmony_ci/** 32062306a36Sopenharmony_ci * ubifs_commit_required - set commit state to "required". 32162306a36Sopenharmony_ci * @c: UBIFS file-system description object 32262306a36Sopenharmony_ci * 32362306a36Sopenharmony_ci * This function is called if a commit is required but cannot be done from the 32462306a36Sopenharmony_ci * calling function, so it is just flagged instead. 32562306a36Sopenharmony_ci */ 32662306a36Sopenharmony_civoid ubifs_commit_required(struct ubifs_info *c) 32762306a36Sopenharmony_ci{ 32862306a36Sopenharmony_ci spin_lock(&c->cs_lock); 32962306a36Sopenharmony_ci switch (c->cmt_state) { 33062306a36Sopenharmony_ci case COMMIT_RESTING: 33162306a36Sopenharmony_ci case COMMIT_BACKGROUND: 33262306a36Sopenharmony_ci dbg_cmt("old: %s, new: %s", dbg_cstate(c->cmt_state), 33362306a36Sopenharmony_ci dbg_cstate(COMMIT_REQUIRED)); 33462306a36Sopenharmony_ci c->cmt_state = COMMIT_REQUIRED; 33562306a36Sopenharmony_ci break; 33662306a36Sopenharmony_ci case COMMIT_RUNNING_BACKGROUND: 33762306a36Sopenharmony_ci dbg_cmt("old: %s, new: %s", dbg_cstate(c->cmt_state), 33862306a36Sopenharmony_ci dbg_cstate(COMMIT_RUNNING_REQUIRED)); 33962306a36Sopenharmony_ci c->cmt_state = COMMIT_RUNNING_REQUIRED; 34062306a36Sopenharmony_ci break; 34162306a36Sopenharmony_ci case COMMIT_REQUIRED: 34262306a36Sopenharmony_ci case COMMIT_RUNNING_REQUIRED: 34362306a36Sopenharmony_ci case COMMIT_BROKEN: 34462306a36Sopenharmony_ci break; 34562306a36Sopenharmony_ci } 34662306a36Sopenharmony_ci spin_unlock(&c->cs_lock); 34762306a36Sopenharmony_ci} 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_ci/** 35062306a36Sopenharmony_ci * ubifs_request_bg_commit - notify the background thread to do a commit. 35162306a36Sopenharmony_ci * @c: UBIFS file-system description object 35262306a36Sopenharmony_ci * 35362306a36Sopenharmony_ci * This function is called if the journal is full enough to make a commit 35462306a36Sopenharmony_ci * worthwhile, so background thread is kicked to start it. 35562306a36Sopenharmony_ci */ 35662306a36Sopenharmony_civoid ubifs_request_bg_commit(struct ubifs_info *c) 35762306a36Sopenharmony_ci{ 35862306a36Sopenharmony_ci spin_lock(&c->cs_lock); 35962306a36Sopenharmony_ci if (c->cmt_state == COMMIT_RESTING) { 36062306a36Sopenharmony_ci dbg_cmt("old: %s, new: %s", dbg_cstate(c->cmt_state), 36162306a36Sopenharmony_ci dbg_cstate(COMMIT_BACKGROUND)); 36262306a36Sopenharmony_ci c->cmt_state = COMMIT_BACKGROUND; 36362306a36Sopenharmony_ci spin_unlock(&c->cs_lock); 36462306a36Sopenharmony_ci ubifs_wake_up_bgt(c); 36562306a36Sopenharmony_ci } else 36662306a36Sopenharmony_ci spin_unlock(&c->cs_lock); 36762306a36Sopenharmony_ci} 36862306a36Sopenharmony_ci 36962306a36Sopenharmony_ci/** 37062306a36Sopenharmony_ci * wait_for_commit - wait for commit. 37162306a36Sopenharmony_ci * @c: UBIFS file-system description object 37262306a36Sopenharmony_ci * 37362306a36Sopenharmony_ci * This function sleeps until the commit operation is no longer running. 37462306a36Sopenharmony_ci */ 37562306a36Sopenharmony_cistatic int wait_for_commit(struct ubifs_info *c) 37662306a36Sopenharmony_ci{ 37762306a36Sopenharmony_ci dbg_cmt("pid %d goes sleep", current->pid); 37862306a36Sopenharmony_ci 37962306a36Sopenharmony_ci /* 38062306a36Sopenharmony_ci * The following sleeps if the condition is false, and will be woken 38162306a36Sopenharmony_ci * when the commit ends. It is possible, although very unlikely, that we 38262306a36Sopenharmony_ci * will wake up and see the subsequent commit running, rather than the 38362306a36Sopenharmony_ci * one we were waiting for, and go back to sleep. However, we will be 38462306a36Sopenharmony_ci * woken again, so there is no danger of sleeping forever. 38562306a36Sopenharmony_ci */ 38662306a36Sopenharmony_ci wait_event(c->cmt_wq, c->cmt_state != COMMIT_RUNNING_BACKGROUND && 38762306a36Sopenharmony_ci c->cmt_state != COMMIT_RUNNING_REQUIRED); 38862306a36Sopenharmony_ci dbg_cmt("commit finished, pid %d woke up", current->pid); 38962306a36Sopenharmony_ci return 0; 39062306a36Sopenharmony_ci} 39162306a36Sopenharmony_ci 39262306a36Sopenharmony_ci/** 39362306a36Sopenharmony_ci * ubifs_run_commit - run or wait for commit. 39462306a36Sopenharmony_ci * @c: UBIFS file-system description object 39562306a36Sopenharmony_ci * 39662306a36Sopenharmony_ci * This function runs commit and returns zero in case of success and a negative 39762306a36Sopenharmony_ci * error code in case of failure. 39862306a36Sopenharmony_ci */ 39962306a36Sopenharmony_ciint ubifs_run_commit(struct ubifs_info *c) 40062306a36Sopenharmony_ci{ 40162306a36Sopenharmony_ci int err = 0; 40262306a36Sopenharmony_ci 40362306a36Sopenharmony_ci spin_lock(&c->cs_lock); 40462306a36Sopenharmony_ci if (c->cmt_state == COMMIT_BROKEN) { 40562306a36Sopenharmony_ci err = -EROFS; 40662306a36Sopenharmony_ci goto out; 40762306a36Sopenharmony_ci } 40862306a36Sopenharmony_ci 40962306a36Sopenharmony_ci if (c->cmt_state == COMMIT_RUNNING_BACKGROUND) 41062306a36Sopenharmony_ci /* 41162306a36Sopenharmony_ci * We set the commit state to 'running required' to indicate 41262306a36Sopenharmony_ci * that we want it to complete as quickly as possible. 41362306a36Sopenharmony_ci */ 41462306a36Sopenharmony_ci c->cmt_state = COMMIT_RUNNING_REQUIRED; 41562306a36Sopenharmony_ci 41662306a36Sopenharmony_ci if (c->cmt_state == COMMIT_RUNNING_REQUIRED) { 41762306a36Sopenharmony_ci spin_unlock(&c->cs_lock); 41862306a36Sopenharmony_ci return wait_for_commit(c); 41962306a36Sopenharmony_ci } 42062306a36Sopenharmony_ci spin_unlock(&c->cs_lock); 42162306a36Sopenharmony_ci 42262306a36Sopenharmony_ci /* Ok, the commit is indeed needed */ 42362306a36Sopenharmony_ci 42462306a36Sopenharmony_ci down_write(&c->commit_sem); 42562306a36Sopenharmony_ci spin_lock(&c->cs_lock); 42662306a36Sopenharmony_ci /* 42762306a36Sopenharmony_ci * Since we unlocked 'c->cs_lock', the state may have changed, so 42862306a36Sopenharmony_ci * re-check it. 42962306a36Sopenharmony_ci */ 43062306a36Sopenharmony_ci if (c->cmt_state == COMMIT_BROKEN) { 43162306a36Sopenharmony_ci err = -EROFS; 43262306a36Sopenharmony_ci goto out_cmt_unlock; 43362306a36Sopenharmony_ci } 43462306a36Sopenharmony_ci 43562306a36Sopenharmony_ci if (c->cmt_state == COMMIT_RUNNING_BACKGROUND) 43662306a36Sopenharmony_ci c->cmt_state = COMMIT_RUNNING_REQUIRED; 43762306a36Sopenharmony_ci 43862306a36Sopenharmony_ci if (c->cmt_state == COMMIT_RUNNING_REQUIRED) { 43962306a36Sopenharmony_ci up_write(&c->commit_sem); 44062306a36Sopenharmony_ci spin_unlock(&c->cs_lock); 44162306a36Sopenharmony_ci return wait_for_commit(c); 44262306a36Sopenharmony_ci } 44362306a36Sopenharmony_ci c->cmt_state = COMMIT_RUNNING_REQUIRED; 44462306a36Sopenharmony_ci spin_unlock(&c->cs_lock); 44562306a36Sopenharmony_ci 44662306a36Sopenharmony_ci err = do_commit(c); 44762306a36Sopenharmony_ci return err; 44862306a36Sopenharmony_ci 44962306a36Sopenharmony_ciout_cmt_unlock: 45062306a36Sopenharmony_ci up_write(&c->commit_sem); 45162306a36Sopenharmony_ciout: 45262306a36Sopenharmony_ci spin_unlock(&c->cs_lock); 45362306a36Sopenharmony_ci return err; 45462306a36Sopenharmony_ci} 45562306a36Sopenharmony_ci 45662306a36Sopenharmony_ci/** 45762306a36Sopenharmony_ci * ubifs_gc_should_commit - determine if it is time for GC to run commit. 45862306a36Sopenharmony_ci * @c: UBIFS file-system description object 45962306a36Sopenharmony_ci * 46062306a36Sopenharmony_ci * This function is called by garbage collection to determine if commit should 46162306a36Sopenharmony_ci * be run. If commit state is @COMMIT_BACKGROUND, which means that the journal 46262306a36Sopenharmony_ci * is full enough to start commit, this function returns true. It is not 46362306a36Sopenharmony_ci * absolutely necessary to commit yet, but it feels like this should be better 46462306a36Sopenharmony_ci * then to keep doing GC. This function returns %1 if GC has to initiate commit 46562306a36Sopenharmony_ci * and %0 if not. 46662306a36Sopenharmony_ci */ 46762306a36Sopenharmony_ciint ubifs_gc_should_commit(struct ubifs_info *c) 46862306a36Sopenharmony_ci{ 46962306a36Sopenharmony_ci int ret = 0; 47062306a36Sopenharmony_ci 47162306a36Sopenharmony_ci spin_lock(&c->cs_lock); 47262306a36Sopenharmony_ci if (c->cmt_state == COMMIT_BACKGROUND) { 47362306a36Sopenharmony_ci dbg_cmt("commit required now"); 47462306a36Sopenharmony_ci c->cmt_state = COMMIT_REQUIRED; 47562306a36Sopenharmony_ci } else 47662306a36Sopenharmony_ci dbg_cmt("commit not requested"); 47762306a36Sopenharmony_ci if (c->cmt_state == COMMIT_REQUIRED) 47862306a36Sopenharmony_ci ret = 1; 47962306a36Sopenharmony_ci spin_unlock(&c->cs_lock); 48062306a36Sopenharmony_ci return ret; 48162306a36Sopenharmony_ci} 48262306a36Sopenharmony_ci 48362306a36Sopenharmony_ci/* 48462306a36Sopenharmony_ci * Everything below is related to debugging. 48562306a36Sopenharmony_ci */ 48662306a36Sopenharmony_ci 48762306a36Sopenharmony_ci/** 48862306a36Sopenharmony_ci * struct idx_node - hold index nodes during index tree traversal. 48962306a36Sopenharmony_ci * @list: list 49062306a36Sopenharmony_ci * @iip: index in parent (slot number of this indexing node in the parent 49162306a36Sopenharmony_ci * indexing node) 49262306a36Sopenharmony_ci * @upper_key: all keys in this indexing node have to be less or equivalent to 49362306a36Sopenharmony_ci * this key 49462306a36Sopenharmony_ci * @idx: index node (8-byte aligned because all node structures must be 8-byte 49562306a36Sopenharmony_ci * aligned) 49662306a36Sopenharmony_ci */ 49762306a36Sopenharmony_cistruct idx_node { 49862306a36Sopenharmony_ci struct list_head list; 49962306a36Sopenharmony_ci int iip; 50062306a36Sopenharmony_ci union ubifs_key upper_key; 50162306a36Sopenharmony_ci struct ubifs_idx_node idx __aligned(8); 50262306a36Sopenharmony_ci}; 50362306a36Sopenharmony_ci 50462306a36Sopenharmony_ci/** 50562306a36Sopenharmony_ci * dbg_old_index_check_init - get information for the next old index check. 50662306a36Sopenharmony_ci * @c: UBIFS file-system description object 50762306a36Sopenharmony_ci * @zroot: root of the index 50862306a36Sopenharmony_ci * 50962306a36Sopenharmony_ci * This function records information about the index that will be needed for the 51062306a36Sopenharmony_ci * next old index check i.e. 'dbg_check_old_index()'. 51162306a36Sopenharmony_ci * 51262306a36Sopenharmony_ci * This function returns %0 on success and a negative error code on failure. 51362306a36Sopenharmony_ci */ 51462306a36Sopenharmony_ciint dbg_old_index_check_init(struct ubifs_info *c, struct ubifs_zbranch *zroot) 51562306a36Sopenharmony_ci{ 51662306a36Sopenharmony_ci struct ubifs_idx_node *idx; 51762306a36Sopenharmony_ci int lnum, offs, len, err = 0; 51862306a36Sopenharmony_ci struct ubifs_debug_info *d = c->dbg; 51962306a36Sopenharmony_ci 52062306a36Sopenharmony_ci d->old_zroot = *zroot; 52162306a36Sopenharmony_ci lnum = d->old_zroot.lnum; 52262306a36Sopenharmony_ci offs = d->old_zroot.offs; 52362306a36Sopenharmony_ci len = d->old_zroot.len; 52462306a36Sopenharmony_ci 52562306a36Sopenharmony_ci idx = kmalloc(c->max_idx_node_sz, GFP_NOFS); 52662306a36Sopenharmony_ci if (!idx) 52762306a36Sopenharmony_ci return -ENOMEM; 52862306a36Sopenharmony_ci 52962306a36Sopenharmony_ci err = ubifs_read_node(c, idx, UBIFS_IDX_NODE, len, lnum, offs); 53062306a36Sopenharmony_ci if (err) 53162306a36Sopenharmony_ci goto out; 53262306a36Sopenharmony_ci 53362306a36Sopenharmony_ci d->old_zroot_level = le16_to_cpu(idx->level); 53462306a36Sopenharmony_ci d->old_zroot_sqnum = le64_to_cpu(idx->ch.sqnum); 53562306a36Sopenharmony_ciout: 53662306a36Sopenharmony_ci kfree(idx); 53762306a36Sopenharmony_ci return err; 53862306a36Sopenharmony_ci} 53962306a36Sopenharmony_ci 54062306a36Sopenharmony_ci/** 54162306a36Sopenharmony_ci * dbg_check_old_index - check the old copy of the index. 54262306a36Sopenharmony_ci * @c: UBIFS file-system description object 54362306a36Sopenharmony_ci * @zroot: root of the new index 54462306a36Sopenharmony_ci * 54562306a36Sopenharmony_ci * In order to be able to recover from an unclean unmount, a complete copy of 54662306a36Sopenharmony_ci * the index must exist on flash. This is the "old" index. The commit process 54762306a36Sopenharmony_ci * must write the "new" index to flash without overwriting or destroying any 54862306a36Sopenharmony_ci * part of the old index. This function is run at commit end in order to check 54962306a36Sopenharmony_ci * that the old index does indeed exist completely intact. 55062306a36Sopenharmony_ci * 55162306a36Sopenharmony_ci * This function returns %0 on success and a negative error code on failure. 55262306a36Sopenharmony_ci */ 55362306a36Sopenharmony_ciint dbg_check_old_index(struct ubifs_info *c, struct ubifs_zbranch *zroot) 55462306a36Sopenharmony_ci{ 55562306a36Sopenharmony_ci int lnum, offs, len, err = 0, last_level, child_cnt; 55662306a36Sopenharmony_ci int first = 1, iip; 55762306a36Sopenharmony_ci struct ubifs_debug_info *d = c->dbg; 55862306a36Sopenharmony_ci union ubifs_key lower_key, upper_key, l_key, u_key; 55962306a36Sopenharmony_ci unsigned long long last_sqnum; 56062306a36Sopenharmony_ci struct ubifs_idx_node *idx; 56162306a36Sopenharmony_ci struct list_head list; 56262306a36Sopenharmony_ci struct idx_node *i; 56362306a36Sopenharmony_ci size_t sz; 56462306a36Sopenharmony_ci 56562306a36Sopenharmony_ci if (!dbg_is_chk_index(c)) 56662306a36Sopenharmony_ci return 0; 56762306a36Sopenharmony_ci 56862306a36Sopenharmony_ci INIT_LIST_HEAD(&list); 56962306a36Sopenharmony_ci 57062306a36Sopenharmony_ci sz = sizeof(struct idx_node) + ubifs_idx_node_sz(c, c->fanout) - 57162306a36Sopenharmony_ci UBIFS_IDX_NODE_SZ; 57262306a36Sopenharmony_ci 57362306a36Sopenharmony_ci /* Start at the old zroot */ 57462306a36Sopenharmony_ci lnum = d->old_zroot.lnum; 57562306a36Sopenharmony_ci offs = d->old_zroot.offs; 57662306a36Sopenharmony_ci len = d->old_zroot.len; 57762306a36Sopenharmony_ci iip = 0; 57862306a36Sopenharmony_ci 57962306a36Sopenharmony_ci /* 58062306a36Sopenharmony_ci * Traverse the index tree preorder depth-first i.e. do a node and then 58162306a36Sopenharmony_ci * its subtrees from left to right. 58262306a36Sopenharmony_ci */ 58362306a36Sopenharmony_ci while (1) { 58462306a36Sopenharmony_ci struct ubifs_branch *br; 58562306a36Sopenharmony_ci 58662306a36Sopenharmony_ci /* Get the next index node */ 58762306a36Sopenharmony_ci i = kmalloc(sz, GFP_NOFS); 58862306a36Sopenharmony_ci if (!i) { 58962306a36Sopenharmony_ci err = -ENOMEM; 59062306a36Sopenharmony_ci goto out_free; 59162306a36Sopenharmony_ci } 59262306a36Sopenharmony_ci i->iip = iip; 59362306a36Sopenharmony_ci /* Keep the index nodes on our path in a linked list */ 59462306a36Sopenharmony_ci list_add_tail(&i->list, &list); 59562306a36Sopenharmony_ci /* Read the index node */ 59662306a36Sopenharmony_ci idx = &i->idx; 59762306a36Sopenharmony_ci err = ubifs_read_node(c, idx, UBIFS_IDX_NODE, len, lnum, offs); 59862306a36Sopenharmony_ci if (err) 59962306a36Sopenharmony_ci goto out_free; 60062306a36Sopenharmony_ci /* Validate index node */ 60162306a36Sopenharmony_ci child_cnt = le16_to_cpu(idx->child_cnt); 60262306a36Sopenharmony_ci if (child_cnt < 1 || child_cnt > c->fanout) { 60362306a36Sopenharmony_ci err = 1; 60462306a36Sopenharmony_ci goto out_dump; 60562306a36Sopenharmony_ci } 60662306a36Sopenharmony_ci if (first) { 60762306a36Sopenharmony_ci first = 0; 60862306a36Sopenharmony_ci /* Check root level and sqnum */ 60962306a36Sopenharmony_ci if (le16_to_cpu(idx->level) != d->old_zroot_level) { 61062306a36Sopenharmony_ci err = 2; 61162306a36Sopenharmony_ci goto out_dump; 61262306a36Sopenharmony_ci } 61362306a36Sopenharmony_ci if (le64_to_cpu(idx->ch.sqnum) != d->old_zroot_sqnum) { 61462306a36Sopenharmony_ci err = 3; 61562306a36Sopenharmony_ci goto out_dump; 61662306a36Sopenharmony_ci } 61762306a36Sopenharmony_ci /* Set last values as though root had a parent */ 61862306a36Sopenharmony_ci last_level = le16_to_cpu(idx->level) + 1; 61962306a36Sopenharmony_ci last_sqnum = le64_to_cpu(idx->ch.sqnum) + 1; 62062306a36Sopenharmony_ci key_read(c, ubifs_idx_key(c, idx), &lower_key); 62162306a36Sopenharmony_ci highest_ino_key(c, &upper_key, INUM_WATERMARK); 62262306a36Sopenharmony_ci } 62362306a36Sopenharmony_ci key_copy(c, &upper_key, &i->upper_key); 62462306a36Sopenharmony_ci if (le16_to_cpu(idx->level) != last_level - 1) { 62562306a36Sopenharmony_ci err = 3; 62662306a36Sopenharmony_ci goto out_dump; 62762306a36Sopenharmony_ci } 62862306a36Sopenharmony_ci /* 62962306a36Sopenharmony_ci * The index is always written bottom up hence a child's sqnum 63062306a36Sopenharmony_ci * is always less than the parents. 63162306a36Sopenharmony_ci */ 63262306a36Sopenharmony_ci if (le64_to_cpu(idx->ch.sqnum) >= last_sqnum) { 63362306a36Sopenharmony_ci err = 4; 63462306a36Sopenharmony_ci goto out_dump; 63562306a36Sopenharmony_ci } 63662306a36Sopenharmony_ci /* Check key range */ 63762306a36Sopenharmony_ci key_read(c, ubifs_idx_key(c, idx), &l_key); 63862306a36Sopenharmony_ci br = ubifs_idx_branch(c, idx, child_cnt - 1); 63962306a36Sopenharmony_ci key_read(c, &br->key, &u_key); 64062306a36Sopenharmony_ci if (keys_cmp(c, &lower_key, &l_key) > 0) { 64162306a36Sopenharmony_ci err = 5; 64262306a36Sopenharmony_ci goto out_dump; 64362306a36Sopenharmony_ci } 64462306a36Sopenharmony_ci if (keys_cmp(c, &upper_key, &u_key) < 0) { 64562306a36Sopenharmony_ci err = 6; 64662306a36Sopenharmony_ci goto out_dump; 64762306a36Sopenharmony_ci } 64862306a36Sopenharmony_ci if (keys_cmp(c, &upper_key, &u_key) == 0) 64962306a36Sopenharmony_ci if (!is_hash_key(c, &u_key)) { 65062306a36Sopenharmony_ci err = 7; 65162306a36Sopenharmony_ci goto out_dump; 65262306a36Sopenharmony_ci } 65362306a36Sopenharmony_ci /* Go to next index node */ 65462306a36Sopenharmony_ci if (le16_to_cpu(idx->level) == 0) { 65562306a36Sopenharmony_ci /* At the bottom, so go up until can go right */ 65662306a36Sopenharmony_ci while (1) { 65762306a36Sopenharmony_ci /* Drop the bottom of the list */ 65862306a36Sopenharmony_ci list_del(&i->list); 65962306a36Sopenharmony_ci kfree(i); 66062306a36Sopenharmony_ci /* No more list means we are done */ 66162306a36Sopenharmony_ci if (list_empty(&list)) 66262306a36Sopenharmony_ci goto out; 66362306a36Sopenharmony_ci /* Look at the new bottom */ 66462306a36Sopenharmony_ci i = list_entry(list.prev, struct idx_node, 66562306a36Sopenharmony_ci list); 66662306a36Sopenharmony_ci idx = &i->idx; 66762306a36Sopenharmony_ci /* Can we go right */ 66862306a36Sopenharmony_ci if (iip + 1 < le16_to_cpu(idx->child_cnt)) { 66962306a36Sopenharmony_ci iip = iip + 1; 67062306a36Sopenharmony_ci break; 67162306a36Sopenharmony_ci } else 67262306a36Sopenharmony_ci /* Nope, so go up again */ 67362306a36Sopenharmony_ci iip = i->iip; 67462306a36Sopenharmony_ci } 67562306a36Sopenharmony_ci } else 67662306a36Sopenharmony_ci /* Go down left */ 67762306a36Sopenharmony_ci iip = 0; 67862306a36Sopenharmony_ci /* 67962306a36Sopenharmony_ci * We have the parent in 'idx' and now we set up for reading the 68062306a36Sopenharmony_ci * child pointed to by slot 'iip'. 68162306a36Sopenharmony_ci */ 68262306a36Sopenharmony_ci last_level = le16_to_cpu(idx->level); 68362306a36Sopenharmony_ci last_sqnum = le64_to_cpu(idx->ch.sqnum); 68462306a36Sopenharmony_ci br = ubifs_idx_branch(c, idx, iip); 68562306a36Sopenharmony_ci lnum = le32_to_cpu(br->lnum); 68662306a36Sopenharmony_ci offs = le32_to_cpu(br->offs); 68762306a36Sopenharmony_ci len = le32_to_cpu(br->len); 68862306a36Sopenharmony_ci key_read(c, &br->key, &lower_key); 68962306a36Sopenharmony_ci if (iip + 1 < le16_to_cpu(idx->child_cnt)) { 69062306a36Sopenharmony_ci br = ubifs_idx_branch(c, idx, iip + 1); 69162306a36Sopenharmony_ci key_read(c, &br->key, &upper_key); 69262306a36Sopenharmony_ci } else 69362306a36Sopenharmony_ci key_copy(c, &i->upper_key, &upper_key); 69462306a36Sopenharmony_ci } 69562306a36Sopenharmony_ciout: 69662306a36Sopenharmony_ci err = dbg_old_index_check_init(c, zroot); 69762306a36Sopenharmony_ci if (err) 69862306a36Sopenharmony_ci goto out_free; 69962306a36Sopenharmony_ci 70062306a36Sopenharmony_ci return 0; 70162306a36Sopenharmony_ci 70262306a36Sopenharmony_ciout_dump: 70362306a36Sopenharmony_ci ubifs_err(c, "dumping index node (iip=%d)", i->iip); 70462306a36Sopenharmony_ci ubifs_dump_node(c, idx, ubifs_idx_node_sz(c, c->fanout)); 70562306a36Sopenharmony_ci list_del(&i->list); 70662306a36Sopenharmony_ci kfree(i); 70762306a36Sopenharmony_ci if (!list_empty(&list)) { 70862306a36Sopenharmony_ci i = list_entry(list.prev, struct idx_node, list); 70962306a36Sopenharmony_ci ubifs_err(c, "dumping parent index node"); 71062306a36Sopenharmony_ci ubifs_dump_node(c, &i->idx, ubifs_idx_node_sz(c, c->fanout)); 71162306a36Sopenharmony_ci } 71262306a36Sopenharmony_ciout_free: 71362306a36Sopenharmony_ci while (!list_empty(&list)) { 71462306a36Sopenharmony_ci i = list_entry(list.next, struct idx_node, list); 71562306a36Sopenharmony_ci list_del(&i->list); 71662306a36Sopenharmony_ci kfree(i); 71762306a36Sopenharmony_ci } 71862306a36Sopenharmony_ci ubifs_err(c, "failed, error %d", err); 71962306a36Sopenharmony_ci if (err > 0) 72062306a36Sopenharmony_ci err = -EINVAL; 72162306a36Sopenharmony_ci return err; 72262306a36Sopenharmony_ci} 723