18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * This file is part of UBIFS.
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (C) 2006-2008 Nokia Corporation.
68c2ecf20Sopenharmony_ci *
78c2ecf20Sopenharmony_ci * Authors: Adrian Hunter
88c2ecf20Sopenharmony_ci *          Artem Bityutskiy (Битюцкий Артём)
98c2ecf20Sopenharmony_ci */
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci/*
128c2ecf20Sopenharmony_ci * This file implements functions that manage the running of the commit process.
138c2ecf20Sopenharmony_ci * Each affected module has its own functions to accomplish their part in the
148c2ecf20Sopenharmony_ci * commit and those functions are called here.
158c2ecf20Sopenharmony_ci *
168c2ecf20Sopenharmony_ci * The commit is the process whereby all updates to the index and LEB properties
178c2ecf20Sopenharmony_ci * are written out together and the journal becomes empty. This keeps the
188c2ecf20Sopenharmony_ci * file system consistent - at all times the state can be recreated by reading
198c2ecf20Sopenharmony_ci * the index and LEB properties and then replaying the journal.
208c2ecf20Sopenharmony_ci *
218c2ecf20Sopenharmony_ci * The commit is split into two parts named "commit start" and "commit end".
228c2ecf20Sopenharmony_ci * During commit start, the commit process has exclusive access to the journal
238c2ecf20Sopenharmony_ci * by holding the commit semaphore down for writing. As few I/O operations as
248c2ecf20Sopenharmony_ci * possible are performed during commit start, instead the nodes that are to be
258c2ecf20Sopenharmony_ci * written are merely identified. During commit end, the commit semaphore is no
268c2ecf20Sopenharmony_ci * longer held and the journal is again in operation, allowing users to continue
278c2ecf20Sopenharmony_ci * to use the file system while the bulk of the commit I/O is performed. The
288c2ecf20Sopenharmony_ci * purpose of this two-step approach is to prevent the commit from causing any
298c2ecf20Sopenharmony_ci * latency blips. Note that in any case, the commit does not prevent lookups
308c2ecf20Sopenharmony_ci * (as permitted by the TNC mutex), or access to VFS data structures e.g. page
318c2ecf20Sopenharmony_ci * cache.
328c2ecf20Sopenharmony_ci */
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_ci#include <linux/freezer.h>
358c2ecf20Sopenharmony_ci#include <linux/kthread.h>
368c2ecf20Sopenharmony_ci#include <linux/slab.h>
378c2ecf20Sopenharmony_ci#include "ubifs.h"
388c2ecf20Sopenharmony_ci
398c2ecf20Sopenharmony_ci/*
408c2ecf20Sopenharmony_ci * nothing_to_commit - check if there is nothing to commit.
418c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object
428c2ecf20Sopenharmony_ci *
438c2ecf20Sopenharmony_ci * This is a helper function which checks if there is anything to commit. It is
448c2ecf20Sopenharmony_ci * used as an optimization to avoid starting the commit if it is not really
458c2ecf20Sopenharmony_ci * necessary. Indeed, the commit operation always assumes flash I/O (e.g.,
468c2ecf20Sopenharmony_ci * writing the commit start node to the log), and it is better to avoid doing
478c2ecf20Sopenharmony_ci * this unnecessarily. E.g., 'ubifs_sync_fs()' runs the commit, but if there is
488c2ecf20Sopenharmony_ci * nothing to commit, it is more optimal to avoid any flash I/O.
498c2ecf20Sopenharmony_ci *
508c2ecf20Sopenharmony_ci * This function has to be called with @c->commit_sem locked for writing -
518c2ecf20Sopenharmony_ci * this function does not take LPT/TNC locks because the @c->commit_sem
528c2ecf20Sopenharmony_ci * guarantees that we have exclusive access to the TNC and LPT data structures.
538c2ecf20Sopenharmony_ci *
548c2ecf20Sopenharmony_ci * This function returns %1 if there is nothing to commit and %0 otherwise.
558c2ecf20Sopenharmony_ci */
568c2ecf20Sopenharmony_cistatic int nothing_to_commit(struct ubifs_info *c)
578c2ecf20Sopenharmony_ci{
588c2ecf20Sopenharmony_ci	/*
598c2ecf20Sopenharmony_ci	 * During mounting or remounting from R/O mode to R/W mode we may
608c2ecf20Sopenharmony_ci	 * commit for various recovery-related reasons.
618c2ecf20Sopenharmony_ci	 */
628c2ecf20Sopenharmony_ci	if (c->mounting || c->remounting_rw)
638c2ecf20Sopenharmony_ci		return 0;
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_ci	/*
668c2ecf20Sopenharmony_ci	 * If the root TNC node is dirty, we definitely have something to
678c2ecf20Sopenharmony_ci	 * commit.
688c2ecf20Sopenharmony_ci	 */
698c2ecf20Sopenharmony_ci	if (c->zroot.znode && ubifs_zn_dirty(c->zroot.znode))
708c2ecf20Sopenharmony_ci		return 0;
718c2ecf20Sopenharmony_ci
728c2ecf20Sopenharmony_ci	/*
738c2ecf20Sopenharmony_ci	 * Even though the TNC is clean, the LPT tree may have dirty nodes. For
748c2ecf20Sopenharmony_ci	 * example, this may happen if the budgeting subsystem invoked GC to
758c2ecf20Sopenharmony_ci	 * make some free space, and the GC found an LEB with only dirty and
768c2ecf20Sopenharmony_ci	 * free space. In this case GC would just change the lprops of this
778c2ecf20Sopenharmony_ci	 * LEB (by turning all space into free space) and unmap it.
788c2ecf20Sopenharmony_ci	 */
798c2ecf20Sopenharmony_ci	if (c->nroot && test_bit(DIRTY_CNODE, &c->nroot->flags))
808c2ecf20Sopenharmony_ci		return 0;
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_ci	ubifs_assert(c, atomic_long_read(&c->dirty_zn_cnt) == 0);
838c2ecf20Sopenharmony_ci	ubifs_assert(c, c->dirty_pn_cnt == 0);
848c2ecf20Sopenharmony_ci	ubifs_assert(c, c->dirty_nn_cnt == 0);
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_ci	return 1;
878c2ecf20Sopenharmony_ci}
888c2ecf20Sopenharmony_ci
898c2ecf20Sopenharmony_ci/**
908c2ecf20Sopenharmony_ci * do_commit - commit the journal.
918c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object
928c2ecf20Sopenharmony_ci *
938c2ecf20Sopenharmony_ci * This function implements UBIFS commit. It has to be called with commit lock
948c2ecf20Sopenharmony_ci * locked. Returns zero in case of success and a negative error code in case of
958c2ecf20Sopenharmony_ci * failure.
968c2ecf20Sopenharmony_ci */
978c2ecf20Sopenharmony_cistatic int do_commit(struct ubifs_info *c)
988c2ecf20Sopenharmony_ci{
998c2ecf20Sopenharmony_ci	int err, new_ltail_lnum, old_ltail_lnum, i;
1008c2ecf20Sopenharmony_ci	struct ubifs_zbranch zroot;
1018c2ecf20Sopenharmony_ci	struct ubifs_lp_stats lst;
1028c2ecf20Sopenharmony_ci
1038c2ecf20Sopenharmony_ci	dbg_cmt("start");
1048c2ecf20Sopenharmony_ci	ubifs_assert(c, !c->ro_media && !c->ro_mount);
1058c2ecf20Sopenharmony_ci
1068c2ecf20Sopenharmony_ci	if (c->ro_error) {
1078c2ecf20Sopenharmony_ci		err = -EROFS;
1088c2ecf20Sopenharmony_ci		goto out_up;
1098c2ecf20Sopenharmony_ci	}
1108c2ecf20Sopenharmony_ci
1118c2ecf20Sopenharmony_ci	if (nothing_to_commit(c)) {
1128c2ecf20Sopenharmony_ci		up_write(&c->commit_sem);
1138c2ecf20Sopenharmony_ci		err = 0;
1148c2ecf20Sopenharmony_ci		goto out_cancel;
1158c2ecf20Sopenharmony_ci	}
1168c2ecf20Sopenharmony_ci
1178c2ecf20Sopenharmony_ci	/* Sync all write buffers (necessary for recovery) */
1188c2ecf20Sopenharmony_ci	for (i = 0; i < c->jhead_cnt; i++) {
1198c2ecf20Sopenharmony_ci		err = ubifs_wbuf_sync(&c->jheads[i].wbuf);
1208c2ecf20Sopenharmony_ci		if (err)
1218c2ecf20Sopenharmony_ci			goto out_up;
1228c2ecf20Sopenharmony_ci	}
1238c2ecf20Sopenharmony_ci
1248c2ecf20Sopenharmony_ci	c->cmt_no += 1;
1258c2ecf20Sopenharmony_ci	err = ubifs_gc_start_commit(c);
1268c2ecf20Sopenharmony_ci	if (err)
1278c2ecf20Sopenharmony_ci		goto out_up;
1288c2ecf20Sopenharmony_ci	err = dbg_check_lprops(c);
1298c2ecf20Sopenharmony_ci	if (err)
1308c2ecf20Sopenharmony_ci		goto out_up;
1318c2ecf20Sopenharmony_ci	err = ubifs_log_start_commit(c, &new_ltail_lnum);
1328c2ecf20Sopenharmony_ci	if (err)
1338c2ecf20Sopenharmony_ci		goto out_up;
1348c2ecf20Sopenharmony_ci	err = ubifs_tnc_start_commit(c, &zroot);
1358c2ecf20Sopenharmony_ci	if (err)
1368c2ecf20Sopenharmony_ci		goto out_up;
1378c2ecf20Sopenharmony_ci	err = ubifs_lpt_start_commit(c);
1388c2ecf20Sopenharmony_ci	if (err)
1398c2ecf20Sopenharmony_ci		goto out_up;
1408c2ecf20Sopenharmony_ci	err = ubifs_orphan_start_commit(c);
1418c2ecf20Sopenharmony_ci	if (err)
1428c2ecf20Sopenharmony_ci		goto out_up;
1438c2ecf20Sopenharmony_ci
1448c2ecf20Sopenharmony_ci	ubifs_get_lp_stats(c, &lst);
1458c2ecf20Sopenharmony_ci
1468c2ecf20Sopenharmony_ci	up_write(&c->commit_sem);
1478c2ecf20Sopenharmony_ci
1488c2ecf20Sopenharmony_ci	err = ubifs_tnc_end_commit(c);
1498c2ecf20Sopenharmony_ci	if (err)
1508c2ecf20Sopenharmony_ci		goto out;
1518c2ecf20Sopenharmony_ci	err = ubifs_lpt_end_commit(c);
1528c2ecf20Sopenharmony_ci	if (err)
1538c2ecf20Sopenharmony_ci		goto out;
1548c2ecf20Sopenharmony_ci	err = ubifs_orphan_end_commit(c);
1558c2ecf20Sopenharmony_ci	if (err)
1568c2ecf20Sopenharmony_ci		goto out;
1578c2ecf20Sopenharmony_ci	err = dbg_check_old_index(c, &zroot);
1588c2ecf20Sopenharmony_ci	if (err)
1598c2ecf20Sopenharmony_ci		goto out;
1608c2ecf20Sopenharmony_ci
1618c2ecf20Sopenharmony_ci	c->mst_node->cmt_no      = cpu_to_le64(c->cmt_no);
1628c2ecf20Sopenharmony_ci	c->mst_node->log_lnum    = cpu_to_le32(new_ltail_lnum);
1638c2ecf20Sopenharmony_ci	c->mst_node->root_lnum   = cpu_to_le32(zroot.lnum);
1648c2ecf20Sopenharmony_ci	c->mst_node->root_offs   = cpu_to_le32(zroot.offs);
1658c2ecf20Sopenharmony_ci	c->mst_node->root_len    = cpu_to_le32(zroot.len);
1668c2ecf20Sopenharmony_ci	c->mst_node->ihead_lnum  = cpu_to_le32(c->ihead_lnum);
1678c2ecf20Sopenharmony_ci	c->mst_node->ihead_offs  = cpu_to_le32(c->ihead_offs);
1688c2ecf20Sopenharmony_ci	c->mst_node->index_size  = cpu_to_le64(c->bi.old_idx_sz);
1698c2ecf20Sopenharmony_ci	c->mst_node->lpt_lnum    = cpu_to_le32(c->lpt_lnum);
1708c2ecf20Sopenharmony_ci	c->mst_node->lpt_offs    = cpu_to_le32(c->lpt_offs);
1718c2ecf20Sopenharmony_ci	c->mst_node->nhead_lnum  = cpu_to_le32(c->nhead_lnum);
1728c2ecf20Sopenharmony_ci	c->mst_node->nhead_offs  = cpu_to_le32(c->nhead_offs);
1738c2ecf20Sopenharmony_ci	c->mst_node->ltab_lnum   = cpu_to_le32(c->ltab_lnum);
1748c2ecf20Sopenharmony_ci	c->mst_node->ltab_offs   = cpu_to_le32(c->ltab_offs);
1758c2ecf20Sopenharmony_ci	c->mst_node->lsave_lnum  = cpu_to_le32(c->lsave_lnum);
1768c2ecf20Sopenharmony_ci	c->mst_node->lsave_offs  = cpu_to_le32(c->lsave_offs);
1778c2ecf20Sopenharmony_ci	c->mst_node->lscan_lnum  = cpu_to_le32(c->lscan_lnum);
1788c2ecf20Sopenharmony_ci	c->mst_node->empty_lebs  = cpu_to_le32(lst.empty_lebs);
1798c2ecf20Sopenharmony_ci	c->mst_node->idx_lebs    = cpu_to_le32(lst.idx_lebs);
1808c2ecf20Sopenharmony_ci	c->mst_node->total_free  = cpu_to_le64(lst.total_free);
1818c2ecf20Sopenharmony_ci	c->mst_node->total_dirty = cpu_to_le64(lst.total_dirty);
1828c2ecf20Sopenharmony_ci	c->mst_node->total_used  = cpu_to_le64(lst.total_used);
1838c2ecf20Sopenharmony_ci	c->mst_node->total_dead  = cpu_to_le64(lst.total_dead);
1848c2ecf20Sopenharmony_ci	c->mst_node->total_dark  = cpu_to_le64(lst.total_dark);
1858c2ecf20Sopenharmony_ci	if (c->no_orphs)
1868c2ecf20Sopenharmony_ci		c->mst_node->flags |= cpu_to_le32(UBIFS_MST_NO_ORPHS);
1878c2ecf20Sopenharmony_ci	else
1888c2ecf20Sopenharmony_ci		c->mst_node->flags &= ~cpu_to_le32(UBIFS_MST_NO_ORPHS);
1898c2ecf20Sopenharmony_ci
1908c2ecf20Sopenharmony_ci	old_ltail_lnum = c->ltail_lnum;
1918c2ecf20Sopenharmony_ci	err = ubifs_log_end_commit(c, new_ltail_lnum);
1928c2ecf20Sopenharmony_ci	if (err)
1938c2ecf20Sopenharmony_ci		goto out;
1948c2ecf20Sopenharmony_ci
1958c2ecf20Sopenharmony_ci	err = ubifs_log_post_commit(c, old_ltail_lnum);
1968c2ecf20Sopenharmony_ci	if (err)
1978c2ecf20Sopenharmony_ci		goto out;
1988c2ecf20Sopenharmony_ci	err = ubifs_gc_end_commit(c);
1998c2ecf20Sopenharmony_ci	if (err)
2008c2ecf20Sopenharmony_ci		goto out;
2018c2ecf20Sopenharmony_ci	err = ubifs_lpt_post_commit(c);
2028c2ecf20Sopenharmony_ci	if (err)
2038c2ecf20Sopenharmony_ci		goto out;
2048c2ecf20Sopenharmony_ci
2058c2ecf20Sopenharmony_ciout_cancel:
2068c2ecf20Sopenharmony_ci	spin_lock(&c->cs_lock);
2078c2ecf20Sopenharmony_ci	c->cmt_state = COMMIT_RESTING;
2088c2ecf20Sopenharmony_ci	wake_up(&c->cmt_wq);
2098c2ecf20Sopenharmony_ci	dbg_cmt("commit end");
2108c2ecf20Sopenharmony_ci	spin_unlock(&c->cs_lock);
2118c2ecf20Sopenharmony_ci	return 0;
2128c2ecf20Sopenharmony_ci
2138c2ecf20Sopenharmony_ciout_up:
2148c2ecf20Sopenharmony_ci	up_write(&c->commit_sem);
2158c2ecf20Sopenharmony_ciout:
2168c2ecf20Sopenharmony_ci	ubifs_err(c, "commit failed, error %d", err);
2178c2ecf20Sopenharmony_ci	spin_lock(&c->cs_lock);
2188c2ecf20Sopenharmony_ci	c->cmt_state = COMMIT_BROKEN;
2198c2ecf20Sopenharmony_ci	wake_up(&c->cmt_wq);
2208c2ecf20Sopenharmony_ci	spin_unlock(&c->cs_lock);
2218c2ecf20Sopenharmony_ci	ubifs_ro_mode(c, err);
2228c2ecf20Sopenharmony_ci	return err;
2238c2ecf20Sopenharmony_ci}
2248c2ecf20Sopenharmony_ci
2258c2ecf20Sopenharmony_ci/**
2268c2ecf20Sopenharmony_ci * run_bg_commit - run background commit if it is needed.
2278c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object
2288c2ecf20Sopenharmony_ci *
2298c2ecf20Sopenharmony_ci * This function runs background commit if it is needed. Returns zero in case
2308c2ecf20Sopenharmony_ci * of success and a negative error code in case of failure.
2318c2ecf20Sopenharmony_ci */
2328c2ecf20Sopenharmony_cistatic int run_bg_commit(struct ubifs_info *c)
2338c2ecf20Sopenharmony_ci{
2348c2ecf20Sopenharmony_ci	spin_lock(&c->cs_lock);
2358c2ecf20Sopenharmony_ci	/*
2368c2ecf20Sopenharmony_ci	 * Run background commit only if background commit was requested or if
2378c2ecf20Sopenharmony_ci	 * commit is required.
2388c2ecf20Sopenharmony_ci	 */
2398c2ecf20Sopenharmony_ci	if (c->cmt_state != COMMIT_BACKGROUND &&
2408c2ecf20Sopenharmony_ci	    c->cmt_state != COMMIT_REQUIRED)
2418c2ecf20Sopenharmony_ci		goto out;
2428c2ecf20Sopenharmony_ci	spin_unlock(&c->cs_lock);
2438c2ecf20Sopenharmony_ci
2448c2ecf20Sopenharmony_ci	down_write(&c->commit_sem);
2458c2ecf20Sopenharmony_ci	spin_lock(&c->cs_lock);
2468c2ecf20Sopenharmony_ci	if (c->cmt_state == COMMIT_REQUIRED)
2478c2ecf20Sopenharmony_ci		c->cmt_state = COMMIT_RUNNING_REQUIRED;
2488c2ecf20Sopenharmony_ci	else if (c->cmt_state == COMMIT_BACKGROUND)
2498c2ecf20Sopenharmony_ci		c->cmt_state = COMMIT_RUNNING_BACKGROUND;
2508c2ecf20Sopenharmony_ci	else
2518c2ecf20Sopenharmony_ci		goto out_cmt_unlock;
2528c2ecf20Sopenharmony_ci	spin_unlock(&c->cs_lock);
2538c2ecf20Sopenharmony_ci
2548c2ecf20Sopenharmony_ci	return do_commit(c);
2558c2ecf20Sopenharmony_ci
2568c2ecf20Sopenharmony_ciout_cmt_unlock:
2578c2ecf20Sopenharmony_ci	up_write(&c->commit_sem);
2588c2ecf20Sopenharmony_ciout:
2598c2ecf20Sopenharmony_ci	spin_unlock(&c->cs_lock);
2608c2ecf20Sopenharmony_ci	return 0;
2618c2ecf20Sopenharmony_ci}
2628c2ecf20Sopenharmony_ci
2638c2ecf20Sopenharmony_ci/**
2648c2ecf20Sopenharmony_ci * ubifs_bg_thread - UBIFS background thread function.
2658c2ecf20Sopenharmony_ci * @info: points to the file-system description object
2668c2ecf20Sopenharmony_ci *
2678c2ecf20Sopenharmony_ci * This function implements various file-system background activities:
2688c2ecf20Sopenharmony_ci * o when a write-buffer timer expires it synchronizes the appropriate
2698c2ecf20Sopenharmony_ci *   write-buffer;
2708c2ecf20Sopenharmony_ci * o when the journal is about to be full, it starts in-advance commit.
2718c2ecf20Sopenharmony_ci *
2728c2ecf20Sopenharmony_ci * Note, other stuff like background garbage collection may be added here in
2738c2ecf20Sopenharmony_ci * future.
2748c2ecf20Sopenharmony_ci */
2758c2ecf20Sopenharmony_ciint ubifs_bg_thread(void *info)
2768c2ecf20Sopenharmony_ci{
2778c2ecf20Sopenharmony_ci	int err;
2788c2ecf20Sopenharmony_ci	struct ubifs_info *c = info;
2798c2ecf20Sopenharmony_ci
2808c2ecf20Sopenharmony_ci	ubifs_msg(c, "background thread \"%s\" started, PID %d",
2818c2ecf20Sopenharmony_ci		  c->bgt_name, current->pid);
2828c2ecf20Sopenharmony_ci	set_freezable();
2838c2ecf20Sopenharmony_ci
2848c2ecf20Sopenharmony_ci	while (1) {
2858c2ecf20Sopenharmony_ci		if (kthread_should_stop())
2868c2ecf20Sopenharmony_ci			break;
2878c2ecf20Sopenharmony_ci
2888c2ecf20Sopenharmony_ci		if (try_to_freeze())
2898c2ecf20Sopenharmony_ci			continue;
2908c2ecf20Sopenharmony_ci
2918c2ecf20Sopenharmony_ci		set_current_state(TASK_INTERRUPTIBLE);
2928c2ecf20Sopenharmony_ci		/* Check if there is something to do */
2938c2ecf20Sopenharmony_ci		if (!c->need_bgt) {
2948c2ecf20Sopenharmony_ci			/*
2958c2ecf20Sopenharmony_ci			 * Nothing prevents us from going sleep now and
2968c2ecf20Sopenharmony_ci			 * be never woken up and block the task which
2978c2ecf20Sopenharmony_ci			 * could wait in 'kthread_stop()' forever.
2988c2ecf20Sopenharmony_ci			 */
2998c2ecf20Sopenharmony_ci			if (kthread_should_stop())
3008c2ecf20Sopenharmony_ci				break;
3018c2ecf20Sopenharmony_ci			schedule();
3028c2ecf20Sopenharmony_ci			continue;
3038c2ecf20Sopenharmony_ci		} else
3048c2ecf20Sopenharmony_ci			__set_current_state(TASK_RUNNING);
3058c2ecf20Sopenharmony_ci
3068c2ecf20Sopenharmony_ci		c->need_bgt = 0;
3078c2ecf20Sopenharmony_ci		err = ubifs_bg_wbufs_sync(c);
3088c2ecf20Sopenharmony_ci		if (err)
3098c2ecf20Sopenharmony_ci			ubifs_ro_mode(c, err);
3108c2ecf20Sopenharmony_ci
3118c2ecf20Sopenharmony_ci		run_bg_commit(c);
3128c2ecf20Sopenharmony_ci		cond_resched();
3138c2ecf20Sopenharmony_ci	}
3148c2ecf20Sopenharmony_ci
3158c2ecf20Sopenharmony_ci	ubifs_msg(c, "background thread \"%s\" stops", c->bgt_name);
3168c2ecf20Sopenharmony_ci	return 0;
3178c2ecf20Sopenharmony_ci}
3188c2ecf20Sopenharmony_ci
3198c2ecf20Sopenharmony_ci/**
3208c2ecf20Sopenharmony_ci * ubifs_commit_required - set commit state to "required".
3218c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object
3228c2ecf20Sopenharmony_ci *
3238c2ecf20Sopenharmony_ci * This function is called if a commit is required but cannot be done from the
3248c2ecf20Sopenharmony_ci * calling function, so it is just flagged instead.
3258c2ecf20Sopenharmony_ci */
3268c2ecf20Sopenharmony_civoid ubifs_commit_required(struct ubifs_info *c)
3278c2ecf20Sopenharmony_ci{
3288c2ecf20Sopenharmony_ci	spin_lock(&c->cs_lock);
3298c2ecf20Sopenharmony_ci	switch (c->cmt_state) {
3308c2ecf20Sopenharmony_ci	case COMMIT_RESTING:
3318c2ecf20Sopenharmony_ci	case COMMIT_BACKGROUND:
3328c2ecf20Sopenharmony_ci		dbg_cmt("old: %s, new: %s", dbg_cstate(c->cmt_state),
3338c2ecf20Sopenharmony_ci			dbg_cstate(COMMIT_REQUIRED));
3348c2ecf20Sopenharmony_ci		c->cmt_state = COMMIT_REQUIRED;
3358c2ecf20Sopenharmony_ci		break;
3368c2ecf20Sopenharmony_ci	case COMMIT_RUNNING_BACKGROUND:
3378c2ecf20Sopenharmony_ci		dbg_cmt("old: %s, new: %s", dbg_cstate(c->cmt_state),
3388c2ecf20Sopenharmony_ci			dbg_cstate(COMMIT_RUNNING_REQUIRED));
3398c2ecf20Sopenharmony_ci		c->cmt_state = COMMIT_RUNNING_REQUIRED;
3408c2ecf20Sopenharmony_ci		break;
3418c2ecf20Sopenharmony_ci	case COMMIT_REQUIRED:
3428c2ecf20Sopenharmony_ci	case COMMIT_RUNNING_REQUIRED:
3438c2ecf20Sopenharmony_ci	case COMMIT_BROKEN:
3448c2ecf20Sopenharmony_ci		break;
3458c2ecf20Sopenharmony_ci	}
3468c2ecf20Sopenharmony_ci	spin_unlock(&c->cs_lock);
3478c2ecf20Sopenharmony_ci}
3488c2ecf20Sopenharmony_ci
3498c2ecf20Sopenharmony_ci/**
3508c2ecf20Sopenharmony_ci * ubifs_request_bg_commit - notify the background thread to do a commit.
3518c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object
3528c2ecf20Sopenharmony_ci *
3538c2ecf20Sopenharmony_ci * This function is called if the journal is full enough to make a commit
3548c2ecf20Sopenharmony_ci * worthwhile, so background thread is kicked to start it.
3558c2ecf20Sopenharmony_ci */
3568c2ecf20Sopenharmony_civoid ubifs_request_bg_commit(struct ubifs_info *c)
3578c2ecf20Sopenharmony_ci{
3588c2ecf20Sopenharmony_ci	spin_lock(&c->cs_lock);
3598c2ecf20Sopenharmony_ci	if (c->cmt_state == COMMIT_RESTING) {
3608c2ecf20Sopenharmony_ci		dbg_cmt("old: %s, new: %s", dbg_cstate(c->cmt_state),
3618c2ecf20Sopenharmony_ci			dbg_cstate(COMMIT_BACKGROUND));
3628c2ecf20Sopenharmony_ci		c->cmt_state = COMMIT_BACKGROUND;
3638c2ecf20Sopenharmony_ci		spin_unlock(&c->cs_lock);
3648c2ecf20Sopenharmony_ci		ubifs_wake_up_bgt(c);
3658c2ecf20Sopenharmony_ci	} else
3668c2ecf20Sopenharmony_ci		spin_unlock(&c->cs_lock);
3678c2ecf20Sopenharmony_ci}
3688c2ecf20Sopenharmony_ci
3698c2ecf20Sopenharmony_ci/**
3708c2ecf20Sopenharmony_ci * wait_for_commit - wait for commit.
3718c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object
3728c2ecf20Sopenharmony_ci *
3738c2ecf20Sopenharmony_ci * This function sleeps until the commit operation is no longer running.
3748c2ecf20Sopenharmony_ci */
3758c2ecf20Sopenharmony_cistatic int wait_for_commit(struct ubifs_info *c)
3768c2ecf20Sopenharmony_ci{
3778c2ecf20Sopenharmony_ci	dbg_cmt("pid %d goes sleep", current->pid);
3788c2ecf20Sopenharmony_ci
3798c2ecf20Sopenharmony_ci	/*
3808c2ecf20Sopenharmony_ci	 * The following sleeps if the condition is false, and will be woken
3818c2ecf20Sopenharmony_ci	 * when the commit ends. It is possible, although very unlikely, that we
3828c2ecf20Sopenharmony_ci	 * will wake up and see the subsequent commit running, rather than the
3838c2ecf20Sopenharmony_ci	 * one we were waiting for, and go back to sleep.  However, we will be
3848c2ecf20Sopenharmony_ci	 * woken again, so there is no danger of sleeping forever.
3858c2ecf20Sopenharmony_ci	 */
3868c2ecf20Sopenharmony_ci	wait_event(c->cmt_wq, c->cmt_state != COMMIT_RUNNING_BACKGROUND &&
3878c2ecf20Sopenharmony_ci			      c->cmt_state != COMMIT_RUNNING_REQUIRED);
3888c2ecf20Sopenharmony_ci	dbg_cmt("commit finished, pid %d woke up", current->pid);
3898c2ecf20Sopenharmony_ci	return 0;
3908c2ecf20Sopenharmony_ci}
3918c2ecf20Sopenharmony_ci
3928c2ecf20Sopenharmony_ci/**
3938c2ecf20Sopenharmony_ci * ubifs_run_commit - run or wait for commit.
3948c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object
3958c2ecf20Sopenharmony_ci *
3968c2ecf20Sopenharmony_ci * This function runs commit and returns zero in case of success and a negative
3978c2ecf20Sopenharmony_ci * error code in case of failure.
3988c2ecf20Sopenharmony_ci */
3998c2ecf20Sopenharmony_ciint ubifs_run_commit(struct ubifs_info *c)
4008c2ecf20Sopenharmony_ci{
4018c2ecf20Sopenharmony_ci	int err = 0;
4028c2ecf20Sopenharmony_ci
4038c2ecf20Sopenharmony_ci	spin_lock(&c->cs_lock);
4048c2ecf20Sopenharmony_ci	if (c->cmt_state == COMMIT_BROKEN) {
4058c2ecf20Sopenharmony_ci		err = -EROFS;
4068c2ecf20Sopenharmony_ci		goto out;
4078c2ecf20Sopenharmony_ci	}
4088c2ecf20Sopenharmony_ci
4098c2ecf20Sopenharmony_ci	if (c->cmt_state == COMMIT_RUNNING_BACKGROUND)
4108c2ecf20Sopenharmony_ci		/*
4118c2ecf20Sopenharmony_ci		 * We set the commit state to 'running required' to indicate
4128c2ecf20Sopenharmony_ci		 * that we want it to complete as quickly as possible.
4138c2ecf20Sopenharmony_ci		 */
4148c2ecf20Sopenharmony_ci		c->cmt_state = COMMIT_RUNNING_REQUIRED;
4158c2ecf20Sopenharmony_ci
4168c2ecf20Sopenharmony_ci	if (c->cmt_state == COMMIT_RUNNING_REQUIRED) {
4178c2ecf20Sopenharmony_ci		spin_unlock(&c->cs_lock);
4188c2ecf20Sopenharmony_ci		return wait_for_commit(c);
4198c2ecf20Sopenharmony_ci	}
4208c2ecf20Sopenharmony_ci	spin_unlock(&c->cs_lock);
4218c2ecf20Sopenharmony_ci
4228c2ecf20Sopenharmony_ci	/* Ok, the commit is indeed needed */
4238c2ecf20Sopenharmony_ci
4248c2ecf20Sopenharmony_ci	down_write(&c->commit_sem);
4258c2ecf20Sopenharmony_ci	spin_lock(&c->cs_lock);
4268c2ecf20Sopenharmony_ci	/*
4278c2ecf20Sopenharmony_ci	 * Since we unlocked 'c->cs_lock', the state may have changed, so
4288c2ecf20Sopenharmony_ci	 * re-check it.
4298c2ecf20Sopenharmony_ci	 */
4308c2ecf20Sopenharmony_ci	if (c->cmt_state == COMMIT_BROKEN) {
4318c2ecf20Sopenharmony_ci		err = -EROFS;
4328c2ecf20Sopenharmony_ci		goto out_cmt_unlock;
4338c2ecf20Sopenharmony_ci	}
4348c2ecf20Sopenharmony_ci
4358c2ecf20Sopenharmony_ci	if (c->cmt_state == COMMIT_RUNNING_BACKGROUND)
4368c2ecf20Sopenharmony_ci		c->cmt_state = COMMIT_RUNNING_REQUIRED;
4378c2ecf20Sopenharmony_ci
4388c2ecf20Sopenharmony_ci	if (c->cmt_state == COMMIT_RUNNING_REQUIRED) {
4398c2ecf20Sopenharmony_ci		up_write(&c->commit_sem);
4408c2ecf20Sopenharmony_ci		spin_unlock(&c->cs_lock);
4418c2ecf20Sopenharmony_ci		return wait_for_commit(c);
4428c2ecf20Sopenharmony_ci	}
4438c2ecf20Sopenharmony_ci	c->cmt_state = COMMIT_RUNNING_REQUIRED;
4448c2ecf20Sopenharmony_ci	spin_unlock(&c->cs_lock);
4458c2ecf20Sopenharmony_ci
4468c2ecf20Sopenharmony_ci	err = do_commit(c);
4478c2ecf20Sopenharmony_ci	return err;
4488c2ecf20Sopenharmony_ci
4498c2ecf20Sopenharmony_ciout_cmt_unlock:
4508c2ecf20Sopenharmony_ci	up_write(&c->commit_sem);
4518c2ecf20Sopenharmony_ciout:
4528c2ecf20Sopenharmony_ci	spin_unlock(&c->cs_lock);
4538c2ecf20Sopenharmony_ci	return err;
4548c2ecf20Sopenharmony_ci}
4558c2ecf20Sopenharmony_ci
4568c2ecf20Sopenharmony_ci/**
4578c2ecf20Sopenharmony_ci * ubifs_gc_should_commit - determine if it is time for GC to run commit.
4588c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object
4598c2ecf20Sopenharmony_ci *
4608c2ecf20Sopenharmony_ci * This function is called by garbage collection to determine if commit should
4618c2ecf20Sopenharmony_ci * be run. If commit state is @COMMIT_BACKGROUND, which means that the journal
4628c2ecf20Sopenharmony_ci * is full enough to start commit, this function returns true. It is not
4638c2ecf20Sopenharmony_ci * absolutely necessary to commit yet, but it feels like this should be better
4648c2ecf20Sopenharmony_ci * then to keep doing GC. This function returns %1 if GC has to initiate commit
4658c2ecf20Sopenharmony_ci * and %0 if not.
4668c2ecf20Sopenharmony_ci */
4678c2ecf20Sopenharmony_ciint ubifs_gc_should_commit(struct ubifs_info *c)
4688c2ecf20Sopenharmony_ci{
4698c2ecf20Sopenharmony_ci	int ret = 0;
4708c2ecf20Sopenharmony_ci
4718c2ecf20Sopenharmony_ci	spin_lock(&c->cs_lock);
4728c2ecf20Sopenharmony_ci	if (c->cmt_state == COMMIT_BACKGROUND) {
4738c2ecf20Sopenharmony_ci		dbg_cmt("commit required now");
4748c2ecf20Sopenharmony_ci		c->cmt_state = COMMIT_REQUIRED;
4758c2ecf20Sopenharmony_ci	} else
4768c2ecf20Sopenharmony_ci		dbg_cmt("commit not requested");
4778c2ecf20Sopenharmony_ci	if (c->cmt_state == COMMIT_REQUIRED)
4788c2ecf20Sopenharmony_ci		ret = 1;
4798c2ecf20Sopenharmony_ci	spin_unlock(&c->cs_lock);
4808c2ecf20Sopenharmony_ci	return ret;
4818c2ecf20Sopenharmony_ci}
4828c2ecf20Sopenharmony_ci
4838c2ecf20Sopenharmony_ci/*
4848c2ecf20Sopenharmony_ci * Everything below is related to debugging.
4858c2ecf20Sopenharmony_ci */
4868c2ecf20Sopenharmony_ci
4878c2ecf20Sopenharmony_ci/**
4888c2ecf20Sopenharmony_ci * struct idx_node - hold index nodes during index tree traversal.
4898c2ecf20Sopenharmony_ci * @list: list
4908c2ecf20Sopenharmony_ci * @iip: index in parent (slot number of this indexing node in the parent
4918c2ecf20Sopenharmony_ci *       indexing node)
4928c2ecf20Sopenharmony_ci * @upper_key: all keys in this indexing node have to be less or equivalent to
4938c2ecf20Sopenharmony_ci *             this key
4948c2ecf20Sopenharmony_ci * @idx: index node (8-byte aligned because all node structures must be 8-byte
4958c2ecf20Sopenharmony_ci *       aligned)
4968c2ecf20Sopenharmony_ci */
4978c2ecf20Sopenharmony_cistruct idx_node {
4988c2ecf20Sopenharmony_ci	struct list_head list;
4998c2ecf20Sopenharmony_ci	int iip;
5008c2ecf20Sopenharmony_ci	union ubifs_key upper_key;
5018c2ecf20Sopenharmony_ci	struct ubifs_idx_node idx __aligned(8);
5028c2ecf20Sopenharmony_ci};
5038c2ecf20Sopenharmony_ci
5048c2ecf20Sopenharmony_ci/**
5058c2ecf20Sopenharmony_ci * dbg_old_index_check_init - get information for the next old index check.
5068c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object
5078c2ecf20Sopenharmony_ci * @zroot: root of the index
5088c2ecf20Sopenharmony_ci *
5098c2ecf20Sopenharmony_ci * This function records information about the index that will be needed for the
5108c2ecf20Sopenharmony_ci * next old index check i.e. 'dbg_check_old_index()'.
5118c2ecf20Sopenharmony_ci *
5128c2ecf20Sopenharmony_ci * This function returns %0 on success and a negative error code on failure.
5138c2ecf20Sopenharmony_ci */
5148c2ecf20Sopenharmony_ciint dbg_old_index_check_init(struct ubifs_info *c, struct ubifs_zbranch *zroot)
5158c2ecf20Sopenharmony_ci{
5168c2ecf20Sopenharmony_ci	struct ubifs_idx_node *idx;
5178c2ecf20Sopenharmony_ci	int lnum, offs, len, err = 0;
5188c2ecf20Sopenharmony_ci	struct ubifs_debug_info *d = c->dbg;
5198c2ecf20Sopenharmony_ci
5208c2ecf20Sopenharmony_ci	d->old_zroot = *zroot;
5218c2ecf20Sopenharmony_ci	lnum = d->old_zroot.lnum;
5228c2ecf20Sopenharmony_ci	offs = d->old_zroot.offs;
5238c2ecf20Sopenharmony_ci	len = d->old_zroot.len;
5248c2ecf20Sopenharmony_ci
5258c2ecf20Sopenharmony_ci	idx = kmalloc(c->max_idx_node_sz, GFP_NOFS);
5268c2ecf20Sopenharmony_ci	if (!idx)
5278c2ecf20Sopenharmony_ci		return -ENOMEM;
5288c2ecf20Sopenharmony_ci
5298c2ecf20Sopenharmony_ci	err = ubifs_read_node(c, idx, UBIFS_IDX_NODE, len, lnum, offs);
5308c2ecf20Sopenharmony_ci	if (err)
5318c2ecf20Sopenharmony_ci		goto out;
5328c2ecf20Sopenharmony_ci
5338c2ecf20Sopenharmony_ci	d->old_zroot_level = le16_to_cpu(idx->level);
5348c2ecf20Sopenharmony_ci	d->old_zroot_sqnum = le64_to_cpu(idx->ch.sqnum);
5358c2ecf20Sopenharmony_ciout:
5368c2ecf20Sopenharmony_ci	kfree(idx);
5378c2ecf20Sopenharmony_ci	return err;
5388c2ecf20Sopenharmony_ci}
5398c2ecf20Sopenharmony_ci
5408c2ecf20Sopenharmony_ci/**
5418c2ecf20Sopenharmony_ci * dbg_check_old_index - check the old copy of the index.
5428c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object
5438c2ecf20Sopenharmony_ci * @zroot: root of the new index
5448c2ecf20Sopenharmony_ci *
5458c2ecf20Sopenharmony_ci * In order to be able to recover from an unclean unmount, a complete copy of
5468c2ecf20Sopenharmony_ci * the index must exist on flash. This is the "old" index. The commit process
5478c2ecf20Sopenharmony_ci * must write the "new" index to flash without overwriting or destroying any
5488c2ecf20Sopenharmony_ci * part of the old index. This function is run at commit end in order to check
5498c2ecf20Sopenharmony_ci * that the old index does indeed exist completely intact.
5508c2ecf20Sopenharmony_ci *
5518c2ecf20Sopenharmony_ci * This function returns %0 on success and a negative error code on failure.
5528c2ecf20Sopenharmony_ci */
5538c2ecf20Sopenharmony_ciint dbg_check_old_index(struct ubifs_info *c, struct ubifs_zbranch *zroot)
5548c2ecf20Sopenharmony_ci{
5558c2ecf20Sopenharmony_ci	int lnum, offs, len, err = 0, last_level, child_cnt;
5568c2ecf20Sopenharmony_ci	int first = 1, iip;
5578c2ecf20Sopenharmony_ci	struct ubifs_debug_info *d = c->dbg;
5588c2ecf20Sopenharmony_ci	union ubifs_key lower_key, upper_key, l_key, u_key;
5598c2ecf20Sopenharmony_ci	unsigned long long last_sqnum;
5608c2ecf20Sopenharmony_ci	struct ubifs_idx_node *idx;
5618c2ecf20Sopenharmony_ci	struct list_head list;
5628c2ecf20Sopenharmony_ci	struct idx_node *i;
5638c2ecf20Sopenharmony_ci	size_t sz;
5648c2ecf20Sopenharmony_ci
5658c2ecf20Sopenharmony_ci	if (!dbg_is_chk_index(c))
5668c2ecf20Sopenharmony_ci		return 0;
5678c2ecf20Sopenharmony_ci
5688c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&list);
5698c2ecf20Sopenharmony_ci
5708c2ecf20Sopenharmony_ci	sz = sizeof(struct idx_node) + ubifs_idx_node_sz(c, c->fanout) -
5718c2ecf20Sopenharmony_ci	     UBIFS_IDX_NODE_SZ;
5728c2ecf20Sopenharmony_ci
5738c2ecf20Sopenharmony_ci	/* Start at the old zroot */
5748c2ecf20Sopenharmony_ci	lnum = d->old_zroot.lnum;
5758c2ecf20Sopenharmony_ci	offs = d->old_zroot.offs;
5768c2ecf20Sopenharmony_ci	len = d->old_zroot.len;
5778c2ecf20Sopenharmony_ci	iip = 0;
5788c2ecf20Sopenharmony_ci
5798c2ecf20Sopenharmony_ci	/*
5808c2ecf20Sopenharmony_ci	 * Traverse the index tree preorder depth-first i.e. do a node and then
5818c2ecf20Sopenharmony_ci	 * its subtrees from left to right.
5828c2ecf20Sopenharmony_ci	 */
5838c2ecf20Sopenharmony_ci	while (1) {
5848c2ecf20Sopenharmony_ci		struct ubifs_branch *br;
5858c2ecf20Sopenharmony_ci
5868c2ecf20Sopenharmony_ci		/* Get the next index node */
5878c2ecf20Sopenharmony_ci		i = kmalloc(sz, GFP_NOFS);
5888c2ecf20Sopenharmony_ci		if (!i) {
5898c2ecf20Sopenharmony_ci			err = -ENOMEM;
5908c2ecf20Sopenharmony_ci			goto out_free;
5918c2ecf20Sopenharmony_ci		}
5928c2ecf20Sopenharmony_ci		i->iip = iip;
5938c2ecf20Sopenharmony_ci		/* Keep the index nodes on our path in a linked list */
5948c2ecf20Sopenharmony_ci		list_add_tail(&i->list, &list);
5958c2ecf20Sopenharmony_ci		/* Read the index node */
5968c2ecf20Sopenharmony_ci		idx = &i->idx;
5978c2ecf20Sopenharmony_ci		err = ubifs_read_node(c, idx, UBIFS_IDX_NODE, len, lnum, offs);
5988c2ecf20Sopenharmony_ci		if (err)
5998c2ecf20Sopenharmony_ci			goto out_free;
6008c2ecf20Sopenharmony_ci		/* Validate index node */
6018c2ecf20Sopenharmony_ci		child_cnt = le16_to_cpu(idx->child_cnt);
6028c2ecf20Sopenharmony_ci		if (child_cnt < 1 || child_cnt > c->fanout) {
6038c2ecf20Sopenharmony_ci			err = 1;
6048c2ecf20Sopenharmony_ci			goto out_dump;
6058c2ecf20Sopenharmony_ci		}
6068c2ecf20Sopenharmony_ci		if (first) {
6078c2ecf20Sopenharmony_ci			first = 0;
6088c2ecf20Sopenharmony_ci			/* Check root level and sqnum */
6098c2ecf20Sopenharmony_ci			if (le16_to_cpu(idx->level) != d->old_zroot_level) {
6108c2ecf20Sopenharmony_ci				err = 2;
6118c2ecf20Sopenharmony_ci				goto out_dump;
6128c2ecf20Sopenharmony_ci			}
6138c2ecf20Sopenharmony_ci			if (le64_to_cpu(idx->ch.sqnum) != d->old_zroot_sqnum) {
6148c2ecf20Sopenharmony_ci				err = 3;
6158c2ecf20Sopenharmony_ci				goto out_dump;
6168c2ecf20Sopenharmony_ci			}
6178c2ecf20Sopenharmony_ci			/* Set last values as though root had a parent */
6188c2ecf20Sopenharmony_ci			last_level = le16_to_cpu(idx->level) + 1;
6198c2ecf20Sopenharmony_ci			last_sqnum = le64_to_cpu(idx->ch.sqnum) + 1;
6208c2ecf20Sopenharmony_ci			key_read(c, ubifs_idx_key(c, idx), &lower_key);
6218c2ecf20Sopenharmony_ci			highest_ino_key(c, &upper_key, INUM_WATERMARK);
6228c2ecf20Sopenharmony_ci		}
6238c2ecf20Sopenharmony_ci		key_copy(c, &upper_key, &i->upper_key);
6248c2ecf20Sopenharmony_ci		if (le16_to_cpu(idx->level) != last_level - 1) {
6258c2ecf20Sopenharmony_ci			err = 3;
6268c2ecf20Sopenharmony_ci			goto out_dump;
6278c2ecf20Sopenharmony_ci		}
6288c2ecf20Sopenharmony_ci		/*
6298c2ecf20Sopenharmony_ci		 * The index is always written bottom up hence a child's sqnum
6308c2ecf20Sopenharmony_ci		 * is always less than the parents.
6318c2ecf20Sopenharmony_ci		 */
6328c2ecf20Sopenharmony_ci		if (le64_to_cpu(idx->ch.sqnum) >= last_sqnum) {
6338c2ecf20Sopenharmony_ci			err = 4;
6348c2ecf20Sopenharmony_ci			goto out_dump;
6358c2ecf20Sopenharmony_ci		}
6368c2ecf20Sopenharmony_ci		/* Check key range */
6378c2ecf20Sopenharmony_ci		key_read(c, ubifs_idx_key(c, idx), &l_key);
6388c2ecf20Sopenharmony_ci		br = ubifs_idx_branch(c, idx, child_cnt - 1);
6398c2ecf20Sopenharmony_ci		key_read(c, &br->key, &u_key);
6408c2ecf20Sopenharmony_ci		if (keys_cmp(c, &lower_key, &l_key) > 0) {
6418c2ecf20Sopenharmony_ci			err = 5;
6428c2ecf20Sopenharmony_ci			goto out_dump;
6438c2ecf20Sopenharmony_ci		}
6448c2ecf20Sopenharmony_ci		if (keys_cmp(c, &upper_key, &u_key) < 0) {
6458c2ecf20Sopenharmony_ci			err = 6;
6468c2ecf20Sopenharmony_ci			goto out_dump;
6478c2ecf20Sopenharmony_ci		}
6488c2ecf20Sopenharmony_ci		if (keys_cmp(c, &upper_key, &u_key) == 0)
6498c2ecf20Sopenharmony_ci			if (!is_hash_key(c, &u_key)) {
6508c2ecf20Sopenharmony_ci				err = 7;
6518c2ecf20Sopenharmony_ci				goto out_dump;
6528c2ecf20Sopenharmony_ci			}
6538c2ecf20Sopenharmony_ci		/* Go to next index node */
6548c2ecf20Sopenharmony_ci		if (le16_to_cpu(idx->level) == 0) {
6558c2ecf20Sopenharmony_ci			/* At the bottom, so go up until can go right */
6568c2ecf20Sopenharmony_ci			while (1) {
6578c2ecf20Sopenharmony_ci				/* Drop the bottom of the list */
6588c2ecf20Sopenharmony_ci				list_del(&i->list);
6598c2ecf20Sopenharmony_ci				kfree(i);
6608c2ecf20Sopenharmony_ci				/* No more list means we are done */
6618c2ecf20Sopenharmony_ci				if (list_empty(&list))
6628c2ecf20Sopenharmony_ci					goto out;
6638c2ecf20Sopenharmony_ci				/* Look at the new bottom */
6648c2ecf20Sopenharmony_ci				i = list_entry(list.prev, struct idx_node,
6658c2ecf20Sopenharmony_ci					       list);
6668c2ecf20Sopenharmony_ci				idx = &i->idx;
6678c2ecf20Sopenharmony_ci				/* Can we go right */
6688c2ecf20Sopenharmony_ci				if (iip + 1 < le16_to_cpu(idx->child_cnt)) {
6698c2ecf20Sopenharmony_ci					iip = iip + 1;
6708c2ecf20Sopenharmony_ci					break;
6718c2ecf20Sopenharmony_ci				} else
6728c2ecf20Sopenharmony_ci					/* Nope, so go up again */
6738c2ecf20Sopenharmony_ci					iip = i->iip;
6748c2ecf20Sopenharmony_ci			}
6758c2ecf20Sopenharmony_ci		} else
6768c2ecf20Sopenharmony_ci			/* Go down left */
6778c2ecf20Sopenharmony_ci			iip = 0;
6788c2ecf20Sopenharmony_ci		/*
6798c2ecf20Sopenharmony_ci		 * We have the parent in 'idx' and now we set up for reading the
6808c2ecf20Sopenharmony_ci		 * child pointed to by slot 'iip'.
6818c2ecf20Sopenharmony_ci		 */
6828c2ecf20Sopenharmony_ci		last_level = le16_to_cpu(idx->level);
6838c2ecf20Sopenharmony_ci		last_sqnum = le64_to_cpu(idx->ch.sqnum);
6848c2ecf20Sopenharmony_ci		br = ubifs_idx_branch(c, idx, iip);
6858c2ecf20Sopenharmony_ci		lnum = le32_to_cpu(br->lnum);
6868c2ecf20Sopenharmony_ci		offs = le32_to_cpu(br->offs);
6878c2ecf20Sopenharmony_ci		len = le32_to_cpu(br->len);
6888c2ecf20Sopenharmony_ci		key_read(c, &br->key, &lower_key);
6898c2ecf20Sopenharmony_ci		if (iip + 1 < le16_to_cpu(idx->child_cnt)) {
6908c2ecf20Sopenharmony_ci			br = ubifs_idx_branch(c, idx, iip + 1);
6918c2ecf20Sopenharmony_ci			key_read(c, &br->key, &upper_key);
6928c2ecf20Sopenharmony_ci		} else
6938c2ecf20Sopenharmony_ci			key_copy(c, &i->upper_key, &upper_key);
6948c2ecf20Sopenharmony_ci	}
6958c2ecf20Sopenharmony_ciout:
6968c2ecf20Sopenharmony_ci	err = dbg_old_index_check_init(c, zroot);
6978c2ecf20Sopenharmony_ci	if (err)
6988c2ecf20Sopenharmony_ci		goto out_free;
6998c2ecf20Sopenharmony_ci
7008c2ecf20Sopenharmony_ci	return 0;
7018c2ecf20Sopenharmony_ci
7028c2ecf20Sopenharmony_ciout_dump:
7038c2ecf20Sopenharmony_ci	ubifs_err(c, "dumping index node (iip=%d)", i->iip);
7048c2ecf20Sopenharmony_ci	ubifs_dump_node(c, idx, ubifs_idx_node_sz(c, c->fanout));
7058c2ecf20Sopenharmony_ci	list_del(&i->list);
7068c2ecf20Sopenharmony_ci	kfree(i);
7078c2ecf20Sopenharmony_ci	if (!list_empty(&list)) {
7088c2ecf20Sopenharmony_ci		i = list_entry(list.prev, struct idx_node, list);
7098c2ecf20Sopenharmony_ci		ubifs_err(c, "dumping parent index node");
7108c2ecf20Sopenharmony_ci		ubifs_dump_node(c, &i->idx, ubifs_idx_node_sz(c, c->fanout));
7118c2ecf20Sopenharmony_ci	}
7128c2ecf20Sopenharmony_ciout_free:
7138c2ecf20Sopenharmony_ci	while (!list_empty(&list)) {
7148c2ecf20Sopenharmony_ci		i = list_entry(list.next, struct idx_node, list);
7158c2ecf20Sopenharmony_ci		list_del(&i->list);
7168c2ecf20Sopenharmony_ci		kfree(i);
7178c2ecf20Sopenharmony_ci	}
7188c2ecf20Sopenharmony_ci	ubifs_err(c, "failed, error %d", err);
7198c2ecf20Sopenharmony_ci	if (err > 0)
7208c2ecf20Sopenharmony_ci		err = -EINVAL;
7218c2ecf20Sopenharmony_ci	return err;
7228c2ecf20Sopenharmony_ci}
723