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 * Copyright (C) 2006, 2007 University of Szeged, Hungary
78c2ecf20Sopenharmony_ci *
88c2ecf20Sopenharmony_ci * Authors: Artem Bityutskiy (Битюцкий Артём)
98c2ecf20Sopenharmony_ci *          Adrian Hunter
108c2ecf20Sopenharmony_ci *          Zoltan Sogor
118c2ecf20Sopenharmony_ci */
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ci/*
148c2ecf20Sopenharmony_ci * This file implements UBIFS I/O subsystem which provides various I/O-related
158c2ecf20Sopenharmony_ci * helper functions (reading/writing/checking/validating nodes) and implements
168c2ecf20Sopenharmony_ci * write-buffering support. Write buffers help to save space which otherwise
178c2ecf20Sopenharmony_ci * would have been wasted for padding to the nearest minimal I/O unit boundary.
188c2ecf20Sopenharmony_ci * Instead, data first goes to the write-buffer and is flushed when the
198c2ecf20Sopenharmony_ci * buffer is full or when it is not used for some time (by timer). This is
208c2ecf20Sopenharmony_ci * similar to the mechanism is used by JFFS2.
218c2ecf20Sopenharmony_ci *
228c2ecf20Sopenharmony_ci * UBIFS distinguishes between minimum write size (@c->min_io_size) and maximum
238c2ecf20Sopenharmony_ci * write size (@c->max_write_size). The latter is the maximum amount of bytes
248c2ecf20Sopenharmony_ci * the underlying flash is able to program at a time, and writing in
258c2ecf20Sopenharmony_ci * @c->max_write_size units should presumably be faster. Obviously,
268c2ecf20Sopenharmony_ci * @c->min_io_size <= @c->max_write_size. Write-buffers are of
278c2ecf20Sopenharmony_ci * @c->max_write_size bytes in size for maximum performance. However, when a
288c2ecf20Sopenharmony_ci * write-buffer is flushed, only the portion of it (aligned to @c->min_io_size
298c2ecf20Sopenharmony_ci * boundary) which contains data is written, not the whole write-buffer,
308c2ecf20Sopenharmony_ci * because this is more space-efficient.
318c2ecf20Sopenharmony_ci *
328c2ecf20Sopenharmony_ci * This optimization adds few complications to the code. Indeed, on the one
338c2ecf20Sopenharmony_ci * hand, we want to write in optimal @c->max_write_size bytes chunks, which
348c2ecf20Sopenharmony_ci * also means aligning writes at the @c->max_write_size bytes offsets. On the
358c2ecf20Sopenharmony_ci * other hand, we do not want to waste space when synchronizing the write
368c2ecf20Sopenharmony_ci * buffer, so during synchronization we writes in smaller chunks. And this makes
378c2ecf20Sopenharmony_ci * the next write offset to be not aligned to @c->max_write_size bytes. So the
388c2ecf20Sopenharmony_ci * have to make sure that the write-buffer offset (@wbuf->offs) becomes aligned
398c2ecf20Sopenharmony_ci * to @c->max_write_size bytes again. We do this by temporarily shrinking
408c2ecf20Sopenharmony_ci * write-buffer size (@wbuf->size).
418c2ecf20Sopenharmony_ci *
428c2ecf20Sopenharmony_ci * Write-buffers are defined by 'struct ubifs_wbuf' objects and protected by
438c2ecf20Sopenharmony_ci * mutexes defined inside these objects. Since sometimes upper-level code
448c2ecf20Sopenharmony_ci * has to lock the write-buffer (e.g. journal space reservation code), many
458c2ecf20Sopenharmony_ci * functions related to write-buffers have "nolock" suffix which means that the
468c2ecf20Sopenharmony_ci * caller has to lock the write-buffer before calling this function.
478c2ecf20Sopenharmony_ci *
488c2ecf20Sopenharmony_ci * UBIFS stores nodes at 64 bit-aligned addresses. If the node length is not
498c2ecf20Sopenharmony_ci * aligned, UBIFS starts the next node from the aligned address, and the padded
508c2ecf20Sopenharmony_ci * bytes may contain any rubbish. In other words, UBIFS does not put padding
518c2ecf20Sopenharmony_ci * bytes in those small gaps. Common headers of nodes store real node lengths,
528c2ecf20Sopenharmony_ci * not aligned lengths. Indexing nodes also store real lengths in branches.
538c2ecf20Sopenharmony_ci *
548c2ecf20Sopenharmony_ci * UBIFS uses padding when it pads to the next min. I/O unit. In this case it
558c2ecf20Sopenharmony_ci * uses padding nodes or padding bytes, if the padding node does not fit.
568c2ecf20Sopenharmony_ci *
578c2ecf20Sopenharmony_ci * All UBIFS nodes are protected by CRC checksums and UBIFS checks CRC when
588c2ecf20Sopenharmony_ci * they are read from the flash media.
598c2ecf20Sopenharmony_ci */
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_ci#include <linux/crc32.h>
628c2ecf20Sopenharmony_ci#include <linux/slab.h>
638c2ecf20Sopenharmony_ci#include "ubifs.h"
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_ci/**
668c2ecf20Sopenharmony_ci * ubifs_ro_mode - switch UBIFS to read read-only mode.
678c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object
688c2ecf20Sopenharmony_ci * @err: error code which is the reason of switching to R/O mode
698c2ecf20Sopenharmony_ci */
708c2ecf20Sopenharmony_civoid ubifs_ro_mode(struct ubifs_info *c, int err)
718c2ecf20Sopenharmony_ci{
728c2ecf20Sopenharmony_ci	if (!c->ro_error) {
738c2ecf20Sopenharmony_ci		c->ro_error = 1;
748c2ecf20Sopenharmony_ci		c->no_chk_data_crc = 0;
758c2ecf20Sopenharmony_ci		c->vfs_sb->s_flags |= SB_RDONLY;
768c2ecf20Sopenharmony_ci		ubifs_warn(c, "switched to read-only mode, error %d", err);
778c2ecf20Sopenharmony_ci		dump_stack();
788c2ecf20Sopenharmony_ci	}
798c2ecf20Sopenharmony_ci}
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_ci/*
828c2ecf20Sopenharmony_ci * Below are simple wrappers over UBI I/O functions which include some
838c2ecf20Sopenharmony_ci * additional checks and UBIFS debugging stuff. See corresponding UBI function
848c2ecf20Sopenharmony_ci * for more information.
858c2ecf20Sopenharmony_ci */
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_ciint ubifs_leb_read(const struct ubifs_info *c, int lnum, void *buf, int offs,
888c2ecf20Sopenharmony_ci		   int len, int even_ebadmsg)
898c2ecf20Sopenharmony_ci{
908c2ecf20Sopenharmony_ci	int err;
918c2ecf20Sopenharmony_ci
928c2ecf20Sopenharmony_ci	err = ubi_read(c->ubi, lnum, buf, offs, len);
938c2ecf20Sopenharmony_ci	/*
948c2ecf20Sopenharmony_ci	 * In case of %-EBADMSG print the error message only if the
958c2ecf20Sopenharmony_ci	 * @even_ebadmsg is true.
968c2ecf20Sopenharmony_ci	 */
978c2ecf20Sopenharmony_ci	if (err && (err != -EBADMSG || even_ebadmsg)) {
988c2ecf20Sopenharmony_ci		ubifs_err(c, "reading %d bytes from LEB %d:%d failed, error %d",
998c2ecf20Sopenharmony_ci			  len, lnum, offs, err);
1008c2ecf20Sopenharmony_ci		dump_stack();
1018c2ecf20Sopenharmony_ci	}
1028c2ecf20Sopenharmony_ci	return err;
1038c2ecf20Sopenharmony_ci}
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_ciint ubifs_leb_write(struct ubifs_info *c, int lnum, const void *buf, int offs,
1068c2ecf20Sopenharmony_ci		    int len)
1078c2ecf20Sopenharmony_ci{
1088c2ecf20Sopenharmony_ci	int err;
1098c2ecf20Sopenharmony_ci
1108c2ecf20Sopenharmony_ci	ubifs_assert(c, !c->ro_media && !c->ro_mount);
1118c2ecf20Sopenharmony_ci	if (c->ro_error)
1128c2ecf20Sopenharmony_ci		return -EROFS;
1138c2ecf20Sopenharmony_ci	if (!dbg_is_tst_rcvry(c))
1148c2ecf20Sopenharmony_ci		err = ubi_leb_write(c->ubi, lnum, buf, offs, len);
1158c2ecf20Sopenharmony_ci	else
1168c2ecf20Sopenharmony_ci		err = dbg_leb_write(c, lnum, buf, offs, len);
1178c2ecf20Sopenharmony_ci	if (err) {
1188c2ecf20Sopenharmony_ci		ubifs_err(c, "writing %d bytes to LEB %d:%d failed, error %d",
1198c2ecf20Sopenharmony_ci			  len, lnum, offs, err);
1208c2ecf20Sopenharmony_ci		ubifs_ro_mode(c, err);
1218c2ecf20Sopenharmony_ci		dump_stack();
1228c2ecf20Sopenharmony_ci	}
1238c2ecf20Sopenharmony_ci	return err;
1248c2ecf20Sopenharmony_ci}
1258c2ecf20Sopenharmony_ci
1268c2ecf20Sopenharmony_ciint ubifs_leb_change(struct ubifs_info *c, int lnum, const void *buf, int len)
1278c2ecf20Sopenharmony_ci{
1288c2ecf20Sopenharmony_ci	int err;
1298c2ecf20Sopenharmony_ci
1308c2ecf20Sopenharmony_ci	ubifs_assert(c, !c->ro_media && !c->ro_mount);
1318c2ecf20Sopenharmony_ci	if (c->ro_error)
1328c2ecf20Sopenharmony_ci		return -EROFS;
1338c2ecf20Sopenharmony_ci	if (!dbg_is_tst_rcvry(c))
1348c2ecf20Sopenharmony_ci		err = ubi_leb_change(c->ubi, lnum, buf, len);
1358c2ecf20Sopenharmony_ci	else
1368c2ecf20Sopenharmony_ci		err = dbg_leb_change(c, lnum, buf, len);
1378c2ecf20Sopenharmony_ci	if (err) {
1388c2ecf20Sopenharmony_ci		ubifs_err(c, "changing %d bytes in LEB %d failed, error %d",
1398c2ecf20Sopenharmony_ci			  len, lnum, err);
1408c2ecf20Sopenharmony_ci		ubifs_ro_mode(c, err);
1418c2ecf20Sopenharmony_ci		dump_stack();
1428c2ecf20Sopenharmony_ci	}
1438c2ecf20Sopenharmony_ci	return err;
1448c2ecf20Sopenharmony_ci}
1458c2ecf20Sopenharmony_ci
1468c2ecf20Sopenharmony_ciint ubifs_leb_unmap(struct ubifs_info *c, int lnum)
1478c2ecf20Sopenharmony_ci{
1488c2ecf20Sopenharmony_ci	int err;
1498c2ecf20Sopenharmony_ci
1508c2ecf20Sopenharmony_ci	ubifs_assert(c, !c->ro_media && !c->ro_mount);
1518c2ecf20Sopenharmony_ci	if (c->ro_error)
1528c2ecf20Sopenharmony_ci		return -EROFS;
1538c2ecf20Sopenharmony_ci	if (!dbg_is_tst_rcvry(c))
1548c2ecf20Sopenharmony_ci		err = ubi_leb_unmap(c->ubi, lnum);
1558c2ecf20Sopenharmony_ci	else
1568c2ecf20Sopenharmony_ci		err = dbg_leb_unmap(c, lnum);
1578c2ecf20Sopenharmony_ci	if (err) {
1588c2ecf20Sopenharmony_ci		ubifs_err(c, "unmap LEB %d failed, error %d", lnum, err);
1598c2ecf20Sopenharmony_ci		ubifs_ro_mode(c, err);
1608c2ecf20Sopenharmony_ci		dump_stack();
1618c2ecf20Sopenharmony_ci	}
1628c2ecf20Sopenharmony_ci	return err;
1638c2ecf20Sopenharmony_ci}
1648c2ecf20Sopenharmony_ci
1658c2ecf20Sopenharmony_ciint ubifs_leb_map(struct ubifs_info *c, int lnum)
1668c2ecf20Sopenharmony_ci{
1678c2ecf20Sopenharmony_ci	int err;
1688c2ecf20Sopenharmony_ci
1698c2ecf20Sopenharmony_ci	ubifs_assert(c, !c->ro_media && !c->ro_mount);
1708c2ecf20Sopenharmony_ci	if (c->ro_error)
1718c2ecf20Sopenharmony_ci		return -EROFS;
1728c2ecf20Sopenharmony_ci	if (!dbg_is_tst_rcvry(c))
1738c2ecf20Sopenharmony_ci		err = ubi_leb_map(c->ubi, lnum);
1748c2ecf20Sopenharmony_ci	else
1758c2ecf20Sopenharmony_ci		err = dbg_leb_map(c, lnum);
1768c2ecf20Sopenharmony_ci	if (err) {
1778c2ecf20Sopenharmony_ci		ubifs_err(c, "mapping LEB %d failed, error %d", lnum, err);
1788c2ecf20Sopenharmony_ci		ubifs_ro_mode(c, err);
1798c2ecf20Sopenharmony_ci		dump_stack();
1808c2ecf20Sopenharmony_ci	}
1818c2ecf20Sopenharmony_ci	return err;
1828c2ecf20Sopenharmony_ci}
1838c2ecf20Sopenharmony_ci
1848c2ecf20Sopenharmony_ciint ubifs_is_mapped(const struct ubifs_info *c, int lnum)
1858c2ecf20Sopenharmony_ci{
1868c2ecf20Sopenharmony_ci	int err;
1878c2ecf20Sopenharmony_ci
1888c2ecf20Sopenharmony_ci	err = ubi_is_mapped(c->ubi, lnum);
1898c2ecf20Sopenharmony_ci	if (err < 0) {
1908c2ecf20Sopenharmony_ci		ubifs_err(c, "ubi_is_mapped failed for LEB %d, error %d",
1918c2ecf20Sopenharmony_ci			  lnum, err);
1928c2ecf20Sopenharmony_ci		dump_stack();
1938c2ecf20Sopenharmony_ci	}
1948c2ecf20Sopenharmony_ci	return err;
1958c2ecf20Sopenharmony_ci}
1968c2ecf20Sopenharmony_ci
1978c2ecf20Sopenharmony_ci/**
1988c2ecf20Sopenharmony_ci * ubifs_check_node - check node.
1998c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object
2008c2ecf20Sopenharmony_ci * @buf: node to check
2018c2ecf20Sopenharmony_ci * @len: node length
2028c2ecf20Sopenharmony_ci * @lnum: logical eraseblock number
2038c2ecf20Sopenharmony_ci * @offs: offset within the logical eraseblock
2048c2ecf20Sopenharmony_ci * @quiet: print no messages
2058c2ecf20Sopenharmony_ci * @must_chk_crc: indicates whether to always check the CRC
2068c2ecf20Sopenharmony_ci *
2078c2ecf20Sopenharmony_ci * This function checks node magic number and CRC checksum. This function also
2088c2ecf20Sopenharmony_ci * validates node length to prevent UBIFS from becoming crazy when an attacker
2098c2ecf20Sopenharmony_ci * feeds it a file-system image with incorrect nodes. For example, too large
2108c2ecf20Sopenharmony_ci * node length in the common header could cause UBIFS to read memory outside of
2118c2ecf20Sopenharmony_ci * allocated buffer when checking the CRC checksum.
2128c2ecf20Sopenharmony_ci *
2138c2ecf20Sopenharmony_ci * This function may skip data nodes CRC checking if @c->no_chk_data_crc is
2148c2ecf20Sopenharmony_ci * true, which is controlled by corresponding UBIFS mount option. However, if
2158c2ecf20Sopenharmony_ci * @must_chk_crc is true, then @c->no_chk_data_crc is ignored and CRC is
2168c2ecf20Sopenharmony_ci * checked. Similarly, if @c->mounting or @c->remounting_rw is true (we are
2178c2ecf20Sopenharmony_ci * mounting or re-mounting to R/W mode), @c->no_chk_data_crc is ignored and CRC
2188c2ecf20Sopenharmony_ci * is checked. This is because during mounting or re-mounting from R/O mode to
2198c2ecf20Sopenharmony_ci * R/W mode we may read journal nodes (when replying the journal or doing the
2208c2ecf20Sopenharmony_ci * recovery) and the journal nodes may potentially be corrupted, so checking is
2218c2ecf20Sopenharmony_ci * required.
2228c2ecf20Sopenharmony_ci *
2238c2ecf20Sopenharmony_ci * This function returns zero in case of success and %-EUCLEAN in case of bad
2248c2ecf20Sopenharmony_ci * CRC or magic.
2258c2ecf20Sopenharmony_ci */
2268c2ecf20Sopenharmony_ciint ubifs_check_node(const struct ubifs_info *c, const void *buf, int len,
2278c2ecf20Sopenharmony_ci		     int lnum, int offs, int quiet, int must_chk_crc)
2288c2ecf20Sopenharmony_ci{
2298c2ecf20Sopenharmony_ci	int err = -EINVAL, type, node_len;
2308c2ecf20Sopenharmony_ci	uint32_t crc, node_crc, magic;
2318c2ecf20Sopenharmony_ci	const struct ubifs_ch *ch = buf;
2328c2ecf20Sopenharmony_ci
2338c2ecf20Sopenharmony_ci	ubifs_assert(c, lnum >= 0 && lnum < c->leb_cnt && offs >= 0);
2348c2ecf20Sopenharmony_ci	ubifs_assert(c, !(offs & 7) && offs < c->leb_size);
2358c2ecf20Sopenharmony_ci
2368c2ecf20Sopenharmony_ci	magic = le32_to_cpu(ch->magic);
2378c2ecf20Sopenharmony_ci	if (magic != UBIFS_NODE_MAGIC) {
2388c2ecf20Sopenharmony_ci		if (!quiet)
2398c2ecf20Sopenharmony_ci			ubifs_err(c, "bad magic %#08x, expected %#08x",
2408c2ecf20Sopenharmony_ci				  magic, UBIFS_NODE_MAGIC);
2418c2ecf20Sopenharmony_ci		err = -EUCLEAN;
2428c2ecf20Sopenharmony_ci		goto out;
2438c2ecf20Sopenharmony_ci	}
2448c2ecf20Sopenharmony_ci
2458c2ecf20Sopenharmony_ci	type = ch->node_type;
2468c2ecf20Sopenharmony_ci	if (type < 0 || type >= UBIFS_NODE_TYPES_CNT) {
2478c2ecf20Sopenharmony_ci		if (!quiet)
2488c2ecf20Sopenharmony_ci			ubifs_err(c, "bad node type %d", type);
2498c2ecf20Sopenharmony_ci		goto out;
2508c2ecf20Sopenharmony_ci	}
2518c2ecf20Sopenharmony_ci
2528c2ecf20Sopenharmony_ci	node_len = le32_to_cpu(ch->len);
2538c2ecf20Sopenharmony_ci	if (node_len + offs > c->leb_size)
2548c2ecf20Sopenharmony_ci		goto out_len;
2558c2ecf20Sopenharmony_ci
2568c2ecf20Sopenharmony_ci	if (c->ranges[type].max_len == 0) {
2578c2ecf20Sopenharmony_ci		if (node_len != c->ranges[type].len)
2588c2ecf20Sopenharmony_ci			goto out_len;
2598c2ecf20Sopenharmony_ci	} else if (node_len < c->ranges[type].min_len ||
2608c2ecf20Sopenharmony_ci		   node_len > c->ranges[type].max_len)
2618c2ecf20Sopenharmony_ci		goto out_len;
2628c2ecf20Sopenharmony_ci
2638c2ecf20Sopenharmony_ci	if (!must_chk_crc && type == UBIFS_DATA_NODE && !c->mounting &&
2648c2ecf20Sopenharmony_ci	    !c->remounting_rw && c->no_chk_data_crc)
2658c2ecf20Sopenharmony_ci		return 0;
2668c2ecf20Sopenharmony_ci
2678c2ecf20Sopenharmony_ci	crc = crc32(UBIFS_CRC32_INIT, buf + 8, node_len - 8);
2688c2ecf20Sopenharmony_ci	node_crc = le32_to_cpu(ch->crc);
2698c2ecf20Sopenharmony_ci	if (crc != node_crc) {
2708c2ecf20Sopenharmony_ci		if (!quiet)
2718c2ecf20Sopenharmony_ci			ubifs_err(c, "bad CRC: calculated %#08x, read %#08x",
2728c2ecf20Sopenharmony_ci				  crc, node_crc);
2738c2ecf20Sopenharmony_ci		err = -EUCLEAN;
2748c2ecf20Sopenharmony_ci		goto out;
2758c2ecf20Sopenharmony_ci	}
2768c2ecf20Sopenharmony_ci
2778c2ecf20Sopenharmony_ci	return 0;
2788c2ecf20Sopenharmony_ci
2798c2ecf20Sopenharmony_ciout_len:
2808c2ecf20Sopenharmony_ci	if (!quiet)
2818c2ecf20Sopenharmony_ci		ubifs_err(c, "bad node length %d", node_len);
2828c2ecf20Sopenharmony_ciout:
2838c2ecf20Sopenharmony_ci	if (!quiet) {
2848c2ecf20Sopenharmony_ci		ubifs_err(c, "bad node at LEB %d:%d", lnum, offs);
2858c2ecf20Sopenharmony_ci		ubifs_dump_node(c, buf, len);
2868c2ecf20Sopenharmony_ci		dump_stack();
2878c2ecf20Sopenharmony_ci	}
2888c2ecf20Sopenharmony_ci	return err;
2898c2ecf20Sopenharmony_ci}
2908c2ecf20Sopenharmony_ci
2918c2ecf20Sopenharmony_ci/**
2928c2ecf20Sopenharmony_ci * ubifs_pad - pad flash space.
2938c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object
2948c2ecf20Sopenharmony_ci * @buf: buffer to put padding to
2958c2ecf20Sopenharmony_ci * @pad: how many bytes to pad
2968c2ecf20Sopenharmony_ci *
2978c2ecf20Sopenharmony_ci * The flash media obliges us to write only in chunks of %c->min_io_size and
2988c2ecf20Sopenharmony_ci * when we have to write less data we add padding node to the write-buffer and
2998c2ecf20Sopenharmony_ci * pad it to the next minimal I/O unit's boundary. Padding nodes help when the
3008c2ecf20Sopenharmony_ci * media is being scanned. If the amount of wasted space is not enough to fit a
3018c2ecf20Sopenharmony_ci * padding node which takes %UBIFS_PAD_NODE_SZ bytes, we write padding bytes
3028c2ecf20Sopenharmony_ci * pattern (%UBIFS_PADDING_BYTE).
3038c2ecf20Sopenharmony_ci *
3048c2ecf20Sopenharmony_ci * Padding nodes are also used to fill gaps when the "commit-in-gaps" method is
3058c2ecf20Sopenharmony_ci * used.
3068c2ecf20Sopenharmony_ci */
3078c2ecf20Sopenharmony_civoid ubifs_pad(const struct ubifs_info *c, void *buf, int pad)
3088c2ecf20Sopenharmony_ci{
3098c2ecf20Sopenharmony_ci	uint32_t crc;
3108c2ecf20Sopenharmony_ci
3118c2ecf20Sopenharmony_ci	ubifs_assert(c, pad >= 0);
3128c2ecf20Sopenharmony_ci
3138c2ecf20Sopenharmony_ci	if (pad >= UBIFS_PAD_NODE_SZ) {
3148c2ecf20Sopenharmony_ci		struct ubifs_ch *ch = buf;
3158c2ecf20Sopenharmony_ci		struct ubifs_pad_node *pad_node = buf;
3168c2ecf20Sopenharmony_ci
3178c2ecf20Sopenharmony_ci		ch->magic = cpu_to_le32(UBIFS_NODE_MAGIC);
3188c2ecf20Sopenharmony_ci		ch->node_type = UBIFS_PAD_NODE;
3198c2ecf20Sopenharmony_ci		ch->group_type = UBIFS_NO_NODE_GROUP;
3208c2ecf20Sopenharmony_ci		ch->padding[0] = ch->padding[1] = 0;
3218c2ecf20Sopenharmony_ci		ch->sqnum = 0;
3228c2ecf20Sopenharmony_ci		ch->len = cpu_to_le32(UBIFS_PAD_NODE_SZ);
3238c2ecf20Sopenharmony_ci		pad -= UBIFS_PAD_NODE_SZ;
3248c2ecf20Sopenharmony_ci		pad_node->pad_len = cpu_to_le32(pad);
3258c2ecf20Sopenharmony_ci		crc = crc32(UBIFS_CRC32_INIT, buf + 8, UBIFS_PAD_NODE_SZ - 8);
3268c2ecf20Sopenharmony_ci		ch->crc = cpu_to_le32(crc);
3278c2ecf20Sopenharmony_ci		memset(buf + UBIFS_PAD_NODE_SZ, 0, pad);
3288c2ecf20Sopenharmony_ci	} else if (pad > 0)
3298c2ecf20Sopenharmony_ci		/* Too little space, padding node won't fit */
3308c2ecf20Sopenharmony_ci		memset(buf, UBIFS_PADDING_BYTE, pad);
3318c2ecf20Sopenharmony_ci}
3328c2ecf20Sopenharmony_ci
3338c2ecf20Sopenharmony_ci/**
3348c2ecf20Sopenharmony_ci * next_sqnum - get next sequence number.
3358c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object
3368c2ecf20Sopenharmony_ci */
3378c2ecf20Sopenharmony_cistatic unsigned long long next_sqnum(struct ubifs_info *c)
3388c2ecf20Sopenharmony_ci{
3398c2ecf20Sopenharmony_ci	unsigned long long sqnum;
3408c2ecf20Sopenharmony_ci
3418c2ecf20Sopenharmony_ci	spin_lock(&c->cnt_lock);
3428c2ecf20Sopenharmony_ci	sqnum = ++c->max_sqnum;
3438c2ecf20Sopenharmony_ci	spin_unlock(&c->cnt_lock);
3448c2ecf20Sopenharmony_ci
3458c2ecf20Sopenharmony_ci	if (unlikely(sqnum >= SQNUM_WARN_WATERMARK)) {
3468c2ecf20Sopenharmony_ci		if (sqnum >= SQNUM_WATERMARK) {
3478c2ecf20Sopenharmony_ci			ubifs_err(c, "sequence number overflow %llu, end of life",
3488c2ecf20Sopenharmony_ci				  sqnum);
3498c2ecf20Sopenharmony_ci			ubifs_ro_mode(c, -EINVAL);
3508c2ecf20Sopenharmony_ci		}
3518c2ecf20Sopenharmony_ci		ubifs_warn(c, "running out of sequence numbers, end of life soon");
3528c2ecf20Sopenharmony_ci	}
3538c2ecf20Sopenharmony_ci
3548c2ecf20Sopenharmony_ci	return sqnum;
3558c2ecf20Sopenharmony_ci}
3568c2ecf20Sopenharmony_ci
3578c2ecf20Sopenharmony_civoid ubifs_init_node(struct ubifs_info *c, void *node, int len, int pad)
3588c2ecf20Sopenharmony_ci{
3598c2ecf20Sopenharmony_ci	struct ubifs_ch *ch = node;
3608c2ecf20Sopenharmony_ci	unsigned long long sqnum = next_sqnum(c);
3618c2ecf20Sopenharmony_ci
3628c2ecf20Sopenharmony_ci	ubifs_assert(c, len >= UBIFS_CH_SZ);
3638c2ecf20Sopenharmony_ci
3648c2ecf20Sopenharmony_ci	ch->magic = cpu_to_le32(UBIFS_NODE_MAGIC);
3658c2ecf20Sopenharmony_ci	ch->len = cpu_to_le32(len);
3668c2ecf20Sopenharmony_ci	ch->group_type = UBIFS_NO_NODE_GROUP;
3678c2ecf20Sopenharmony_ci	ch->sqnum = cpu_to_le64(sqnum);
3688c2ecf20Sopenharmony_ci	ch->padding[0] = ch->padding[1] = 0;
3698c2ecf20Sopenharmony_ci
3708c2ecf20Sopenharmony_ci	if (pad) {
3718c2ecf20Sopenharmony_ci		len = ALIGN(len, 8);
3728c2ecf20Sopenharmony_ci		pad = ALIGN(len, c->min_io_size) - len;
3738c2ecf20Sopenharmony_ci		ubifs_pad(c, node + len, pad);
3748c2ecf20Sopenharmony_ci	}
3758c2ecf20Sopenharmony_ci}
3768c2ecf20Sopenharmony_ci
3778c2ecf20Sopenharmony_civoid ubifs_crc_node(struct ubifs_info *c, void *node, int len)
3788c2ecf20Sopenharmony_ci{
3798c2ecf20Sopenharmony_ci	struct ubifs_ch *ch = node;
3808c2ecf20Sopenharmony_ci	uint32_t crc;
3818c2ecf20Sopenharmony_ci
3828c2ecf20Sopenharmony_ci	crc = crc32(UBIFS_CRC32_INIT, node + 8, len - 8);
3838c2ecf20Sopenharmony_ci	ch->crc = cpu_to_le32(crc);
3848c2ecf20Sopenharmony_ci}
3858c2ecf20Sopenharmony_ci
3868c2ecf20Sopenharmony_ci/**
3878c2ecf20Sopenharmony_ci * ubifs_prepare_node_hmac - prepare node to be written to flash.
3888c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object
3898c2ecf20Sopenharmony_ci * @node: the node to pad
3908c2ecf20Sopenharmony_ci * @len: node length
3918c2ecf20Sopenharmony_ci * @hmac_offs: offset of the HMAC in the node
3928c2ecf20Sopenharmony_ci * @pad: if the buffer has to be padded
3938c2ecf20Sopenharmony_ci *
3948c2ecf20Sopenharmony_ci * This function prepares node at @node to be written to the media - it
3958c2ecf20Sopenharmony_ci * calculates node CRC, fills the common header, and adds proper padding up to
3968c2ecf20Sopenharmony_ci * the next minimum I/O unit if @pad is not zero. if @hmac_offs is positive then
3978c2ecf20Sopenharmony_ci * a HMAC is inserted into the node at the given offset.
3988c2ecf20Sopenharmony_ci *
3998c2ecf20Sopenharmony_ci * This function returns 0 for success or a negative error code otherwise.
4008c2ecf20Sopenharmony_ci */
4018c2ecf20Sopenharmony_ciint ubifs_prepare_node_hmac(struct ubifs_info *c, void *node, int len,
4028c2ecf20Sopenharmony_ci			    int hmac_offs, int pad)
4038c2ecf20Sopenharmony_ci{
4048c2ecf20Sopenharmony_ci	int err;
4058c2ecf20Sopenharmony_ci
4068c2ecf20Sopenharmony_ci	ubifs_init_node(c, node, len, pad);
4078c2ecf20Sopenharmony_ci
4088c2ecf20Sopenharmony_ci	if (hmac_offs > 0) {
4098c2ecf20Sopenharmony_ci		err = ubifs_node_insert_hmac(c, node, len, hmac_offs);
4108c2ecf20Sopenharmony_ci		if (err)
4118c2ecf20Sopenharmony_ci			return err;
4128c2ecf20Sopenharmony_ci	}
4138c2ecf20Sopenharmony_ci
4148c2ecf20Sopenharmony_ci	ubifs_crc_node(c, node, len);
4158c2ecf20Sopenharmony_ci
4168c2ecf20Sopenharmony_ci	return 0;
4178c2ecf20Sopenharmony_ci}
4188c2ecf20Sopenharmony_ci
4198c2ecf20Sopenharmony_ci/**
4208c2ecf20Sopenharmony_ci * ubifs_prepare_node - prepare node to be written to flash.
4218c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object
4228c2ecf20Sopenharmony_ci * @node: the node to pad
4238c2ecf20Sopenharmony_ci * @len: node length
4248c2ecf20Sopenharmony_ci * @pad: if the buffer has to be padded
4258c2ecf20Sopenharmony_ci *
4268c2ecf20Sopenharmony_ci * This function prepares node at @node to be written to the media - it
4278c2ecf20Sopenharmony_ci * calculates node CRC, fills the common header, and adds proper padding up to
4288c2ecf20Sopenharmony_ci * the next minimum I/O unit if @pad is not zero.
4298c2ecf20Sopenharmony_ci */
4308c2ecf20Sopenharmony_civoid ubifs_prepare_node(struct ubifs_info *c, void *node, int len, int pad)
4318c2ecf20Sopenharmony_ci{
4328c2ecf20Sopenharmony_ci	/*
4338c2ecf20Sopenharmony_ci	 * Deliberately ignore return value since this function can only fail
4348c2ecf20Sopenharmony_ci	 * when a hmac offset is given.
4358c2ecf20Sopenharmony_ci	 */
4368c2ecf20Sopenharmony_ci	ubifs_prepare_node_hmac(c, node, len, 0, pad);
4378c2ecf20Sopenharmony_ci}
4388c2ecf20Sopenharmony_ci
4398c2ecf20Sopenharmony_ci/**
4408c2ecf20Sopenharmony_ci * ubifs_prep_grp_node - prepare node of a group to be written to flash.
4418c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object
4428c2ecf20Sopenharmony_ci * @node: the node to pad
4438c2ecf20Sopenharmony_ci * @len: node length
4448c2ecf20Sopenharmony_ci * @last: indicates the last node of the group
4458c2ecf20Sopenharmony_ci *
4468c2ecf20Sopenharmony_ci * This function prepares node at @node to be written to the media - it
4478c2ecf20Sopenharmony_ci * calculates node CRC and fills the common header.
4488c2ecf20Sopenharmony_ci */
4498c2ecf20Sopenharmony_civoid ubifs_prep_grp_node(struct ubifs_info *c, void *node, int len, int last)
4508c2ecf20Sopenharmony_ci{
4518c2ecf20Sopenharmony_ci	uint32_t crc;
4528c2ecf20Sopenharmony_ci	struct ubifs_ch *ch = node;
4538c2ecf20Sopenharmony_ci	unsigned long long sqnum = next_sqnum(c);
4548c2ecf20Sopenharmony_ci
4558c2ecf20Sopenharmony_ci	ubifs_assert(c, len >= UBIFS_CH_SZ);
4568c2ecf20Sopenharmony_ci
4578c2ecf20Sopenharmony_ci	ch->magic = cpu_to_le32(UBIFS_NODE_MAGIC);
4588c2ecf20Sopenharmony_ci	ch->len = cpu_to_le32(len);
4598c2ecf20Sopenharmony_ci	if (last)
4608c2ecf20Sopenharmony_ci		ch->group_type = UBIFS_LAST_OF_NODE_GROUP;
4618c2ecf20Sopenharmony_ci	else
4628c2ecf20Sopenharmony_ci		ch->group_type = UBIFS_IN_NODE_GROUP;
4638c2ecf20Sopenharmony_ci	ch->sqnum = cpu_to_le64(sqnum);
4648c2ecf20Sopenharmony_ci	ch->padding[0] = ch->padding[1] = 0;
4658c2ecf20Sopenharmony_ci	crc = crc32(UBIFS_CRC32_INIT, node + 8, len - 8);
4668c2ecf20Sopenharmony_ci	ch->crc = cpu_to_le32(crc);
4678c2ecf20Sopenharmony_ci}
4688c2ecf20Sopenharmony_ci
4698c2ecf20Sopenharmony_ci/**
4708c2ecf20Sopenharmony_ci * wbuf_timer_callback - write-buffer timer callback function.
4718c2ecf20Sopenharmony_ci * @timer: timer data (write-buffer descriptor)
4728c2ecf20Sopenharmony_ci *
4738c2ecf20Sopenharmony_ci * This function is called when the write-buffer timer expires.
4748c2ecf20Sopenharmony_ci */
4758c2ecf20Sopenharmony_cistatic enum hrtimer_restart wbuf_timer_callback_nolock(struct hrtimer *timer)
4768c2ecf20Sopenharmony_ci{
4778c2ecf20Sopenharmony_ci	struct ubifs_wbuf *wbuf = container_of(timer, struct ubifs_wbuf, timer);
4788c2ecf20Sopenharmony_ci
4798c2ecf20Sopenharmony_ci	dbg_io("jhead %s", dbg_jhead(wbuf->jhead));
4808c2ecf20Sopenharmony_ci	wbuf->need_sync = 1;
4818c2ecf20Sopenharmony_ci	wbuf->c->need_wbuf_sync = 1;
4828c2ecf20Sopenharmony_ci	ubifs_wake_up_bgt(wbuf->c);
4838c2ecf20Sopenharmony_ci	return HRTIMER_NORESTART;
4848c2ecf20Sopenharmony_ci}
4858c2ecf20Sopenharmony_ci
4868c2ecf20Sopenharmony_ci/**
4878c2ecf20Sopenharmony_ci * new_wbuf_timer - start new write-buffer timer.
4888c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object
4898c2ecf20Sopenharmony_ci * @wbuf: write-buffer descriptor
4908c2ecf20Sopenharmony_ci */
4918c2ecf20Sopenharmony_cistatic void new_wbuf_timer_nolock(struct ubifs_info *c, struct ubifs_wbuf *wbuf)
4928c2ecf20Sopenharmony_ci{
4938c2ecf20Sopenharmony_ci	ktime_t softlimit = ms_to_ktime(dirty_writeback_interval * 10);
4948c2ecf20Sopenharmony_ci	unsigned long long delta = dirty_writeback_interval;
4958c2ecf20Sopenharmony_ci
4968c2ecf20Sopenharmony_ci	/* centi to milli, milli to nano, then 10% */
4978c2ecf20Sopenharmony_ci	delta *= 10ULL * NSEC_PER_MSEC / 10ULL;
4988c2ecf20Sopenharmony_ci
4998c2ecf20Sopenharmony_ci	ubifs_assert(c, !hrtimer_active(&wbuf->timer));
5008c2ecf20Sopenharmony_ci	ubifs_assert(c, delta <= ULONG_MAX);
5018c2ecf20Sopenharmony_ci
5028c2ecf20Sopenharmony_ci	if (wbuf->no_timer)
5038c2ecf20Sopenharmony_ci		return;
5048c2ecf20Sopenharmony_ci	dbg_io("set timer for jhead %s, %llu-%llu millisecs",
5058c2ecf20Sopenharmony_ci	       dbg_jhead(wbuf->jhead),
5068c2ecf20Sopenharmony_ci	       div_u64(ktime_to_ns(softlimit), USEC_PER_SEC),
5078c2ecf20Sopenharmony_ci	       div_u64(ktime_to_ns(softlimit) + delta, USEC_PER_SEC));
5088c2ecf20Sopenharmony_ci	hrtimer_start_range_ns(&wbuf->timer, softlimit, delta,
5098c2ecf20Sopenharmony_ci			       HRTIMER_MODE_REL);
5108c2ecf20Sopenharmony_ci}
5118c2ecf20Sopenharmony_ci
5128c2ecf20Sopenharmony_ci/**
5138c2ecf20Sopenharmony_ci * cancel_wbuf_timer - cancel write-buffer timer.
5148c2ecf20Sopenharmony_ci * @wbuf: write-buffer descriptor
5158c2ecf20Sopenharmony_ci */
5168c2ecf20Sopenharmony_cistatic void cancel_wbuf_timer_nolock(struct ubifs_wbuf *wbuf)
5178c2ecf20Sopenharmony_ci{
5188c2ecf20Sopenharmony_ci	if (wbuf->no_timer)
5198c2ecf20Sopenharmony_ci		return;
5208c2ecf20Sopenharmony_ci	wbuf->need_sync = 0;
5218c2ecf20Sopenharmony_ci	hrtimer_cancel(&wbuf->timer);
5228c2ecf20Sopenharmony_ci}
5238c2ecf20Sopenharmony_ci
5248c2ecf20Sopenharmony_ci/**
5258c2ecf20Sopenharmony_ci * ubifs_wbuf_sync_nolock - synchronize write-buffer.
5268c2ecf20Sopenharmony_ci * @wbuf: write-buffer to synchronize
5278c2ecf20Sopenharmony_ci *
5288c2ecf20Sopenharmony_ci * This function synchronizes write-buffer @buf and returns zero in case of
5298c2ecf20Sopenharmony_ci * success or a negative error code in case of failure.
5308c2ecf20Sopenharmony_ci *
5318c2ecf20Sopenharmony_ci * Note, although write-buffers are of @c->max_write_size, this function does
5328c2ecf20Sopenharmony_ci * not necessarily writes all @c->max_write_size bytes to the flash. Instead,
5338c2ecf20Sopenharmony_ci * if the write-buffer is only partially filled with data, only the used part
5348c2ecf20Sopenharmony_ci * of the write-buffer (aligned on @c->min_io_size boundary) is synchronized.
5358c2ecf20Sopenharmony_ci * This way we waste less space.
5368c2ecf20Sopenharmony_ci */
5378c2ecf20Sopenharmony_ciint ubifs_wbuf_sync_nolock(struct ubifs_wbuf *wbuf)
5388c2ecf20Sopenharmony_ci{
5398c2ecf20Sopenharmony_ci	struct ubifs_info *c = wbuf->c;
5408c2ecf20Sopenharmony_ci	int err, dirt, sync_len;
5418c2ecf20Sopenharmony_ci
5428c2ecf20Sopenharmony_ci	cancel_wbuf_timer_nolock(wbuf);
5438c2ecf20Sopenharmony_ci	if (!wbuf->used || wbuf->lnum == -1)
5448c2ecf20Sopenharmony_ci		/* Write-buffer is empty or not seeked */
5458c2ecf20Sopenharmony_ci		return 0;
5468c2ecf20Sopenharmony_ci
5478c2ecf20Sopenharmony_ci	dbg_io("LEB %d:%d, %d bytes, jhead %s",
5488c2ecf20Sopenharmony_ci	       wbuf->lnum, wbuf->offs, wbuf->used, dbg_jhead(wbuf->jhead));
5498c2ecf20Sopenharmony_ci	ubifs_assert(c, !(wbuf->avail & 7));
5508c2ecf20Sopenharmony_ci	ubifs_assert(c, wbuf->offs + wbuf->size <= c->leb_size);
5518c2ecf20Sopenharmony_ci	ubifs_assert(c, wbuf->size >= c->min_io_size);
5528c2ecf20Sopenharmony_ci	ubifs_assert(c, wbuf->size <= c->max_write_size);
5538c2ecf20Sopenharmony_ci	ubifs_assert(c, wbuf->size % c->min_io_size == 0);
5548c2ecf20Sopenharmony_ci	ubifs_assert(c, !c->ro_media && !c->ro_mount);
5558c2ecf20Sopenharmony_ci	if (c->leb_size - wbuf->offs >= c->max_write_size)
5568c2ecf20Sopenharmony_ci		ubifs_assert(c, !((wbuf->offs + wbuf->size) % c->max_write_size));
5578c2ecf20Sopenharmony_ci
5588c2ecf20Sopenharmony_ci	if (c->ro_error)
5598c2ecf20Sopenharmony_ci		return -EROFS;
5608c2ecf20Sopenharmony_ci
5618c2ecf20Sopenharmony_ci	/*
5628c2ecf20Sopenharmony_ci	 * Do not write whole write buffer but write only the minimum necessary
5638c2ecf20Sopenharmony_ci	 * amount of min. I/O units.
5648c2ecf20Sopenharmony_ci	 */
5658c2ecf20Sopenharmony_ci	sync_len = ALIGN(wbuf->used, c->min_io_size);
5668c2ecf20Sopenharmony_ci	dirt = sync_len - wbuf->used;
5678c2ecf20Sopenharmony_ci	if (dirt)
5688c2ecf20Sopenharmony_ci		ubifs_pad(c, wbuf->buf + wbuf->used, dirt);
5698c2ecf20Sopenharmony_ci	err = ubifs_leb_write(c, wbuf->lnum, wbuf->buf, wbuf->offs, sync_len);
5708c2ecf20Sopenharmony_ci	if (err)
5718c2ecf20Sopenharmony_ci		return err;
5728c2ecf20Sopenharmony_ci
5738c2ecf20Sopenharmony_ci	spin_lock(&wbuf->lock);
5748c2ecf20Sopenharmony_ci	wbuf->offs += sync_len;
5758c2ecf20Sopenharmony_ci	/*
5768c2ecf20Sopenharmony_ci	 * Now @wbuf->offs is not necessarily aligned to @c->max_write_size.
5778c2ecf20Sopenharmony_ci	 * But our goal is to optimize writes and make sure we write in
5788c2ecf20Sopenharmony_ci	 * @c->max_write_size chunks and to @c->max_write_size-aligned offset.
5798c2ecf20Sopenharmony_ci	 * Thus, if @wbuf->offs is not aligned to @c->max_write_size now, make
5808c2ecf20Sopenharmony_ci	 * sure that @wbuf->offs + @wbuf->size is aligned to
5818c2ecf20Sopenharmony_ci	 * @c->max_write_size. This way we make sure that after next
5828c2ecf20Sopenharmony_ci	 * write-buffer flush we are again at the optimal offset (aligned to
5838c2ecf20Sopenharmony_ci	 * @c->max_write_size).
5848c2ecf20Sopenharmony_ci	 */
5858c2ecf20Sopenharmony_ci	if (c->leb_size - wbuf->offs < c->max_write_size)
5868c2ecf20Sopenharmony_ci		wbuf->size = c->leb_size - wbuf->offs;
5878c2ecf20Sopenharmony_ci	else if (wbuf->offs & (c->max_write_size - 1))
5888c2ecf20Sopenharmony_ci		wbuf->size = ALIGN(wbuf->offs, c->max_write_size) - wbuf->offs;
5898c2ecf20Sopenharmony_ci	else
5908c2ecf20Sopenharmony_ci		wbuf->size = c->max_write_size;
5918c2ecf20Sopenharmony_ci	wbuf->avail = wbuf->size;
5928c2ecf20Sopenharmony_ci	wbuf->used = 0;
5938c2ecf20Sopenharmony_ci	wbuf->next_ino = 0;
5948c2ecf20Sopenharmony_ci	spin_unlock(&wbuf->lock);
5958c2ecf20Sopenharmony_ci
5968c2ecf20Sopenharmony_ci	if (wbuf->sync_callback)
5978c2ecf20Sopenharmony_ci		err = wbuf->sync_callback(c, wbuf->lnum,
5988c2ecf20Sopenharmony_ci					  c->leb_size - wbuf->offs, dirt);
5998c2ecf20Sopenharmony_ci	return err;
6008c2ecf20Sopenharmony_ci}
6018c2ecf20Sopenharmony_ci
6028c2ecf20Sopenharmony_ci/**
6038c2ecf20Sopenharmony_ci * ubifs_wbuf_seek_nolock - seek write-buffer.
6048c2ecf20Sopenharmony_ci * @wbuf: write-buffer
6058c2ecf20Sopenharmony_ci * @lnum: logical eraseblock number to seek to
6068c2ecf20Sopenharmony_ci * @offs: logical eraseblock offset to seek to
6078c2ecf20Sopenharmony_ci *
6088c2ecf20Sopenharmony_ci * This function targets the write-buffer to logical eraseblock @lnum:@offs.
6098c2ecf20Sopenharmony_ci * The write-buffer has to be empty. Returns zero in case of success and a
6108c2ecf20Sopenharmony_ci * negative error code in case of failure.
6118c2ecf20Sopenharmony_ci */
6128c2ecf20Sopenharmony_ciint ubifs_wbuf_seek_nolock(struct ubifs_wbuf *wbuf, int lnum, int offs)
6138c2ecf20Sopenharmony_ci{
6148c2ecf20Sopenharmony_ci	const struct ubifs_info *c = wbuf->c;
6158c2ecf20Sopenharmony_ci
6168c2ecf20Sopenharmony_ci	dbg_io("LEB %d:%d, jhead %s", lnum, offs, dbg_jhead(wbuf->jhead));
6178c2ecf20Sopenharmony_ci	ubifs_assert(c, lnum >= 0 && lnum < c->leb_cnt);
6188c2ecf20Sopenharmony_ci	ubifs_assert(c, offs >= 0 && offs <= c->leb_size);
6198c2ecf20Sopenharmony_ci	ubifs_assert(c, offs % c->min_io_size == 0 && !(offs & 7));
6208c2ecf20Sopenharmony_ci	ubifs_assert(c, lnum != wbuf->lnum);
6218c2ecf20Sopenharmony_ci	ubifs_assert(c, wbuf->used == 0);
6228c2ecf20Sopenharmony_ci
6238c2ecf20Sopenharmony_ci	spin_lock(&wbuf->lock);
6248c2ecf20Sopenharmony_ci	wbuf->lnum = lnum;
6258c2ecf20Sopenharmony_ci	wbuf->offs = offs;
6268c2ecf20Sopenharmony_ci	if (c->leb_size - wbuf->offs < c->max_write_size)
6278c2ecf20Sopenharmony_ci		wbuf->size = c->leb_size - wbuf->offs;
6288c2ecf20Sopenharmony_ci	else if (wbuf->offs & (c->max_write_size - 1))
6298c2ecf20Sopenharmony_ci		wbuf->size = ALIGN(wbuf->offs, c->max_write_size) - wbuf->offs;
6308c2ecf20Sopenharmony_ci	else
6318c2ecf20Sopenharmony_ci		wbuf->size = c->max_write_size;
6328c2ecf20Sopenharmony_ci	wbuf->avail = wbuf->size;
6338c2ecf20Sopenharmony_ci	wbuf->used = 0;
6348c2ecf20Sopenharmony_ci	spin_unlock(&wbuf->lock);
6358c2ecf20Sopenharmony_ci
6368c2ecf20Sopenharmony_ci	return 0;
6378c2ecf20Sopenharmony_ci}
6388c2ecf20Sopenharmony_ci
6398c2ecf20Sopenharmony_ci/**
6408c2ecf20Sopenharmony_ci * ubifs_bg_wbufs_sync - synchronize write-buffers.
6418c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object
6428c2ecf20Sopenharmony_ci *
6438c2ecf20Sopenharmony_ci * This function is called by background thread to synchronize write-buffers.
6448c2ecf20Sopenharmony_ci * Returns zero in case of success and a negative error code in case of
6458c2ecf20Sopenharmony_ci * failure.
6468c2ecf20Sopenharmony_ci */
6478c2ecf20Sopenharmony_ciint ubifs_bg_wbufs_sync(struct ubifs_info *c)
6488c2ecf20Sopenharmony_ci{
6498c2ecf20Sopenharmony_ci	int err, i;
6508c2ecf20Sopenharmony_ci
6518c2ecf20Sopenharmony_ci	ubifs_assert(c, !c->ro_media && !c->ro_mount);
6528c2ecf20Sopenharmony_ci	if (!c->need_wbuf_sync)
6538c2ecf20Sopenharmony_ci		return 0;
6548c2ecf20Sopenharmony_ci	c->need_wbuf_sync = 0;
6558c2ecf20Sopenharmony_ci
6568c2ecf20Sopenharmony_ci	if (c->ro_error) {
6578c2ecf20Sopenharmony_ci		err = -EROFS;
6588c2ecf20Sopenharmony_ci		goto out_timers;
6598c2ecf20Sopenharmony_ci	}
6608c2ecf20Sopenharmony_ci
6618c2ecf20Sopenharmony_ci	dbg_io("synchronize");
6628c2ecf20Sopenharmony_ci	for (i = 0; i < c->jhead_cnt; i++) {
6638c2ecf20Sopenharmony_ci		struct ubifs_wbuf *wbuf = &c->jheads[i].wbuf;
6648c2ecf20Sopenharmony_ci
6658c2ecf20Sopenharmony_ci		cond_resched();
6668c2ecf20Sopenharmony_ci
6678c2ecf20Sopenharmony_ci		/*
6688c2ecf20Sopenharmony_ci		 * If the mutex is locked then wbuf is being changed, so
6698c2ecf20Sopenharmony_ci		 * synchronization is not necessary.
6708c2ecf20Sopenharmony_ci		 */
6718c2ecf20Sopenharmony_ci		if (mutex_is_locked(&wbuf->io_mutex))
6728c2ecf20Sopenharmony_ci			continue;
6738c2ecf20Sopenharmony_ci
6748c2ecf20Sopenharmony_ci		mutex_lock_nested(&wbuf->io_mutex, wbuf->jhead);
6758c2ecf20Sopenharmony_ci		if (!wbuf->need_sync) {
6768c2ecf20Sopenharmony_ci			mutex_unlock(&wbuf->io_mutex);
6778c2ecf20Sopenharmony_ci			continue;
6788c2ecf20Sopenharmony_ci		}
6798c2ecf20Sopenharmony_ci
6808c2ecf20Sopenharmony_ci		err = ubifs_wbuf_sync_nolock(wbuf);
6818c2ecf20Sopenharmony_ci		mutex_unlock(&wbuf->io_mutex);
6828c2ecf20Sopenharmony_ci		if (err) {
6838c2ecf20Sopenharmony_ci			ubifs_err(c, "cannot sync write-buffer, error %d", err);
6848c2ecf20Sopenharmony_ci			ubifs_ro_mode(c, err);
6858c2ecf20Sopenharmony_ci			goto out_timers;
6868c2ecf20Sopenharmony_ci		}
6878c2ecf20Sopenharmony_ci	}
6888c2ecf20Sopenharmony_ci
6898c2ecf20Sopenharmony_ci	return 0;
6908c2ecf20Sopenharmony_ci
6918c2ecf20Sopenharmony_ciout_timers:
6928c2ecf20Sopenharmony_ci	/* Cancel all timers to prevent repeated errors */
6938c2ecf20Sopenharmony_ci	for (i = 0; i < c->jhead_cnt; i++) {
6948c2ecf20Sopenharmony_ci		struct ubifs_wbuf *wbuf = &c->jheads[i].wbuf;
6958c2ecf20Sopenharmony_ci
6968c2ecf20Sopenharmony_ci		mutex_lock_nested(&wbuf->io_mutex, wbuf->jhead);
6978c2ecf20Sopenharmony_ci		cancel_wbuf_timer_nolock(wbuf);
6988c2ecf20Sopenharmony_ci		mutex_unlock(&wbuf->io_mutex);
6998c2ecf20Sopenharmony_ci	}
7008c2ecf20Sopenharmony_ci	return err;
7018c2ecf20Sopenharmony_ci}
7028c2ecf20Sopenharmony_ci
7038c2ecf20Sopenharmony_ci/**
7048c2ecf20Sopenharmony_ci * ubifs_wbuf_write_nolock - write data to flash via write-buffer.
7058c2ecf20Sopenharmony_ci * @wbuf: write-buffer
7068c2ecf20Sopenharmony_ci * @buf: node to write
7078c2ecf20Sopenharmony_ci * @len: node length
7088c2ecf20Sopenharmony_ci *
7098c2ecf20Sopenharmony_ci * This function writes data to flash via write-buffer @wbuf. This means that
7108c2ecf20Sopenharmony_ci * the last piece of the node won't reach the flash media immediately if it
7118c2ecf20Sopenharmony_ci * does not take whole max. write unit (@c->max_write_size). Instead, the node
7128c2ecf20Sopenharmony_ci * will sit in RAM until the write-buffer is synchronized (e.g., by timer, or
7138c2ecf20Sopenharmony_ci * because more data are appended to the write-buffer).
7148c2ecf20Sopenharmony_ci *
7158c2ecf20Sopenharmony_ci * This function returns zero in case of success and a negative error code in
7168c2ecf20Sopenharmony_ci * case of failure. If the node cannot be written because there is no more
7178c2ecf20Sopenharmony_ci * space in this logical eraseblock, %-ENOSPC is returned.
7188c2ecf20Sopenharmony_ci */
7198c2ecf20Sopenharmony_ciint ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len)
7208c2ecf20Sopenharmony_ci{
7218c2ecf20Sopenharmony_ci	struct ubifs_info *c = wbuf->c;
7228c2ecf20Sopenharmony_ci	int err, n, written = 0, aligned_len = ALIGN(len, 8);
7238c2ecf20Sopenharmony_ci
7248c2ecf20Sopenharmony_ci	dbg_io("%d bytes (%s) to jhead %s wbuf at LEB %d:%d", len,
7258c2ecf20Sopenharmony_ci	       dbg_ntype(((struct ubifs_ch *)buf)->node_type),
7268c2ecf20Sopenharmony_ci	       dbg_jhead(wbuf->jhead), wbuf->lnum, wbuf->offs + wbuf->used);
7278c2ecf20Sopenharmony_ci	ubifs_assert(c, len > 0 && wbuf->lnum >= 0 && wbuf->lnum < c->leb_cnt);
7288c2ecf20Sopenharmony_ci	ubifs_assert(c, wbuf->offs >= 0 && wbuf->offs % c->min_io_size == 0);
7298c2ecf20Sopenharmony_ci	ubifs_assert(c, !(wbuf->offs & 7) && wbuf->offs <= c->leb_size);
7308c2ecf20Sopenharmony_ci	ubifs_assert(c, wbuf->avail > 0 && wbuf->avail <= wbuf->size);
7318c2ecf20Sopenharmony_ci	ubifs_assert(c, wbuf->size >= c->min_io_size);
7328c2ecf20Sopenharmony_ci	ubifs_assert(c, wbuf->size <= c->max_write_size);
7338c2ecf20Sopenharmony_ci	ubifs_assert(c, wbuf->size % c->min_io_size == 0);
7348c2ecf20Sopenharmony_ci	ubifs_assert(c, mutex_is_locked(&wbuf->io_mutex));
7358c2ecf20Sopenharmony_ci	ubifs_assert(c, !c->ro_media && !c->ro_mount);
7368c2ecf20Sopenharmony_ci	ubifs_assert(c, !c->space_fixup);
7378c2ecf20Sopenharmony_ci	if (c->leb_size - wbuf->offs >= c->max_write_size)
7388c2ecf20Sopenharmony_ci		ubifs_assert(c, !((wbuf->offs + wbuf->size) % c->max_write_size));
7398c2ecf20Sopenharmony_ci
7408c2ecf20Sopenharmony_ci	if (c->leb_size - wbuf->offs - wbuf->used < aligned_len) {
7418c2ecf20Sopenharmony_ci		err = -ENOSPC;
7428c2ecf20Sopenharmony_ci		goto out;
7438c2ecf20Sopenharmony_ci	}
7448c2ecf20Sopenharmony_ci
7458c2ecf20Sopenharmony_ci	cancel_wbuf_timer_nolock(wbuf);
7468c2ecf20Sopenharmony_ci
7478c2ecf20Sopenharmony_ci	if (c->ro_error)
7488c2ecf20Sopenharmony_ci		return -EROFS;
7498c2ecf20Sopenharmony_ci
7508c2ecf20Sopenharmony_ci	if (aligned_len <= wbuf->avail) {
7518c2ecf20Sopenharmony_ci		/*
7528c2ecf20Sopenharmony_ci		 * The node is not very large and fits entirely within
7538c2ecf20Sopenharmony_ci		 * write-buffer.
7548c2ecf20Sopenharmony_ci		 */
7558c2ecf20Sopenharmony_ci		memcpy(wbuf->buf + wbuf->used, buf, len);
7568c2ecf20Sopenharmony_ci		if (aligned_len > len) {
7578c2ecf20Sopenharmony_ci			ubifs_assert(c, aligned_len - len < 8);
7588c2ecf20Sopenharmony_ci			ubifs_pad(c, wbuf->buf + wbuf->used + len, aligned_len - len);
7598c2ecf20Sopenharmony_ci		}
7608c2ecf20Sopenharmony_ci
7618c2ecf20Sopenharmony_ci		if (aligned_len == wbuf->avail) {
7628c2ecf20Sopenharmony_ci			dbg_io("flush jhead %s wbuf to LEB %d:%d",
7638c2ecf20Sopenharmony_ci			       dbg_jhead(wbuf->jhead), wbuf->lnum, wbuf->offs);
7648c2ecf20Sopenharmony_ci			err = ubifs_leb_write(c, wbuf->lnum, wbuf->buf,
7658c2ecf20Sopenharmony_ci					      wbuf->offs, wbuf->size);
7668c2ecf20Sopenharmony_ci			if (err)
7678c2ecf20Sopenharmony_ci				goto out;
7688c2ecf20Sopenharmony_ci
7698c2ecf20Sopenharmony_ci			spin_lock(&wbuf->lock);
7708c2ecf20Sopenharmony_ci			wbuf->offs += wbuf->size;
7718c2ecf20Sopenharmony_ci			if (c->leb_size - wbuf->offs >= c->max_write_size)
7728c2ecf20Sopenharmony_ci				wbuf->size = c->max_write_size;
7738c2ecf20Sopenharmony_ci			else
7748c2ecf20Sopenharmony_ci				wbuf->size = c->leb_size - wbuf->offs;
7758c2ecf20Sopenharmony_ci			wbuf->avail = wbuf->size;
7768c2ecf20Sopenharmony_ci			wbuf->used = 0;
7778c2ecf20Sopenharmony_ci			wbuf->next_ino = 0;
7788c2ecf20Sopenharmony_ci			spin_unlock(&wbuf->lock);
7798c2ecf20Sopenharmony_ci		} else {
7808c2ecf20Sopenharmony_ci			spin_lock(&wbuf->lock);
7818c2ecf20Sopenharmony_ci			wbuf->avail -= aligned_len;
7828c2ecf20Sopenharmony_ci			wbuf->used += aligned_len;
7838c2ecf20Sopenharmony_ci			spin_unlock(&wbuf->lock);
7848c2ecf20Sopenharmony_ci		}
7858c2ecf20Sopenharmony_ci
7868c2ecf20Sopenharmony_ci		goto exit;
7878c2ecf20Sopenharmony_ci	}
7888c2ecf20Sopenharmony_ci
7898c2ecf20Sopenharmony_ci	if (wbuf->used) {
7908c2ecf20Sopenharmony_ci		/*
7918c2ecf20Sopenharmony_ci		 * The node is large enough and does not fit entirely within
7928c2ecf20Sopenharmony_ci		 * current available space. We have to fill and flush
7938c2ecf20Sopenharmony_ci		 * write-buffer and switch to the next max. write unit.
7948c2ecf20Sopenharmony_ci		 */
7958c2ecf20Sopenharmony_ci		dbg_io("flush jhead %s wbuf to LEB %d:%d",
7968c2ecf20Sopenharmony_ci		       dbg_jhead(wbuf->jhead), wbuf->lnum, wbuf->offs);
7978c2ecf20Sopenharmony_ci		memcpy(wbuf->buf + wbuf->used, buf, wbuf->avail);
7988c2ecf20Sopenharmony_ci		err = ubifs_leb_write(c, wbuf->lnum, wbuf->buf, wbuf->offs,
7998c2ecf20Sopenharmony_ci				      wbuf->size);
8008c2ecf20Sopenharmony_ci		if (err)
8018c2ecf20Sopenharmony_ci			goto out;
8028c2ecf20Sopenharmony_ci
8038c2ecf20Sopenharmony_ci		wbuf->offs += wbuf->size;
8048c2ecf20Sopenharmony_ci		len -= wbuf->avail;
8058c2ecf20Sopenharmony_ci		aligned_len -= wbuf->avail;
8068c2ecf20Sopenharmony_ci		written += wbuf->avail;
8078c2ecf20Sopenharmony_ci	} else if (wbuf->offs & (c->max_write_size - 1)) {
8088c2ecf20Sopenharmony_ci		/*
8098c2ecf20Sopenharmony_ci		 * The write-buffer offset is not aligned to
8108c2ecf20Sopenharmony_ci		 * @c->max_write_size and @wbuf->size is less than
8118c2ecf20Sopenharmony_ci		 * @c->max_write_size. Write @wbuf->size bytes to make sure the
8128c2ecf20Sopenharmony_ci		 * following writes are done in optimal @c->max_write_size
8138c2ecf20Sopenharmony_ci		 * chunks.
8148c2ecf20Sopenharmony_ci		 */
8158c2ecf20Sopenharmony_ci		dbg_io("write %d bytes to LEB %d:%d",
8168c2ecf20Sopenharmony_ci		       wbuf->size, wbuf->lnum, wbuf->offs);
8178c2ecf20Sopenharmony_ci		err = ubifs_leb_write(c, wbuf->lnum, buf, wbuf->offs,
8188c2ecf20Sopenharmony_ci				      wbuf->size);
8198c2ecf20Sopenharmony_ci		if (err)
8208c2ecf20Sopenharmony_ci			goto out;
8218c2ecf20Sopenharmony_ci
8228c2ecf20Sopenharmony_ci		wbuf->offs += wbuf->size;
8238c2ecf20Sopenharmony_ci		len -= wbuf->size;
8248c2ecf20Sopenharmony_ci		aligned_len -= wbuf->size;
8258c2ecf20Sopenharmony_ci		written += wbuf->size;
8268c2ecf20Sopenharmony_ci	}
8278c2ecf20Sopenharmony_ci
8288c2ecf20Sopenharmony_ci	/*
8298c2ecf20Sopenharmony_ci	 * The remaining data may take more whole max. write units, so write the
8308c2ecf20Sopenharmony_ci	 * remains multiple to max. write unit size directly to the flash media.
8318c2ecf20Sopenharmony_ci	 * We align node length to 8-byte boundary because we anyway flash wbuf
8328c2ecf20Sopenharmony_ci	 * if the remaining space is less than 8 bytes.
8338c2ecf20Sopenharmony_ci	 */
8348c2ecf20Sopenharmony_ci	n = aligned_len >> c->max_write_shift;
8358c2ecf20Sopenharmony_ci	if (n) {
8368c2ecf20Sopenharmony_ci		int m = n - 1;
8378c2ecf20Sopenharmony_ci
8388c2ecf20Sopenharmony_ci		dbg_io("write %d bytes to LEB %d:%d", n, wbuf->lnum,
8398c2ecf20Sopenharmony_ci		       wbuf->offs);
8408c2ecf20Sopenharmony_ci
8418c2ecf20Sopenharmony_ci		if (m) {
8428c2ecf20Sopenharmony_ci			/* '(n-1)<<c->max_write_shift < len' is always true. */
8438c2ecf20Sopenharmony_ci			m <<= c->max_write_shift;
8448c2ecf20Sopenharmony_ci			err = ubifs_leb_write(c, wbuf->lnum, buf + written,
8458c2ecf20Sopenharmony_ci					      wbuf->offs, m);
8468c2ecf20Sopenharmony_ci			if (err)
8478c2ecf20Sopenharmony_ci				goto out;
8488c2ecf20Sopenharmony_ci			wbuf->offs += m;
8498c2ecf20Sopenharmony_ci			aligned_len -= m;
8508c2ecf20Sopenharmony_ci			len -= m;
8518c2ecf20Sopenharmony_ci			written += m;
8528c2ecf20Sopenharmony_ci		}
8538c2ecf20Sopenharmony_ci
8548c2ecf20Sopenharmony_ci		/*
8558c2ecf20Sopenharmony_ci		 * The non-written len of buf may be less than 'n' because
8568c2ecf20Sopenharmony_ci		 * parameter 'len' is not 8 bytes aligned, so here we read
8578c2ecf20Sopenharmony_ci		 * min(len, n) bytes from buf.
8588c2ecf20Sopenharmony_ci		 */
8598c2ecf20Sopenharmony_ci		n = 1 << c->max_write_shift;
8608c2ecf20Sopenharmony_ci		memcpy(wbuf->buf, buf + written, min(len, n));
8618c2ecf20Sopenharmony_ci		if (n > len) {
8628c2ecf20Sopenharmony_ci			ubifs_assert(c, n - len < 8);
8638c2ecf20Sopenharmony_ci			ubifs_pad(c, wbuf->buf + len, n - len);
8648c2ecf20Sopenharmony_ci		}
8658c2ecf20Sopenharmony_ci
8668c2ecf20Sopenharmony_ci		err = ubifs_leb_write(c, wbuf->lnum, wbuf->buf, wbuf->offs, n);
8678c2ecf20Sopenharmony_ci		if (err)
8688c2ecf20Sopenharmony_ci			goto out;
8698c2ecf20Sopenharmony_ci		wbuf->offs += n;
8708c2ecf20Sopenharmony_ci		aligned_len -= n;
8718c2ecf20Sopenharmony_ci		len -= min(len, n);
8728c2ecf20Sopenharmony_ci		written += n;
8738c2ecf20Sopenharmony_ci	}
8748c2ecf20Sopenharmony_ci
8758c2ecf20Sopenharmony_ci	spin_lock(&wbuf->lock);
8768c2ecf20Sopenharmony_ci	if (aligned_len) {
8778c2ecf20Sopenharmony_ci		/*
8788c2ecf20Sopenharmony_ci		 * And now we have what's left and what does not take whole
8798c2ecf20Sopenharmony_ci		 * max. write unit, so write it to the write-buffer and we are
8808c2ecf20Sopenharmony_ci		 * done.
8818c2ecf20Sopenharmony_ci		 */
8828c2ecf20Sopenharmony_ci		memcpy(wbuf->buf, buf + written, len);
8838c2ecf20Sopenharmony_ci		if (aligned_len > len) {
8848c2ecf20Sopenharmony_ci			ubifs_assert(c, aligned_len - len < 8);
8858c2ecf20Sopenharmony_ci			ubifs_pad(c, wbuf->buf + len, aligned_len - len);
8868c2ecf20Sopenharmony_ci		}
8878c2ecf20Sopenharmony_ci	}
8888c2ecf20Sopenharmony_ci
8898c2ecf20Sopenharmony_ci	if (c->leb_size - wbuf->offs >= c->max_write_size)
8908c2ecf20Sopenharmony_ci		wbuf->size = c->max_write_size;
8918c2ecf20Sopenharmony_ci	else
8928c2ecf20Sopenharmony_ci		wbuf->size = c->leb_size - wbuf->offs;
8938c2ecf20Sopenharmony_ci	wbuf->avail = wbuf->size - aligned_len;
8948c2ecf20Sopenharmony_ci	wbuf->used = aligned_len;
8958c2ecf20Sopenharmony_ci	wbuf->next_ino = 0;
8968c2ecf20Sopenharmony_ci	spin_unlock(&wbuf->lock);
8978c2ecf20Sopenharmony_ci
8988c2ecf20Sopenharmony_ciexit:
8998c2ecf20Sopenharmony_ci	if (wbuf->sync_callback) {
9008c2ecf20Sopenharmony_ci		int free = c->leb_size - wbuf->offs - wbuf->used;
9018c2ecf20Sopenharmony_ci
9028c2ecf20Sopenharmony_ci		err = wbuf->sync_callback(c, wbuf->lnum, free, 0);
9038c2ecf20Sopenharmony_ci		if (err)
9048c2ecf20Sopenharmony_ci			goto out;
9058c2ecf20Sopenharmony_ci	}
9068c2ecf20Sopenharmony_ci
9078c2ecf20Sopenharmony_ci	if (wbuf->used)
9088c2ecf20Sopenharmony_ci		new_wbuf_timer_nolock(c, wbuf);
9098c2ecf20Sopenharmony_ci
9108c2ecf20Sopenharmony_ci	return 0;
9118c2ecf20Sopenharmony_ci
9128c2ecf20Sopenharmony_ciout:
9138c2ecf20Sopenharmony_ci	ubifs_err(c, "cannot write %d bytes to LEB %d:%d, error %d",
9148c2ecf20Sopenharmony_ci		  len, wbuf->lnum, wbuf->offs, err);
9158c2ecf20Sopenharmony_ci	ubifs_dump_node(c, buf, written + len);
9168c2ecf20Sopenharmony_ci	dump_stack();
9178c2ecf20Sopenharmony_ci	ubifs_dump_leb(c, wbuf->lnum);
9188c2ecf20Sopenharmony_ci	return err;
9198c2ecf20Sopenharmony_ci}
9208c2ecf20Sopenharmony_ci
9218c2ecf20Sopenharmony_ci/**
9228c2ecf20Sopenharmony_ci * ubifs_write_node_hmac - write node to the media.
9238c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object
9248c2ecf20Sopenharmony_ci * @buf: the node to write
9258c2ecf20Sopenharmony_ci * @len: node length
9268c2ecf20Sopenharmony_ci * @lnum: logical eraseblock number
9278c2ecf20Sopenharmony_ci * @offs: offset within the logical eraseblock
9288c2ecf20Sopenharmony_ci * @hmac_offs: offset of the HMAC within the node
9298c2ecf20Sopenharmony_ci *
9308c2ecf20Sopenharmony_ci * This function automatically fills node magic number, assigns sequence
9318c2ecf20Sopenharmony_ci * number, and calculates node CRC checksum. The length of the @buf buffer has
9328c2ecf20Sopenharmony_ci * to be aligned to the minimal I/O unit size. This function automatically
9338c2ecf20Sopenharmony_ci * appends padding node and padding bytes if needed. Returns zero in case of
9348c2ecf20Sopenharmony_ci * success and a negative error code in case of failure.
9358c2ecf20Sopenharmony_ci */
9368c2ecf20Sopenharmony_ciint ubifs_write_node_hmac(struct ubifs_info *c, void *buf, int len, int lnum,
9378c2ecf20Sopenharmony_ci			  int offs, int hmac_offs)
9388c2ecf20Sopenharmony_ci{
9398c2ecf20Sopenharmony_ci	int err, buf_len = ALIGN(len, c->min_io_size);
9408c2ecf20Sopenharmony_ci
9418c2ecf20Sopenharmony_ci	dbg_io("LEB %d:%d, %s, length %d (aligned %d)",
9428c2ecf20Sopenharmony_ci	       lnum, offs, dbg_ntype(((struct ubifs_ch *)buf)->node_type), len,
9438c2ecf20Sopenharmony_ci	       buf_len);
9448c2ecf20Sopenharmony_ci	ubifs_assert(c, lnum >= 0 && lnum < c->leb_cnt && offs >= 0);
9458c2ecf20Sopenharmony_ci	ubifs_assert(c, offs % c->min_io_size == 0 && offs < c->leb_size);
9468c2ecf20Sopenharmony_ci	ubifs_assert(c, !c->ro_media && !c->ro_mount);
9478c2ecf20Sopenharmony_ci	ubifs_assert(c, !c->space_fixup);
9488c2ecf20Sopenharmony_ci
9498c2ecf20Sopenharmony_ci	if (c->ro_error)
9508c2ecf20Sopenharmony_ci		return -EROFS;
9518c2ecf20Sopenharmony_ci
9528c2ecf20Sopenharmony_ci	err = ubifs_prepare_node_hmac(c, buf, len, hmac_offs, 1);
9538c2ecf20Sopenharmony_ci	if (err)
9548c2ecf20Sopenharmony_ci		return err;
9558c2ecf20Sopenharmony_ci
9568c2ecf20Sopenharmony_ci	err = ubifs_leb_write(c, lnum, buf, offs, buf_len);
9578c2ecf20Sopenharmony_ci	if (err)
9588c2ecf20Sopenharmony_ci		ubifs_dump_node(c, buf, len);
9598c2ecf20Sopenharmony_ci
9608c2ecf20Sopenharmony_ci	return err;
9618c2ecf20Sopenharmony_ci}
9628c2ecf20Sopenharmony_ci
9638c2ecf20Sopenharmony_ci/**
9648c2ecf20Sopenharmony_ci * ubifs_write_node - write node to the media.
9658c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object
9668c2ecf20Sopenharmony_ci * @buf: the node to write
9678c2ecf20Sopenharmony_ci * @len: node length
9688c2ecf20Sopenharmony_ci * @lnum: logical eraseblock number
9698c2ecf20Sopenharmony_ci * @offs: offset within the logical eraseblock
9708c2ecf20Sopenharmony_ci *
9718c2ecf20Sopenharmony_ci * This function automatically fills node magic number, assigns sequence
9728c2ecf20Sopenharmony_ci * number, and calculates node CRC checksum. The length of the @buf buffer has
9738c2ecf20Sopenharmony_ci * to be aligned to the minimal I/O unit size. This function automatically
9748c2ecf20Sopenharmony_ci * appends padding node and padding bytes if needed. Returns zero in case of
9758c2ecf20Sopenharmony_ci * success and a negative error code in case of failure.
9768c2ecf20Sopenharmony_ci */
9778c2ecf20Sopenharmony_ciint ubifs_write_node(struct ubifs_info *c, void *buf, int len, int lnum,
9788c2ecf20Sopenharmony_ci		     int offs)
9798c2ecf20Sopenharmony_ci{
9808c2ecf20Sopenharmony_ci	return ubifs_write_node_hmac(c, buf, len, lnum, offs, -1);
9818c2ecf20Sopenharmony_ci}
9828c2ecf20Sopenharmony_ci
9838c2ecf20Sopenharmony_ci/**
9848c2ecf20Sopenharmony_ci * ubifs_read_node_wbuf - read node from the media or write-buffer.
9858c2ecf20Sopenharmony_ci * @wbuf: wbuf to check for un-written data
9868c2ecf20Sopenharmony_ci * @buf: buffer to read to
9878c2ecf20Sopenharmony_ci * @type: node type
9888c2ecf20Sopenharmony_ci * @len: node length
9898c2ecf20Sopenharmony_ci * @lnum: logical eraseblock number
9908c2ecf20Sopenharmony_ci * @offs: offset within the logical eraseblock
9918c2ecf20Sopenharmony_ci *
9928c2ecf20Sopenharmony_ci * This function reads a node of known type and length, checks it and stores
9938c2ecf20Sopenharmony_ci * in @buf. If the node partially or fully sits in the write-buffer, this
9948c2ecf20Sopenharmony_ci * function takes data from the buffer, otherwise it reads the flash media.
9958c2ecf20Sopenharmony_ci * Returns zero in case of success, %-EUCLEAN if CRC mismatched and a negative
9968c2ecf20Sopenharmony_ci * error code in case of failure.
9978c2ecf20Sopenharmony_ci */
9988c2ecf20Sopenharmony_ciint ubifs_read_node_wbuf(struct ubifs_wbuf *wbuf, void *buf, int type, int len,
9998c2ecf20Sopenharmony_ci			 int lnum, int offs)
10008c2ecf20Sopenharmony_ci{
10018c2ecf20Sopenharmony_ci	const struct ubifs_info *c = wbuf->c;
10028c2ecf20Sopenharmony_ci	int err, rlen, overlap;
10038c2ecf20Sopenharmony_ci	struct ubifs_ch *ch = buf;
10048c2ecf20Sopenharmony_ci
10058c2ecf20Sopenharmony_ci	dbg_io("LEB %d:%d, %s, length %d, jhead %s", lnum, offs,
10068c2ecf20Sopenharmony_ci	       dbg_ntype(type), len, dbg_jhead(wbuf->jhead));
10078c2ecf20Sopenharmony_ci	ubifs_assert(c, wbuf && lnum >= 0 && lnum < c->leb_cnt && offs >= 0);
10088c2ecf20Sopenharmony_ci	ubifs_assert(c, !(offs & 7) && offs < c->leb_size);
10098c2ecf20Sopenharmony_ci	ubifs_assert(c, type >= 0 && type < UBIFS_NODE_TYPES_CNT);
10108c2ecf20Sopenharmony_ci
10118c2ecf20Sopenharmony_ci	spin_lock(&wbuf->lock);
10128c2ecf20Sopenharmony_ci	overlap = (lnum == wbuf->lnum && offs + len > wbuf->offs);
10138c2ecf20Sopenharmony_ci	if (!overlap) {
10148c2ecf20Sopenharmony_ci		/* We may safely unlock the write-buffer and read the data */
10158c2ecf20Sopenharmony_ci		spin_unlock(&wbuf->lock);
10168c2ecf20Sopenharmony_ci		return ubifs_read_node(c, buf, type, len, lnum, offs);
10178c2ecf20Sopenharmony_ci	}
10188c2ecf20Sopenharmony_ci
10198c2ecf20Sopenharmony_ci	/* Don't read under wbuf */
10208c2ecf20Sopenharmony_ci	rlen = wbuf->offs - offs;
10218c2ecf20Sopenharmony_ci	if (rlen < 0)
10228c2ecf20Sopenharmony_ci		rlen = 0;
10238c2ecf20Sopenharmony_ci
10248c2ecf20Sopenharmony_ci	/* Copy the rest from the write-buffer */
10258c2ecf20Sopenharmony_ci	memcpy(buf + rlen, wbuf->buf + offs + rlen - wbuf->offs, len - rlen);
10268c2ecf20Sopenharmony_ci	spin_unlock(&wbuf->lock);
10278c2ecf20Sopenharmony_ci
10288c2ecf20Sopenharmony_ci	if (rlen > 0) {
10298c2ecf20Sopenharmony_ci		/* Read everything that goes before write-buffer */
10308c2ecf20Sopenharmony_ci		err = ubifs_leb_read(c, lnum, buf, offs, rlen, 0);
10318c2ecf20Sopenharmony_ci		if (err && err != -EBADMSG)
10328c2ecf20Sopenharmony_ci			return err;
10338c2ecf20Sopenharmony_ci	}
10348c2ecf20Sopenharmony_ci
10358c2ecf20Sopenharmony_ci	if (type != ch->node_type) {
10368c2ecf20Sopenharmony_ci		ubifs_err(c, "bad node type (%d but expected %d)",
10378c2ecf20Sopenharmony_ci			  ch->node_type, type);
10388c2ecf20Sopenharmony_ci		goto out;
10398c2ecf20Sopenharmony_ci	}
10408c2ecf20Sopenharmony_ci
10418c2ecf20Sopenharmony_ci	err = ubifs_check_node(c, buf, len, lnum, offs, 0, 0);
10428c2ecf20Sopenharmony_ci	if (err) {
10438c2ecf20Sopenharmony_ci		ubifs_err(c, "expected node type %d", type);
10448c2ecf20Sopenharmony_ci		return err;
10458c2ecf20Sopenharmony_ci	}
10468c2ecf20Sopenharmony_ci
10478c2ecf20Sopenharmony_ci	rlen = le32_to_cpu(ch->len);
10488c2ecf20Sopenharmony_ci	if (rlen != len) {
10498c2ecf20Sopenharmony_ci		ubifs_err(c, "bad node length %d, expected %d", rlen, len);
10508c2ecf20Sopenharmony_ci		goto out;
10518c2ecf20Sopenharmony_ci	}
10528c2ecf20Sopenharmony_ci
10538c2ecf20Sopenharmony_ci	return 0;
10548c2ecf20Sopenharmony_ci
10558c2ecf20Sopenharmony_ciout:
10568c2ecf20Sopenharmony_ci	ubifs_err(c, "bad node at LEB %d:%d", lnum, offs);
10578c2ecf20Sopenharmony_ci	ubifs_dump_node(c, buf, len);
10588c2ecf20Sopenharmony_ci	dump_stack();
10598c2ecf20Sopenharmony_ci	return -EINVAL;
10608c2ecf20Sopenharmony_ci}
10618c2ecf20Sopenharmony_ci
10628c2ecf20Sopenharmony_ci/**
10638c2ecf20Sopenharmony_ci * ubifs_read_node - read node.
10648c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object
10658c2ecf20Sopenharmony_ci * @buf: buffer to read to
10668c2ecf20Sopenharmony_ci * @type: node type
10678c2ecf20Sopenharmony_ci * @len: node length (not aligned)
10688c2ecf20Sopenharmony_ci * @lnum: logical eraseblock number
10698c2ecf20Sopenharmony_ci * @offs: offset within the logical eraseblock
10708c2ecf20Sopenharmony_ci *
10718c2ecf20Sopenharmony_ci * This function reads a node of known type and and length, checks it and
10728c2ecf20Sopenharmony_ci * stores in @buf. Returns zero in case of success, %-EUCLEAN if CRC mismatched
10738c2ecf20Sopenharmony_ci * and a negative error code in case of failure.
10748c2ecf20Sopenharmony_ci */
10758c2ecf20Sopenharmony_ciint ubifs_read_node(const struct ubifs_info *c, void *buf, int type, int len,
10768c2ecf20Sopenharmony_ci		    int lnum, int offs)
10778c2ecf20Sopenharmony_ci{
10788c2ecf20Sopenharmony_ci	int err, l;
10798c2ecf20Sopenharmony_ci	struct ubifs_ch *ch = buf;
10808c2ecf20Sopenharmony_ci
10818c2ecf20Sopenharmony_ci	dbg_io("LEB %d:%d, %s, length %d", lnum, offs, dbg_ntype(type), len);
10828c2ecf20Sopenharmony_ci	ubifs_assert(c, lnum >= 0 && lnum < c->leb_cnt && offs >= 0);
10838c2ecf20Sopenharmony_ci	ubifs_assert(c, len >= UBIFS_CH_SZ && offs + len <= c->leb_size);
10848c2ecf20Sopenharmony_ci	ubifs_assert(c, !(offs & 7) && offs < c->leb_size);
10858c2ecf20Sopenharmony_ci	ubifs_assert(c, type >= 0 && type < UBIFS_NODE_TYPES_CNT);
10868c2ecf20Sopenharmony_ci
10878c2ecf20Sopenharmony_ci	err = ubifs_leb_read(c, lnum, buf, offs, len, 0);
10888c2ecf20Sopenharmony_ci	if (err && err != -EBADMSG)
10898c2ecf20Sopenharmony_ci		return err;
10908c2ecf20Sopenharmony_ci
10918c2ecf20Sopenharmony_ci	if (type != ch->node_type) {
10928c2ecf20Sopenharmony_ci		ubifs_errc(c, "bad node type (%d but expected %d)",
10938c2ecf20Sopenharmony_ci			   ch->node_type, type);
10948c2ecf20Sopenharmony_ci		goto out;
10958c2ecf20Sopenharmony_ci	}
10968c2ecf20Sopenharmony_ci
10978c2ecf20Sopenharmony_ci	err = ubifs_check_node(c, buf, len, lnum, offs, 0, 0);
10988c2ecf20Sopenharmony_ci	if (err) {
10998c2ecf20Sopenharmony_ci		ubifs_errc(c, "expected node type %d", type);
11008c2ecf20Sopenharmony_ci		return err;
11018c2ecf20Sopenharmony_ci	}
11028c2ecf20Sopenharmony_ci
11038c2ecf20Sopenharmony_ci	l = le32_to_cpu(ch->len);
11048c2ecf20Sopenharmony_ci	if (l != len) {
11058c2ecf20Sopenharmony_ci		ubifs_errc(c, "bad node length %d, expected %d", l, len);
11068c2ecf20Sopenharmony_ci		goto out;
11078c2ecf20Sopenharmony_ci	}
11088c2ecf20Sopenharmony_ci
11098c2ecf20Sopenharmony_ci	return 0;
11108c2ecf20Sopenharmony_ci
11118c2ecf20Sopenharmony_ciout:
11128c2ecf20Sopenharmony_ci	ubifs_errc(c, "bad node at LEB %d:%d, LEB mapping status %d", lnum,
11138c2ecf20Sopenharmony_ci		   offs, ubi_is_mapped(c->ubi, lnum));
11148c2ecf20Sopenharmony_ci	if (!c->probing) {
11158c2ecf20Sopenharmony_ci		ubifs_dump_node(c, buf, len);
11168c2ecf20Sopenharmony_ci		dump_stack();
11178c2ecf20Sopenharmony_ci	}
11188c2ecf20Sopenharmony_ci	return -EINVAL;
11198c2ecf20Sopenharmony_ci}
11208c2ecf20Sopenharmony_ci
11218c2ecf20Sopenharmony_ci/**
11228c2ecf20Sopenharmony_ci * ubifs_wbuf_init - initialize write-buffer.
11238c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object
11248c2ecf20Sopenharmony_ci * @wbuf: write-buffer to initialize
11258c2ecf20Sopenharmony_ci *
11268c2ecf20Sopenharmony_ci * This function initializes write-buffer. Returns zero in case of success
11278c2ecf20Sopenharmony_ci * %-ENOMEM in case of failure.
11288c2ecf20Sopenharmony_ci */
11298c2ecf20Sopenharmony_ciint ubifs_wbuf_init(struct ubifs_info *c, struct ubifs_wbuf *wbuf)
11308c2ecf20Sopenharmony_ci{
11318c2ecf20Sopenharmony_ci	size_t size;
11328c2ecf20Sopenharmony_ci
11338c2ecf20Sopenharmony_ci	wbuf->buf = kmalloc(c->max_write_size, GFP_KERNEL);
11348c2ecf20Sopenharmony_ci	if (!wbuf->buf)
11358c2ecf20Sopenharmony_ci		return -ENOMEM;
11368c2ecf20Sopenharmony_ci
11378c2ecf20Sopenharmony_ci	size = (c->max_write_size / UBIFS_CH_SZ + 1) * sizeof(ino_t);
11388c2ecf20Sopenharmony_ci	wbuf->inodes = kmalloc(size, GFP_KERNEL);
11398c2ecf20Sopenharmony_ci	if (!wbuf->inodes) {
11408c2ecf20Sopenharmony_ci		kfree(wbuf->buf);
11418c2ecf20Sopenharmony_ci		wbuf->buf = NULL;
11428c2ecf20Sopenharmony_ci		return -ENOMEM;
11438c2ecf20Sopenharmony_ci	}
11448c2ecf20Sopenharmony_ci
11458c2ecf20Sopenharmony_ci	wbuf->used = 0;
11468c2ecf20Sopenharmony_ci	wbuf->lnum = wbuf->offs = -1;
11478c2ecf20Sopenharmony_ci	/*
11488c2ecf20Sopenharmony_ci	 * If the LEB starts at the max. write size aligned address, then
11498c2ecf20Sopenharmony_ci	 * write-buffer size has to be set to @c->max_write_size. Otherwise,
11508c2ecf20Sopenharmony_ci	 * set it to something smaller so that it ends at the closest max.
11518c2ecf20Sopenharmony_ci	 * write size boundary.
11528c2ecf20Sopenharmony_ci	 */
11538c2ecf20Sopenharmony_ci	size = c->max_write_size - (c->leb_start % c->max_write_size);
11548c2ecf20Sopenharmony_ci	wbuf->avail = wbuf->size = size;
11558c2ecf20Sopenharmony_ci	wbuf->sync_callback = NULL;
11568c2ecf20Sopenharmony_ci	mutex_init(&wbuf->io_mutex);
11578c2ecf20Sopenharmony_ci	spin_lock_init(&wbuf->lock);
11588c2ecf20Sopenharmony_ci	wbuf->c = c;
11598c2ecf20Sopenharmony_ci	wbuf->next_ino = 0;
11608c2ecf20Sopenharmony_ci
11618c2ecf20Sopenharmony_ci	hrtimer_init(&wbuf->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
11628c2ecf20Sopenharmony_ci	wbuf->timer.function = wbuf_timer_callback_nolock;
11638c2ecf20Sopenharmony_ci	return 0;
11648c2ecf20Sopenharmony_ci}
11658c2ecf20Sopenharmony_ci
11668c2ecf20Sopenharmony_ci/**
11678c2ecf20Sopenharmony_ci * ubifs_wbuf_add_ino_nolock - add an inode number into the wbuf inode array.
11688c2ecf20Sopenharmony_ci * @wbuf: the write-buffer where to add
11698c2ecf20Sopenharmony_ci * @inum: the inode number
11708c2ecf20Sopenharmony_ci *
11718c2ecf20Sopenharmony_ci * This function adds an inode number to the inode array of the write-buffer.
11728c2ecf20Sopenharmony_ci */
11738c2ecf20Sopenharmony_civoid ubifs_wbuf_add_ino_nolock(struct ubifs_wbuf *wbuf, ino_t inum)
11748c2ecf20Sopenharmony_ci{
11758c2ecf20Sopenharmony_ci	if (!wbuf->buf)
11768c2ecf20Sopenharmony_ci		/* NOR flash or something similar */
11778c2ecf20Sopenharmony_ci		return;
11788c2ecf20Sopenharmony_ci
11798c2ecf20Sopenharmony_ci	spin_lock(&wbuf->lock);
11808c2ecf20Sopenharmony_ci	if (wbuf->used)
11818c2ecf20Sopenharmony_ci		wbuf->inodes[wbuf->next_ino++] = inum;
11828c2ecf20Sopenharmony_ci	spin_unlock(&wbuf->lock);
11838c2ecf20Sopenharmony_ci}
11848c2ecf20Sopenharmony_ci
11858c2ecf20Sopenharmony_ci/**
11868c2ecf20Sopenharmony_ci * wbuf_has_ino - returns if the wbuf contains data from the inode.
11878c2ecf20Sopenharmony_ci * @wbuf: the write-buffer
11888c2ecf20Sopenharmony_ci * @inum: the inode number
11898c2ecf20Sopenharmony_ci *
11908c2ecf20Sopenharmony_ci * This function returns with %1 if the write-buffer contains some data from the
11918c2ecf20Sopenharmony_ci * given inode otherwise it returns with %0.
11928c2ecf20Sopenharmony_ci */
11938c2ecf20Sopenharmony_cistatic int wbuf_has_ino(struct ubifs_wbuf *wbuf, ino_t inum)
11948c2ecf20Sopenharmony_ci{
11958c2ecf20Sopenharmony_ci	int i, ret = 0;
11968c2ecf20Sopenharmony_ci
11978c2ecf20Sopenharmony_ci	spin_lock(&wbuf->lock);
11988c2ecf20Sopenharmony_ci	for (i = 0; i < wbuf->next_ino; i++)
11998c2ecf20Sopenharmony_ci		if (inum == wbuf->inodes[i]) {
12008c2ecf20Sopenharmony_ci			ret = 1;
12018c2ecf20Sopenharmony_ci			break;
12028c2ecf20Sopenharmony_ci		}
12038c2ecf20Sopenharmony_ci	spin_unlock(&wbuf->lock);
12048c2ecf20Sopenharmony_ci
12058c2ecf20Sopenharmony_ci	return ret;
12068c2ecf20Sopenharmony_ci}
12078c2ecf20Sopenharmony_ci
12088c2ecf20Sopenharmony_ci/**
12098c2ecf20Sopenharmony_ci * ubifs_sync_wbufs_by_inode - synchronize write-buffers for an inode.
12108c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object
12118c2ecf20Sopenharmony_ci * @inode: inode to synchronize
12128c2ecf20Sopenharmony_ci *
12138c2ecf20Sopenharmony_ci * This function synchronizes write-buffers which contain nodes belonging to
12148c2ecf20Sopenharmony_ci * @inode. Returns zero in case of success and a negative error code in case of
12158c2ecf20Sopenharmony_ci * failure.
12168c2ecf20Sopenharmony_ci */
12178c2ecf20Sopenharmony_ciint ubifs_sync_wbufs_by_inode(struct ubifs_info *c, struct inode *inode)
12188c2ecf20Sopenharmony_ci{
12198c2ecf20Sopenharmony_ci	int i, err = 0;
12208c2ecf20Sopenharmony_ci
12218c2ecf20Sopenharmony_ci	for (i = 0; i < c->jhead_cnt; i++) {
12228c2ecf20Sopenharmony_ci		struct ubifs_wbuf *wbuf = &c->jheads[i].wbuf;
12238c2ecf20Sopenharmony_ci
12248c2ecf20Sopenharmony_ci		if (i == GCHD)
12258c2ecf20Sopenharmony_ci			/*
12268c2ecf20Sopenharmony_ci			 * GC head is special, do not look at it. Even if the
12278c2ecf20Sopenharmony_ci			 * head contains something related to this inode, it is
12288c2ecf20Sopenharmony_ci			 * a _copy_ of corresponding on-flash node which sits
12298c2ecf20Sopenharmony_ci			 * somewhere else.
12308c2ecf20Sopenharmony_ci			 */
12318c2ecf20Sopenharmony_ci			continue;
12328c2ecf20Sopenharmony_ci
12338c2ecf20Sopenharmony_ci		if (!wbuf_has_ino(wbuf, inode->i_ino))
12348c2ecf20Sopenharmony_ci			continue;
12358c2ecf20Sopenharmony_ci
12368c2ecf20Sopenharmony_ci		mutex_lock_nested(&wbuf->io_mutex, wbuf->jhead);
12378c2ecf20Sopenharmony_ci		if (wbuf_has_ino(wbuf, inode->i_ino))
12388c2ecf20Sopenharmony_ci			err = ubifs_wbuf_sync_nolock(wbuf);
12398c2ecf20Sopenharmony_ci		mutex_unlock(&wbuf->io_mutex);
12408c2ecf20Sopenharmony_ci
12418c2ecf20Sopenharmony_ci		if (err) {
12428c2ecf20Sopenharmony_ci			ubifs_ro_mode(c, err);
12438c2ecf20Sopenharmony_ci			return err;
12448c2ecf20Sopenharmony_ci		}
12458c2ecf20Sopenharmony_ci	}
12468c2ecf20Sopenharmony_ci	return 0;
12478c2ecf20Sopenharmony_ci}
1248