// SPDX-License-Identifier: GPL-2.0-only /* * This file is part of UBIFS. * * Copyright (C) 2006-2008 Nokia Corporation. * * Authors: Adrian Hunter * Artem Bityutskiy (Битюцкий Артём) */ /* * This file implements functions that manage the running of the commit process. * Each affected module has its own functions to accomplish their part in the * commit and those functions are called here. * * The commit is the process whereby all updates to the index and LEB properties * are written out together and the journal becomes empty. This keeps the * file system consistent - at all times the state can be recreated by reading * the index and LEB properties and then replaying the journal. * * The commit is split into two parts named "commit start" and "commit end". * During commit start, the commit process has exclusive access to the journal * by holding the commit semaphore down for writing. As few I/O operations as * possible are performed during commit start, instead the nodes that are to be * written are merely identified. During commit end, the commit semaphore is no * longer held and the journal is again in operation, allowing users to continue * to use the file system while the bulk of the commit I/O is performed. The * purpose of this two-step approach is to prevent the commit from causing any * latency blips. Note that in any case, the commit does not prevent lookups * (as permitted by the TNC mutex), or access to VFS data structures e.g. page * cache. */ #include <linux/freezer.h> #include <linux/kthread.h> #include <linux/slab.h> #include "ubifs.h" /* * nothing_to_commit - check if there is nothing to commit. * @c: UBIFS file-system description object * * This is a helper function which checks if there is anything to commit. It is * used as an optimization to avoid starting the commit if it is not really * necessary. Indeed, the commit operation always assumes flash I/O (e.g., * writing the commit start node to the log), and it is better to avoid doing * this unnecessarily. E.g., 'ubifs_sync_fs()' runs the commit, but if there is * nothing to commit, it is more optimal to avoid any flash I/O. * * This function has to be called with @c->commit_sem locked for writing - * this function does not take LPT/TNC locks because the @c->commit_sem * guarantees that we have exclusive access to the TNC and LPT data structures. * * This function returns %1 if there is nothing to commit and %0 otherwise. */ static int nothing_to_commit(struct ubifs_info *c) { … } /** * 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) { … } /** * run_bg_commit - run background commit if it is needed. * @c: UBIFS file-system description object * * This function runs background commit if it is needed. Returns zero in case * of success and a negative error code in case of failure. */ static int run_bg_commit(struct ubifs_info *c) { … } /** * ubifs_bg_thread - UBIFS background thread function. * @info: points to the file-system description object * * This function implements various file-system background activities: * o when a write-buffer timer expires it synchronizes the appropriate * write-buffer; * o when the journal is about to be full, it starts in-advance commit. * * Note, other stuff like background garbage collection may be added here in * future. */ int ubifs_bg_thread(void *info) { … } /** * ubifs_commit_required - set commit state to "required". * @c: UBIFS file-system description object * * This function is called if a commit is required but cannot be done from the * calling function, so it is just flagged instead. */ void ubifs_commit_required(struct ubifs_info *c) { … } /** * ubifs_request_bg_commit - notify the background thread to do a commit. * @c: UBIFS file-system description object * * This function is called if the journal is full enough to make a commit * worthwhile, so background thread is kicked to start it. */ void ubifs_request_bg_commit(struct ubifs_info *c) { … } /** * wait_for_commit - wait for commit. * @c: UBIFS file-system description object * * This function sleeps until the commit operation is no longer running. */ static int wait_for_commit(struct ubifs_info *c) { … } /** * ubifs_run_commit - run or wait for commit. * @c: UBIFS file-system description object * * This function runs commit and returns zero in case of success and a negative * error code in case of failure. */ int ubifs_run_commit(struct ubifs_info *c) { … } /** * ubifs_gc_should_commit - determine if it is time for GC to run commit. * @c: UBIFS file-system description object * * This function is called by garbage collection to determine if commit should * be run. If commit state is @COMMIT_BACKGROUND, which means that the journal * is full enough to start commit, this function returns true. It is not * absolutely necessary to commit yet, but it feels like this should be better * then to keep doing GC. This function returns %1 if GC has to initiate commit * and %0 if not. */ int ubifs_gc_should_commit(struct ubifs_info *c) { … } /* * Everything below is related to debugging. */ /** * struct idx_node - hold index nodes during index tree traversal. * @list: list * @iip: index in parent (slot number of this indexing node in the parent * indexing node) * @upper_key: all keys in this indexing node have to be less or equivalent to * this key * @idx: index node (8-byte aligned because all node structures must be 8-byte * aligned) */ struct idx_node { … }; /** * dbg_old_index_check_init - get information for the next old index check. * @c: UBIFS file-system description object * @zroot: root of the index * * This function records information about the index that will be needed for the * next old index check i.e. 'dbg_check_old_index()'. * * This function returns %0 on success and a negative error code on failure. */ int dbg_old_index_check_init(struct ubifs_info *c, struct ubifs_zbranch *zroot) { … } /** * dbg_check_old_index - check the old copy of the index. * @c: UBIFS file-system description object * @zroot: root of the new index * * In order to be able to recover from an unclean unmount, a complete copy of * the index must exist on flash. This is the "old" index. The commit process * must write the "new" index to flash without overwriting or destroying any * part of the old index. This function is run at commit end in order to check * that the old index does indeed exist completely intact. * * This function returns %0 on success and a negative error code on failure. */ int dbg_check_old_index(struct ubifs_info *c, struct ubifs_zbranch *zroot) { … }