// 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 TNC functions for committing */ #include <linux/random.h> #include "ubifs.h" /** * make_idx_node - make an index node for fill-the-gaps method of TNC commit. * @c: UBIFS file-system description object * @idx: buffer in which to place new index node * @znode: znode from which to make new index node * @lnum: LEB number where new index node will be written * @offs: offset where new index node will be written * @len: length of new index node */ static int make_idx_node(struct ubifs_info *c, struct ubifs_idx_node *idx, struct ubifs_znode *znode, int lnum, int offs, int len) { … } /** * fill_gap - make index nodes in gaps in dirty index LEBs. * @c: UBIFS file-system description object * @lnum: LEB number that gap appears in * @gap_start: offset of start of gap * @gap_end: offset of end of gap * @dirt: adds dirty space to this * * This function returns the number of index nodes written into the gap. */ static int fill_gap(struct ubifs_info *c, int lnum, int gap_start, int gap_end, int *dirt) { … } /** * find_old_idx - find an index node obsoleted since the last commit start. * @c: UBIFS file-system description object * @lnum: LEB number of obsoleted index node * @offs: offset of obsoleted index node * * Returns %1 if found and %0 otherwise. */ static int find_old_idx(struct ubifs_info *c, int lnum, int offs) { … } /** * is_idx_node_in_use - determine if an index node can be overwritten. * @c: UBIFS file-system description object * @key: key of index node * @level: index node level * @lnum: LEB number of index node * @offs: offset of index node * * If @key / @lnum / @offs identify an index node that was not part of the old * index, then this function returns %0 (obsolete). Else if the index node was * part of the old index but is now dirty %1 is returned, else if it is clean %2 * is returned. A negative error code is returned on failure. */ static int is_idx_node_in_use(struct ubifs_info *c, union ubifs_key *key, int level, int lnum, int offs) { … } /** * layout_leb_in_gaps - layout index nodes using in-the-gaps method. * @c: UBIFS file-system description object * @p: return LEB number in @c->gap_lebs[p] * * This function lays out new index nodes for dirty znodes using in-the-gaps * method of TNC commit. * This function merely puts the next znode into the next gap, making no attempt * to try to maximise the number of znodes that fit. * This function returns the number of index nodes written into the gaps, or a * negative error code on failure. */ static int layout_leb_in_gaps(struct ubifs_info *c, int p) { … } /** * get_leb_cnt - calculate the number of empty LEBs needed to commit. * @c: UBIFS file-system description object * @cnt: number of znodes to commit * * This function returns the number of empty LEBs needed to commit @cnt znodes * to the current index head. The number is not exact and may be more than * needed. */ static int get_leb_cnt(struct ubifs_info *c, int cnt) { … } /** * layout_in_gaps - in-the-gaps method of committing TNC. * @c: UBIFS file-system description object * @cnt: number of dirty znodes to commit. * * This function lays out new index nodes for dirty znodes using in-the-gaps * method of TNC commit. * * This function returns %0 on success and a negative error code on failure. */ static int layout_in_gaps(struct ubifs_info *c, int cnt) { … } /** * layout_in_empty_space - layout index nodes in empty space. * @c: UBIFS file-system description object * * This function lays out new index nodes for dirty znodes using empty LEBs. * * This function returns %0 on success and a negative error code on failure. */ static int layout_in_empty_space(struct ubifs_info *c) { … } /** * layout_commit - determine positions of index nodes to commit. * @c: UBIFS file-system description object * @no_space: indicates that insufficient empty LEBs were allocated * @cnt: number of znodes to commit * * Calculate and update the positions of index nodes to commit. If there were * an insufficient number of empty LEBs allocated, then index nodes are placed * into the gaps created by obsolete index nodes in non-empty index LEBs. For * this purpose, an obsolete index node is one that was not in the index as at * the end of the last commit. To write "in-the-gaps" requires that those index * LEBs are updated atomically in-place. */ static int layout_commit(struct ubifs_info *c, int no_space, int cnt) { … } /** * find_first_dirty - find first dirty znode. * @znode: znode to begin searching from */ static struct ubifs_znode *find_first_dirty(struct ubifs_znode *znode) { … } /** * find_next_dirty - find next dirty znode. * @znode: znode to begin searching from */ static struct ubifs_znode *find_next_dirty(struct ubifs_znode *znode) { … } /** * get_znodes_to_commit - create list of dirty znodes to commit. * @c: UBIFS file-system description object * * This function returns the number of znodes to commit. */ static int get_znodes_to_commit(struct ubifs_info *c) { … } /** * alloc_idx_lebs - allocate empty LEBs to be used to commit. * @c: UBIFS file-system description object * @cnt: number of znodes to commit * * This function returns %-ENOSPC if it cannot allocate a sufficient number of * empty LEBs. %0 is returned on success, otherwise a negative error code * is returned. */ static int alloc_idx_lebs(struct ubifs_info *c, int cnt) { … } /** * free_unused_idx_lebs - free unused LEBs that were allocated for the commit. * @c: UBIFS file-system description object * * It is possible that we allocate more empty LEBs for the commit than we need. * This functions frees the surplus. * * This function returns %0 on success and a negative error code on failure. */ static int free_unused_idx_lebs(struct ubifs_info *c) { … } /** * free_idx_lebs - free unused LEBs after commit end. * @c: UBIFS file-system description object * * This function returns %0 on success and a negative error code on failure. */ static int free_idx_lebs(struct ubifs_info *c) { … } /** * ubifs_tnc_start_commit - start TNC commit. * @c: UBIFS file-system description object * @zroot: new index root position is returned here * * This function prepares the list of indexing nodes to commit and lays out * their positions on flash. If there is not enough free space it uses the * in-gap commit method. Returns zero in case of success and a negative error * code in case of failure. */ int ubifs_tnc_start_commit(struct ubifs_info *c, struct ubifs_zbranch *zroot) { … } /** * write_index - write index nodes. * @c: UBIFS file-system description object * * This function writes the index nodes whose positions were laid out in the * layout_in_empty_space function. */ static int write_index(struct ubifs_info *c) { … } /** * free_obsolete_znodes - free obsolete znodes. * @c: UBIFS file-system description object * * At the end of commit end, obsolete znodes are freed. */ static void free_obsolete_znodes(struct ubifs_info *c) { … } /** * return_gap_lebs - return LEBs used by the in-gap commit method. * @c: UBIFS file-system description object * * This function clears the "taken" flag for the LEBs which were used by the * "commit in-the-gaps" method. */ static int return_gap_lebs(struct ubifs_info *c) { … } /** * ubifs_tnc_end_commit - update the TNC for commit end. * @c: UBIFS file-system description object * * Write the dirty znodes. */ int ubifs_tnc_end_commit(struct ubifs_info *c) { … }