linux/fs/ubifs/lpt_commit.c

// 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 commit-related functionality of the LEB properties
 * subsystem.
 */

#include <linux/crc16.h>
#include <linux/slab.h>
#include <linux/random.h>
#include "ubifs.h"

static int dbg_populate_lsave(struct ubifs_info *c);

/**
 * first_dirty_cnode - find first dirty cnode.
 * @c: UBIFS file-system description object
 * @nnode: nnode at which to start
 *
 * This function returns the first dirty cnode or %NULL if there is not one.
 */
static struct ubifs_cnode *first_dirty_cnode(const struct ubifs_info *c, struct ubifs_nnode *nnode)
{}

/**
 * next_dirty_cnode - find next dirty cnode.
 * @c: UBIFS file-system description object
 * @cnode: cnode from which to begin searching
 *
 * This function returns the next dirty cnode or %NULL if there is not one.
 */
static struct ubifs_cnode *next_dirty_cnode(const struct ubifs_info *c, struct ubifs_cnode *cnode)
{}

/**
 * get_cnodes_to_commit - create list of dirty cnodes to commit.
 * @c: UBIFS file-system description object
 *
 * This function returns the number of cnodes to commit.
 */
static int get_cnodes_to_commit(struct ubifs_info *c)
{}

/**
 * upd_ltab - update LPT LEB properties.
 * @c: UBIFS file-system description object
 * @lnum: LEB number
 * @free: amount of free space
 * @dirty: amount of dirty space to add
 */
static void upd_ltab(struct ubifs_info *c, int lnum, int free, int dirty)
{}

/**
 * alloc_lpt_leb - allocate an LPT LEB that is empty.
 * @c: UBIFS file-system description object
 * @lnum: LEB number is passed and returned here
 *
 * This function finds the next empty LEB in the ltab starting from @lnum. If a
 * an empty LEB is found it is returned in @lnum and the function returns %0.
 * Otherwise the function returns -ENOSPC.  Note however, that LPT is designed
 * never to run out of space.
 */
static int alloc_lpt_leb(struct ubifs_info *c, int *lnum)
{}

/**
 * layout_cnodes - layout cnodes for commit.
 * @c: UBIFS file-system description object
 *
 * This function returns %0 on success and a negative error code on failure.
 */
static int layout_cnodes(struct ubifs_info *c)
{}

/**
 * realloc_lpt_leb - allocate an LPT LEB that is empty.
 * @c: UBIFS file-system description object
 * @lnum: LEB number is passed and returned here
 *
 * This function duplicates exactly the results of the function alloc_lpt_leb.
 * It is used during end commit to reallocate the same LEB numbers that were
 * allocated by alloc_lpt_leb during start commit.
 *
 * This function finds the next LEB that was allocated by the alloc_lpt_leb
 * function starting from @lnum. If a LEB is found it is returned in @lnum and
 * the function returns %0. Otherwise the function returns -ENOSPC.
 * Note however, that LPT is designed never to run out of space.
 */
static int realloc_lpt_leb(struct ubifs_info *c, int *lnum)
{}

/**
 * write_cnodes - write cnodes for commit.
 * @c: UBIFS file-system description object
 *
 * This function returns %0 on success and a negative error code on failure.
 */
static int write_cnodes(struct ubifs_info *c)
{}

/**
 * next_pnode_to_dirty - find next pnode to dirty.
 * @c: UBIFS file-system description object
 * @pnode: pnode
 *
 * This function returns the next pnode to dirty or %NULL if there are no more
 * pnodes.  Note that pnodes that have never been written (lnum == 0) are
 * skipped.
 */
static struct ubifs_pnode *next_pnode_to_dirty(struct ubifs_info *c,
					       struct ubifs_pnode *pnode)
{}

/**
 * add_pnode_dirt - add dirty space to LPT LEB properties.
 * @c: UBIFS file-system description object
 * @pnode: pnode for which to add dirt
 */
static void add_pnode_dirt(struct ubifs_info *c, struct ubifs_pnode *pnode)
{}

/**
 * do_make_pnode_dirty - mark a pnode dirty.
 * @c: UBIFS file-system description object
 * @pnode: pnode to mark dirty
 */
static void do_make_pnode_dirty(struct ubifs_info *c, struct ubifs_pnode *pnode)
{}

/**
 * make_tree_dirty - mark the entire LEB properties tree dirty.
 * @c: UBIFS file-system description object
 *
 * This function is used by the "small" LPT model to cause the entire LEB
 * properties tree to be written.  The "small" LPT model does not use LPT
 * garbage collection because it is more efficient to write the entire tree
 * (because it is small).
 *
 * This function returns %0 on success and a negative error code on failure.
 */
static int make_tree_dirty(struct ubifs_info *c)
{}

/**
 * need_write_all - determine if the LPT area is running out of free space.
 * @c: UBIFS file-system description object
 *
 * This function returns %1 if the LPT area is running out of free space and %0
 * if it is not.
 */
static int need_write_all(struct ubifs_info *c)
{}

/**
 * lpt_tgc_start - start trivial garbage collection of LPT LEBs.
 * @c: UBIFS file-system description object
 *
 * LPT trivial garbage collection is where a LPT LEB contains only dirty and
 * free space and so may be reused as soon as the next commit is completed.
 * This function is called during start commit to mark LPT LEBs for trivial GC.
 */
static void lpt_tgc_start(struct ubifs_info *c)
{}

/**
 * lpt_tgc_end - end trivial garbage collection of LPT LEBs.
 * @c: UBIFS file-system description object
 *
 * LPT trivial garbage collection is where a LPT LEB contains only dirty and
 * free space and so may be reused as soon as the next commit is completed.
 * This function is called after the commit is completed (master node has been
 * written) and un-maps LPT LEBs that were marked for trivial GC.
 */
static int lpt_tgc_end(struct ubifs_info *c)
{}

/**
 * populate_lsave - fill the lsave array with important LEB numbers.
 * @c: the UBIFS file-system description object
 *
 * This function is only called for the "big" model. It records a small number
 * of LEB numbers of important LEBs.  Important LEBs are ones that are (from
 * most important to least important): empty, freeable, freeable index, dirty
 * index, dirty or free. Upon mount, we read this list of LEB numbers and bring
 * their pnodes into memory.  That will stop us from having to scan the LPT
 * straight away. For the "small" model we assume that scanning the LPT is no
 * big deal.
 */
static void populate_lsave(struct ubifs_info *c)
{}

/**
 * nnode_lookup - lookup a nnode in the LPT.
 * @c: UBIFS file-system description object
 * @i: nnode number
 *
 * This function returns a pointer to the nnode on success or a negative
 * error code on failure.
 */
static struct ubifs_nnode *nnode_lookup(struct ubifs_info *c, int i)
{}

/**
 * make_nnode_dirty - find a nnode and, if found, make it dirty.
 * @c: UBIFS file-system description object
 * @node_num: nnode number of nnode to make dirty
 * @lnum: LEB number where nnode was written
 * @offs: offset where nnode was written
 *
 * This function is used by LPT garbage collection.  LPT garbage collection is
 * used only for the "big" LPT model (c->big_lpt == 1).  Garbage collection
 * simply involves marking all the nodes in the LEB being garbage-collected as
 * dirty.  The dirty nodes are written next commit, after which the LEB is free
 * to be reused.
 *
 * This function returns %0 on success and a negative error code on failure.
 */
static int make_nnode_dirty(struct ubifs_info *c, int node_num, int lnum,
			    int offs)
{}

/**
 * make_pnode_dirty - find a pnode and, if found, make it dirty.
 * @c: UBIFS file-system description object
 * @node_num: pnode number of pnode to make dirty
 * @lnum: LEB number where pnode was written
 * @offs: offset where pnode was written
 *
 * This function is used by LPT garbage collection.  LPT garbage collection is
 * used only for the "big" LPT model (c->big_lpt == 1).  Garbage collection
 * simply involves marking all the nodes in the LEB being garbage-collected as
 * dirty.  The dirty nodes are written next commit, after which the LEB is free
 * to be reused.
 *
 * This function returns %0 on success and a negative error code on failure.
 */
static int make_pnode_dirty(struct ubifs_info *c, int node_num, int lnum,
			    int offs)
{}

/**
 * make_ltab_dirty - make ltab node dirty.
 * @c: UBIFS file-system description object
 * @lnum: LEB number where ltab was written
 * @offs: offset where ltab was written
 *
 * This function is used by LPT garbage collection.  LPT garbage collection is
 * used only for the "big" LPT model (c->big_lpt == 1).  Garbage collection
 * simply involves marking all the nodes in the LEB being garbage-collected as
 * dirty.  The dirty nodes are written next commit, after which the LEB is free
 * to be reused.
 *
 * This function returns %0 on success and a negative error code on failure.
 */
static int make_ltab_dirty(struct ubifs_info *c, int lnum, int offs)
{}

/**
 * make_lsave_dirty - make lsave node dirty.
 * @c: UBIFS file-system description object
 * @lnum: LEB number where lsave was written
 * @offs: offset where lsave was written
 *
 * This function is used by LPT garbage collection.  LPT garbage collection is
 * used only for the "big" LPT model (c->big_lpt == 1).  Garbage collection
 * simply involves marking all the nodes in the LEB being garbage-collected as
 * dirty.  The dirty nodes are written next commit, after which the LEB is free
 * to be reused.
 *
 * This function returns %0 on success and a negative error code on failure.
 */
static int make_lsave_dirty(struct ubifs_info *c, int lnum, int offs)
{}

/**
 * make_node_dirty - make node dirty.
 * @c: UBIFS file-system description object
 * @node_type: LPT node type
 * @node_num: node number
 * @lnum: LEB number where node was written
 * @offs: offset where node was written
 *
 * This function is used by LPT garbage collection.  LPT garbage collection is
 * used only for the "big" LPT model (c->big_lpt == 1).  Garbage collection
 * simply involves marking all the nodes in the LEB being garbage-collected as
 * dirty.  The dirty nodes are written next commit, after which the LEB is free
 * to be reused.
 *
 * This function returns %0 on success and a negative error code on failure.
 */
static int make_node_dirty(struct ubifs_info *c, int node_type, int node_num,
			   int lnum, int offs)
{}

/**
 * get_lpt_node_len - return the length of a node based on its type.
 * @c: UBIFS file-system description object
 * @node_type: LPT node type
 */
static int get_lpt_node_len(const struct ubifs_info *c, int node_type)
{}

/**
 * get_pad_len - return the length of padding in a buffer.
 * @c: UBIFS file-system description object
 * @buf: buffer
 * @len: length of buffer
 */
static int get_pad_len(const struct ubifs_info *c, uint8_t *buf, int len)
{}

/**
 * get_lpt_node_type - return type (and node number) of a node in a buffer.
 * @c: UBIFS file-system description object
 * @buf: buffer
 * @node_num: node number is returned here
 */
static int get_lpt_node_type(const struct ubifs_info *c, uint8_t *buf,
			     int *node_num)
{}

/**
 * is_a_node - determine if a buffer contains a node.
 * @c: UBIFS file-system description object
 * @buf: buffer
 * @len: length of buffer
 *
 * This function returns %1 if the buffer contains a node or %0 if it does not.
 */
static int is_a_node(const struct ubifs_info *c, uint8_t *buf, int len)
{}

/**
 * lpt_gc_lnum - garbage collect a LPT LEB.
 * @c: UBIFS file-system description object
 * @lnum: LEB number to garbage collect
 *
 * LPT garbage collection is used only for the "big" LPT model
 * (c->big_lpt == 1).  Garbage collection simply involves marking all the nodes
 * in the LEB being garbage-collected as dirty.  The dirty nodes are written
 * next commit, after which the LEB is free to be reused.
 *
 * This function returns %0 on success and a negative error code on failure.
 */
static int lpt_gc_lnum(struct ubifs_info *c, int lnum)
{}

/**
 * lpt_gc - LPT garbage collection.
 * @c: UBIFS file-system description object
 *
 * Select a LPT LEB for LPT garbage collection and call 'lpt_gc_lnum()'.
 * Returns %0 on success and a negative error code on failure.
 */
static int lpt_gc(struct ubifs_info *c)
{}

/**
 * ubifs_lpt_start_commit - UBIFS commit starts.
 * @c: the UBIFS file-system description object
 *
 * This function has to be called when UBIFS starts the commit operation.
 * This function "freezes" all currently dirty LEB properties and does not
 * change them anymore. Further changes are saved and tracked separately
 * because they are not part of this commit. This function returns zero in case
 * of success and a negative error code in case of failure.
 */
int ubifs_lpt_start_commit(struct ubifs_info *c)
{}

/**
 * free_obsolete_cnodes - free obsolete cnodes for commit end.
 * @c: UBIFS file-system description object
 */
static void free_obsolete_cnodes(struct ubifs_info *c)
{}

/**
 * ubifs_lpt_end_commit - finish the commit operation.
 * @c: the UBIFS file-system description object
 *
 * This function has to be called when the commit operation finishes. It
 * flushes the changes which were "frozen" by 'ubifs_lprops_start_commit()' to
 * the media. Returns zero in case of success and a negative error code in case
 * of failure.
 */
int ubifs_lpt_end_commit(struct ubifs_info *c)
{}

/**
 * ubifs_lpt_post_commit - post commit LPT trivial GC and LPT GC.
 * @c: UBIFS file-system description object
 *
 * LPT trivial GC is completed after a commit. Also LPT GC is done after a
 * commit for the "big" LPT model.
 */
int ubifs_lpt_post_commit(struct ubifs_info *c)
{}

/**
 * first_nnode - find the first nnode in memory.
 * @c: UBIFS file-system description object
 * @hght: height of tree where nnode found is returned here
 *
 * This function returns a pointer to the nnode found or %NULL if no nnode is
 * found. This function is a helper to 'ubifs_lpt_free()'.
 */
static struct ubifs_nnode *first_nnode(struct ubifs_info *c, int *hght)
{}

/**
 * next_nnode - find the next nnode in memory.
 * @c: UBIFS file-system description object
 * @nnode: nnode from which to start.
 * @hght: height of tree where nnode is, is passed and returned here
 *
 * This function returns a pointer to the nnode found or %NULL if no nnode is
 * found. This function is a helper to 'ubifs_lpt_free()'.
 */
static struct ubifs_nnode *next_nnode(struct ubifs_info *c,
				      struct ubifs_nnode *nnode, int *hght)
{}

/**
 * ubifs_lpt_free - free resources owned by the LPT.
 * @c: UBIFS file-system description object
 * @wr_only: free only resources used for writing
 */
void ubifs_lpt_free(struct ubifs_info *c, int wr_only)
{}

/*
 * Everything below is related to debugging.
 */

/**
 * dbg_is_all_ff - determine if a buffer contains only 0xFF bytes.
 * @buf: buffer
 * @len: buffer length
 */
static int dbg_is_all_ff(uint8_t *buf, int len)
{}

/**
 * dbg_is_nnode_dirty - determine if a nnode is dirty.
 * @c: the UBIFS file-system description object
 * @lnum: LEB number where nnode was written
 * @offs: offset where nnode was written
 */
static int dbg_is_nnode_dirty(struct ubifs_info *c, int lnum, int offs)
{}

/**
 * dbg_is_pnode_dirty - determine if a pnode is dirty.
 * @c: the UBIFS file-system description object
 * @lnum: LEB number where pnode was written
 * @offs: offset where pnode was written
 */
static int dbg_is_pnode_dirty(struct ubifs_info *c, int lnum, int offs)
{}

/**
 * dbg_is_ltab_dirty - determine if a ltab node is dirty.
 * @c: the UBIFS file-system description object
 * @lnum: LEB number where ltab node was written
 * @offs: offset where ltab node was written
 */
static int dbg_is_ltab_dirty(struct ubifs_info *c, int lnum, int offs)
{}

/**
 * dbg_is_lsave_dirty - determine if a lsave node is dirty.
 * @c: the UBIFS file-system description object
 * @lnum: LEB number where lsave node was written
 * @offs: offset where lsave node was written
 */
static int dbg_is_lsave_dirty(struct ubifs_info *c, int lnum, int offs)
{}

/**
 * dbg_is_node_dirty - determine if a node is dirty.
 * @c: the UBIFS file-system description object
 * @node_type: node type
 * @lnum: LEB number where node was written
 * @offs: offset where node was written
 */
static int dbg_is_node_dirty(struct ubifs_info *c, int node_type, int lnum,
			     int offs)
{}

/**
 * dbg_check_ltab_lnum - check the ltab for a LPT LEB number.
 * @c: the UBIFS file-system description object
 * @lnum: LEB number where node was written
 *
 * This function returns %0 on success and a negative error code on failure.
 */
static int dbg_check_ltab_lnum(struct ubifs_info *c, int lnum)
{}

/**
 * dbg_check_ltab - check the free and dirty space in the ltab.
 * @c: the UBIFS file-system description object
 *
 * This function returns %0 on success and a negative error code on failure.
 */
int dbg_check_ltab(struct ubifs_info *c)
{}

/**
 * dbg_chk_lpt_free_spc - check LPT free space is enough to write entire LPT.
 * @c: the UBIFS file-system description object
 *
 * This function returns %0 on success and a negative error code on failure.
 */
int dbg_chk_lpt_free_spc(struct ubifs_info *c)
{}

/**
 * dbg_chk_lpt_sz - check LPT does not write more than LPT size.
 * @c: the UBIFS file-system description object
 * @action: what to do
 * @len: length written
 *
 * This function returns %0 on success and a negative error code on failure.
 * The @action argument may be one of:
 *   o %0 - LPT debugging checking starts, initialize debugging variables;
 *   o %1 - wrote an LPT node, increase LPT size by @len bytes;
 *   o %2 - switched to a different LEB and wasted @len bytes;
 *   o %3 - check that we've written the right number of bytes.
 *   o %4 - wasted @len bytes;
 */
int dbg_chk_lpt_sz(struct ubifs_info *c, int action, int len)
{}

/**
 * dump_lpt_leb - dump an LPT LEB.
 * @c: UBIFS file-system description object
 * @lnum: LEB number to dump
 *
 * This function dumps an LEB from LPT area. Nodes in this area are very
 * different to nodes in the main area (e.g., they do not have common headers,
 * they do not have 8-byte alignments, etc), so we have a separate function to
 * dump LPT area LEBs. Note, LPT has to be locked by the caller.
 */
static void dump_lpt_leb(const struct ubifs_info *c, int lnum)
{}

/**
 * ubifs_dump_lpt_lebs - dump LPT lebs.
 * @c: UBIFS file-system description object
 *
 * This function dumps all LPT LEBs. The caller has to make sure the LPT is
 * locked.
 */
void ubifs_dump_lpt_lebs(const struct ubifs_info *c)
{}

/**
 * dbg_populate_lsave - debugging version of 'populate_lsave()'
 * @c: UBIFS file-system description object
 *
 * This is a debugging version for 'populate_lsave()' which populates lsave
 * with random LEBs instead of useful LEBs, which is good for test coverage.
 * Returns zero if lsave has not been populated (this debugging feature is
 * disabled) an non-zero if lsave has been populated.
 */
static int dbg_populate_lsave(struct ubifs_info *c)
{}