18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * This file is part of UBIFS. 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2006-2008 Nokia Corporation 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Authors: Adrian Hunter 88c2ecf20Sopenharmony_ci * Artem Bityutskiy (Битюцкий Артём) 98c2ecf20Sopenharmony_ci */ 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci/* 128c2ecf20Sopenharmony_ci * This file implements functions needed to recover from unclean un-mounts. 138c2ecf20Sopenharmony_ci * When UBIFS is mounted, it checks a flag on the master node to determine if 148c2ecf20Sopenharmony_ci * an un-mount was completed successfully. If not, the process of mounting 158c2ecf20Sopenharmony_ci * incorporates additional checking and fixing of on-flash data structures. 168c2ecf20Sopenharmony_ci * UBIFS always cleans away all remnants of an unclean un-mount, so that 178c2ecf20Sopenharmony_ci * errors do not accumulate. However UBIFS defers recovery if it is mounted 188c2ecf20Sopenharmony_ci * read-only, and the flash is not modified in that case. 198c2ecf20Sopenharmony_ci * 208c2ecf20Sopenharmony_ci * The general UBIFS approach to the recovery is that it recovers from 218c2ecf20Sopenharmony_ci * corruptions which could be caused by power cuts, but it refuses to recover 228c2ecf20Sopenharmony_ci * from corruption caused by other reasons. And UBIFS tries to distinguish 238c2ecf20Sopenharmony_ci * between these 2 reasons of corruptions and silently recover in the former 248c2ecf20Sopenharmony_ci * case and loudly complain in the latter case. 258c2ecf20Sopenharmony_ci * 268c2ecf20Sopenharmony_ci * UBIFS writes only to erased LEBs, so it writes only to the flash space 278c2ecf20Sopenharmony_ci * containing only 0xFFs. UBIFS also always writes strictly from the beginning 288c2ecf20Sopenharmony_ci * of the LEB to the end. And UBIFS assumes that the underlying flash media 298c2ecf20Sopenharmony_ci * writes in @c->max_write_size bytes at a time. 308c2ecf20Sopenharmony_ci * 318c2ecf20Sopenharmony_ci * Hence, if UBIFS finds a corrupted node at offset X, it expects only the min. 328c2ecf20Sopenharmony_ci * I/O unit corresponding to offset X to contain corrupted data, all the 338c2ecf20Sopenharmony_ci * following min. I/O units have to contain empty space (all 0xFFs). If this is 348c2ecf20Sopenharmony_ci * not true, the corruption cannot be the result of a power cut, and UBIFS 358c2ecf20Sopenharmony_ci * refuses to mount. 368c2ecf20Sopenharmony_ci */ 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci#include <linux/crc32.h> 398c2ecf20Sopenharmony_ci#include <linux/slab.h> 408c2ecf20Sopenharmony_ci#include "ubifs.h" 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci/** 438c2ecf20Sopenharmony_ci * is_empty - determine whether a buffer is empty (contains all 0xff). 448c2ecf20Sopenharmony_ci * @buf: buffer to clean 458c2ecf20Sopenharmony_ci * @len: length of buffer 468c2ecf20Sopenharmony_ci * 478c2ecf20Sopenharmony_ci * This function returns %1 if the buffer is empty (contains all 0xff) otherwise 488c2ecf20Sopenharmony_ci * %0 is returned. 498c2ecf20Sopenharmony_ci */ 508c2ecf20Sopenharmony_cistatic int is_empty(void *buf, int len) 518c2ecf20Sopenharmony_ci{ 528c2ecf20Sopenharmony_ci uint8_t *p = buf; 538c2ecf20Sopenharmony_ci int i; 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci for (i = 0; i < len; i++) 568c2ecf20Sopenharmony_ci if (*p++ != 0xff) 578c2ecf20Sopenharmony_ci return 0; 588c2ecf20Sopenharmony_ci return 1; 598c2ecf20Sopenharmony_ci} 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ci/** 628c2ecf20Sopenharmony_ci * first_non_ff - find offset of the first non-0xff byte. 638c2ecf20Sopenharmony_ci * @buf: buffer to search in 648c2ecf20Sopenharmony_ci * @len: length of buffer 658c2ecf20Sopenharmony_ci * 668c2ecf20Sopenharmony_ci * This function returns offset of the first non-0xff byte in @buf or %-1 if 678c2ecf20Sopenharmony_ci * the buffer contains only 0xff bytes. 688c2ecf20Sopenharmony_ci */ 698c2ecf20Sopenharmony_cistatic int first_non_ff(void *buf, int len) 708c2ecf20Sopenharmony_ci{ 718c2ecf20Sopenharmony_ci uint8_t *p = buf; 728c2ecf20Sopenharmony_ci int i; 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci for (i = 0; i < len; i++) 758c2ecf20Sopenharmony_ci if (*p++ != 0xff) 768c2ecf20Sopenharmony_ci return i; 778c2ecf20Sopenharmony_ci return -1; 788c2ecf20Sopenharmony_ci} 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci/** 818c2ecf20Sopenharmony_ci * get_master_node - get the last valid master node allowing for corruption. 828c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object 838c2ecf20Sopenharmony_ci * @lnum: LEB number 848c2ecf20Sopenharmony_ci * @pbuf: buffer containing the LEB read, is returned here 858c2ecf20Sopenharmony_ci * @mst: master node, if found, is returned here 868c2ecf20Sopenharmony_ci * @cor: corruption, if found, is returned here 878c2ecf20Sopenharmony_ci * 888c2ecf20Sopenharmony_ci * This function allocates a buffer, reads the LEB into it, and finds and 898c2ecf20Sopenharmony_ci * returns the last valid master node allowing for one area of corruption. 908c2ecf20Sopenharmony_ci * The corrupt area, if there is one, must be consistent with the assumption 918c2ecf20Sopenharmony_ci * that it is the result of an unclean unmount while the master node was being 928c2ecf20Sopenharmony_ci * written. Under those circumstances, it is valid to use the previously written 938c2ecf20Sopenharmony_ci * master node. 948c2ecf20Sopenharmony_ci * 958c2ecf20Sopenharmony_ci * This function returns %0 on success and a negative error code on failure. 968c2ecf20Sopenharmony_ci */ 978c2ecf20Sopenharmony_cistatic int get_master_node(const struct ubifs_info *c, int lnum, void **pbuf, 988c2ecf20Sopenharmony_ci struct ubifs_mst_node **mst, void **cor) 998c2ecf20Sopenharmony_ci{ 1008c2ecf20Sopenharmony_ci const int sz = c->mst_node_alsz; 1018c2ecf20Sopenharmony_ci int err, offs, len; 1028c2ecf20Sopenharmony_ci void *sbuf, *buf; 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_ci sbuf = vmalloc(c->leb_size); 1058c2ecf20Sopenharmony_ci if (!sbuf) 1068c2ecf20Sopenharmony_ci return -ENOMEM; 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci err = ubifs_leb_read(c, lnum, sbuf, 0, c->leb_size, 0); 1098c2ecf20Sopenharmony_ci if (err && err != -EBADMSG) 1108c2ecf20Sopenharmony_ci goto out_free; 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci /* Find the first position that is definitely not a node */ 1138c2ecf20Sopenharmony_ci offs = 0; 1148c2ecf20Sopenharmony_ci buf = sbuf; 1158c2ecf20Sopenharmony_ci len = c->leb_size; 1168c2ecf20Sopenharmony_ci while (offs + UBIFS_MST_NODE_SZ <= c->leb_size) { 1178c2ecf20Sopenharmony_ci struct ubifs_ch *ch = buf; 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci if (le32_to_cpu(ch->magic) != UBIFS_NODE_MAGIC) 1208c2ecf20Sopenharmony_ci break; 1218c2ecf20Sopenharmony_ci offs += sz; 1228c2ecf20Sopenharmony_ci buf += sz; 1238c2ecf20Sopenharmony_ci len -= sz; 1248c2ecf20Sopenharmony_ci } 1258c2ecf20Sopenharmony_ci /* See if there was a valid master node before that */ 1268c2ecf20Sopenharmony_ci if (offs) { 1278c2ecf20Sopenharmony_ci int ret; 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_ci offs -= sz; 1308c2ecf20Sopenharmony_ci buf -= sz; 1318c2ecf20Sopenharmony_ci len += sz; 1328c2ecf20Sopenharmony_ci ret = ubifs_scan_a_node(c, buf, len, lnum, offs, 1); 1338c2ecf20Sopenharmony_ci if (ret != SCANNED_A_NODE && offs) { 1348c2ecf20Sopenharmony_ci /* Could have been corruption so check one place back */ 1358c2ecf20Sopenharmony_ci offs -= sz; 1368c2ecf20Sopenharmony_ci buf -= sz; 1378c2ecf20Sopenharmony_ci len += sz; 1388c2ecf20Sopenharmony_ci ret = ubifs_scan_a_node(c, buf, len, lnum, offs, 1); 1398c2ecf20Sopenharmony_ci if (ret != SCANNED_A_NODE) 1408c2ecf20Sopenharmony_ci /* 1418c2ecf20Sopenharmony_ci * We accept only one area of corruption because 1428c2ecf20Sopenharmony_ci * we are assuming that it was caused while 1438c2ecf20Sopenharmony_ci * trying to write a master node. 1448c2ecf20Sopenharmony_ci */ 1458c2ecf20Sopenharmony_ci goto out_err; 1468c2ecf20Sopenharmony_ci } 1478c2ecf20Sopenharmony_ci if (ret == SCANNED_A_NODE) { 1488c2ecf20Sopenharmony_ci struct ubifs_ch *ch = buf; 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ci if (ch->node_type != UBIFS_MST_NODE) 1518c2ecf20Sopenharmony_ci goto out_err; 1528c2ecf20Sopenharmony_ci dbg_rcvry("found a master node at %d:%d", lnum, offs); 1538c2ecf20Sopenharmony_ci *mst = buf; 1548c2ecf20Sopenharmony_ci offs += sz; 1558c2ecf20Sopenharmony_ci buf += sz; 1568c2ecf20Sopenharmony_ci len -= sz; 1578c2ecf20Sopenharmony_ci } 1588c2ecf20Sopenharmony_ci } 1598c2ecf20Sopenharmony_ci /* Check for corruption */ 1608c2ecf20Sopenharmony_ci if (offs < c->leb_size) { 1618c2ecf20Sopenharmony_ci if (!is_empty(buf, min_t(int, len, sz))) { 1628c2ecf20Sopenharmony_ci *cor = buf; 1638c2ecf20Sopenharmony_ci dbg_rcvry("found corruption at %d:%d", lnum, offs); 1648c2ecf20Sopenharmony_ci } 1658c2ecf20Sopenharmony_ci offs += sz; 1668c2ecf20Sopenharmony_ci buf += sz; 1678c2ecf20Sopenharmony_ci len -= sz; 1688c2ecf20Sopenharmony_ci } 1698c2ecf20Sopenharmony_ci /* Check remaining empty space */ 1708c2ecf20Sopenharmony_ci if (offs < c->leb_size) 1718c2ecf20Sopenharmony_ci if (!is_empty(buf, len)) 1728c2ecf20Sopenharmony_ci goto out_err; 1738c2ecf20Sopenharmony_ci *pbuf = sbuf; 1748c2ecf20Sopenharmony_ci return 0; 1758c2ecf20Sopenharmony_ci 1768c2ecf20Sopenharmony_ciout_err: 1778c2ecf20Sopenharmony_ci err = -EINVAL; 1788c2ecf20Sopenharmony_ciout_free: 1798c2ecf20Sopenharmony_ci vfree(sbuf); 1808c2ecf20Sopenharmony_ci *mst = NULL; 1818c2ecf20Sopenharmony_ci *cor = NULL; 1828c2ecf20Sopenharmony_ci return err; 1838c2ecf20Sopenharmony_ci} 1848c2ecf20Sopenharmony_ci 1858c2ecf20Sopenharmony_ci/** 1868c2ecf20Sopenharmony_ci * write_rcvrd_mst_node - write recovered master node. 1878c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object 1888c2ecf20Sopenharmony_ci * @mst: master node 1898c2ecf20Sopenharmony_ci * 1908c2ecf20Sopenharmony_ci * This function returns %0 on success and a negative error code on failure. 1918c2ecf20Sopenharmony_ci */ 1928c2ecf20Sopenharmony_cistatic int write_rcvrd_mst_node(struct ubifs_info *c, 1938c2ecf20Sopenharmony_ci struct ubifs_mst_node *mst) 1948c2ecf20Sopenharmony_ci{ 1958c2ecf20Sopenharmony_ci int err = 0, lnum = UBIFS_MST_LNUM, sz = c->mst_node_alsz; 1968c2ecf20Sopenharmony_ci __le32 save_flags; 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_ci dbg_rcvry("recovery"); 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_ci save_flags = mst->flags; 2018c2ecf20Sopenharmony_ci mst->flags |= cpu_to_le32(UBIFS_MST_RCVRY); 2028c2ecf20Sopenharmony_ci 2038c2ecf20Sopenharmony_ci err = ubifs_prepare_node_hmac(c, mst, UBIFS_MST_NODE_SZ, 2048c2ecf20Sopenharmony_ci offsetof(struct ubifs_mst_node, hmac), 1); 2058c2ecf20Sopenharmony_ci if (err) 2068c2ecf20Sopenharmony_ci goto out; 2078c2ecf20Sopenharmony_ci err = ubifs_leb_change(c, lnum, mst, sz); 2088c2ecf20Sopenharmony_ci if (err) 2098c2ecf20Sopenharmony_ci goto out; 2108c2ecf20Sopenharmony_ci err = ubifs_leb_change(c, lnum + 1, mst, sz); 2118c2ecf20Sopenharmony_ci if (err) 2128c2ecf20Sopenharmony_ci goto out; 2138c2ecf20Sopenharmony_ciout: 2148c2ecf20Sopenharmony_ci mst->flags = save_flags; 2158c2ecf20Sopenharmony_ci return err; 2168c2ecf20Sopenharmony_ci} 2178c2ecf20Sopenharmony_ci 2188c2ecf20Sopenharmony_ci/** 2198c2ecf20Sopenharmony_ci * ubifs_recover_master_node - recover the master node. 2208c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object 2218c2ecf20Sopenharmony_ci * 2228c2ecf20Sopenharmony_ci * This function recovers the master node from corruption that may occur due to 2238c2ecf20Sopenharmony_ci * an unclean unmount. 2248c2ecf20Sopenharmony_ci * 2258c2ecf20Sopenharmony_ci * This function returns %0 on success and a negative error code on failure. 2268c2ecf20Sopenharmony_ci */ 2278c2ecf20Sopenharmony_ciint ubifs_recover_master_node(struct ubifs_info *c) 2288c2ecf20Sopenharmony_ci{ 2298c2ecf20Sopenharmony_ci void *buf1 = NULL, *buf2 = NULL, *cor1 = NULL, *cor2 = NULL; 2308c2ecf20Sopenharmony_ci struct ubifs_mst_node *mst1 = NULL, *mst2 = NULL, *mst; 2318c2ecf20Sopenharmony_ci const int sz = c->mst_node_alsz; 2328c2ecf20Sopenharmony_ci int err, offs1, offs2; 2338c2ecf20Sopenharmony_ci 2348c2ecf20Sopenharmony_ci dbg_rcvry("recovery"); 2358c2ecf20Sopenharmony_ci 2368c2ecf20Sopenharmony_ci err = get_master_node(c, UBIFS_MST_LNUM, &buf1, &mst1, &cor1); 2378c2ecf20Sopenharmony_ci if (err) 2388c2ecf20Sopenharmony_ci goto out_free; 2398c2ecf20Sopenharmony_ci 2408c2ecf20Sopenharmony_ci err = get_master_node(c, UBIFS_MST_LNUM + 1, &buf2, &mst2, &cor2); 2418c2ecf20Sopenharmony_ci if (err) 2428c2ecf20Sopenharmony_ci goto out_free; 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_ci if (mst1) { 2458c2ecf20Sopenharmony_ci offs1 = (void *)mst1 - buf1; 2468c2ecf20Sopenharmony_ci if ((le32_to_cpu(mst1->flags) & UBIFS_MST_RCVRY) && 2478c2ecf20Sopenharmony_ci (offs1 == 0 && !cor1)) { 2488c2ecf20Sopenharmony_ci /* 2498c2ecf20Sopenharmony_ci * mst1 was written by recovery at offset 0 with no 2508c2ecf20Sopenharmony_ci * corruption. 2518c2ecf20Sopenharmony_ci */ 2528c2ecf20Sopenharmony_ci dbg_rcvry("recovery recovery"); 2538c2ecf20Sopenharmony_ci mst = mst1; 2548c2ecf20Sopenharmony_ci } else if (mst2) { 2558c2ecf20Sopenharmony_ci offs2 = (void *)mst2 - buf2; 2568c2ecf20Sopenharmony_ci if (offs1 == offs2) { 2578c2ecf20Sopenharmony_ci /* Same offset, so must be the same */ 2588c2ecf20Sopenharmony_ci if (ubifs_compare_master_node(c, mst1, mst2)) 2598c2ecf20Sopenharmony_ci goto out_err; 2608c2ecf20Sopenharmony_ci mst = mst1; 2618c2ecf20Sopenharmony_ci } else if (offs2 + sz == offs1) { 2628c2ecf20Sopenharmony_ci /* 1st LEB was written, 2nd was not */ 2638c2ecf20Sopenharmony_ci if (cor1) 2648c2ecf20Sopenharmony_ci goto out_err; 2658c2ecf20Sopenharmony_ci mst = mst1; 2668c2ecf20Sopenharmony_ci } else if (offs1 == 0 && 2678c2ecf20Sopenharmony_ci c->leb_size - offs2 - sz < sz) { 2688c2ecf20Sopenharmony_ci /* 1st LEB was unmapped and written, 2nd not */ 2698c2ecf20Sopenharmony_ci if (cor1) 2708c2ecf20Sopenharmony_ci goto out_err; 2718c2ecf20Sopenharmony_ci mst = mst1; 2728c2ecf20Sopenharmony_ci } else 2738c2ecf20Sopenharmony_ci goto out_err; 2748c2ecf20Sopenharmony_ci } else { 2758c2ecf20Sopenharmony_ci /* 2768c2ecf20Sopenharmony_ci * 2nd LEB was unmapped and about to be written, so 2778c2ecf20Sopenharmony_ci * there must be only one master node in the first LEB 2788c2ecf20Sopenharmony_ci * and no corruption. 2798c2ecf20Sopenharmony_ci */ 2808c2ecf20Sopenharmony_ci if (offs1 != 0 || cor1) 2818c2ecf20Sopenharmony_ci goto out_err; 2828c2ecf20Sopenharmony_ci mst = mst1; 2838c2ecf20Sopenharmony_ci } 2848c2ecf20Sopenharmony_ci } else { 2858c2ecf20Sopenharmony_ci if (!mst2) 2868c2ecf20Sopenharmony_ci goto out_err; 2878c2ecf20Sopenharmony_ci /* 2888c2ecf20Sopenharmony_ci * 1st LEB was unmapped and about to be written, so there must 2898c2ecf20Sopenharmony_ci * be no room left in 2nd LEB. 2908c2ecf20Sopenharmony_ci */ 2918c2ecf20Sopenharmony_ci offs2 = (void *)mst2 - buf2; 2928c2ecf20Sopenharmony_ci if (offs2 + sz + sz <= c->leb_size) 2938c2ecf20Sopenharmony_ci goto out_err; 2948c2ecf20Sopenharmony_ci mst = mst2; 2958c2ecf20Sopenharmony_ci } 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_ci ubifs_msg(c, "recovered master node from LEB %d", 2988c2ecf20Sopenharmony_ci (mst == mst1 ? UBIFS_MST_LNUM : UBIFS_MST_LNUM + 1)); 2998c2ecf20Sopenharmony_ci 3008c2ecf20Sopenharmony_ci memcpy(c->mst_node, mst, UBIFS_MST_NODE_SZ); 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_ci if (c->ro_mount) { 3038c2ecf20Sopenharmony_ci /* Read-only mode. Keep a copy for switching to rw mode */ 3048c2ecf20Sopenharmony_ci c->rcvrd_mst_node = kmalloc(sz, GFP_KERNEL); 3058c2ecf20Sopenharmony_ci if (!c->rcvrd_mst_node) { 3068c2ecf20Sopenharmony_ci err = -ENOMEM; 3078c2ecf20Sopenharmony_ci goto out_free; 3088c2ecf20Sopenharmony_ci } 3098c2ecf20Sopenharmony_ci memcpy(c->rcvrd_mst_node, c->mst_node, UBIFS_MST_NODE_SZ); 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_ci /* 3128c2ecf20Sopenharmony_ci * We had to recover the master node, which means there was an 3138c2ecf20Sopenharmony_ci * unclean reboot. However, it is possible that the master node 3148c2ecf20Sopenharmony_ci * is clean at this point, i.e., %UBIFS_MST_DIRTY is not set. 3158c2ecf20Sopenharmony_ci * E.g., consider the following chain of events: 3168c2ecf20Sopenharmony_ci * 3178c2ecf20Sopenharmony_ci * 1. UBIFS was cleanly unmounted, so the master node is clean 3188c2ecf20Sopenharmony_ci * 2. UBIFS is being mounted R/W and starts changing the master 3198c2ecf20Sopenharmony_ci * node in the first (%UBIFS_MST_LNUM). A power cut happens, 3208c2ecf20Sopenharmony_ci * so this LEB ends up with some amount of garbage at the 3218c2ecf20Sopenharmony_ci * end. 3228c2ecf20Sopenharmony_ci * 3. UBIFS is being mounted R/O. We reach this place and 3238c2ecf20Sopenharmony_ci * recover the master node from the second LEB 3248c2ecf20Sopenharmony_ci * (%UBIFS_MST_LNUM + 1). But we cannot update the media 3258c2ecf20Sopenharmony_ci * because we are being mounted R/O. We have to defer the 3268c2ecf20Sopenharmony_ci * operation. 3278c2ecf20Sopenharmony_ci * 4. However, this master node (@c->mst_node) is marked as 3288c2ecf20Sopenharmony_ci * clean (since the step 1). And if we just return, the 3298c2ecf20Sopenharmony_ci * mount code will be confused and won't recover the master 3308c2ecf20Sopenharmony_ci * node when it is re-mounter R/W later. 3318c2ecf20Sopenharmony_ci * 3328c2ecf20Sopenharmony_ci * Thus, to force the recovery by marking the master node as 3338c2ecf20Sopenharmony_ci * dirty. 3348c2ecf20Sopenharmony_ci */ 3358c2ecf20Sopenharmony_ci c->mst_node->flags |= cpu_to_le32(UBIFS_MST_DIRTY); 3368c2ecf20Sopenharmony_ci } else { 3378c2ecf20Sopenharmony_ci /* Write the recovered master node */ 3388c2ecf20Sopenharmony_ci c->max_sqnum = le64_to_cpu(mst->ch.sqnum) - 1; 3398c2ecf20Sopenharmony_ci err = write_rcvrd_mst_node(c, c->mst_node); 3408c2ecf20Sopenharmony_ci if (err) 3418c2ecf20Sopenharmony_ci goto out_free; 3428c2ecf20Sopenharmony_ci } 3438c2ecf20Sopenharmony_ci 3448c2ecf20Sopenharmony_ci vfree(buf2); 3458c2ecf20Sopenharmony_ci vfree(buf1); 3468c2ecf20Sopenharmony_ci 3478c2ecf20Sopenharmony_ci return 0; 3488c2ecf20Sopenharmony_ci 3498c2ecf20Sopenharmony_ciout_err: 3508c2ecf20Sopenharmony_ci err = -EINVAL; 3518c2ecf20Sopenharmony_ciout_free: 3528c2ecf20Sopenharmony_ci ubifs_err(c, "failed to recover master node"); 3538c2ecf20Sopenharmony_ci if (mst1) { 3548c2ecf20Sopenharmony_ci ubifs_err(c, "dumping first master node"); 3558c2ecf20Sopenharmony_ci ubifs_dump_node(c, mst1, c->leb_size - ((void *)mst1 - buf1)); 3568c2ecf20Sopenharmony_ci } 3578c2ecf20Sopenharmony_ci if (mst2) { 3588c2ecf20Sopenharmony_ci ubifs_err(c, "dumping second master node"); 3598c2ecf20Sopenharmony_ci ubifs_dump_node(c, mst2, c->leb_size - ((void *)mst2 - buf2)); 3608c2ecf20Sopenharmony_ci } 3618c2ecf20Sopenharmony_ci vfree(buf2); 3628c2ecf20Sopenharmony_ci vfree(buf1); 3638c2ecf20Sopenharmony_ci return err; 3648c2ecf20Sopenharmony_ci} 3658c2ecf20Sopenharmony_ci 3668c2ecf20Sopenharmony_ci/** 3678c2ecf20Sopenharmony_ci * ubifs_write_rcvrd_mst_node - write the recovered master node. 3688c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object 3698c2ecf20Sopenharmony_ci * 3708c2ecf20Sopenharmony_ci * This function writes the master node that was recovered during mounting in 3718c2ecf20Sopenharmony_ci * read-only mode and must now be written because we are remounting rw. 3728c2ecf20Sopenharmony_ci * 3738c2ecf20Sopenharmony_ci * This function returns %0 on success and a negative error code on failure. 3748c2ecf20Sopenharmony_ci */ 3758c2ecf20Sopenharmony_ciint ubifs_write_rcvrd_mst_node(struct ubifs_info *c) 3768c2ecf20Sopenharmony_ci{ 3778c2ecf20Sopenharmony_ci int err; 3788c2ecf20Sopenharmony_ci 3798c2ecf20Sopenharmony_ci if (!c->rcvrd_mst_node) 3808c2ecf20Sopenharmony_ci return 0; 3818c2ecf20Sopenharmony_ci c->rcvrd_mst_node->flags |= cpu_to_le32(UBIFS_MST_DIRTY); 3828c2ecf20Sopenharmony_ci c->mst_node->flags |= cpu_to_le32(UBIFS_MST_DIRTY); 3838c2ecf20Sopenharmony_ci err = write_rcvrd_mst_node(c, c->rcvrd_mst_node); 3848c2ecf20Sopenharmony_ci if (err) 3858c2ecf20Sopenharmony_ci return err; 3868c2ecf20Sopenharmony_ci kfree(c->rcvrd_mst_node); 3878c2ecf20Sopenharmony_ci c->rcvrd_mst_node = NULL; 3888c2ecf20Sopenharmony_ci return 0; 3898c2ecf20Sopenharmony_ci} 3908c2ecf20Sopenharmony_ci 3918c2ecf20Sopenharmony_ci/** 3928c2ecf20Sopenharmony_ci * is_last_write - determine if an offset was in the last write to a LEB. 3938c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object 3948c2ecf20Sopenharmony_ci * @buf: buffer to check 3958c2ecf20Sopenharmony_ci * @offs: offset to check 3968c2ecf20Sopenharmony_ci * 3978c2ecf20Sopenharmony_ci * This function returns %1 if @offs was in the last write to the LEB whose data 3988c2ecf20Sopenharmony_ci * is in @buf, otherwise %0 is returned. The determination is made by checking 3998c2ecf20Sopenharmony_ci * for subsequent empty space starting from the next @c->max_write_size 4008c2ecf20Sopenharmony_ci * boundary. 4018c2ecf20Sopenharmony_ci */ 4028c2ecf20Sopenharmony_cistatic int is_last_write(const struct ubifs_info *c, void *buf, int offs) 4038c2ecf20Sopenharmony_ci{ 4048c2ecf20Sopenharmony_ci int empty_offs, check_len; 4058c2ecf20Sopenharmony_ci uint8_t *p; 4068c2ecf20Sopenharmony_ci 4078c2ecf20Sopenharmony_ci /* 4088c2ecf20Sopenharmony_ci * Round up to the next @c->max_write_size boundary i.e. @offs is in 4098c2ecf20Sopenharmony_ci * the last wbuf written. After that should be empty space. 4108c2ecf20Sopenharmony_ci */ 4118c2ecf20Sopenharmony_ci empty_offs = ALIGN(offs + 1, c->max_write_size); 4128c2ecf20Sopenharmony_ci check_len = c->leb_size - empty_offs; 4138c2ecf20Sopenharmony_ci p = buf + empty_offs - offs; 4148c2ecf20Sopenharmony_ci return is_empty(p, check_len); 4158c2ecf20Sopenharmony_ci} 4168c2ecf20Sopenharmony_ci 4178c2ecf20Sopenharmony_ci/** 4188c2ecf20Sopenharmony_ci * clean_buf - clean the data from an LEB sitting in a buffer. 4198c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object 4208c2ecf20Sopenharmony_ci * @buf: buffer to clean 4218c2ecf20Sopenharmony_ci * @lnum: LEB number to clean 4228c2ecf20Sopenharmony_ci * @offs: offset from which to clean 4238c2ecf20Sopenharmony_ci * @len: length of buffer 4248c2ecf20Sopenharmony_ci * 4258c2ecf20Sopenharmony_ci * This function pads up to the next min_io_size boundary (if there is one) and 4268c2ecf20Sopenharmony_ci * sets empty space to all 0xff. @buf, @offs and @len are updated to the next 4278c2ecf20Sopenharmony_ci * @c->min_io_size boundary. 4288c2ecf20Sopenharmony_ci */ 4298c2ecf20Sopenharmony_cistatic void clean_buf(const struct ubifs_info *c, void **buf, int lnum, 4308c2ecf20Sopenharmony_ci int *offs, int *len) 4318c2ecf20Sopenharmony_ci{ 4328c2ecf20Sopenharmony_ci int empty_offs, pad_len; 4338c2ecf20Sopenharmony_ci 4348c2ecf20Sopenharmony_ci dbg_rcvry("cleaning corruption at %d:%d", lnum, *offs); 4358c2ecf20Sopenharmony_ci 4368c2ecf20Sopenharmony_ci ubifs_assert(c, !(*offs & 7)); 4378c2ecf20Sopenharmony_ci empty_offs = ALIGN(*offs, c->min_io_size); 4388c2ecf20Sopenharmony_ci pad_len = empty_offs - *offs; 4398c2ecf20Sopenharmony_ci ubifs_pad(c, *buf, pad_len); 4408c2ecf20Sopenharmony_ci *offs += pad_len; 4418c2ecf20Sopenharmony_ci *buf += pad_len; 4428c2ecf20Sopenharmony_ci *len -= pad_len; 4438c2ecf20Sopenharmony_ci memset(*buf, 0xff, c->leb_size - empty_offs); 4448c2ecf20Sopenharmony_ci} 4458c2ecf20Sopenharmony_ci 4468c2ecf20Sopenharmony_ci/** 4478c2ecf20Sopenharmony_ci * no_more_nodes - determine if there are no more nodes in a buffer. 4488c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object 4498c2ecf20Sopenharmony_ci * @buf: buffer to check 4508c2ecf20Sopenharmony_ci * @len: length of buffer 4518c2ecf20Sopenharmony_ci * @lnum: LEB number of the LEB from which @buf was read 4528c2ecf20Sopenharmony_ci * @offs: offset from which @buf was read 4538c2ecf20Sopenharmony_ci * 4548c2ecf20Sopenharmony_ci * This function ensures that the corrupted node at @offs is the last thing 4558c2ecf20Sopenharmony_ci * written to a LEB. This function returns %1 if more data is not found and 4568c2ecf20Sopenharmony_ci * %0 if more data is found. 4578c2ecf20Sopenharmony_ci */ 4588c2ecf20Sopenharmony_cistatic int no_more_nodes(const struct ubifs_info *c, void *buf, int len, 4598c2ecf20Sopenharmony_ci int lnum, int offs) 4608c2ecf20Sopenharmony_ci{ 4618c2ecf20Sopenharmony_ci struct ubifs_ch *ch = buf; 4628c2ecf20Sopenharmony_ci int skip, dlen = le32_to_cpu(ch->len); 4638c2ecf20Sopenharmony_ci 4648c2ecf20Sopenharmony_ci /* Check for empty space after the corrupt node's common header */ 4658c2ecf20Sopenharmony_ci skip = ALIGN(offs + UBIFS_CH_SZ, c->max_write_size) - offs; 4668c2ecf20Sopenharmony_ci if (is_empty(buf + skip, len - skip)) 4678c2ecf20Sopenharmony_ci return 1; 4688c2ecf20Sopenharmony_ci /* 4698c2ecf20Sopenharmony_ci * The area after the common header size is not empty, so the common 4708c2ecf20Sopenharmony_ci * header must be intact. Check it. 4718c2ecf20Sopenharmony_ci */ 4728c2ecf20Sopenharmony_ci if (ubifs_check_node(c, buf, len, lnum, offs, 1, 0) != -EUCLEAN) { 4738c2ecf20Sopenharmony_ci dbg_rcvry("unexpected bad common header at %d:%d", lnum, offs); 4748c2ecf20Sopenharmony_ci return 0; 4758c2ecf20Sopenharmony_ci } 4768c2ecf20Sopenharmony_ci /* Now we know the corrupt node's length we can skip over it */ 4778c2ecf20Sopenharmony_ci skip = ALIGN(offs + dlen, c->max_write_size) - offs; 4788c2ecf20Sopenharmony_ci /* After which there should be empty space */ 4798c2ecf20Sopenharmony_ci if (is_empty(buf + skip, len - skip)) 4808c2ecf20Sopenharmony_ci return 1; 4818c2ecf20Sopenharmony_ci dbg_rcvry("unexpected data at %d:%d", lnum, offs + skip); 4828c2ecf20Sopenharmony_ci return 0; 4838c2ecf20Sopenharmony_ci} 4848c2ecf20Sopenharmony_ci 4858c2ecf20Sopenharmony_ci/** 4868c2ecf20Sopenharmony_ci * fix_unclean_leb - fix an unclean LEB. 4878c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object 4888c2ecf20Sopenharmony_ci * @sleb: scanned LEB information 4898c2ecf20Sopenharmony_ci * @start: offset where scan started 4908c2ecf20Sopenharmony_ci */ 4918c2ecf20Sopenharmony_cistatic int fix_unclean_leb(struct ubifs_info *c, struct ubifs_scan_leb *sleb, 4928c2ecf20Sopenharmony_ci int start) 4938c2ecf20Sopenharmony_ci{ 4948c2ecf20Sopenharmony_ci int lnum = sleb->lnum, endpt = start; 4958c2ecf20Sopenharmony_ci 4968c2ecf20Sopenharmony_ci /* Get the end offset of the last node we are keeping */ 4978c2ecf20Sopenharmony_ci if (!list_empty(&sleb->nodes)) { 4988c2ecf20Sopenharmony_ci struct ubifs_scan_node *snod; 4998c2ecf20Sopenharmony_ci 5008c2ecf20Sopenharmony_ci snod = list_entry(sleb->nodes.prev, 5018c2ecf20Sopenharmony_ci struct ubifs_scan_node, list); 5028c2ecf20Sopenharmony_ci endpt = snod->offs + snod->len; 5038c2ecf20Sopenharmony_ci } 5048c2ecf20Sopenharmony_ci 5058c2ecf20Sopenharmony_ci if (c->ro_mount && !c->remounting_rw) { 5068c2ecf20Sopenharmony_ci /* Add to recovery list */ 5078c2ecf20Sopenharmony_ci struct ubifs_unclean_leb *ucleb; 5088c2ecf20Sopenharmony_ci 5098c2ecf20Sopenharmony_ci dbg_rcvry("need to fix LEB %d start %d endpt %d", 5108c2ecf20Sopenharmony_ci lnum, start, sleb->endpt); 5118c2ecf20Sopenharmony_ci ucleb = kzalloc(sizeof(struct ubifs_unclean_leb), GFP_NOFS); 5128c2ecf20Sopenharmony_ci if (!ucleb) 5138c2ecf20Sopenharmony_ci return -ENOMEM; 5148c2ecf20Sopenharmony_ci ucleb->lnum = lnum; 5158c2ecf20Sopenharmony_ci ucleb->endpt = endpt; 5168c2ecf20Sopenharmony_ci list_add_tail(&ucleb->list, &c->unclean_leb_list); 5178c2ecf20Sopenharmony_ci } else { 5188c2ecf20Sopenharmony_ci /* Write the fixed LEB back to flash */ 5198c2ecf20Sopenharmony_ci int err; 5208c2ecf20Sopenharmony_ci 5218c2ecf20Sopenharmony_ci dbg_rcvry("fixing LEB %d start %d endpt %d", 5228c2ecf20Sopenharmony_ci lnum, start, sleb->endpt); 5238c2ecf20Sopenharmony_ci if (endpt == 0) { 5248c2ecf20Sopenharmony_ci err = ubifs_leb_unmap(c, lnum); 5258c2ecf20Sopenharmony_ci if (err) 5268c2ecf20Sopenharmony_ci return err; 5278c2ecf20Sopenharmony_ci } else { 5288c2ecf20Sopenharmony_ci int len = ALIGN(endpt, c->min_io_size); 5298c2ecf20Sopenharmony_ci 5308c2ecf20Sopenharmony_ci if (start) { 5318c2ecf20Sopenharmony_ci err = ubifs_leb_read(c, lnum, sleb->buf, 0, 5328c2ecf20Sopenharmony_ci start, 1); 5338c2ecf20Sopenharmony_ci if (err) 5348c2ecf20Sopenharmony_ci return err; 5358c2ecf20Sopenharmony_ci } 5368c2ecf20Sopenharmony_ci /* Pad to min_io_size */ 5378c2ecf20Sopenharmony_ci if (len > endpt) { 5388c2ecf20Sopenharmony_ci int pad_len = len - ALIGN(endpt, 8); 5398c2ecf20Sopenharmony_ci 5408c2ecf20Sopenharmony_ci if (pad_len > 0) { 5418c2ecf20Sopenharmony_ci void *buf = sleb->buf + len - pad_len; 5428c2ecf20Sopenharmony_ci 5438c2ecf20Sopenharmony_ci ubifs_pad(c, buf, pad_len); 5448c2ecf20Sopenharmony_ci } 5458c2ecf20Sopenharmony_ci } 5468c2ecf20Sopenharmony_ci err = ubifs_leb_change(c, lnum, sleb->buf, len); 5478c2ecf20Sopenharmony_ci if (err) 5488c2ecf20Sopenharmony_ci return err; 5498c2ecf20Sopenharmony_ci } 5508c2ecf20Sopenharmony_ci } 5518c2ecf20Sopenharmony_ci return 0; 5528c2ecf20Sopenharmony_ci} 5538c2ecf20Sopenharmony_ci 5548c2ecf20Sopenharmony_ci/** 5558c2ecf20Sopenharmony_ci * drop_last_group - drop the last group of nodes. 5568c2ecf20Sopenharmony_ci * @sleb: scanned LEB information 5578c2ecf20Sopenharmony_ci * @offs: offset of dropped nodes is returned here 5588c2ecf20Sopenharmony_ci * 5598c2ecf20Sopenharmony_ci * This is a helper function for 'ubifs_recover_leb()' which drops the last 5608c2ecf20Sopenharmony_ci * group of nodes of the scanned LEB. 5618c2ecf20Sopenharmony_ci */ 5628c2ecf20Sopenharmony_cistatic void drop_last_group(struct ubifs_scan_leb *sleb, int *offs) 5638c2ecf20Sopenharmony_ci{ 5648c2ecf20Sopenharmony_ci while (!list_empty(&sleb->nodes)) { 5658c2ecf20Sopenharmony_ci struct ubifs_scan_node *snod; 5668c2ecf20Sopenharmony_ci struct ubifs_ch *ch; 5678c2ecf20Sopenharmony_ci 5688c2ecf20Sopenharmony_ci snod = list_entry(sleb->nodes.prev, struct ubifs_scan_node, 5698c2ecf20Sopenharmony_ci list); 5708c2ecf20Sopenharmony_ci ch = snod->node; 5718c2ecf20Sopenharmony_ci if (ch->group_type != UBIFS_IN_NODE_GROUP) 5728c2ecf20Sopenharmony_ci break; 5738c2ecf20Sopenharmony_ci 5748c2ecf20Sopenharmony_ci dbg_rcvry("dropping grouped node at %d:%d", 5758c2ecf20Sopenharmony_ci sleb->lnum, snod->offs); 5768c2ecf20Sopenharmony_ci *offs = snod->offs; 5778c2ecf20Sopenharmony_ci list_del(&snod->list); 5788c2ecf20Sopenharmony_ci kfree(snod); 5798c2ecf20Sopenharmony_ci sleb->nodes_cnt -= 1; 5808c2ecf20Sopenharmony_ci } 5818c2ecf20Sopenharmony_ci} 5828c2ecf20Sopenharmony_ci 5838c2ecf20Sopenharmony_ci/** 5848c2ecf20Sopenharmony_ci * drop_last_node - drop the last node. 5858c2ecf20Sopenharmony_ci * @sleb: scanned LEB information 5868c2ecf20Sopenharmony_ci * @offs: offset of dropped nodes is returned here 5878c2ecf20Sopenharmony_ci * 5888c2ecf20Sopenharmony_ci * This is a helper function for 'ubifs_recover_leb()' which drops the last 5898c2ecf20Sopenharmony_ci * node of the scanned LEB. 5908c2ecf20Sopenharmony_ci */ 5918c2ecf20Sopenharmony_cistatic void drop_last_node(struct ubifs_scan_leb *sleb, int *offs) 5928c2ecf20Sopenharmony_ci{ 5938c2ecf20Sopenharmony_ci struct ubifs_scan_node *snod; 5948c2ecf20Sopenharmony_ci 5958c2ecf20Sopenharmony_ci if (!list_empty(&sleb->nodes)) { 5968c2ecf20Sopenharmony_ci snod = list_entry(sleb->nodes.prev, struct ubifs_scan_node, 5978c2ecf20Sopenharmony_ci list); 5988c2ecf20Sopenharmony_ci 5998c2ecf20Sopenharmony_ci dbg_rcvry("dropping last node at %d:%d", 6008c2ecf20Sopenharmony_ci sleb->lnum, snod->offs); 6018c2ecf20Sopenharmony_ci *offs = snod->offs; 6028c2ecf20Sopenharmony_ci list_del(&snod->list); 6038c2ecf20Sopenharmony_ci kfree(snod); 6048c2ecf20Sopenharmony_ci sleb->nodes_cnt -= 1; 6058c2ecf20Sopenharmony_ci } 6068c2ecf20Sopenharmony_ci} 6078c2ecf20Sopenharmony_ci 6088c2ecf20Sopenharmony_ci/** 6098c2ecf20Sopenharmony_ci * ubifs_recover_leb - scan and recover a LEB. 6108c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object 6118c2ecf20Sopenharmony_ci * @lnum: LEB number 6128c2ecf20Sopenharmony_ci * @offs: offset 6138c2ecf20Sopenharmony_ci * @sbuf: LEB-sized buffer to use 6148c2ecf20Sopenharmony_ci * @jhead: journal head number this LEB belongs to (%-1 if the LEB does not 6158c2ecf20Sopenharmony_ci * belong to any journal head) 6168c2ecf20Sopenharmony_ci * 6178c2ecf20Sopenharmony_ci * This function does a scan of a LEB, but caters for errors that might have 6188c2ecf20Sopenharmony_ci * been caused by the unclean unmount from which we are attempting to recover. 6198c2ecf20Sopenharmony_ci * Returns the scanned information on success and a negative error code on 6208c2ecf20Sopenharmony_ci * failure. 6218c2ecf20Sopenharmony_ci */ 6228c2ecf20Sopenharmony_cistruct ubifs_scan_leb *ubifs_recover_leb(struct ubifs_info *c, int lnum, 6238c2ecf20Sopenharmony_ci int offs, void *sbuf, int jhead) 6248c2ecf20Sopenharmony_ci{ 6258c2ecf20Sopenharmony_ci int ret = 0, err, len = c->leb_size - offs, start = offs, min_io_unit; 6268c2ecf20Sopenharmony_ci int grouped = jhead == -1 ? 0 : c->jheads[jhead].grouped; 6278c2ecf20Sopenharmony_ci struct ubifs_scan_leb *sleb; 6288c2ecf20Sopenharmony_ci void *buf = sbuf + offs; 6298c2ecf20Sopenharmony_ci 6308c2ecf20Sopenharmony_ci dbg_rcvry("%d:%d, jhead %d, grouped %d", lnum, offs, jhead, grouped); 6318c2ecf20Sopenharmony_ci 6328c2ecf20Sopenharmony_ci sleb = ubifs_start_scan(c, lnum, offs, sbuf); 6338c2ecf20Sopenharmony_ci if (IS_ERR(sleb)) 6348c2ecf20Sopenharmony_ci return sleb; 6358c2ecf20Sopenharmony_ci 6368c2ecf20Sopenharmony_ci ubifs_assert(c, len >= 8); 6378c2ecf20Sopenharmony_ci while (len >= 8) { 6388c2ecf20Sopenharmony_ci dbg_scan("look at LEB %d:%d (%d bytes left)", 6398c2ecf20Sopenharmony_ci lnum, offs, len); 6408c2ecf20Sopenharmony_ci 6418c2ecf20Sopenharmony_ci cond_resched(); 6428c2ecf20Sopenharmony_ci 6438c2ecf20Sopenharmony_ci /* 6448c2ecf20Sopenharmony_ci * Scan quietly until there is an error from which we cannot 6458c2ecf20Sopenharmony_ci * recover 6468c2ecf20Sopenharmony_ci */ 6478c2ecf20Sopenharmony_ci ret = ubifs_scan_a_node(c, buf, len, lnum, offs, 1); 6488c2ecf20Sopenharmony_ci if (ret == SCANNED_A_NODE) { 6498c2ecf20Sopenharmony_ci /* A valid node, and not a padding node */ 6508c2ecf20Sopenharmony_ci struct ubifs_ch *ch = buf; 6518c2ecf20Sopenharmony_ci int node_len; 6528c2ecf20Sopenharmony_ci 6538c2ecf20Sopenharmony_ci err = ubifs_add_snod(c, sleb, buf, offs); 6548c2ecf20Sopenharmony_ci if (err) 6558c2ecf20Sopenharmony_ci goto error; 6568c2ecf20Sopenharmony_ci node_len = ALIGN(le32_to_cpu(ch->len), 8); 6578c2ecf20Sopenharmony_ci offs += node_len; 6588c2ecf20Sopenharmony_ci buf += node_len; 6598c2ecf20Sopenharmony_ci len -= node_len; 6608c2ecf20Sopenharmony_ci } else if (ret > 0) { 6618c2ecf20Sopenharmony_ci /* Padding bytes or a valid padding node */ 6628c2ecf20Sopenharmony_ci offs += ret; 6638c2ecf20Sopenharmony_ci buf += ret; 6648c2ecf20Sopenharmony_ci len -= ret; 6658c2ecf20Sopenharmony_ci } else if (ret == SCANNED_EMPTY_SPACE || 6668c2ecf20Sopenharmony_ci ret == SCANNED_GARBAGE || 6678c2ecf20Sopenharmony_ci ret == SCANNED_A_BAD_PAD_NODE || 6688c2ecf20Sopenharmony_ci ret == SCANNED_A_CORRUPT_NODE) { 6698c2ecf20Sopenharmony_ci dbg_rcvry("found corruption (%d) at %d:%d", 6708c2ecf20Sopenharmony_ci ret, lnum, offs); 6718c2ecf20Sopenharmony_ci break; 6728c2ecf20Sopenharmony_ci } else { 6738c2ecf20Sopenharmony_ci ubifs_err(c, "unexpected return value %d", ret); 6748c2ecf20Sopenharmony_ci err = -EINVAL; 6758c2ecf20Sopenharmony_ci goto error; 6768c2ecf20Sopenharmony_ci } 6778c2ecf20Sopenharmony_ci } 6788c2ecf20Sopenharmony_ci 6798c2ecf20Sopenharmony_ci if (ret == SCANNED_GARBAGE || ret == SCANNED_A_BAD_PAD_NODE) { 6808c2ecf20Sopenharmony_ci if (!is_last_write(c, buf, offs)) 6818c2ecf20Sopenharmony_ci goto corrupted_rescan; 6828c2ecf20Sopenharmony_ci } else if (ret == SCANNED_A_CORRUPT_NODE) { 6838c2ecf20Sopenharmony_ci if (!no_more_nodes(c, buf, len, lnum, offs)) 6848c2ecf20Sopenharmony_ci goto corrupted_rescan; 6858c2ecf20Sopenharmony_ci } else if (!is_empty(buf, len)) { 6868c2ecf20Sopenharmony_ci if (!is_last_write(c, buf, offs)) { 6878c2ecf20Sopenharmony_ci int corruption = first_non_ff(buf, len); 6888c2ecf20Sopenharmony_ci 6898c2ecf20Sopenharmony_ci /* 6908c2ecf20Sopenharmony_ci * See header comment for this file for more 6918c2ecf20Sopenharmony_ci * explanations about the reasons we have this check. 6928c2ecf20Sopenharmony_ci */ 6938c2ecf20Sopenharmony_ci ubifs_err(c, "corrupt empty space LEB %d:%d, corruption starts at %d", 6948c2ecf20Sopenharmony_ci lnum, offs, corruption); 6958c2ecf20Sopenharmony_ci /* Make sure we dump interesting non-0xFF data */ 6968c2ecf20Sopenharmony_ci offs += corruption; 6978c2ecf20Sopenharmony_ci buf += corruption; 6988c2ecf20Sopenharmony_ci goto corrupted; 6998c2ecf20Sopenharmony_ci } 7008c2ecf20Sopenharmony_ci } 7018c2ecf20Sopenharmony_ci 7028c2ecf20Sopenharmony_ci min_io_unit = round_down(offs, c->min_io_size); 7038c2ecf20Sopenharmony_ci if (grouped) 7048c2ecf20Sopenharmony_ci /* 7058c2ecf20Sopenharmony_ci * If nodes are grouped, always drop the incomplete group at 7068c2ecf20Sopenharmony_ci * the end. 7078c2ecf20Sopenharmony_ci */ 7088c2ecf20Sopenharmony_ci drop_last_group(sleb, &offs); 7098c2ecf20Sopenharmony_ci 7108c2ecf20Sopenharmony_ci if (jhead == GCHD) { 7118c2ecf20Sopenharmony_ci /* 7128c2ecf20Sopenharmony_ci * If this LEB belongs to the GC head then while we are in the 7138c2ecf20Sopenharmony_ci * middle of the same min. I/O unit keep dropping nodes. So 7148c2ecf20Sopenharmony_ci * basically, what we want is to make sure that the last min. 7158c2ecf20Sopenharmony_ci * I/O unit where we saw the corruption is dropped completely 7168c2ecf20Sopenharmony_ci * with all the uncorrupted nodes which may possibly sit there. 7178c2ecf20Sopenharmony_ci * 7188c2ecf20Sopenharmony_ci * In other words, let's name the min. I/O unit where the 7198c2ecf20Sopenharmony_ci * corruption starts B, and the previous min. I/O unit A. The 7208c2ecf20Sopenharmony_ci * below code tries to deal with a situation when half of B 7218c2ecf20Sopenharmony_ci * contains valid nodes or the end of a valid node, and the 7228c2ecf20Sopenharmony_ci * second half of B contains corrupted data or garbage. This 7238c2ecf20Sopenharmony_ci * means that UBIFS had been writing to B just before the power 7248c2ecf20Sopenharmony_ci * cut happened. I do not know how realistic is this scenario 7258c2ecf20Sopenharmony_ci * that half of the min. I/O unit had been written successfully 7268c2ecf20Sopenharmony_ci * and the other half not, but this is possible in our 'failure 7278c2ecf20Sopenharmony_ci * mode emulation' infrastructure at least. 7288c2ecf20Sopenharmony_ci * 7298c2ecf20Sopenharmony_ci * So what is the problem, why we need to drop those nodes? Why 7308c2ecf20Sopenharmony_ci * can't we just clean-up the second half of B by putting a 7318c2ecf20Sopenharmony_ci * padding node there? We can, and this works fine with one 7328c2ecf20Sopenharmony_ci * exception which was reproduced with power cut emulation 7338c2ecf20Sopenharmony_ci * testing and happens extremely rarely. 7348c2ecf20Sopenharmony_ci * 7358c2ecf20Sopenharmony_ci * Imagine the file-system is full, we run GC which starts 7368c2ecf20Sopenharmony_ci * moving valid nodes from LEB X to LEB Y (obviously, LEB Y is 7378c2ecf20Sopenharmony_ci * the current GC head LEB). The @c->gc_lnum is -1, which means 7388c2ecf20Sopenharmony_ci * that GC will retain LEB X and will try to continue. Imagine 7398c2ecf20Sopenharmony_ci * that LEB X is currently the dirtiest LEB, and the amount of 7408c2ecf20Sopenharmony_ci * used space in LEB Y is exactly the same as amount of free 7418c2ecf20Sopenharmony_ci * space in LEB X. 7428c2ecf20Sopenharmony_ci * 7438c2ecf20Sopenharmony_ci * And a power cut happens when nodes are moved from LEB X to 7448c2ecf20Sopenharmony_ci * LEB Y. We are here trying to recover LEB Y which is the GC 7458c2ecf20Sopenharmony_ci * head LEB. We find the min. I/O unit B as described above. 7468c2ecf20Sopenharmony_ci * Then we clean-up LEB Y by padding min. I/O unit. And later 7478c2ecf20Sopenharmony_ci * 'ubifs_rcvry_gc_commit()' function fails, because it cannot 7488c2ecf20Sopenharmony_ci * find a dirty LEB which could be GC'd into LEB Y! Even LEB X 7498c2ecf20Sopenharmony_ci * does not match because the amount of valid nodes there does 7508c2ecf20Sopenharmony_ci * not fit the free space in LEB Y any more! And this is 7518c2ecf20Sopenharmony_ci * because of the padding node which we added to LEB Y. The 7528c2ecf20Sopenharmony_ci * user-visible effect of this which I once observed and 7538c2ecf20Sopenharmony_ci * analysed is that we cannot mount the file-system with 7548c2ecf20Sopenharmony_ci * -ENOSPC error. 7558c2ecf20Sopenharmony_ci * 7568c2ecf20Sopenharmony_ci * So obviously, to make sure that situation does not happen we 7578c2ecf20Sopenharmony_ci * should free min. I/O unit B in LEB Y completely and the last 7588c2ecf20Sopenharmony_ci * used min. I/O unit in LEB Y should be A. This is basically 7598c2ecf20Sopenharmony_ci * what the below code tries to do. 7608c2ecf20Sopenharmony_ci */ 7618c2ecf20Sopenharmony_ci while (offs > min_io_unit) 7628c2ecf20Sopenharmony_ci drop_last_node(sleb, &offs); 7638c2ecf20Sopenharmony_ci } 7648c2ecf20Sopenharmony_ci 7658c2ecf20Sopenharmony_ci buf = sbuf + offs; 7668c2ecf20Sopenharmony_ci len = c->leb_size - offs; 7678c2ecf20Sopenharmony_ci 7688c2ecf20Sopenharmony_ci clean_buf(c, &buf, lnum, &offs, &len); 7698c2ecf20Sopenharmony_ci ubifs_end_scan(c, sleb, lnum, offs); 7708c2ecf20Sopenharmony_ci 7718c2ecf20Sopenharmony_ci err = fix_unclean_leb(c, sleb, start); 7728c2ecf20Sopenharmony_ci if (err) 7738c2ecf20Sopenharmony_ci goto error; 7748c2ecf20Sopenharmony_ci 7758c2ecf20Sopenharmony_ci return sleb; 7768c2ecf20Sopenharmony_ci 7778c2ecf20Sopenharmony_cicorrupted_rescan: 7788c2ecf20Sopenharmony_ci /* Re-scan the corrupted data with verbose messages */ 7798c2ecf20Sopenharmony_ci ubifs_err(c, "corruption %d", ret); 7808c2ecf20Sopenharmony_ci ubifs_scan_a_node(c, buf, len, lnum, offs, 0); 7818c2ecf20Sopenharmony_cicorrupted: 7828c2ecf20Sopenharmony_ci ubifs_scanned_corruption(c, lnum, offs, buf); 7838c2ecf20Sopenharmony_ci err = -EUCLEAN; 7848c2ecf20Sopenharmony_cierror: 7858c2ecf20Sopenharmony_ci ubifs_err(c, "LEB %d scanning failed", lnum); 7868c2ecf20Sopenharmony_ci ubifs_scan_destroy(sleb); 7878c2ecf20Sopenharmony_ci return ERR_PTR(err); 7888c2ecf20Sopenharmony_ci} 7898c2ecf20Sopenharmony_ci 7908c2ecf20Sopenharmony_ci/** 7918c2ecf20Sopenharmony_ci * get_cs_sqnum - get commit start sequence number. 7928c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object 7938c2ecf20Sopenharmony_ci * @lnum: LEB number of commit start node 7948c2ecf20Sopenharmony_ci * @offs: offset of commit start node 7958c2ecf20Sopenharmony_ci * @cs_sqnum: commit start sequence number is returned here 7968c2ecf20Sopenharmony_ci * 7978c2ecf20Sopenharmony_ci * This function returns %0 on success and a negative error code on failure. 7988c2ecf20Sopenharmony_ci */ 7998c2ecf20Sopenharmony_cistatic int get_cs_sqnum(struct ubifs_info *c, int lnum, int offs, 8008c2ecf20Sopenharmony_ci unsigned long long *cs_sqnum) 8018c2ecf20Sopenharmony_ci{ 8028c2ecf20Sopenharmony_ci struct ubifs_cs_node *cs_node = NULL; 8038c2ecf20Sopenharmony_ci int err, ret; 8048c2ecf20Sopenharmony_ci 8058c2ecf20Sopenharmony_ci dbg_rcvry("at %d:%d", lnum, offs); 8068c2ecf20Sopenharmony_ci cs_node = kmalloc(UBIFS_CS_NODE_SZ, GFP_KERNEL); 8078c2ecf20Sopenharmony_ci if (!cs_node) 8088c2ecf20Sopenharmony_ci return -ENOMEM; 8098c2ecf20Sopenharmony_ci if (c->leb_size - offs < UBIFS_CS_NODE_SZ) 8108c2ecf20Sopenharmony_ci goto out_err; 8118c2ecf20Sopenharmony_ci err = ubifs_leb_read(c, lnum, (void *)cs_node, offs, 8128c2ecf20Sopenharmony_ci UBIFS_CS_NODE_SZ, 0); 8138c2ecf20Sopenharmony_ci if (err && err != -EBADMSG) 8148c2ecf20Sopenharmony_ci goto out_free; 8158c2ecf20Sopenharmony_ci ret = ubifs_scan_a_node(c, cs_node, UBIFS_CS_NODE_SZ, lnum, offs, 0); 8168c2ecf20Sopenharmony_ci if (ret != SCANNED_A_NODE) { 8178c2ecf20Sopenharmony_ci ubifs_err(c, "Not a valid node"); 8188c2ecf20Sopenharmony_ci goto out_err; 8198c2ecf20Sopenharmony_ci } 8208c2ecf20Sopenharmony_ci if (cs_node->ch.node_type != UBIFS_CS_NODE) { 8218c2ecf20Sopenharmony_ci ubifs_err(c, "Not a CS node, type is %d", cs_node->ch.node_type); 8228c2ecf20Sopenharmony_ci goto out_err; 8238c2ecf20Sopenharmony_ci } 8248c2ecf20Sopenharmony_ci if (le64_to_cpu(cs_node->cmt_no) != c->cmt_no) { 8258c2ecf20Sopenharmony_ci ubifs_err(c, "CS node cmt_no %llu != current cmt_no %llu", 8268c2ecf20Sopenharmony_ci (unsigned long long)le64_to_cpu(cs_node->cmt_no), 8278c2ecf20Sopenharmony_ci c->cmt_no); 8288c2ecf20Sopenharmony_ci goto out_err; 8298c2ecf20Sopenharmony_ci } 8308c2ecf20Sopenharmony_ci *cs_sqnum = le64_to_cpu(cs_node->ch.sqnum); 8318c2ecf20Sopenharmony_ci dbg_rcvry("commit start sqnum %llu", *cs_sqnum); 8328c2ecf20Sopenharmony_ci kfree(cs_node); 8338c2ecf20Sopenharmony_ci return 0; 8348c2ecf20Sopenharmony_ci 8358c2ecf20Sopenharmony_ciout_err: 8368c2ecf20Sopenharmony_ci err = -EINVAL; 8378c2ecf20Sopenharmony_ciout_free: 8388c2ecf20Sopenharmony_ci ubifs_err(c, "failed to get CS sqnum"); 8398c2ecf20Sopenharmony_ci kfree(cs_node); 8408c2ecf20Sopenharmony_ci return err; 8418c2ecf20Sopenharmony_ci} 8428c2ecf20Sopenharmony_ci 8438c2ecf20Sopenharmony_ci/** 8448c2ecf20Sopenharmony_ci * ubifs_recover_log_leb - scan and recover a log LEB. 8458c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object 8468c2ecf20Sopenharmony_ci * @lnum: LEB number 8478c2ecf20Sopenharmony_ci * @offs: offset 8488c2ecf20Sopenharmony_ci * @sbuf: LEB-sized buffer to use 8498c2ecf20Sopenharmony_ci * 8508c2ecf20Sopenharmony_ci * This function does a scan of a LEB, but caters for errors that might have 8518c2ecf20Sopenharmony_ci * been caused by unclean reboots from which we are attempting to recover 8528c2ecf20Sopenharmony_ci * (assume that only the last log LEB can be corrupted by an unclean reboot). 8538c2ecf20Sopenharmony_ci * 8548c2ecf20Sopenharmony_ci * This function returns %0 on success and a negative error code on failure. 8558c2ecf20Sopenharmony_ci */ 8568c2ecf20Sopenharmony_cistruct ubifs_scan_leb *ubifs_recover_log_leb(struct ubifs_info *c, int lnum, 8578c2ecf20Sopenharmony_ci int offs, void *sbuf) 8588c2ecf20Sopenharmony_ci{ 8598c2ecf20Sopenharmony_ci struct ubifs_scan_leb *sleb; 8608c2ecf20Sopenharmony_ci int next_lnum; 8618c2ecf20Sopenharmony_ci 8628c2ecf20Sopenharmony_ci dbg_rcvry("LEB %d", lnum); 8638c2ecf20Sopenharmony_ci next_lnum = lnum + 1; 8648c2ecf20Sopenharmony_ci if (next_lnum >= UBIFS_LOG_LNUM + c->log_lebs) 8658c2ecf20Sopenharmony_ci next_lnum = UBIFS_LOG_LNUM; 8668c2ecf20Sopenharmony_ci if (next_lnum != c->ltail_lnum) { 8678c2ecf20Sopenharmony_ci /* 8688c2ecf20Sopenharmony_ci * We can only recover at the end of the log, so check that the 8698c2ecf20Sopenharmony_ci * next log LEB is empty or out of date. 8708c2ecf20Sopenharmony_ci */ 8718c2ecf20Sopenharmony_ci sleb = ubifs_scan(c, next_lnum, 0, sbuf, 0); 8728c2ecf20Sopenharmony_ci if (IS_ERR(sleb)) 8738c2ecf20Sopenharmony_ci return sleb; 8748c2ecf20Sopenharmony_ci if (sleb->nodes_cnt) { 8758c2ecf20Sopenharmony_ci struct ubifs_scan_node *snod; 8768c2ecf20Sopenharmony_ci unsigned long long cs_sqnum = c->cs_sqnum; 8778c2ecf20Sopenharmony_ci 8788c2ecf20Sopenharmony_ci snod = list_entry(sleb->nodes.next, 8798c2ecf20Sopenharmony_ci struct ubifs_scan_node, list); 8808c2ecf20Sopenharmony_ci if (cs_sqnum == 0) { 8818c2ecf20Sopenharmony_ci int err; 8828c2ecf20Sopenharmony_ci 8838c2ecf20Sopenharmony_ci err = get_cs_sqnum(c, lnum, offs, &cs_sqnum); 8848c2ecf20Sopenharmony_ci if (err) { 8858c2ecf20Sopenharmony_ci ubifs_scan_destroy(sleb); 8868c2ecf20Sopenharmony_ci return ERR_PTR(err); 8878c2ecf20Sopenharmony_ci } 8888c2ecf20Sopenharmony_ci } 8898c2ecf20Sopenharmony_ci if (snod->sqnum > cs_sqnum) { 8908c2ecf20Sopenharmony_ci ubifs_err(c, "unrecoverable log corruption in LEB %d", 8918c2ecf20Sopenharmony_ci lnum); 8928c2ecf20Sopenharmony_ci ubifs_scan_destroy(sleb); 8938c2ecf20Sopenharmony_ci return ERR_PTR(-EUCLEAN); 8948c2ecf20Sopenharmony_ci } 8958c2ecf20Sopenharmony_ci } 8968c2ecf20Sopenharmony_ci ubifs_scan_destroy(sleb); 8978c2ecf20Sopenharmony_ci } 8988c2ecf20Sopenharmony_ci return ubifs_recover_leb(c, lnum, offs, sbuf, -1); 8998c2ecf20Sopenharmony_ci} 9008c2ecf20Sopenharmony_ci 9018c2ecf20Sopenharmony_ci/** 9028c2ecf20Sopenharmony_ci * recover_head - recover a head. 9038c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object 9048c2ecf20Sopenharmony_ci * @lnum: LEB number of head to recover 9058c2ecf20Sopenharmony_ci * @offs: offset of head to recover 9068c2ecf20Sopenharmony_ci * @sbuf: LEB-sized buffer to use 9078c2ecf20Sopenharmony_ci * 9088c2ecf20Sopenharmony_ci * This function ensures that there is no data on the flash at a head location. 9098c2ecf20Sopenharmony_ci * 9108c2ecf20Sopenharmony_ci * This function returns %0 on success and a negative error code on failure. 9118c2ecf20Sopenharmony_ci */ 9128c2ecf20Sopenharmony_cistatic int recover_head(struct ubifs_info *c, int lnum, int offs, void *sbuf) 9138c2ecf20Sopenharmony_ci{ 9148c2ecf20Sopenharmony_ci int len = c->max_write_size, err; 9158c2ecf20Sopenharmony_ci 9168c2ecf20Sopenharmony_ci if (offs + len > c->leb_size) 9178c2ecf20Sopenharmony_ci len = c->leb_size - offs; 9188c2ecf20Sopenharmony_ci 9198c2ecf20Sopenharmony_ci if (!len) 9208c2ecf20Sopenharmony_ci return 0; 9218c2ecf20Sopenharmony_ci 9228c2ecf20Sopenharmony_ci /* Read at the head location and check it is empty flash */ 9238c2ecf20Sopenharmony_ci err = ubifs_leb_read(c, lnum, sbuf, offs, len, 1); 9248c2ecf20Sopenharmony_ci if (err || !is_empty(sbuf, len)) { 9258c2ecf20Sopenharmony_ci dbg_rcvry("cleaning head at %d:%d", lnum, offs); 9268c2ecf20Sopenharmony_ci if (offs == 0) 9278c2ecf20Sopenharmony_ci return ubifs_leb_unmap(c, lnum); 9288c2ecf20Sopenharmony_ci err = ubifs_leb_read(c, lnum, sbuf, 0, offs, 1); 9298c2ecf20Sopenharmony_ci if (err) 9308c2ecf20Sopenharmony_ci return err; 9318c2ecf20Sopenharmony_ci return ubifs_leb_change(c, lnum, sbuf, offs); 9328c2ecf20Sopenharmony_ci } 9338c2ecf20Sopenharmony_ci 9348c2ecf20Sopenharmony_ci return 0; 9358c2ecf20Sopenharmony_ci} 9368c2ecf20Sopenharmony_ci 9378c2ecf20Sopenharmony_ci/** 9388c2ecf20Sopenharmony_ci * ubifs_recover_inl_heads - recover index and LPT heads. 9398c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object 9408c2ecf20Sopenharmony_ci * @sbuf: LEB-sized buffer to use 9418c2ecf20Sopenharmony_ci * 9428c2ecf20Sopenharmony_ci * This function ensures that there is no data on the flash at the index and 9438c2ecf20Sopenharmony_ci * LPT head locations. 9448c2ecf20Sopenharmony_ci * 9458c2ecf20Sopenharmony_ci * This deals with the recovery of a half-completed journal commit. UBIFS is 9468c2ecf20Sopenharmony_ci * careful never to overwrite the last version of the index or the LPT. Because 9478c2ecf20Sopenharmony_ci * the index and LPT are wandering trees, data from a half-completed commit will 9488c2ecf20Sopenharmony_ci * not be referenced anywhere in UBIFS. The data will be either in LEBs that are 9498c2ecf20Sopenharmony_ci * assumed to be empty and will be unmapped anyway before use, or in the index 9508c2ecf20Sopenharmony_ci * and LPT heads. 9518c2ecf20Sopenharmony_ci * 9528c2ecf20Sopenharmony_ci * This function returns %0 on success and a negative error code on failure. 9538c2ecf20Sopenharmony_ci */ 9548c2ecf20Sopenharmony_ciint ubifs_recover_inl_heads(struct ubifs_info *c, void *sbuf) 9558c2ecf20Sopenharmony_ci{ 9568c2ecf20Sopenharmony_ci int err; 9578c2ecf20Sopenharmony_ci 9588c2ecf20Sopenharmony_ci ubifs_assert(c, !c->ro_mount || c->remounting_rw); 9598c2ecf20Sopenharmony_ci 9608c2ecf20Sopenharmony_ci dbg_rcvry("checking index head at %d:%d", c->ihead_lnum, c->ihead_offs); 9618c2ecf20Sopenharmony_ci err = recover_head(c, c->ihead_lnum, c->ihead_offs, sbuf); 9628c2ecf20Sopenharmony_ci if (err) 9638c2ecf20Sopenharmony_ci return err; 9648c2ecf20Sopenharmony_ci 9658c2ecf20Sopenharmony_ci dbg_rcvry("checking LPT head at %d:%d", c->nhead_lnum, c->nhead_offs); 9668c2ecf20Sopenharmony_ci 9678c2ecf20Sopenharmony_ci return recover_head(c, c->nhead_lnum, c->nhead_offs, sbuf); 9688c2ecf20Sopenharmony_ci} 9698c2ecf20Sopenharmony_ci 9708c2ecf20Sopenharmony_ci/** 9718c2ecf20Sopenharmony_ci * clean_an_unclean_leb - read and write a LEB to remove corruption. 9728c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object 9738c2ecf20Sopenharmony_ci * @ucleb: unclean LEB information 9748c2ecf20Sopenharmony_ci * @sbuf: LEB-sized buffer to use 9758c2ecf20Sopenharmony_ci * 9768c2ecf20Sopenharmony_ci * This function reads a LEB up to a point pre-determined by the mount recovery, 9778c2ecf20Sopenharmony_ci * checks the nodes, and writes the result back to the flash, thereby cleaning 9788c2ecf20Sopenharmony_ci * off any following corruption, or non-fatal ECC errors. 9798c2ecf20Sopenharmony_ci * 9808c2ecf20Sopenharmony_ci * This function returns %0 on success and a negative error code on failure. 9818c2ecf20Sopenharmony_ci */ 9828c2ecf20Sopenharmony_cistatic int clean_an_unclean_leb(struct ubifs_info *c, 9838c2ecf20Sopenharmony_ci struct ubifs_unclean_leb *ucleb, void *sbuf) 9848c2ecf20Sopenharmony_ci{ 9858c2ecf20Sopenharmony_ci int err, lnum = ucleb->lnum, offs = 0, len = ucleb->endpt, quiet = 1; 9868c2ecf20Sopenharmony_ci void *buf = sbuf; 9878c2ecf20Sopenharmony_ci 9888c2ecf20Sopenharmony_ci dbg_rcvry("LEB %d len %d", lnum, len); 9898c2ecf20Sopenharmony_ci 9908c2ecf20Sopenharmony_ci if (len == 0) { 9918c2ecf20Sopenharmony_ci /* Nothing to read, just unmap it */ 9928c2ecf20Sopenharmony_ci return ubifs_leb_unmap(c, lnum); 9938c2ecf20Sopenharmony_ci } 9948c2ecf20Sopenharmony_ci 9958c2ecf20Sopenharmony_ci err = ubifs_leb_read(c, lnum, buf, offs, len, 0); 9968c2ecf20Sopenharmony_ci if (err && err != -EBADMSG) 9978c2ecf20Sopenharmony_ci return err; 9988c2ecf20Sopenharmony_ci 9998c2ecf20Sopenharmony_ci while (len >= 8) { 10008c2ecf20Sopenharmony_ci int ret; 10018c2ecf20Sopenharmony_ci 10028c2ecf20Sopenharmony_ci cond_resched(); 10038c2ecf20Sopenharmony_ci 10048c2ecf20Sopenharmony_ci /* Scan quietly until there is an error */ 10058c2ecf20Sopenharmony_ci ret = ubifs_scan_a_node(c, buf, len, lnum, offs, quiet); 10068c2ecf20Sopenharmony_ci 10078c2ecf20Sopenharmony_ci if (ret == SCANNED_A_NODE) { 10088c2ecf20Sopenharmony_ci /* A valid node, and not a padding node */ 10098c2ecf20Sopenharmony_ci struct ubifs_ch *ch = buf; 10108c2ecf20Sopenharmony_ci int node_len; 10118c2ecf20Sopenharmony_ci 10128c2ecf20Sopenharmony_ci node_len = ALIGN(le32_to_cpu(ch->len), 8); 10138c2ecf20Sopenharmony_ci offs += node_len; 10148c2ecf20Sopenharmony_ci buf += node_len; 10158c2ecf20Sopenharmony_ci len -= node_len; 10168c2ecf20Sopenharmony_ci continue; 10178c2ecf20Sopenharmony_ci } 10188c2ecf20Sopenharmony_ci 10198c2ecf20Sopenharmony_ci if (ret > 0) { 10208c2ecf20Sopenharmony_ci /* Padding bytes or a valid padding node */ 10218c2ecf20Sopenharmony_ci offs += ret; 10228c2ecf20Sopenharmony_ci buf += ret; 10238c2ecf20Sopenharmony_ci len -= ret; 10248c2ecf20Sopenharmony_ci continue; 10258c2ecf20Sopenharmony_ci } 10268c2ecf20Sopenharmony_ci 10278c2ecf20Sopenharmony_ci if (ret == SCANNED_EMPTY_SPACE) { 10288c2ecf20Sopenharmony_ci ubifs_err(c, "unexpected empty space at %d:%d", 10298c2ecf20Sopenharmony_ci lnum, offs); 10308c2ecf20Sopenharmony_ci return -EUCLEAN; 10318c2ecf20Sopenharmony_ci } 10328c2ecf20Sopenharmony_ci 10338c2ecf20Sopenharmony_ci if (quiet) { 10348c2ecf20Sopenharmony_ci /* Redo the last scan but noisily */ 10358c2ecf20Sopenharmony_ci quiet = 0; 10368c2ecf20Sopenharmony_ci continue; 10378c2ecf20Sopenharmony_ci } 10388c2ecf20Sopenharmony_ci 10398c2ecf20Sopenharmony_ci ubifs_scanned_corruption(c, lnum, offs, buf); 10408c2ecf20Sopenharmony_ci return -EUCLEAN; 10418c2ecf20Sopenharmony_ci } 10428c2ecf20Sopenharmony_ci 10438c2ecf20Sopenharmony_ci /* Pad to min_io_size */ 10448c2ecf20Sopenharmony_ci len = ALIGN(ucleb->endpt, c->min_io_size); 10458c2ecf20Sopenharmony_ci if (len > ucleb->endpt) { 10468c2ecf20Sopenharmony_ci int pad_len = len - ALIGN(ucleb->endpt, 8); 10478c2ecf20Sopenharmony_ci 10488c2ecf20Sopenharmony_ci if (pad_len > 0) { 10498c2ecf20Sopenharmony_ci buf = c->sbuf + len - pad_len; 10508c2ecf20Sopenharmony_ci ubifs_pad(c, buf, pad_len); 10518c2ecf20Sopenharmony_ci } 10528c2ecf20Sopenharmony_ci } 10538c2ecf20Sopenharmony_ci 10548c2ecf20Sopenharmony_ci /* Write back the LEB atomically */ 10558c2ecf20Sopenharmony_ci err = ubifs_leb_change(c, lnum, sbuf, len); 10568c2ecf20Sopenharmony_ci if (err) 10578c2ecf20Sopenharmony_ci return err; 10588c2ecf20Sopenharmony_ci 10598c2ecf20Sopenharmony_ci dbg_rcvry("cleaned LEB %d", lnum); 10608c2ecf20Sopenharmony_ci 10618c2ecf20Sopenharmony_ci return 0; 10628c2ecf20Sopenharmony_ci} 10638c2ecf20Sopenharmony_ci 10648c2ecf20Sopenharmony_ci/** 10658c2ecf20Sopenharmony_ci * ubifs_clean_lebs - clean LEBs recovered during read-only mount. 10668c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object 10678c2ecf20Sopenharmony_ci * @sbuf: LEB-sized buffer to use 10688c2ecf20Sopenharmony_ci * 10698c2ecf20Sopenharmony_ci * This function cleans a LEB identified during recovery that needs to be 10708c2ecf20Sopenharmony_ci * written but was not because UBIFS was mounted read-only. This happens when 10718c2ecf20Sopenharmony_ci * remounting to read-write mode. 10728c2ecf20Sopenharmony_ci * 10738c2ecf20Sopenharmony_ci * This function returns %0 on success and a negative error code on failure. 10748c2ecf20Sopenharmony_ci */ 10758c2ecf20Sopenharmony_ciint ubifs_clean_lebs(struct ubifs_info *c, void *sbuf) 10768c2ecf20Sopenharmony_ci{ 10778c2ecf20Sopenharmony_ci dbg_rcvry("recovery"); 10788c2ecf20Sopenharmony_ci while (!list_empty(&c->unclean_leb_list)) { 10798c2ecf20Sopenharmony_ci struct ubifs_unclean_leb *ucleb; 10808c2ecf20Sopenharmony_ci int err; 10818c2ecf20Sopenharmony_ci 10828c2ecf20Sopenharmony_ci ucleb = list_entry(c->unclean_leb_list.next, 10838c2ecf20Sopenharmony_ci struct ubifs_unclean_leb, list); 10848c2ecf20Sopenharmony_ci err = clean_an_unclean_leb(c, ucleb, sbuf); 10858c2ecf20Sopenharmony_ci if (err) 10868c2ecf20Sopenharmony_ci return err; 10878c2ecf20Sopenharmony_ci list_del(&ucleb->list); 10888c2ecf20Sopenharmony_ci kfree(ucleb); 10898c2ecf20Sopenharmony_ci } 10908c2ecf20Sopenharmony_ci return 0; 10918c2ecf20Sopenharmony_ci} 10928c2ecf20Sopenharmony_ci 10938c2ecf20Sopenharmony_ci/** 10948c2ecf20Sopenharmony_ci * grab_empty_leb - grab an empty LEB to use as GC LEB and run commit. 10958c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object 10968c2ecf20Sopenharmony_ci * 10978c2ecf20Sopenharmony_ci * This is a helper function for 'ubifs_rcvry_gc_commit()' which grabs an empty 10988c2ecf20Sopenharmony_ci * LEB to be used as GC LEB (@c->gc_lnum), and then runs the commit. Returns 10998c2ecf20Sopenharmony_ci * zero in case of success and a negative error code in case of failure. 11008c2ecf20Sopenharmony_ci */ 11018c2ecf20Sopenharmony_cistatic int grab_empty_leb(struct ubifs_info *c) 11028c2ecf20Sopenharmony_ci{ 11038c2ecf20Sopenharmony_ci int lnum, err; 11048c2ecf20Sopenharmony_ci 11058c2ecf20Sopenharmony_ci /* 11068c2ecf20Sopenharmony_ci * Note, it is very important to first search for an empty LEB and then 11078c2ecf20Sopenharmony_ci * run the commit, not vice-versa. The reason is that there might be 11088c2ecf20Sopenharmony_ci * only one empty LEB at the moment, the one which has been the 11098c2ecf20Sopenharmony_ci * @c->gc_lnum just before the power cut happened. During the regular 11108c2ecf20Sopenharmony_ci * UBIFS operation (not now) @c->gc_lnum is marked as "taken", so no 11118c2ecf20Sopenharmony_ci * one but GC can grab it. But at this moment this single empty LEB is 11128c2ecf20Sopenharmony_ci * not marked as taken, so if we run commit - what happens? Right, the 11138c2ecf20Sopenharmony_ci * commit will grab it and write the index there. Remember that the 11148c2ecf20Sopenharmony_ci * index always expands as long as there is free space, and it only 11158c2ecf20Sopenharmony_ci * starts consolidating when we run out of space. 11168c2ecf20Sopenharmony_ci * 11178c2ecf20Sopenharmony_ci * IOW, if we run commit now, we might not be able to find a free LEB 11188c2ecf20Sopenharmony_ci * after this. 11198c2ecf20Sopenharmony_ci */ 11208c2ecf20Sopenharmony_ci lnum = ubifs_find_free_leb_for_idx(c); 11218c2ecf20Sopenharmony_ci if (lnum < 0) { 11228c2ecf20Sopenharmony_ci ubifs_err(c, "could not find an empty LEB"); 11238c2ecf20Sopenharmony_ci ubifs_dump_lprops(c); 11248c2ecf20Sopenharmony_ci ubifs_dump_budg(c, &c->bi); 11258c2ecf20Sopenharmony_ci return lnum; 11268c2ecf20Sopenharmony_ci } 11278c2ecf20Sopenharmony_ci 11288c2ecf20Sopenharmony_ci /* Reset the index flag */ 11298c2ecf20Sopenharmony_ci err = ubifs_change_one_lp(c, lnum, LPROPS_NC, LPROPS_NC, 0, 11308c2ecf20Sopenharmony_ci LPROPS_INDEX, 0); 11318c2ecf20Sopenharmony_ci if (err) 11328c2ecf20Sopenharmony_ci return err; 11338c2ecf20Sopenharmony_ci 11348c2ecf20Sopenharmony_ci c->gc_lnum = lnum; 11358c2ecf20Sopenharmony_ci dbg_rcvry("found empty LEB %d, run commit", lnum); 11368c2ecf20Sopenharmony_ci 11378c2ecf20Sopenharmony_ci return ubifs_run_commit(c); 11388c2ecf20Sopenharmony_ci} 11398c2ecf20Sopenharmony_ci 11408c2ecf20Sopenharmony_ci/** 11418c2ecf20Sopenharmony_ci * ubifs_rcvry_gc_commit - recover the GC LEB number and run the commit. 11428c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object 11438c2ecf20Sopenharmony_ci * 11448c2ecf20Sopenharmony_ci * Out-of-place garbage collection requires always one empty LEB with which to 11458c2ecf20Sopenharmony_ci * start garbage collection. The LEB number is recorded in c->gc_lnum and is 11468c2ecf20Sopenharmony_ci * written to the master node on unmounting. In the case of an unclean unmount 11478c2ecf20Sopenharmony_ci * the value of gc_lnum recorded in the master node is out of date and cannot 11488c2ecf20Sopenharmony_ci * be used. Instead, recovery must allocate an empty LEB for this purpose. 11498c2ecf20Sopenharmony_ci * However, there may not be enough empty space, in which case it must be 11508c2ecf20Sopenharmony_ci * possible to GC the dirtiest LEB into the GC head LEB. 11518c2ecf20Sopenharmony_ci * 11528c2ecf20Sopenharmony_ci * This function also runs the commit which causes the TNC updates from 11538c2ecf20Sopenharmony_ci * size-recovery and orphans to be written to the flash. That is important to 11548c2ecf20Sopenharmony_ci * ensure correct replay order for subsequent mounts. 11558c2ecf20Sopenharmony_ci * 11568c2ecf20Sopenharmony_ci * This function returns %0 on success and a negative error code on failure. 11578c2ecf20Sopenharmony_ci */ 11588c2ecf20Sopenharmony_ciint ubifs_rcvry_gc_commit(struct ubifs_info *c) 11598c2ecf20Sopenharmony_ci{ 11608c2ecf20Sopenharmony_ci struct ubifs_wbuf *wbuf = &c->jheads[GCHD].wbuf; 11618c2ecf20Sopenharmony_ci struct ubifs_lprops lp; 11628c2ecf20Sopenharmony_ci int err; 11638c2ecf20Sopenharmony_ci 11648c2ecf20Sopenharmony_ci dbg_rcvry("GC head LEB %d, offs %d", wbuf->lnum, wbuf->offs); 11658c2ecf20Sopenharmony_ci 11668c2ecf20Sopenharmony_ci c->gc_lnum = -1; 11678c2ecf20Sopenharmony_ci if (wbuf->lnum == -1 || wbuf->offs == c->leb_size) 11688c2ecf20Sopenharmony_ci return grab_empty_leb(c); 11698c2ecf20Sopenharmony_ci 11708c2ecf20Sopenharmony_ci err = ubifs_find_dirty_leb(c, &lp, wbuf->offs, 2); 11718c2ecf20Sopenharmony_ci if (err) { 11728c2ecf20Sopenharmony_ci if (err != -ENOSPC) 11738c2ecf20Sopenharmony_ci return err; 11748c2ecf20Sopenharmony_ci 11758c2ecf20Sopenharmony_ci dbg_rcvry("could not find a dirty LEB"); 11768c2ecf20Sopenharmony_ci return grab_empty_leb(c); 11778c2ecf20Sopenharmony_ci } 11788c2ecf20Sopenharmony_ci 11798c2ecf20Sopenharmony_ci ubifs_assert(c, !(lp.flags & LPROPS_INDEX)); 11808c2ecf20Sopenharmony_ci ubifs_assert(c, lp.free + lp.dirty >= wbuf->offs); 11818c2ecf20Sopenharmony_ci 11828c2ecf20Sopenharmony_ci /* 11838c2ecf20Sopenharmony_ci * We run the commit before garbage collection otherwise subsequent 11848c2ecf20Sopenharmony_ci * mounts will see the GC and orphan deletion in a different order. 11858c2ecf20Sopenharmony_ci */ 11868c2ecf20Sopenharmony_ci dbg_rcvry("committing"); 11878c2ecf20Sopenharmony_ci err = ubifs_run_commit(c); 11888c2ecf20Sopenharmony_ci if (err) 11898c2ecf20Sopenharmony_ci return err; 11908c2ecf20Sopenharmony_ci 11918c2ecf20Sopenharmony_ci dbg_rcvry("GC'ing LEB %d", lp.lnum); 11928c2ecf20Sopenharmony_ci mutex_lock_nested(&wbuf->io_mutex, wbuf->jhead); 11938c2ecf20Sopenharmony_ci err = ubifs_garbage_collect_leb(c, &lp); 11948c2ecf20Sopenharmony_ci if (err >= 0) { 11958c2ecf20Sopenharmony_ci int err2 = ubifs_wbuf_sync_nolock(wbuf); 11968c2ecf20Sopenharmony_ci 11978c2ecf20Sopenharmony_ci if (err2) 11988c2ecf20Sopenharmony_ci err = err2; 11998c2ecf20Sopenharmony_ci } 12008c2ecf20Sopenharmony_ci mutex_unlock(&wbuf->io_mutex); 12018c2ecf20Sopenharmony_ci if (err < 0) { 12028c2ecf20Sopenharmony_ci ubifs_err(c, "GC failed, error %d", err); 12038c2ecf20Sopenharmony_ci if (err == -EAGAIN) 12048c2ecf20Sopenharmony_ci err = -EINVAL; 12058c2ecf20Sopenharmony_ci return err; 12068c2ecf20Sopenharmony_ci } 12078c2ecf20Sopenharmony_ci 12088c2ecf20Sopenharmony_ci ubifs_assert(c, err == LEB_RETAINED); 12098c2ecf20Sopenharmony_ci if (err != LEB_RETAINED) 12108c2ecf20Sopenharmony_ci return -EINVAL; 12118c2ecf20Sopenharmony_ci 12128c2ecf20Sopenharmony_ci err = ubifs_leb_unmap(c, c->gc_lnum); 12138c2ecf20Sopenharmony_ci if (err) 12148c2ecf20Sopenharmony_ci return err; 12158c2ecf20Sopenharmony_ci 12168c2ecf20Sopenharmony_ci dbg_rcvry("allocated LEB %d for GC", lp.lnum); 12178c2ecf20Sopenharmony_ci return 0; 12188c2ecf20Sopenharmony_ci} 12198c2ecf20Sopenharmony_ci 12208c2ecf20Sopenharmony_ci/** 12218c2ecf20Sopenharmony_ci * struct size_entry - inode size information for recovery. 12228c2ecf20Sopenharmony_ci * @rb: link in the RB-tree of sizes 12238c2ecf20Sopenharmony_ci * @inum: inode number 12248c2ecf20Sopenharmony_ci * @i_size: size on inode 12258c2ecf20Sopenharmony_ci * @d_size: maximum size based on data nodes 12268c2ecf20Sopenharmony_ci * @exists: indicates whether the inode exists 12278c2ecf20Sopenharmony_ci * @inode: inode if pinned in memory awaiting rw mode to fix it 12288c2ecf20Sopenharmony_ci */ 12298c2ecf20Sopenharmony_cistruct size_entry { 12308c2ecf20Sopenharmony_ci struct rb_node rb; 12318c2ecf20Sopenharmony_ci ino_t inum; 12328c2ecf20Sopenharmony_ci loff_t i_size; 12338c2ecf20Sopenharmony_ci loff_t d_size; 12348c2ecf20Sopenharmony_ci int exists; 12358c2ecf20Sopenharmony_ci struct inode *inode; 12368c2ecf20Sopenharmony_ci}; 12378c2ecf20Sopenharmony_ci 12388c2ecf20Sopenharmony_ci/** 12398c2ecf20Sopenharmony_ci * add_ino - add an entry to the size tree. 12408c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object 12418c2ecf20Sopenharmony_ci * @inum: inode number 12428c2ecf20Sopenharmony_ci * @i_size: size on inode 12438c2ecf20Sopenharmony_ci * @d_size: maximum size based on data nodes 12448c2ecf20Sopenharmony_ci * @exists: indicates whether the inode exists 12458c2ecf20Sopenharmony_ci */ 12468c2ecf20Sopenharmony_cistatic int add_ino(struct ubifs_info *c, ino_t inum, loff_t i_size, 12478c2ecf20Sopenharmony_ci loff_t d_size, int exists) 12488c2ecf20Sopenharmony_ci{ 12498c2ecf20Sopenharmony_ci struct rb_node **p = &c->size_tree.rb_node, *parent = NULL; 12508c2ecf20Sopenharmony_ci struct size_entry *e; 12518c2ecf20Sopenharmony_ci 12528c2ecf20Sopenharmony_ci while (*p) { 12538c2ecf20Sopenharmony_ci parent = *p; 12548c2ecf20Sopenharmony_ci e = rb_entry(parent, struct size_entry, rb); 12558c2ecf20Sopenharmony_ci if (inum < e->inum) 12568c2ecf20Sopenharmony_ci p = &(*p)->rb_left; 12578c2ecf20Sopenharmony_ci else 12588c2ecf20Sopenharmony_ci p = &(*p)->rb_right; 12598c2ecf20Sopenharmony_ci } 12608c2ecf20Sopenharmony_ci 12618c2ecf20Sopenharmony_ci e = kzalloc(sizeof(struct size_entry), GFP_KERNEL); 12628c2ecf20Sopenharmony_ci if (!e) 12638c2ecf20Sopenharmony_ci return -ENOMEM; 12648c2ecf20Sopenharmony_ci 12658c2ecf20Sopenharmony_ci e->inum = inum; 12668c2ecf20Sopenharmony_ci e->i_size = i_size; 12678c2ecf20Sopenharmony_ci e->d_size = d_size; 12688c2ecf20Sopenharmony_ci e->exists = exists; 12698c2ecf20Sopenharmony_ci 12708c2ecf20Sopenharmony_ci rb_link_node(&e->rb, parent, p); 12718c2ecf20Sopenharmony_ci rb_insert_color(&e->rb, &c->size_tree); 12728c2ecf20Sopenharmony_ci 12738c2ecf20Sopenharmony_ci return 0; 12748c2ecf20Sopenharmony_ci} 12758c2ecf20Sopenharmony_ci 12768c2ecf20Sopenharmony_ci/** 12778c2ecf20Sopenharmony_ci * find_ino - find an entry on the size tree. 12788c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object 12798c2ecf20Sopenharmony_ci * @inum: inode number 12808c2ecf20Sopenharmony_ci */ 12818c2ecf20Sopenharmony_cistatic struct size_entry *find_ino(struct ubifs_info *c, ino_t inum) 12828c2ecf20Sopenharmony_ci{ 12838c2ecf20Sopenharmony_ci struct rb_node *p = c->size_tree.rb_node; 12848c2ecf20Sopenharmony_ci struct size_entry *e; 12858c2ecf20Sopenharmony_ci 12868c2ecf20Sopenharmony_ci while (p) { 12878c2ecf20Sopenharmony_ci e = rb_entry(p, struct size_entry, rb); 12888c2ecf20Sopenharmony_ci if (inum < e->inum) 12898c2ecf20Sopenharmony_ci p = p->rb_left; 12908c2ecf20Sopenharmony_ci else if (inum > e->inum) 12918c2ecf20Sopenharmony_ci p = p->rb_right; 12928c2ecf20Sopenharmony_ci else 12938c2ecf20Sopenharmony_ci return e; 12948c2ecf20Sopenharmony_ci } 12958c2ecf20Sopenharmony_ci return NULL; 12968c2ecf20Sopenharmony_ci} 12978c2ecf20Sopenharmony_ci 12988c2ecf20Sopenharmony_ci/** 12998c2ecf20Sopenharmony_ci * remove_ino - remove an entry from the size tree. 13008c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object 13018c2ecf20Sopenharmony_ci * @inum: inode number 13028c2ecf20Sopenharmony_ci */ 13038c2ecf20Sopenharmony_cistatic void remove_ino(struct ubifs_info *c, ino_t inum) 13048c2ecf20Sopenharmony_ci{ 13058c2ecf20Sopenharmony_ci struct size_entry *e = find_ino(c, inum); 13068c2ecf20Sopenharmony_ci 13078c2ecf20Sopenharmony_ci if (!e) 13088c2ecf20Sopenharmony_ci return; 13098c2ecf20Sopenharmony_ci rb_erase(&e->rb, &c->size_tree); 13108c2ecf20Sopenharmony_ci kfree(e); 13118c2ecf20Sopenharmony_ci} 13128c2ecf20Sopenharmony_ci 13138c2ecf20Sopenharmony_ci/** 13148c2ecf20Sopenharmony_ci * ubifs_destroy_size_tree - free resources related to the size tree. 13158c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object 13168c2ecf20Sopenharmony_ci */ 13178c2ecf20Sopenharmony_civoid ubifs_destroy_size_tree(struct ubifs_info *c) 13188c2ecf20Sopenharmony_ci{ 13198c2ecf20Sopenharmony_ci struct size_entry *e, *n; 13208c2ecf20Sopenharmony_ci 13218c2ecf20Sopenharmony_ci rbtree_postorder_for_each_entry_safe(e, n, &c->size_tree, rb) { 13228c2ecf20Sopenharmony_ci iput(e->inode); 13238c2ecf20Sopenharmony_ci kfree(e); 13248c2ecf20Sopenharmony_ci } 13258c2ecf20Sopenharmony_ci 13268c2ecf20Sopenharmony_ci c->size_tree = RB_ROOT; 13278c2ecf20Sopenharmony_ci} 13288c2ecf20Sopenharmony_ci 13298c2ecf20Sopenharmony_ci/** 13308c2ecf20Sopenharmony_ci * ubifs_recover_size_accum - accumulate inode sizes for recovery. 13318c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object 13328c2ecf20Sopenharmony_ci * @key: node key 13338c2ecf20Sopenharmony_ci * @deletion: node is for a deletion 13348c2ecf20Sopenharmony_ci * @new_size: inode size 13358c2ecf20Sopenharmony_ci * 13368c2ecf20Sopenharmony_ci * This function has two purposes: 13378c2ecf20Sopenharmony_ci * 1) to ensure there are no data nodes that fall outside the inode size 13388c2ecf20Sopenharmony_ci * 2) to ensure there are no data nodes for inodes that do not exist 13398c2ecf20Sopenharmony_ci * To accomplish those purposes, a rb-tree is constructed containing an entry 13408c2ecf20Sopenharmony_ci * for each inode number in the journal that has not been deleted, and recording 13418c2ecf20Sopenharmony_ci * the size from the inode node, the maximum size of any data node (also altered 13428c2ecf20Sopenharmony_ci * by truncations) and a flag indicating a inode number for which no inode node 13438c2ecf20Sopenharmony_ci * was present in the journal. 13448c2ecf20Sopenharmony_ci * 13458c2ecf20Sopenharmony_ci * Note that there is still the possibility that there are data nodes that have 13468c2ecf20Sopenharmony_ci * been committed that are beyond the inode size, however the only way to find 13478c2ecf20Sopenharmony_ci * them would be to scan the entire index. Alternatively, some provision could 13488c2ecf20Sopenharmony_ci * be made to record the size of inodes at the start of commit, which would seem 13498c2ecf20Sopenharmony_ci * very cumbersome for a scenario that is quite unlikely and the only negative 13508c2ecf20Sopenharmony_ci * consequence of which is wasted space. 13518c2ecf20Sopenharmony_ci * 13528c2ecf20Sopenharmony_ci * This functions returns %0 on success and a negative error code on failure. 13538c2ecf20Sopenharmony_ci */ 13548c2ecf20Sopenharmony_ciint ubifs_recover_size_accum(struct ubifs_info *c, union ubifs_key *key, 13558c2ecf20Sopenharmony_ci int deletion, loff_t new_size) 13568c2ecf20Sopenharmony_ci{ 13578c2ecf20Sopenharmony_ci ino_t inum = key_inum(c, key); 13588c2ecf20Sopenharmony_ci struct size_entry *e; 13598c2ecf20Sopenharmony_ci int err; 13608c2ecf20Sopenharmony_ci 13618c2ecf20Sopenharmony_ci switch (key_type(c, key)) { 13628c2ecf20Sopenharmony_ci case UBIFS_INO_KEY: 13638c2ecf20Sopenharmony_ci if (deletion) 13648c2ecf20Sopenharmony_ci remove_ino(c, inum); 13658c2ecf20Sopenharmony_ci else { 13668c2ecf20Sopenharmony_ci e = find_ino(c, inum); 13678c2ecf20Sopenharmony_ci if (e) { 13688c2ecf20Sopenharmony_ci e->i_size = new_size; 13698c2ecf20Sopenharmony_ci e->exists = 1; 13708c2ecf20Sopenharmony_ci } else { 13718c2ecf20Sopenharmony_ci err = add_ino(c, inum, new_size, 0, 1); 13728c2ecf20Sopenharmony_ci if (err) 13738c2ecf20Sopenharmony_ci return err; 13748c2ecf20Sopenharmony_ci } 13758c2ecf20Sopenharmony_ci } 13768c2ecf20Sopenharmony_ci break; 13778c2ecf20Sopenharmony_ci case UBIFS_DATA_KEY: 13788c2ecf20Sopenharmony_ci e = find_ino(c, inum); 13798c2ecf20Sopenharmony_ci if (e) { 13808c2ecf20Sopenharmony_ci if (new_size > e->d_size) 13818c2ecf20Sopenharmony_ci e->d_size = new_size; 13828c2ecf20Sopenharmony_ci } else { 13838c2ecf20Sopenharmony_ci err = add_ino(c, inum, 0, new_size, 0); 13848c2ecf20Sopenharmony_ci if (err) 13858c2ecf20Sopenharmony_ci return err; 13868c2ecf20Sopenharmony_ci } 13878c2ecf20Sopenharmony_ci break; 13888c2ecf20Sopenharmony_ci case UBIFS_TRUN_KEY: 13898c2ecf20Sopenharmony_ci e = find_ino(c, inum); 13908c2ecf20Sopenharmony_ci if (e) 13918c2ecf20Sopenharmony_ci e->d_size = new_size; 13928c2ecf20Sopenharmony_ci break; 13938c2ecf20Sopenharmony_ci } 13948c2ecf20Sopenharmony_ci return 0; 13958c2ecf20Sopenharmony_ci} 13968c2ecf20Sopenharmony_ci 13978c2ecf20Sopenharmony_ci/** 13988c2ecf20Sopenharmony_ci * fix_size_in_place - fix inode size in place on flash. 13998c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object 14008c2ecf20Sopenharmony_ci * @e: inode size information for recovery 14018c2ecf20Sopenharmony_ci */ 14028c2ecf20Sopenharmony_cistatic int fix_size_in_place(struct ubifs_info *c, struct size_entry *e) 14038c2ecf20Sopenharmony_ci{ 14048c2ecf20Sopenharmony_ci struct ubifs_ino_node *ino = c->sbuf; 14058c2ecf20Sopenharmony_ci unsigned char *p; 14068c2ecf20Sopenharmony_ci union ubifs_key key; 14078c2ecf20Sopenharmony_ci int err, lnum, offs, len; 14088c2ecf20Sopenharmony_ci loff_t i_size; 14098c2ecf20Sopenharmony_ci uint32_t crc; 14108c2ecf20Sopenharmony_ci 14118c2ecf20Sopenharmony_ci /* Locate the inode node LEB number and offset */ 14128c2ecf20Sopenharmony_ci ino_key_init(c, &key, e->inum); 14138c2ecf20Sopenharmony_ci err = ubifs_tnc_locate(c, &key, ino, &lnum, &offs); 14148c2ecf20Sopenharmony_ci if (err) 14158c2ecf20Sopenharmony_ci goto out; 14168c2ecf20Sopenharmony_ci /* 14178c2ecf20Sopenharmony_ci * If the size recorded on the inode node is greater than the size that 14188c2ecf20Sopenharmony_ci * was calculated from nodes in the journal then don't change the inode. 14198c2ecf20Sopenharmony_ci */ 14208c2ecf20Sopenharmony_ci i_size = le64_to_cpu(ino->size); 14218c2ecf20Sopenharmony_ci if (i_size >= e->d_size) 14228c2ecf20Sopenharmony_ci return 0; 14238c2ecf20Sopenharmony_ci /* Read the LEB */ 14248c2ecf20Sopenharmony_ci err = ubifs_leb_read(c, lnum, c->sbuf, 0, c->leb_size, 1); 14258c2ecf20Sopenharmony_ci if (err) 14268c2ecf20Sopenharmony_ci goto out; 14278c2ecf20Sopenharmony_ci /* Change the size field and recalculate the CRC */ 14288c2ecf20Sopenharmony_ci ino = c->sbuf + offs; 14298c2ecf20Sopenharmony_ci ino->size = cpu_to_le64(e->d_size); 14308c2ecf20Sopenharmony_ci len = le32_to_cpu(ino->ch.len); 14318c2ecf20Sopenharmony_ci crc = crc32(UBIFS_CRC32_INIT, (void *)ino + 8, len - 8); 14328c2ecf20Sopenharmony_ci ino->ch.crc = cpu_to_le32(crc); 14338c2ecf20Sopenharmony_ci /* Work out where data in the LEB ends and free space begins */ 14348c2ecf20Sopenharmony_ci p = c->sbuf; 14358c2ecf20Sopenharmony_ci len = c->leb_size - 1; 14368c2ecf20Sopenharmony_ci while (p[len] == 0xff) 14378c2ecf20Sopenharmony_ci len -= 1; 14388c2ecf20Sopenharmony_ci len = ALIGN(len + 1, c->min_io_size); 14398c2ecf20Sopenharmony_ci /* Atomically write the fixed LEB back again */ 14408c2ecf20Sopenharmony_ci err = ubifs_leb_change(c, lnum, c->sbuf, len); 14418c2ecf20Sopenharmony_ci if (err) 14428c2ecf20Sopenharmony_ci goto out; 14438c2ecf20Sopenharmony_ci dbg_rcvry("inode %lu at %d:%d size %lld -> %lld", 14448c2ecf20Sopenharmony_ci (unsigned long)e->inum, lnum, offs, i_size, e->d_size); 14458c2ecf20Sopenharmony_ci return 0; 14468c2ecf20Sopenharmony_ci 14478c2ecf20Sopenharmony_ciout: 14488c2ecf20Sopenharmony_ci ubifs_warn(c, "inode %lu failed to fix size %lld -> %lld error %d", 14498c2ecf20Sopenharmony_ci (unsigned long)e->inum, e->i_size, e->d_size, err); 14508c2ecf20Sopenharmony_ci return err; 14518c2ecf20Sopenharmony_ci} 14528c2ecf20Sopenharmony_ci 14538c2ecf20Sopenharmony_ci/** 14548c2ecf20Sopenharmony_ci * inode_fix_size - fix inode size 14558c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object 14568c2ecf20Sopenharmony_ci * @e: inode size information for recovery 14578c2ecf20Sopenharmony_ci */ 14588c2ecf20Sopenharmony_cistatic int inode_fix_size(struct ubifs_info *c, struct size_entry *e) 14598c2ecf20Sopenharmony_ci{ 14608c2ecf20Sopenharmony_ci struct inode *inode; 14618c2ecf20Sopenharmony_ci struct ubifs_inode *ui; 14628c2ecf20Sopenharmony_ci int err; 14638c2ecf20Sopenharmony_ci 14648c2ecf20Sopenharmony_ci if (c->ro_mount) 14658c2ecf20Sopenharmony_ci ubifs_assert(c, !e->inode); 14668c2ecf20Sopenharmony_ci 14678c2ecf20Sopenharmony_ci if (e->inode) { 14688c2ecf20Sopenharmony_ci /* Remounting rw, pick up inode we stored earlier */ 14698c2ecf20Sopenharmony_ci inode = e->inode; 14708c2ecf20Sopenharmony_ci } else { 14718c2ecf20Sopenharmony_ci inode = ubifs_iget(c->vfs_sb, e->inum); 14728c2ecf20Sopenharmony_ci if (IS_ERR(inode)) 14738c2ecf20Sopenharmony_ci return PTR_ERR(inode); 14748c2ecf20Sopenharmony_ci 14758c2ecf20Sopenharmony_ci if (inode->i_size >= e->d_size) { 14768c2ecf20Sopenharmony_ci /* 14778c2ecf20Sopenharmony_ci * The original inode in the index already has a size 14788c2ecf20Sopenharmony_ci * big enough, nothing to do 14798c2ecf20Sopenharmony_ci */ 14808c2ecf20Sopenharmony_ci iput(inode); 14818c2ecf20Sopenharmony_ci return 0; 14828c2ecf20Sopenharmony_ci } 14838c2ecf20Sopenharmony_ci 14848c2ecf20Sopenharmony_ci dbg_rcvry("ino %lu size %lld -> %lld", 14858c2ecf20Sopenharmony_ci (unsigned long)e->inum, 14868c2ecf20Sopenharmony_ci inode->i_size, e->d_size); 14878c2ecf20Sopenharmony_ci 14888c2ecf20Sopenharmony_ci ui = ubifs_inode(inode); 14898c2ecf20Sopenharmony_ci 14908c2ecf20Sopenharmony_ci inode->i_size = e->d_size; 14918c2ecf20Sopenharmony_ci ui->ui_size = e->d_size; 14928c2ecf20Sopenharmony_ci ui->synced_i_size = e->d_size; 14938c2ecf20Sopenharmony_ci 14948c2ecf20Sopenharmony_ci e->inode = inode; 14958c2ecf20Sopenharmony_ci } 14968c2ecf20Sopenharmony_ci 14978c2ecf20Sopenharmony_ci /* 14988c2ecf20Sopenharmony_ci * In readonly mode just keep the inode pinned in memory until we go 14998c2ecf20Sopenharmony_ci * readwrite. In readwrite mode write the inode to the journal with the 15008c2ecf20Sopenharmony_ci * fixed size. 15018c2ecf20Sopenharmony_ci */ 15028c2ecf20Sopenharmony_ci if (c->ro_mount) 15038c2ecf20Sopenharmony_ci return 0; 15048c2ecf20Sopenharmony_ci 15058c2ecf20Sopenharmony_ci err = ubifs_jnl_write_inode(c, inode); 15068c2ecf20Sopenharmony_ci 15078c2ecf20Sopenharmony_ci iput(inode); 15088c2ecf20Sopenharmony_ci 15098c2ecf20Sopenharmony_ci if (err) 15108c2ecf20Sopenharmony_ci return err; 15118c2ecf20Sopenharmony_ci 15128c2ecf20Sopenharmony_ci rb_erase(&e->rb, &c->size_tree); 15138c2ecf20Sopenharmony_ci kfree(e); 15148c2ecf20Sopenharmony_ci 15158c2ecf20Sopenharmony_ci return 0; 15168c2ecf20Sopenharmony_ci} 15178c2ecf20Sopenharmony_ci 15188c2ecf20Sopenharmony_ci/** 15198c2ecf20Sopenharmony_ci * ubifs_recover_size - recover inode size. 15208c2ecf20Sopenharmony_ci * @c: UBIFS file-system description object 15218c2ecf20Sopenharmony_ci * @in_place: If true, do a in-place size fixup 15228c2ecf20Sopenharmony_ci * 15238c2ecf20Sopenharmony_ci * This function attempts to fix inode size discrepancies identified by the 15248c2ecf20Sopenharmony_ci * 'ubifs_recover_size_accum()' function. 15258c2ecf20Sopenharmony_ci * 15268c2ecf20Sopenharmony_ci * This functions returns %0 on success and a negative error code on failure. 15278c2ecf20Sopenharmony_ci */ 15288c2ecf20Sopenharmony_ciint ubifs_recover_size(struct ubifs_info *c, bool in_place) 15298c2ecf20Sopenharmony_ci{ 15308c2ecf20Sopenharmony_ci struct rb_node *this = rb_first(&c->size_tree); 15318c2ecf20Sopenharmony_ci 15328c2ecf20Sopenharmony_ci while (this) { 15338c2ecf20Sopenharmony_ci struct size_entry *e; 15348c2ecf20Sopenharmony_ci int err; 15358c2ecf20Sopenharmony_ci 15368c2ecf20Sopenharmony_ci e = rb_entry(this, struct size_entry, rb); 15378c2ecf20Sopenharmony_ci 15388c2ecf20Sopenharmony_ci this = rb_next(this); 15398c2ecf20Sopenharmony_ci 15408c2ecf20Sopenharmony_ci if (!e->exists) { 15418c2ecf20Sopenharmony_ci union ubifs_key key; 15428c2ecf20Sopenharmony_ci 15438c2ecf20Sopenharmony_ci ino_key_init(c, &key, e->inum); 15448c2ecf20Sopenharmony_ci err = ubifs_tnc_lookup(c, &key, c->sbuf); 15458c2ecf20Sopenharmony_ci if (err && err != -ENOENT) 15468c2ecf20Sopenharmony_ci return err; 15478c2ecf20Sopenharmony_ci if (err == -ENOENT) { 15488c2ecf20Sopenharmony_ci /* Remove data nodes that have no inode */ 15498c2ecf20Sopenharmony_ci dbg_rcvry("removing ino %lu", 15508c2ecf20Sopenharmony_ci (unsigned long)e->inum); 15518c2ecf20Sopenharmony_ci err = ubifs_tnc_remove_ino(c, e->inum); 15528c2ecf20Sopenharmony_ci if (err) 15538c2ecf20Sopenharmony_ci return err; 15548c2ecf20Sopenharmony_ci } else { 15558c2ecf20Sopenharmony_ci struct ubifs_ino_node *ino = c->sbuf; 15568c2ecf20Sopenharmony_ci 15578c2ecf20Sopenharmony_ci e->exists = 1; 15588c2ecf20Sopenharmony_ci e->i_size = le64_to_cpu(ino->size); 15598c2ecf20Sopenharmony_ci } 15608c2ecf20Sopenharmony_ci } 15618c2ecf20Sopenharmony_ci 15628c2ecf20Sopenharmony_ci if (e->exists && e->i_size < e->d_size) { 15638c2ecf20Sopenharmony_ci ubifs_assert(c, !(c->ro_mount && in_place)); 15648c2ecf20Sopenharmony_ci 15658c2ecf20Sopenharmony_ci /* 15668c2ecf20Sopenharmony_ci * We found data that is outside the found inode size, 15678c2ecf20Sopenharmony_ci * fixup the inode size 15688c2ecf20Sopenharmony_ci */ 15698c2ecf20Sopenharmony_ci 15708c2ecf20Sopenharmony_ci if (in_place) { 15718c2ecf20Sopenharmony_ci err = fix_size_in_place(c, e); 15728c2ecf20Sopenharmony_ci if (err) 15738c2ecf20Sopenharmony_ci return err; 15748c2ecf20Sopenharmony_ci iput(e->inode); 15758c2ecf20Sopenharmony_ci } else { 15768c2ecf20Sopenharmony_ci err = inode_fix_size(c, e); 15778c2ecf20Sopenharmony_ci if (err) 15788c2ecf20Sopenharmony_ci return err; 15798c2ecf20Sopenharmony_ci continue; 15808c2ecf20Sopenharmony_ci } 15818c2ecf20Sopenharmony_ci } 15828c2ecf20Sopenharmony_ci 15838c2ecf20Sopenharmony_ci rb_erase(&e->rb, &c->size_tree); 15848c2ecf20Sopenharmony_ci kfree(e); 15858c2ecf20Sopenharmony_ci } 15868c2ecf20Sopenharmony_ci 15878c2ecf20Sopenharmony_ci return 0; 15888c2ecf20Sopenharmony_ci} 1589