162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * This file is part of UBIFS. 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2006-2008 Nokia Corporation 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Authors: Adrian Hunter 862306a36Sopenharmony_ci * Artem Bityutskiy (Битюцкий Артём) 962306a36Sopenharmony_ci */ 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci/* 1262306a36Sopenharmony_ci * This file implements functions needed to recover from unclean un-mounts. 1362306a36Sopenharmony_ci * When UBIFS is mounted, it checks a flag on the master node to determine if 1462306a36Sopenharmony_ci * an un-mount was completed successfully. If not, the process of mounting 1562306a36Sopenharmony_ci * incorporates additional checking and fixing of on-flash data structures. 1662306a36Sopenharmony_ci * UBIFS always cleans away all remnants of an unclean un-mount, so that 1762306a36Sopenharmony_ci * errors do not accumulate. However UBIFS defers recovery if it is mounted 1862306a36Sopenharmony_ci * read-only, and the flash is not modified in that case. 1962306a36Sopenharmony_ci * 2062306a36Sopenharmony_ci * The general UBIFS approach to the recovery is that it recovers from 2162306a36Sopenharmony_ci * corruptions which could be caused by power cuts, but it refuses to recover 2262306a36Sopenharmony_ci * from corruption caused by other reasons. And UBIFS tries to distinguish 2362306a36Sopenharmony_ci * between these 2 reasons of corruptions and silently recover in the former 2462306a36Sopenharmony_ci * case and loudly complain in the latter case. 2562306a36Sopenharmony_ci * 2662306a36Sopenharmony_ci * UBIFS writes only to erased LEBs, so it writes only to the flash space 2762306a36Sopenharmony_ci * containing only 0xFFs. UBIFS also always writes strictly from the beginning 2862306a36Sopenharmony_ci * of the LEB to the end. And UBIFS assumes that the underlying flash media 2962306a36Sopenharmony_ci * writes in @c->max_write_size bytes at a time. 3062306a36Sopenharmony_ci * 3162306a36Sopenharmony_ci * Hence, if UBIFS finds a corrupted node at offset X, it expects only the min. 3262306a36Sopenharmony_ci * I/O unit corresponding to offset X to contain corrupted data, all the 3362306a36Sopenharmony_ci * following min. I/O units have to contain empty space (all 0xFFs). If this is 3462306a36Sopenharmony_ci * not true, the corruption cannot be the result of a power cut, and UBIFS 3562306a36Sopenharmony_ci * refuses to mount. 3662306a36Sopenharmony_ci */ 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci#include <linux/crc32.h> 3962306a36Sopenharmony_ci#include <linux/slab.h> 4062306a36Sopenharmony_ci#include "ubifs.h" 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci/** 4362306a36Sopenharmony_ci * is_empty - determine whether a buffer is empty (contains all 0xff). 4462306a36Sopenharmony_ci * @buf: buffer to clean 4562306a36Sopenharmony_ci * @len: length of buffer 4662306a36Sopenharmony_ci * 4762306a36Sopenharmony_ci * This function returns %1 if the buffer is empty (contains all 0xff) otherwise 4862306a36Sopenharmony_ci * %0 is returned. 4962306a36Sopenharmony_ci */ 5062306a36Sopenharmony_cistatic int is_empty(void *buf, int len) 5162306a36Sopenharmony_ci{ 5262306a36Sopenharmony_ci uint8_t *p = buf; 5362306a36Sopenharmony_ci int i; 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci for (i = 0; i < len; i++) 5662306a36Sopenharmony_ci if (*p++ != 0xff) 5762306a36Sopenharmony_ci return 0; 5862306a36Sopenharmony_ci return 1; 5962306a36Sopenharmony_ci} 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci/** 6262306a36Sopenharmony_ci * first_non_ff - find offset of the first non-0xff byte. 6362306a36Sopenharmony_ci * @buf: buffer to search in 6462306a36Sopenharmony_ci * @len: length of buffer 6562306a36Sopenharmony_ci * 6662306a36Sopenharmony_ci * This function returns offset of the first non-0xff byte in @buf or %-1 if 6762306a36Sopenharmony_ci * the buffer contains only 0xff bytes. 6862306a36Sopenharmony_ci */ 6962306a36Sopenharmony_cistatic int first_non_ff(void *buf, int len) 7062306a36Sopenharmony_ci{ 7162306a36Sopenharmony_ci uint8_t *p = buf; 7262306a36Sopenharmony_ci int i; 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci for (i = 0; i < len; i++) 7562306a36Sopenharmony_ci if (*p++ != 0xff) 7662306a36Sopenharmony_ci return i; 7762306a36Sopenharmony_ci return -1; 7862306a36Sopenharmony_ci} 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci/** 8162306a36Sopenharmony_ci * get_master_node - get the last valid master node allowing for corruption. 8262306a36Sopenharmony_ci * @c: UBIFS file-system description object 8362306a36Sopenharmony_ci * @lnum: LEB number 8462306a36Sopenharmony_ci * @pbuf: buffer containing the LEB read, is returned here 8562306a36Sopenharmony_ci * @mst: master node, if found, is returned here 8662306a36Sopenharmony_ci * @cor: corruption, if found, is returned here 8762306a36Sopenharmony_ci * 8862306a36Sopenharmony_ci * This function allocates a buffer, reads the LEB into it, and finds and 8962306a36Sopenharmony_ci * returns the last valid master node allowing for one area of corruption. 9062306a36Sopenharmony_ci * The corrupt area, if there is one, must be consistent with the assumption 9162306a36Sopenharmony_ci * that it is the result of an unclean unmount while the master node was being 9262306a36Sopenharmony_ci * written. Under those circumstances, it is valid to use the previously written 9362306a36Sopenharmony_ci * master node. 9462306a36Sopenharmony_ci * 9562306a36Sopenharmony_ci * This function returns %0 on success and a negative error code on failure. 9662306a36Sopenharmony_ci */ 9762306a36Sopenharmony_cistatic int get_master_node(const struct ubifs_info *c, int lnum, void **pbuf, 9862306a36Sopenharmony_ci struct ubifs_mst_node **mst, void **cor) 9962306a36Sopenharmony_ci{ 10062306a36Sopenharmony_ci const int sz = c->mst_node_alsz; 10162306a36Sopenharmony_ci int err, offs, len; 10262306a36Sopenharmony_ci void *sbuf, *buf; 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci sbuf = vmalloc(c->leb_size); 10562306a36Sopenharmony_ci if (!sbuf) 10662306a36Sopenharmony_ci return -ENOMEM; 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci err = ubifs_leb_read(c, lnum, sbuf, 0, c->leb_size, 0); 10962306a36Sopenharmony_ci if (err && err != -EBADMSG) 11062306a36Sopenharmony_ci goto out_free; 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci /* Find the first position that is definitely not a node */ 11362306a36Sopenharmony_ci offs = 0; 11462306a36Sopenharmony_ci buf = sbuf; 11562306a36Sopenharmony_ci len = c->leb_size; 11662306a36Sopenharmony_ci while (offs + UBIFS_MST_NODE_SZ <= c->leb_size) { 11762306a36Sopenharmony_ci struct ubifs_ch *ch = buf; 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci if (le32_to_cpu(ch->magic) != UBIFS_NODE_MAGIC) 12062306a36Sopenharmony_ci break; 12162306a36Sopenharmony_ci offs += sz; 12262306a36Sopenharmony_ci buf += sz; 12362306a36Sopenharmony_ci len -= sz; 12462306a36Sopenharmony_ci } 12562306a36Sopenharmony_ci /* See if there was a valid master node before that */ 12662306a36Sopenharmony_ci if (offs) { 12762306a36Sopenharmony_ci int ret; 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ci offs -= sz; 13062306a36Sopenharmony_ci buf -= sz; 13162306a36Sopenharmony_ci len += sz; 13262306a36Sopenharmony_ci ret = ubifs_scan_a_node(c, buf, len, lnum, offs, 1); 13362306a36Sopenharmony_ci if (ret != SCANNED_A_NODE && offs) { 13462306a36Sopenharmony_ci /* Could have been corruption so check one place back */ 13562306a36Sopenharmony_ci offs -= sz; 13662306a36Sopenharmony_ci buf -= sz; 13762306a36Sopenharmony_ci len += sz; 13862306a36Sopenharmony_ci ret = ubifs_scan_a_node(c, buf, len, lnum, offs, 1); 13962306a36Sopenharmony_ci if (ret != SCANNED_A_NODE) 14062306a36Sopenharmony_ci /* 14162306a36Sopenharmony_ci * We accept only one area of corruption because 14262306a36Sopenharmony_ci * we are assuming that it was caused while 14362306a36Sopenharmony_ci * trying to write a master node. 14462306a36Sopenharmony_ci */ 14562306a36Sopenharmony_ci goto out_err; 14662306a36Sopenharmony_ci } 14762306a36Sopenharmony_ci if (ret == SCANNED_A_NODE) { 14862306a36Sopenharmony_ci struct ubifs_ch *ch = buf; 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_ci if (ch->node_type != UBIFS_MST_NODE) 15162306a36Sopenharmony_ci goto out_err; 15262306a36Sopenharmony_ci dbg_rcvry("found a master node at %d:%d", lnum, offs); 15362306a36Sopenharmony_ci *mst = buf; 15462306a36Sopenharmony_ci offs += sz; 15562306a36Sopenharmony_ci buf += sz; 15662306a36Sopenharmony_ci len -= sz; 15762306a36Sopenharmony_ci } 15862306a36Sopenharmony_ci } 15962306a36Sopenharmony_ci /* Check for corruption */ 16062306a36Sopenharmony_ci if (offs < c->leb_size) { 16162306a36Sopenharmony_ci if (!is_empty(buf, min_t(int, len, sz))) { 16262306a36Sopenharmony_ci *cor = buf; 16362306a36Sopenharmony_ci dbg_rcvry("found corruption at %d:%d", lnum, offs); 16462306a36Sopenharmony_ci } 16562306a36Sopenharmony_ci offs += sz; 16662306a36Sopenharmony_ci buf += sz; 16762306a36Sopenharmony_ci len -= sz; 16862306a36Sopenharmony_ci } 16962306a36Sopenharmony_ci /* Check remaining empty space */ 17062306a36Sopenharmony_ci if (offs < c->leb_size) 17162306a36Sopenharmony_ci if (!is_empty(buf, len)) 17262306a36Sopenharmony_ci goto out_err; 17362306a36Sopenharmony_ci *pbuf = sbuf; 17462306a36Sopenharmony_ci return 0; 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_ciout_err: 17762306a36Sopenharmony_ci err = -EINVAL; 17862306a36Sopenharmony_ciout_free: 17962306a36Sopenharmony_ci vfree(sbuf); 18062306a36Sopenharmony_ci *mst = NULL; 18162306a36Sopenharmony_ci *cor = NULL; 18262306a36Sopenharmony_ci return err; 18362306a36Sopenharmony_ci} 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci/** 18662306a36Sopenharmony_ci * write_rcvrd_mst_node - write recovered master node. 18762306a36Sopenharmony_ci * @c: UBIFS file-system description object 18862306a36Sopenharmony_ci * @mst: master node 18962306a36Sopenharmony_ci * 19062306a36Sopenharmony_ci * This function returns %0 on success and a negative error code on failure. 19162306a36Sopenharmony_ci */ 19262306a36Sopenharmony_cistatic int write_rcvrd_mst_node(struct ubifs_info *c, 19362306a36Sopenharmony_ci struct ubifs_mst_node *mst) 19462306a36Sopenharmony_ci{ 19562306a36Sopenharmony_ci int err = 0, lnum = UBIFS_MST_LNUM, sz = c->mst_node_alsz; 19662306a36Sopenharmony_ci __le32 save_flags; 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_ci dbg_rcvry("recovery"); 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_ci save_flags = mst->flags; 20162306a36Sopenharmony_ci mst->flags |= cpu_to_le32(UBIFS_MST_RCVRY); 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ci err = ubifs_prepare_node_hmac(c, mst, UBIFS_MST_NODE_SZ, 20462306a36Sopenharmony_ci offsetof(struct ubifs_mst_node, hmac), 1); 20562306a36Sopenharmony_ci if (err) 20662306a36Sopenharmony_ci goto out; 20762306a36Sopenharmony_ci err = ubifs_leb_change(c, lnum, mst, sz); 20862306a36Sopenharmony_ci if (err) 20962306a36Sopenharmony_ci goto out; 21062306a36Sopenharmony_ci err = ubifs_leb_change(c, lnum + 1, mst, sz); 21162306a36Sopenharmony_ci if (err) 21262306a36Sopenharmony_ci goto out; 21362306a36Sopenharmony_ciout: 21462306a36Sopenharmony_ci mst->flags = save_flags; 21562306a36Sopenharmony_ci return err; 21662306a36Sopenharmony_ci} 21762306a36Sopenharmony_ci 21862306a36Sopenharmony_ci/** 21962306a36Sopenharmony_ci * ubifs_recover_master_node - recover the master node. 22062306a36Sopenharmony_ci * @c: UBIFS file-system description object 22162306a36Sopenharmony_ci * 22262306a36Sopenharmony_ci * This function recovers the master node from corruption that may occur due to 22362306a36Sopenharmony_ci * an unclean unmount. 22462306a36Sopenharmony_ci * 22562306a36Sopenharmony_ci * This function returns %0 on success and a negative error code on failure. 22662306a36Sopenharmony_ci */ 22762306a36Sopenharmony_ciint ubifs_recover_master_node(struct ubifs_info *c) 22862306a36Sopenharmony_ci{ 22962306a36Sopenharmony_ci void *buf1 = NULL, *buf2 = NULL, *cor1 = NULL, *cor2 = NULL; 23062306a36Sopenharmony_ci struct ubifs_mst_node *mst1 = NULL, *mst2 = NULL, *mst; 23162306a36Sopenharmony_ci const int sz = c->mst_node_alsz; 23262306a36Sopenharmony_ci int err, offs1, offs2; 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_ci dbg_rcvry("recovery"); 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_ci err = get_master_node(c, UBIFS_MST_LNUM, &buf1, &mst1, &cor1); 23762306a36Sopenharmony_ci if (err) 23862306a36Sopenharmony_ci goto out_free; 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_ci err = get_master_node(c, UBIFS_MST_LNUM + 1, &buf2, &mst2, &cor2); 24162306a36Sopenharmony_ci if (err) 24262306a36Sopenharmony_ci goto out_free; 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ci if (mst1) { 24562306a36Sopenharmony_ci offs1 = (void *)mst1 - buf1; 24662306a36Sopenharmony_ci if ((le32_to_cpu(mst1->flags) & UBIFS_MST_RCVRY) && 24762306a36Sopenharmony_ci (offs1 == 0 && !cor1)) { 24862306a36Sopenharmony_ci /* 24962306a36Sopenharmony_ci * mst1 was written by recovery at offset 0 with no 25062306a36Sopenharmony_ci * corruption. 25162306a36Sopenharmony_ci */ 25262306a36Sopenharmony_ci dbg_rcvry("recovery recovery"); 25362306a36Sopenharmony_ci mst = mst1; 25462306a36Sopenharmony_ci } else if (mst2) { 25562306a36Sopenharmony_ci offs2 = (void *)mst2 - buf2; 25662306a36Sopenharmony_ci if (offs1 == offs2) { 25762306a36Sopenharmony_ci /* Same offset, so must be the same */ 25862306a36Sopenharmony_ci if (ubifs_compare_master_node(c, mst1, mst2)) 25962306a36Sopenharmony_ci goto out_err; 26062306a36Sopenharmony_ci mst = mst1; 26162306a36Sopenharmony_ci } else if (offs2 + sz == offs1) { 26262306a36Sopenharmony_ci /* 1st LEB was written, 2nd was not */ 26362306a36Sopenharmony_ci if (cor1) 26462306a36Sopenharmony_ci goto out_err; 26562306a36Sopenharmony_ci mst = mst1; 26662306a36Sopenharmony_ci } else if (offs1 == 0 && 26762306a36Sopenharmony_ci c->leb_size - offs2 - sz < sz) { 26862306a36Sopenharmony_ci /* 1st LEB was unmapped and written, 2nd not */ 26962306a36Sopenharmony_ci if (cor1) 27062306a36Sopenharmony_ci goto out_err; 27162306a36Sopenharmony_ci mst = mst1; 27262306a36Sopenharmony_ci } else 27362306a36Sopenharmony_ci goto out_err; 27462306a36Sopenharmony_ci } else { 27562306a36Sopenharmony_ci /* 27662306a36Sopenharmony_ci * 2nd LEB was unmapped and about to be written, so 27762306a36Sopenharmony_ci * there must be only one master node in the first LEB 27862306a36Sopenharmony_ci * and no corruption. 27962306a36Sopenharmony_ci */ 28062306a36Sopenharmony_ci if (offs1 != 0 || cor1) 28162306a36Sopenharmony_ci goto out_err; 28262306a36Sopenharmony_ci mst = mst1; 28362306a36Sopenharmony_ci } 28462306a36Sopenharmony_ci } else { 28562306a36Sopenharmony_ci if (!mst2) 28662306a36Sopenharmony_ci goto out_err; 28762306a36Sopenharmony_ci /* 28862306a36Sopenharmony_ci * 1st LEB was unmapped and about to be written, so there must 28962306a36Sopenharmony_ci * be no room left in 2nd LEB. 29062306a36Sopenharmony_ci */ 29162306a36Sopenharmony_ci offs2 = (void *)mst2 - buf2; 29262306a36Sopenharmony_ci if (offs2 + sz + sz <= c->leb_size) 29362306a36Sopenharmony_ci goto out_err; 29462306a36Sopenharmony_ci mst = mst2; 29562306a36Sopenharmony_ci } 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_ci ubifs_msg(c, "recovered master node from LEB %d", 29862306a36Sopenharmony_ci (mst == mst1 ? UBIFS_MST_LNUM : UBIFS_MST_LNUM + 1)); 29962306a36Sopenharmony_ci 30062306a36Sopenharmony_ci memcpy(c->mst_node, mst, UBIFS_MST_NODE_SZ); 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_ci if (c->ro_mount) { 30362306a36Sopenharmony_ci /* Read-only mode. Keep a copy for switching to rw mode */ 30462306a36Sopenharmony_ci c->rcvrd_mst_node = kmalloc(sz, GFP_KERNEL); 30562306a36Sopenharmony_ci if (!c->rcvrd_mst_node) { 30662306a36Sopenharmony_ci err = -ENOMEM; 30762306a36Sopenharmony_ci goto out_free; 30862306a36Sopenharmony_ci } 30962306a36Sopenharmony_ci memcpy(c->rcvrd_mst_node, c->mst_node, UBIFS_MST_NODE_SZ); 31062306a36Sopenharmony_ci 31162306a36Sopenharmony_ci /* 31262306a36Sopenharmony_ci * We had to recover the master node, which means there was an 31362306a36Sopenharmony_ci * unclean reboot. However, it is possible that the master node 31462306a36Sopenharmony_ci * is clean at this point, i.e., %UBIFS_MST_DIRTY is not set. 31562306a36Sopenharmony_ci * E.g., consider the following chain of events: 31662306a36Sopenharmony_ci * 31762306a36Sopenharmony_ci * 1. UBIFS was cleanly unmounted, so the master node is clean 31862306a36Sopenharmony_ci * 2. UBIFS is being mounted R/W and starts changing the master 31962306a36Sopenharmony_ci * node in the first (%UBIFS_MST_LNUM). A power cut happens, 32062306a36Sopenharmony_ci * so this LEB ends up with some amount of garbage at the 32162306a36Sopenharmony_ci * end. 32262306a36Sopenharmony_ci * 3. UBIFS is being mounted R/O. We reach this place and 32362306a36Sopenharmony_ci * recover the master node from the second LEB 32462306a36Sopenharmony_ci * (%UBIFS_MST_LNUM + 1). But we cannot update the media 32562306a36Sopenharmony_ci * because we are being mounted R/O. We have to defer the 32662306a36Sopenharmony_ci * operation. 32762306a36Sopenharmony_ci * 4. However, this master node (@c->mst_node) is marked as 32862306a36Sopenharmony_ci * clean (since the step 1). And if we just return, the 32962306a36Sopenharmony_ci * mount code will be confused and won't recover the master 33062306a36Sopenharmony_ci * node when it is re-mounter R/W later. 33162306a36Sopenharmony_ci * 33262306a36Sopenharmony_ci * Thus, to force the recovery by marking the master node as 33362306a36Sopenharmony_ci * dirty. 33462306a36Sopenharmony_ci */ 33562306a36Sopenharmony_ci c->mst_node->flags |= cpu_to_le32(UBIFS_MST_DIRTY); 33662306a36Sopenharmony_ci } else { 33762306a36Sopenharmony_ci /* Write the recovered master node */ 33862306a36Sopenharmony_ci c->max_sqnum = le64_to_cpu(mst->ch.sqnum) - 1; 33962306a36Sopenharmony_ci err = write_rcvrd_mst_node(c, c->mst_node); 34062306a36Sopenharmony_ci if (err) 34162306a36Sopenharmony_ci goto out_free; 34262306a36Sopenharmony_ci } 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_ci vfree(buf2); 34562306a36Sopenharmony_ci vfree(buf1); 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_ci return 0; 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_ciout_err: 35062306a36Sopenharmony_ci err = -EINVAL; 35162306a36Sopenharmony_ciout_free: 35262306a36Sopenharmony_ci ubifs_err(c, "failed to recover master node"); 35362306a36Sopenharmony_ci if (mst1) { 35462306a36Sopenharmony_ci ubifs_err(c, "dumping first master node"); 35562306a36Sopenharmony_ci ubifs_dump_node(c, mst1, c->leb_size - ((void *)mst1 - buf1)); 35662306a36Sopenharmony_ci } 35762306a36Sopenharmony_ci if (mst2) { 35862306a36Sopenharmony_ci ubifs_err(c, "dumping second master node"); 35962306a36Sopenharmony_ci ubifs_dump_node(c, mst2, c->leb_size - ((void *)mst2 - buf2)); 36062306a36Sopenharmony_ci } 36162306a36Sopenharmony_ci vfree(buf2); 36262306a36Sopenharmony_ci vfree(buf1); 36362306a36Sopenharmony_ci return err; 36462306a36Sopenharmony_ci} 36562306a36Sopenharmony_ci 36662306a36Sopenharmony_ci/** 36762306a36Sopenharmony_ci * ubifs_write_rcvrd_mst_node - write the recovered master node. 36862306a36Sopenharmony_ci * @c: UBIFS file-system description object 36962306a36Sopenharmony_ci * 37062306a36Sopenharmony_ci * This function writes the master node that was recovered during mounting in 37162306a36Sopenharmony_ci * read-only mode and must now be written because we are remounting rw. 37262306a36Sopenharmony_ci * 37362306a36Sopenharmony_ci * This function returns %0 on success and a negative error code on failure. 37462306a36Sopenharmony_ci */ 37562306a36Sopenharmony_ciint ubifs_write_rcvrd_mst_node(struct ubifs_info *c) 37662306a36Sopenharmony_ci{ 37762306a36Sopenharmony_ci int err; 37862306a36Sopenharmony_ci 37962306a36Sopenharmony_ci if (!c->rcvrd_mst_node) 38062306a36Sopenharmony_ci return 0; 38162306a36Sopenharmony_ci c->rcvrd_mst_node->flags |= cpu_to_le32(UBIFS_MST_DIRTY); 38262306a36Sopenharmony_ci c->mst_node->flags |= cpu_to_le32(UBIFS_MST_DIRTY); 38362306a36Sopenharmony_ci err = write_rcvrd_mst_node(c, c->rcvrd_mst_node); 38462306a36Sopenharmony_ci if (err) 38562306a36Sopenharmony_ci return err; 38662306a36Sopenharmony_ci kfree(c->rcvrd_mst_node); 38762306a36Sopenharmony_ci c->rcvrd_mst_node = NULL; 38862306a36Sopenharmony_ci return 0; 38962306a36Sopenharmony_ci} 39062306a36Sopenharmony_ci 39162306a36Sopenharmony_ci/** 39262306a36Sopenharmony_ci * is_last_write - determine if an offset was in the last write to a LEB. 39362306a36Sopenharmony_ci * @c: UBIFS file-system description object 39462306a36Sopenharmony_ci * @buf: buffer to check 39562306a36Sopenharmony_ci * @offs: offset to check 39662306a36Sopenharmony_ci * 39762306a36Sopenharmony_ci * This function returns %1 if @offs was in the last write to the LEB whose data 39862306a36Sopenharmony_ci * is in @buf, otherwise %0 is returned. The determination is made by checking 39962306a36Sopenharmony_ci * for subsequent empty space starting from the next @c->max_write_size 40062306a36Sopenharmony_ci * boundary. 40162306a36Sopenharmony_ci */ 40262306a36Sopenharmony_cistatic int is_last_write(const struct ubifs_info *c, void *buf, int offs) 40362306a36Sopenharmony_ci{ 40462306a36Sopenharmony_ci int empty_offs, check_len; 40562306a36Sopenharmony_ci uint8_t *p; 40662306a36Sopenharmony_ci 40762306a36Sopenharmony_ci /* 40862306a36Sopenharmony_ci * Round up to the next @c->max_write_size boundary i.e. @offs is in 40962306a36Sopenharmony_ci * the last wbuf written. After that should be empty space. 41062306a36Sopenharmony_ci */ 41162306a36Sopenharmony_ci empty_offs = ALIGN(offs + 1, c->max_write_size); 41262306a36Sopenharmony_ci check_len = c->leb_size - empty_offs; 41362306a36Sopenharmony_ci p = buf + empty_offs - offs; 41462306a36Sopenharmony_ci return is_empty(p, check_len); 41562306a36Sopenharmony_ci} 41662306a36Sopenharmony_ci 41762306a36Sopenharmony_ci/** 41862306a36Sopenharmony_ci * clean_buf - clean the data from an LEB sitting in a buffer. 41962306a36Sopenharmony_ci * @c: UBIFS file-system description object 42062306a36Sopenharmony_ci * @buf: buffer to clean 42162306a36Sopenharmony_ci * @lnum: LEB number to clean 42262306a36Sopenharmony_ci * @offs: offset from which to clean 42362306a36Sopenharmony_ci * @len: length of buffer 42462306a36Sopenharmony_ci * 42562306a36Sopenharmony_ci * This function pads up to the next min_io_size boundary (if there is one) and 42662306a36Sopenharmony_ci * sets empty space to all 0xff. @buf, @offs and @len are updated to the next 42762306a36Sopenharmony_ci * @c->min_io_size boundary. 42862306a36Sopenharmony_ci */ 42962306a36Sopenharmony_cistatic void clean_buf(const struct ubifs_info *c, void **buf, int lnum, 43062306a36Sopenharmony_ci int *offs, int *len) 43162306a36Sopenharmony_ci{ 43262306a36Sopenharmony_ci int empty_offs, pad_len; 43362306a36Sopenharmony_ci 43462306a36Sopenharmony_ci dbg_rcvry("cleaning corruption at %d:%d", lnum, *offs); 43562306a36Sopenharmony_ci 43662306a36Sopenharmony_ci ubifs_assert(c, !(*offs & 7)); 43762306a36Sopenharmony_ci empty_offs = ALIGN(*offs, c->min_io_size); 43862306a36Sopenharmony_ci pad_len = empty_offs - *offs; 43962306a36Sopenharmony_ci ubifs_pad(c, *buf, pad_len); 44062306a36Sopenharmony_ci *offs += pad_len; 44162306a36Sopenharmony_ci *buf += pad_len; 44262306a36Sopenharmony_ci *len -= pad_len; 44362306a36Sopenharmony_ci memset(*buf, 0xff, c->leb_size - empty_offs); 44462306a36Sopenharmony_ci} 44562306a36Sopenharmony_ci 44662306a36Sopenharmony_ci/** 44762306a36Sopenharmony_ci * no_more_nodes - determine if there are no more nodes in a buffer. 44862306a36Sopenharmony_ci * @c: UBIFS file-system description object 44962306a36Sopenharmony_ci * @buf: buffer to check 45062306a36Sopenharmony_ci * @len: length of buffer 45162306a36Sopenharmony_ci * @lnum: LEB number of the LEB from which @buf was read 45262306a36Sopenharmony_ci * @offs: offset from which @buf was read 45362306a36Sopenharmony_ci * 45462306a36Sopenharmony_ci * This function ensures that the corrupted node at @offs is the last thing 45562306a36Sopenharmony_ci * written to a LEB. This function returns %1 if more data is not found and 45662306a36Sopenharmony_ci * %0 if more data is found. 45762306a36Sopenharmony_ci */ 45862306a36Sopenharmony_cistatic int no_more_nodes(const struct ubifs_info *c, void *buf, int len, 45962306a36Sopenharmony_ci int lnum, int offs) 46062306a36Sopenharmony_ci{ 46162306a36Sopenharmony_ci struct ubifs_ch *ch = buf; 46262306a36Sopenharmony_ci int skip, dlen = le32_to_cpu(ch->len); 46362306a36Sopenharmony_ci 46462306a36Sopenharmony_ci /* Check for empty space after the corrupt node's common header */ 46562306a36Sopenharmony_ci skip = ALIGN(offs + UBIFS_CH_SZ, c->max_write_size) - offs; 46662306a36Sopenharmony_ci if (is_empty(buf + skip, len - skip)) 46762306a36Sopenharmony_ci return 1; 46862306a36Sopenharmony_ci /* 46962306a36Sopenharmony_ci * The area after the common header size is not empty, so the common 47062306a36Sopenharmony_ci * header must be intact. Check it. 47162306a36Sopenharmony_ci */ 47262306a36Sopenharmony_ci if (ubifs_check_node(c, buf, len, lnum, offs, 1, 0) != -EUCLEAN) { 47362306a36Sopenharmony_ci dbg_rcvry("unexpected bad common header at %d:%d", lnum, offs); 47462306a36Sopenharmony_ci return 0; 47562306a36Sopenharmony_ci } 47662306a36Sopenharmony_ci /* Now we know the corrupt node's length we can skip over it */ 47762306a36Sopenharmony_ci skip = ALIGN(offs + dlen, c->max_write_size) - offs; 47862306a36Sopenharmony_ci /* After which there should be empty space */ 47962306a36Sopenharmony_ci if (is_empty(buf + skip, len - skip)) 48062306a36Sopenharmony_ci return 1; 48162306a36Sopenharmony_ci dbg_rcvry("unexpected data at %d:%d", lnum, offs + skip); 48262306a36Sopenharmony_ci return 0; 48362306a36Sopenharmony_ci} 48462306a36Sopenharmony_ci 48562306a36Sopenharmony_ci/** 48662306a36Sopenharmony_ci * fix_unclean_leb - fix an unclean LEB. 48762306a36Sopenharmony_ci * @c: UBIFS file-system description object 48862306a36Sopenharmony_ci * @sleb: scanned LEB information 48962306a36Sopenharmony_ci * @start: offset where scan started 49062306a36Sopenharmony_ci */ 49162306a36Sopenharmony_cistatic int fix_unclean_leb(struct ubifs_info *c, struct ubifs_scan_leb *sleb, 49262306a36Sopenharmony_ci int start) 49362306a36Sopenharmony_ci{ 49462306a36Sopenharmony_ci int lnum = sleb->lnum, endpt = start; 49562306a36Sopenharmony_ci 49662306a36Sopenharmony_ci /* Get the end offset of the last node we are keeping */ 49762306a36Sopenharmony_ci if (!list_empty(&sleb->nodes)) { 49862306a36Sopenharmony_ci struct ubifs_scan_node *snod; 49962306a36Sopenharmony_ci 50062306a36Sopenharmony_ci snod = list_entry(sleb->nodes.prev, 50162306a36Sopenharmony_ci struct ubifs_scan_node, list); 50262306a36Sopenharmony_ci endpt = snod->offs + snod->len; 50362306a36Sopenharmony_ci } 50462306a36Sopenharmony_ci 50562306a36Sopenharmony_ci if (c->ro_mount && !c->remounting_rw) { 50662306a36Sopenharmony_ci /* Add to recovery list */ 50762306a36Sopenharmony_ci struct ubifs_unclean_leb *ucleb; 50862306a36Sopenharmony_ci 50962306a36Sopenharmony_ci dbg_rcvry("need to fix LEB %d start %d endpt %d", 51062306a36Sopenharmony_ci lnum, start, sleb->endpt); 51162306a36Sopenharmony_ci ucleb = kzalloc(sizeof(struct ubifs_unclean_leb), GFP_NOFS); 51262306a36Sopenharmony_ci if (!ucleb) 51362306a36Sopenharmony_ci return -ENOMEM; 51462306a36Sopenharmony_ci ucleb->lnum = lnum; 51562306a36Sopenharmony_ci ucleb->endpt = endpt; 51662306a36Sopenharmony_ci list_add_tail(&ucleb->list, &c->unclean_leb_list); 51762306a36Sopenharmony_ci } else { 51862306a36Sopenharmony_ci /* Write the fixed LEB back to flash */ 51962306a36Sopenharmony_ci int err; 52062306a36Sopenharmony_ci 52162306a36Sopenharmony_ci dbg_rcvry("fixing LEB %d start %d endpt %d", 52262306a36Sopenharmony_ci lnum, start, sleb->endpt); 52362306a36Sopenharmony_ci if (endpt == 0) { 52462306a36Sopenharmony_ci err = ubifs_leb_unmap(c, lnum); 52562306a36Sopenharmony_ci if (err) 52662306a36Sopenharmony_ci return err; 52762306a36Sopenharmony_ci } else { 52862306a36Sopenharmony_ci int len = ALIGN(endpt, c->min_io_size); 52962306a36Sopenharmony_ci 53062306a36Sopenharmony_ci if (start) { 53162306a36Sopenharmony_ci err = ubifs_leb_read(c, lnum, sleb->buf, 0, 53262306a36Sopenharmony_ci start, 1); 53362306a36Sopenharmony_ci if (err) 53462306a36Sopenharmony_ci return err; 53562306a36Sopenharmony_ci } 53662306a36Sopenharmony_ci /* Pad to min_io_size */ 53762306a36Sopenharmony_ci if (len > endpt) { 53862306a36Sopenharmony_ci int pad_len = len - ALIGN(endpt, 8); 53962306a36Sopenharmony_ci 54062306a36Sopenharmony_ci if (pad_len > 0) { 54162306a36Sopenharmony_ci void *buf = sleb->buf + len - pad_len; 54262306a36Sopenharmony_ci 54362306a36Sopenharmony_ci ubifs_pad(c, buf, pad_len); 54462306a36Sopenharmony_ci } 54562306a36Sopenharmony_ci } 54662306a36Sopenharmony_ci err = ubifs_leb_change(c, lnum, sleb->buf, len); 54762306a36Sopenharmony_ci if (err) 54862306a36Sopenharmony_ci return err; 54962306a36Sopenharmony_ci } 55062306a36Sopenharmony_ci } 55162306a36Sopenharmony_ci return 0; 55262306a36Sopenharmony_ci} 55362306a36Sopenharmony_ci 55462306a36Sopenharmony_ci/** 55562306a36Sopenharmony_ci * drop_last_group - drop the last group of nodes. 55662306a36Sopenharmony_ci * @sleb: scanned LEB information 55762306a36Sopenharmony_ci * @offs: offset of dropped nodes is returned here 55862306a36Sopenharmony_ci * 55962306a36Sopenharmony_ci * This is a helper function for 'ubifs_recover_leb()' which drops the last 56062306a36Sopenharmony_ci * group of nodes of the scanned LEB. 56162306a36Sopenharmony_ci */ 56262306a36Sopenharmony_cistatic void drop_last_group(struct ubifs_scan_leb *sleb, int *offs) 56362306a36Sopenharmony_ci{ 56462306a36Sopenharmony_ci while (!list_empty(&sleb->nodes)) { 56562306a36Sopenharmony_ci struct ubifs_scan_node *snod; 56662306a36Sopenharmony_ci struct ubifs_ch *ch; 56762306a36Sopenharmony_ci 56862306a36Sopenharmony_ci snod = list_entry(sleb->nodes.prev, struct ubifs_scan_node, 56962306a36Sopenharmony_ci list); 57062306a36Sopenharmony_ci ch = snod->node; 57162306a36Sopenharmony_ci if (ch->group_type != UBIFS_IN_NODE_GROUP) 57262306a36Sopenharmony_ci break; 57362306a36Sopenharmony_ci 57462306a36Sopenharmony_ci dbg_rcvry("dropping grouped node at %d:%d", 57562306a36Sopenharmony_ci sleb->lnum, snod->offs); 57662306a36Sopenharmony_ci *offs = snod->offs; 57762306a36Sopenharmony_ci list_del(&snod->list); 57862306a36Sopenharmony_ci kfree(snod); 57962306a36Sopenharmony_ci sleb->nodes_cnt -= 1; 58062306a36Sopenharmony_ci } 58162306a36Sopenharmony_ci} 58262306a36Sopenharmony_ci 58362306a36Sopenharmony_ci/** 58462306a36Sopenharmony_ci * drop_last_node - drop the last node. 58562306a36Sopenharmony_ci * @sleb: scanned LEB information 58662306a36Sopenharmony_ci * @offs: offset of dropped nodes is returned here 58762306a36Sopenharmony_ci * 58862306a36Sopenharmony_ci * This is a helper function for 'ubifs_recover_leb()' which drops the last 58962306a36Sopenharmony_ci * node of the scanned LEB. 59062306a36Sopenharmony_ci */ 59162306a36Sopenharmony_cistatic void drop_last_node(struct ubifs_scan_leb *sleb, int *offs) 59262306a36Sopenharmony_ci{ 59362306a36Sopenharmony_ci struct ubifs_scan_node *snod; 59462306a36Sopenharmony_ci 59562306a36Sopenharmony_ci if (!list_empty(&sleb->nodes)) { 59662306a36Sopenharmony_ci snod = list_entry(sleb->nodes.prev, struct ubifs_scan_node, 59762306a36Sopenharmony_ci list); 59862306a36Sopenharmony_ci 59962306a36Sopenharmony_ci dbg_rcvry("dropping last node at %d:%d", 60062306a36Sopenharmony_ci sleb->lnum, snod->offs); 60162306a36Sopenharmony_ci *offs = snod->offs; 60262306a36Sopenharmony_ci list_del(&snod->list); 60362306a36Sopenharmony_ci kfree(snod); 60462306a36Sopenharmony_ci sleb->nodes_cnt -= 1; 60562306a36Sopenharmony_ci } 60662306a36Sopenharmony_ci} 60762306a36Sopenharmony_ci 60862306a36Sopenharmony_ci/** 60962306a36Sopenharmony_ci * ubifs_recover_leb - scan and recover a LEB. 61062306a36Sopenharmony_ci * @c: UBIFS file-system description object 61162306a36Sopenharmony_ci * @lnum: LEB number 61262306a36Sopenharmony_ci * @offs: offset 61362306a36Sopenharmony_ci * @sbuf: LEB-sized buffer to use 61462306a36Sopenharmony_ci * @jhead: journal head number this LEB belongs to (%-1 if the LEB does not 61562306a36Sopenharmony_ci * belong to any journal head) 61662306a36Sopenharmony_ci * 61762306a36Sopenharmony_ci * This function does a scan of a LEB, but caters for errors that might have 61862306a36Sopenharmony_ci * been caused by the unclean unmount from which we are attempting to recover. 61962306a36Sopenharmony_ci * Returns the scanned information on success and a negative error code on 62062306a36Sopenharmony_ci * failure. 62162306a36Sopenharmony_ci */ 62262306a36Sopenharmony_cistruct ubifs_scan_leb *ubifs_recover_leb(struct ubifs_info *c, int lnum, 62362306a36Sopenharmony_ci int offs, void *sbuf, int jhead) 62462306a36Sopenharmony_ci{ 62562306a36Sopenharmony_ci int ret = 0, err, len = c->leb_size - offs, start = offs, min_io_unit; 62662306a36Sopenharmony_ci int grouped = jhead == -1 ? 0 : c->jheads[jhead].grouped; 62762306a36Sopenharmony_ci struct ubifs_scan_leb *sleb; 62862306a36Sopenharmony_ci void *buf = sbuf + offs; 62962306a36Sopenharmony_ci 63062306a36Sopenharmony_ci dbg_rcvry("%d:%d, jhead %d, grouped %d", lnum, offs, jhead, grouped); 63162306a36Sopenharmony_ci 63262306a36Sopenharmony_ci sleb = ubifs_start_scan(c, lnum, offs, sbuf); 63362306a36Sopenharmony_ci if (IS_ERR(sleb)) 63462306a36Sopenharmony_ci return sleb; 63562306a36Sopenharmony_ci 63662306a36Sopenharmony_ci ubifs_assert(c, len >= 8); 63762306a36Sopenharmony_ci while (len >= 8) { 63862306a36Sopenharmony_ci dbg_scan("look at LEB %d:%d (%d bytes left)", 63962306a36Sopenharmony_ci lnum, offs, len); 64062306a36Sopenharmony_ci 64162306a36Sopenharmony_ci cond_resched(); 64262306a36Sopenharmony_ci 64362306a36Sopenharmony_ci /* 64462306a36Sopenharmony_ci * Scan quietly until there is an error from which we cannot 64562306a36Sopenharmony_ci * recover 64662306a36Sopenharmony_ci */ 64762306a36Sopenharmony_ci ret = ubifs_scan_a_node(c, buf, len, lnum, offs, 1); 64862306a36Sopenharmony_ci if (ret == SCANNED_A_NODE) { 64962306a36Sopenharmony_ci /* A valid node, and not a padding node */ 65062306a36Sopenharmony_ci struct ubifs_ch *ch = buf; 65162306a36Sopenharmony_ci int node_len; 65262306a36Sopenharmony_ci 65362306a36Sopenharmony_ci err = ubifs_add_snod(c, sleb, buf, offs); 65462306a36Sopenharmony_ci if (err) 65562306a36Sopenharmony_ci goto error; 65662306a36Sopenharmony_ci node_len = ALIGN(le32_to_cpu(ch->len), 8); 65762306a36Sopenharmony_ci offs += node_len; 65862306a36Sopenharmony_ci buf += node_len; 65962306a36Sopenharmony_ci len -= node_len; 66062306a36Sopenharmony_ci } else if (ret > 0) { 66162306a36Sopenharmony_ci /* Padding bytes or a valid padding node */ 66262306a36Sopenharmony_ci offs += ret; 66362306a36Sopenharmony_ci buf += ret; 66462306a36Sopenharmony_ci len -= ret; 66562306a36Sopenharmony_ci } else if (ret == SCANNED_EMPTY_SPACE || 66662306a36Sopenharmony_ci ret == SCANNED_GARBAGE || 66762306a36Sopenharmony_ci ret == SCANNED_A_BAD_PAD_NODE || 66862306a36Sopenharmony_ci ret == SCANNED_A_CORRUPT_NODE) { 66962306a36Sopenharmony_ci dbg_rcvry("found corruption (%d) at %d:%d", 67062306a36Sopenharmony_ci ret, lnum, offs); 67162306a36Sopenharmony_ci break; 67262306a36Sopenharmony_ci } else { 67362306a36Sopenharmony_ci ubifs_err(c, "unexpected return value %d", ret); 67462306a36Sopenharmony_ci err = -EINVAL; 67562306a36Sopenharmony_ci goto error; 67662306a36Sopenharmony_ci } 67762306a36Sopenharmony_ci } 67862306a36Sopenharmony_ci 67962306a36Sopenharmony_ci if (ret == SCANNED_GARBAGE || ret == SCANNED_A_BAD_PAD_NODE) { 68062306a36Sopenharmony_ci if (!is_last_write(c, buf, offs)) 68162306a36Sopenharmony_ci goto corrupted_rescan; 68262306a36Sopenharmony_ci } else if (ret == SCANNED_A_CORRUPT_NODE) { 68362306a36Sopenharmony_ci if (!no_more_nodes(c, buf, len, lnum, offs)) 68462306a36Sopenharmony_ci goto corrupted_rescan; 68562306a36Sopenharmony_ci } else if (!is_empty(buf, len)) { 68662306a36Sopenharmony_ci if (!is_last_write(c, buf, offs)) { 68762306a36Sopenharmony_ci int corruption = first_non_ff(buf, len); 68862306a36Sopenharmony_ci 68962306a36Sopenharmony_ci /* 69062306a36Sopenharmony_ci * See header comment for this file for more 69162306a36Sopenharmony_ci * explanations about the reasons we have this check. 69262306a36Sopenharmony_ci */ 69362306a36Sopenharmony_ci ubifs_err(c, "corrupt empty space LEB %d:%d, corruption starts at %d", 69462306a36Sopenharmony_ci lnum, offs, corruption); 69562306a36Sopenharmony_ci /* Make sure we dump interesting non-0xFF data */ 69662306a36Sopenharmony_ci offs += corruption; 69762306a36Sopenharmony_ci buf += corruption; 69862306a36Sopenharmony_ci goto corrupted; 69962306a36Sopenharmony_ci } 70062306a36Sopenharmony_ci } 70162306a36Sopenharmony_ci 70262306a36Sopenharmony_ci min_io_unit = round_down(offs, c->min_io_size); 70362306a36Sopenharmony_ci if (grouped) 70462306a36Sopenharmony_ci /* 70562306a36Sopenharmony_ci * If nodes are grouped, always drop the incomplete group at 70662306a36Sopenharmony_ci * the end. 70762306a36Sopenharmony_ci */ 70862306a36Sopenharmony_ci drop_last_group(sleb, &offs); 70962306a36Sopenharmony_ci 71062306a36Sopenharmony_ci if (jhead == GCHD) { 71162306a36Sopenharmony_ci /* 71262306a36Sopenharmony_ci * If this LEB belongs to the GC head then while we are in the 71362306a36Sopenharmony_ci * middle of the same min. I/O unit keep dropping nodes. So 71462306a36Sopenharmony_ci * basically, what we want is to make sure that the last min. 71562306a36Sopenharmony_ci * I/O unit where we saw the corruption is dropped completely 71662306a36Sopenharmony_ci * with all the uncorrupted nodes which may possibly sit there. 71762306a36Sopenharmony_ci * 71862306a36Sopenharmony_ci * In other words, let's name the min. I/O unit where the 71962306a36Sopenharmony_ci * corruption starts B, and the previous min. I/O unit A. The 72062306a36Sopenharmony_ci * below code tries to deal with a situation when half of B 72162306a36Sopenharmony_ci * contains valid nodes or the end of a valid node, and the 72262306a36Sopenharmony_ci * second half of B contains corrupted data or garbage. This 72362306a36Sopenharmony_ci * means that UBIFS had been writing to B just before the power 72462306a36Sopenharmony_ci * cut happened. I do not know how realistic is this scenario 72562306a36Sopenharmony_ci * that half of the min. I/O unit had been written successfully 72662306a36Sopenharmony_ci * and the other half not, but this is possible in our 'failure 72762306a36Sopenharmony_ci * mode emulation' infrastructure at least. 72862306a36Sopenharmony_ci * 72962306a36Sopenharmony_ci * So what is the problem, why we need to drop those nodes? Why 73062306a36Sopenharmony_ci * can't we just clean-up the second half of B by putting a 73162306a36Sopenharmony_ci * padding node there? We can, and this works fine with one 73262306a36Sopenharmony_ci * exception which was reproduced with power cut emulation 73362306a36Sopenharmony_ci * testing and happens extremely rarely. 73462306a36Sopenharmony_ci * 73562306a36Sopenharmony_ci * Imagine the file-system is full, we run GC which starts 73662306a36Sopenharmony_ci * moving valid nodes from LEB X to LEB Y (obviously, LEB Y is 73762306a36Sopenharmony_ci * the current GC head LEB). The @c->gc_lnum is -1, which means 73862306a36Sopenharmony_ci * that GC will retain LEB X and will try to continue. Imagine 73962306a36Sopenharmony_ci * that LEB X is currently the dirtiest LEB, and the amount of 74062306a36Sopenharmony_ci * used space in LEB Y is exactly the same as amount of free 74162306a36Sopenharmony_ci * space in LEB X. 74262306a36Sopenharmony_ci * 74362306a36Sopenharmony_ci * And a power cut happens when nodes are moved from LEB X to 74462306a36Sopenharmony_ci * LEB Y. We are here trying to recover LEB Y which is the GC 74562306a36Sopenharmony_ci * head LEB. We find the min. I/O unit B as described above. 74662306a36Sopenharmony_ci * Then we clean-up LEB Y by padding min. I/O unit. And later 74762306a36Sopenharmony_ci * 'ubifs_rcvry_gc_commit()' function fails, because it cannot 74862306a36Sopenharmony_ci * find a dirty LEB which could be GC'd into LEB Y! Even LEB X 74962306a36Sopenharmony_ci * does not match because the amount of valid nodes there does 75062306a36Sopenharmony_ci * not fit the free space in LEB Y any more! And this is 75162306a36Sopenharmony_ci * because of the padding node which we added to LEB Y. The 75262306a36Sopenharmony_ci * user-visible effect of this which I once observed and 75362306a36Sopenharmony_ci * analysed is that we cannot mount the file-system with 75462306a36Sopenharmony_ci * -ENOSPC error. 75562306a36Sopenharmony_ci * 75662306a36Sopenharmony_ci * So obviously, to make sure that situation does not happen we 75762306a36Sopenharmony_ci * should free min. I/O unit B in LEB Y completely and the last 75862306a36Sopenharmony_ci * used min. I/O unit in LEB Y should be A. This is basically 75962306a36Sopenharmony_ci * what the below code tries to do. 76062306a36Sopenharmony_ci */ 76162306a36Sopenharmony_ci while (offs > min_io_unit) 76262306a36Sopenharmony_ci drop_last_node(sleb, &offs); 76362306a36Sopenharmony_ci } 76462306a36Sopenharmony_ci 76562306a36Sopenharmony_ci buf = sbuf + offs; 76662306a36Sopenharmony_ci len = c->leb_size - offs; 76762306a36Sopenharmony_ci 76862306a36Sopenharmony_ci clean_buf(c, &buf, lnum, &offs, &len); 76962306a36Sopenharmony_ci ubifs_end_scan(c, sleb, lnum, offs); 77062306a36Sopenharmony_ci 77162306a36Sopenharmony_ci err = fix_unclean_leb(c, sleb, start); 77262306a36Sopenharmony_ci if (err) 77362306a36Sopenharmony_ci goto error; 77462306a36Sopenharmony_ci 77562306a36Sopenharmony_ci return sleb; 77662306a36Sopenharmony_ci 77762306a36Sopenharmony_cicorrupted_rescan: 77862306a36Sopenharmony_ci /* Re-scan the corrupted data with verbose messages */ 77962306a36Sopenharmony_ci ubifs_err(c, "corruption %d", ret); 78062306a36Sopenharmony_ci ubifs_scan_a_node(c, buf, len, lnum, offs, 0); 78162306a36Sopenharmony_cicorrupted: 78262306a36Sopenharmony_ci ubifs_scanned_corruption(c, lnum, offs, buf); 78362306a36Sopenharmony_ci err = -EUCLEAN; 78462306a36Sopenharmony_cierror: 78562306a36Sopenharmony_ci ubifs_err(c, "LEB %d scanning failed", lnum); 78662306a36Sopenharmony_ci ubifs_scan_destroy(sleb); 78762306a36Sopenharmony_ci return ERR_PTR(err); 78862306a36Sopenharmony_ci} 78962306a36Sopenharmony_ci 79062306a36Sopenharmony_ci/** 79162306a36Sopenharmony_ci * get_cs_sqnum - get commit start sequence number. 79262306a36Sopenharmony_ci * @c: UBIFS file-system description object 79362306a36Sopenharmony_ci * @lnum: LEB number of commit start node 79462306a36Sopenharmony_ci * @offs: offset of commit start node 79562306a36Sopenharmony_ci * @cs_sqnum: commit start sequence number is returned here 79662306a36Sopenharmony_ci * 79762306a36Sopenharmony_ci * This function returns %0 on success and a negative error code on failure. 79862306a36Sopenharmony_ci */ 79962306a36Sopenharmony_cistatic int get_cs_sqnum(struct ubifs_info *c, int lnum, int offs, 80062306a36Sopenharmony_ci unsigned long long *cs_sqnum) 80162306a36Sopenharmony_ci{ 80262306a36Sopenharmony_ci struct ubifs_cs_node *cs_node = NULL; 80362306a36Sopenharmony_ci int err, ret; 80462306a36Sopenharmony_ci 80562306a36Sopenharmony_ci dbg_rcvry("at %d:%d", lnum, offs); 80662306a36Sopenharmony_ci cs_node = kmalloc(UBIFS_CS_NODE_SZ, GFP_KERNEL); 80762306a36Sopenharmony_ci if (!cs_node) 80862306a36Sopenharmony_ci return -ENOMEM; 80962306a36Sopenharmony_ci if (c->leb_size - offs < UBIFS_CS_NODE_SZ) 81062306a36Sopenharmony_ci goto out_err; 81162306a36Sopenharmony_ci err = ubifs_leb_read(c, lnum, (void *)cs_node, offs, 81262306a36Sopenharmony_ci UBIFS_CS_NODE_SZ, 0); 81362306a36Sopenharmony_ci if (err && err != -EBADMSG) 81462306a36Sopenharmony_ci goto out_free; 81562306a36Sopenharmony_ci ret = ubifs_scan_a_node(c, cs_node, UBIFS_CS_NODE_SZ, lnum, offs, 0); 81662306a36Sopenharmony_ci if (ret != SCANNED_A_NODE) { 81762306a36Sopenharmony_ci ubifs_err(c, "Not a valid node"); 81862306a36Sopenharmony_ci goto out_err; 81962306a36Sopenharmony_ci } 82062306a36Sopenharmony_ci if (cs_node->ch.node_type != UBIFS_CS_NODE) { 82162306a36Sopenharmony_ci ubifs_err(c, "Not a CS node, type is %d", cs_node->ch.node_type); 82262306a36Sopenharmony_ci goto out_err; 82362306a36Sopenharmony_ci } 82462306a36Sopenharmony_ci if (le64_to_cpu(cs_node->cmt_no) != c->cmt_no) { 82562306a36Sopenharmony_ci ubifs_err(c, "CS node cmt_no %llu != current cmt_no %llu", 82662306a36Sopenharmony_ci (unsigned long long)le64_to_cpu(cs_node->cmt_no), 82762306a36Sopenharmony_ci c->cmt_no); 82862306a36Sopenharmony_ci goto out_err; 82962306a36Sopenharmony_ci } 83062306a36Sopenharmony_ci *cs_sqnum = le64_to_cpu(cs_node->ch.sqnum); 83162306a36Sopenharmony_ci dbg_rcvry("commit start sqnum %llu", *cs_sqnum); 83262306a36Sopenharmony_ci kfree(cs_node); 83362306a36Sopenharmony_ci return 0; 83462306a36Sopenharmony_ci 83562306a36Sopenharmony_ciout_err: 83662306a36Sopenharmony_ci err = -EINVAL; 83762306a36Sopenharmony_ciout_free: 83862306a36Sopenharmony_ci ubifs_err(c, "failed to get CS sqnum"); 83962306a36Sopenharmony_ci kfree(cs_node); 84062306a36Sopenharmony_ci return err; 84162306a36Sopenharmony_ci} 84262306a36Sopenharmony_ci 84362306a36Sopenharmony_ci/** 84462306a36Sopenharmony_ci * ubifs_recover_log_leb - scan and recover a log LEB. 84562306a36Sopenharmony_ci * @c: UBIFS file-system description object 84662306a36Sopenharmony_ci * @lnum: LEB number 84762306a36Sopenharmony_ci * @offs: offset 84862306a36Sopenharmony_ci * @sbuf: LEB-sized buffer to use 84962306a36Sopenharmony_ci * 85062306a36Sopenharmony_ci * This function does a scan of a LEB, but caters for errors that might have 85162306a36Sopenharmony_ci * been caused by unclean reboots from which we are attempting to recover 85262306a36Sopenharmony_ci * (assume that only the last log LEB can be corrupted by an unclean reboot). 85362306a36Sopenharmony_ci * 85462306a36Sopenharmony_ci * This function returns %0 on success and a negative error code on failure. 85562306a36Sopenharmony_ci */ 85662306a36Sopenharmony_cistruct ubifs_scan_leb *ubifs_recover_log_leb(struct ubifs_info *c, int lnum, 85762306a36Sopenharmony_ci int offs, void *sbuf) 85862306a36Sopenharmony_ci{ 85962306a36Sopenharmony_ci struct ubifs_scan_leb *sleb; 86062306a36Sopenharmony_ci int next_lnum; 86162306a36Sopenharmony_ci 86262306a36Sopenharmony_ci dbg_rcvry("LEB %d", lnum); 86362306a36Sopenharmony_ci next_lnum = lnum + 1; 86462306a36Sopenharmony_ci if (next_lnum >= UBIFS_LOG_LNUM + c->log_lebs) 86562306a36Sopenharmony_ci next_lnum = UBIFS_LOG_LNUM; 86662306a36Sopenharmony_ci if (next_lnum != c->ltail_lnum) { 86762306a36Sopenharmony_ci /* 86862306a36Sopenharmony_ci * We can only recover at the end of the log, so check that the 86962306a36Sopenharmony_ci * next log LEB is empty or out of date. 87062306a36Sopenharmony_ci */ 87162306a36Sopenharmony_ci sleb = ubifs_scan(c, next_lnum, 0, sbuf, 0); 87262306a36Sopenharmony_ci if (IS_ERR(sleb)) 87362306a36Sopenharmony_ci return sleb; 87462306a36Sopenharmony_ci if (sleb->nodes_cnt) { 87562306a36Sopenharmony_ci struct ubifs_scan_node *snod; 87662306a36Sopenharmony_ci unsigned long long cs_sqnum = c->cs_sqnum; 87762306a36Sopenharmony_ci 87862306a36Sopenharmony_ci snod = list_entry(sleb->nodes.next, 87962306a36Sopenharmony_ci struct ubifs_scan_node, list); 88062306a36Sopenharmony_ci if (cs_sqnum == 0) { 88162306a36Sopenharmony_ci int err; 88262306a36Sopenharmony_ci 88362306a36Sopenharmony_ci err = get_cs_sqnum(c, lnum, offs, &cs_sqnum); 88462306a36Sopenharmony_ci if (err) { 88562306a36Sopenharmony_ci ubifs_scan_destroy(sleb); 88662306a36Sopenharmony_ci return ERR_PTR(err); 88762306a36Sopenharmony_ci } 88862306a36Sopenharmony_ci } 88962306a36Sopenharmony_ci if (snod->sqnum > cs_sqnum) { 89062306a36Sopenharmony_ci ubifs_err(c, "unrecoverable log corruption in LEB %d", 89162306a36Sopenharmony_ci lnum); 89262306a36Sopenharmony_ci ubifs_scan_destroy(sleb); 89362306a36Sopenharmony_ci return ERR_PTR(-EUCLEAN); 89462306a36Sopenharmony_ci } 89562306a36Sopenharmony_ci } 89662306a36Sopenharmony_ci ubifs_scan_destroy(sleb); 89762306a36Sopenharmony_ci } 89862306a36Sopenharmony_ci return ubifs_recover_leb(c, lnum, offs, sbuf, -1); 89962306a36Sopenharmony_ci} 90062306a36Sopenharmony_ci 90162306a36Sopenharmony_ci/** 90262306a36Sopenharmony_ci * recover_head - recover a head. 90362306a36Sopenharmony_ci * @c: UBIFS file-system description object 90462306a36Sopenharmony_ci * @lnum: LEB number of head to recover 90562306a36Sopenharmony_ci * @offs: offset of head to recover 90662306a36Sopenharmony_ci * @sbuf: LEB-sized buffer to use 90762306a36Sopenharmony_ci * 90862306a36Sopenharmony_ci * This function ensures that there is no data on the flash at a head location. 90962306a36Sopenharmony_ci * 91062306a36Sopenharmony_ci * This function returns %0 on success and a negative error code on failure. 91162306a36Sopenharmony_ci */ 91262306a36Sopenharmony_cistatic int recover_head(struct ubifs_info *c, int lnum, int offs, void *sbuf) 91362306a36Sopenharmony_ci{ 91462306a36Sopenharmony_ci int len = c->max_write_size, err; 91562306a36Sopenharmony_ci 91662306a36Sopenharmony_ci if (offs + len > c->leb_size) 91762306a36Sopenharmony_ci len = c->leb_size - offs; 91862306a36Sopenharmony_ci 91962306a36Sopenharmony_ci if (!len) 92062306a36Sopenharmony_ci return 0; 92162306a36Sopenharmony_ci 92262306a36Sopenharmony_ci /* Read at the head location and check it is empty flash */ 92362306a36Sopenharmony_ci err = ubifs_leb_read(c, lnum, sbuf, offs, len, 1); 92462306a36Sopenharmony_ci if (err || !is_empty(sbuf, len)) { 92562306a36Sopenharmony_ci dbg_rcvry("cleaning head at %d:%d", lnum, offs); 92662306a36Sopenharmony_ci if (offs == 0) 92762306a36Sopenharmony_ci return ubifs_leb_unmap(c, lnum); 92862306a36Sopenharmony_ci err = ubifs_leb_read(c, lnum, sbuf, 0, offs, 1); 92962306a36Sopenharmony_ci if (err) 93062306a36Sopenharmony_ci return err; 93162306a36Sopenharmony_ci return ubifs_leb_change(c, lnum, sbuf, offs); 93262306a36Sopenharmony_ci } 93362306a36Sopenharmony_ci 93462306a36Sopenharmony_ci return 0; 93562306a36Sopenharmony_ci} 93662306a36Sopenharmony_ci 93762306a36Sopenharmony_ci/** 93862306a36Sopenharmony_ci * ubifs_recover_inl_heads - recover index and LPT heads. 93962306a36Sopenharmony_ci * @c: UBIFS file-system description object 94062306a36Sopenharmony_ci * @sbuf: LEB-sized buffer to use 94162306a36Sopenharmony_ci * 94262306a36Sopenharmony_ci * This function ensures that there is no data on the flash at the index and 94362306a36Sopenharmony_ci * LPT head locations. 94462306a36Sopenharmony_ci * 94562306a36Sopenharmony_ci * This deals with the recovery of a half-completed journal commit. UBIFS is 94662306a36Sopenharmony_ci * careful never to overwrite the last version of the index or the LPT. Because 94762306a36Sopenharmony_ci * the index and LPT are wandering trees, data from a half-completed commit will 94862306a36Sopenharmony_ci * not be referenced anywhere in UBIFS. The data will be either in LEBs that are 94962306a36Sopenharmony_ci * assumed to be empty and will be unmapped anyway before use, or in the index 95062306a36Sopenharmony_ci * and LPT heads. 95162306a36Sopenharmony_ci * 95262306a36Sopenharmony_ci * This function returns %0 on success and a negative error code on failure. 95362306a36Sopenharmony_ci */ 95462306a36Sopenharmony_ciint ubifs_recover_inl_heads(struct ubifs_info *c, void *sbuf) 95562306a36Sopenharmony_ci{ 95662306a36Sopenharmony_ci int err; 95762306a36Sopenharmony_ci 95862306a36Sopenharmony_ci ubifs_assert(c, !c->ro_mount || c->remounting_rw); 95962306a36Sopenharmony_ci 96062306a36Sopenharmony_ci dbg_rcvry("checking index head at %d:%d", c->ihead_lnum, c->ihead_offs); 96162306a36Sopenharmony_ci err = recover_head(c, c->ihead_lnum, c->ihead_offs, sbuf); 96262306a36Sopenharmony_ci if (err) 96362306a36Sopenharmony_ci return err; 96462306a36Sopenharmony_ci 96562306a36Sopenharmony_ci dbg_rcvry("checking LPT head at %d:%d", c->nhead_lnum, c->nhead_offs); 96662306a36Sopenharmony_ci 96762306a36Sopenharmony_ci return recover_head(c, c->nhead_lnum, c->nhead_offs, sbuf); 96862306a36Sopenharmony_ci} 96962306a36Sopenharmony_ci 97062306a36Sopenharmony_ci/** 97162306a36Sopenharmony_ci * clean_an_unclean_leb - read and write a LEB to remove corruption. 97262306a36Sopenharmony_ci * @c: UBIFS file-system description object 97362306a36Sopenharmony_ci * @ucleb: unclean LEB information 97462306a36Sopenharmony_ci * @sbuf: LEB-sized buffer to use 97562306a36Sopenharmony_ci * 97662306a36Sopenharmony_ci * This function reads a LEB up to a point pre-determined by the mount recovery, 97762306a36Sopenharmony_ci * checks the nodes, and writes the result back to the flash, thereby cleaning 97862306a36Sopenharmony_ci * off any following corruption, or non-fatal ECC errors. 97962306a36Sopenharmony_ci * 98062306a36Sopenharmony_ci * This function returns %0 on success and a negative error code on failure. 98162306a36Sopenharmony_ci */ 98262306a36Sopenharmony_cistatic int clean_an_unclean_leb(struct ubifs_info *c, 98362306a36Sopenharmony_ci struct ubifs_unclean_leb *ucleb, void *sbuf) 98462306a36Sopenharmony_ci{ 98562306a36Sopenharmony_ci int err, lnum = ucleb->lnum, offs = 0, len = ucleb->endpt, quiet = 1; 98662306a36Sopenharmony_ci void *buf = sbuf; 98762306a36Sopenharmony_ci 98862306a36Sopenharmony_ci dbg_rcvry("LEB %d len %d", lnum, len); 98962306a36Sopenharmony_ci 99062306a36Sopenharmony_ci if (len == 0) { 99162306a36Sopenharmony_ci /* Nothing to read, just unmap it */ 99262306a36Sopenharmony_ci return ubifs_leb_unmap(c, lnum); 99362306a36Sopenharmony_ci } 99462306a36Sopenharmony_ci 99562306a36Sopenharmony_ci err = ubifs_leb_read(c, lnum, buf, offs, len, 0); 99662306a36Sopenharmony_ci if (err && err != -EBADMSG) 99762306a36Sopenharmony_ci return err; 99862306a36Sopenharmony_ci 99962306a36Sopenharmony_ci while (len >= 8) { 100062306a36Sopenharmony_ci int ret; 100162306a36Sopenharmony_ci 100262306a36Sopenharmony_ci cond_resched(); 100362306a36Sopenharmony_ci 100462306a36Sopenharmony_ci /* Scan quietly until there is an error */ 100562306a36Sopenharmony_ci ret = ubifs_scan_a_node(c, buf, len, lnum, offs, quiet); 100662306a36Sopenharmony_ci 100762306a36Sopenharmony_ci if (ret == SCANNED_A_NODE) { 100862306a36Sopenharmony_ci /* A valid node, and not a padding node */ 100962306a36Sopenharmony_ci struct ubifs_ch *ch = buf; 101062306a36Sopenharmony_ci int node_len; 101162306a36Sopenharmony_ci 101262306a36Sopenharmony_ci node_len = ALIGN(le32_to_cpu(ch->len), 8); 101362306a36Sopenharmony_ci offs += node_len; 101462306a36Sopenharmony_ci buf += node_len; 101562306a36Sopenharmony_ci len -= node_len; 101662306a36Sopenharmony_ci continue; 101762306a36Sopenharmony_ci } 101862306a36Sopenharmony_ci 101962306a36Sopenharmony_ci if (ret > 0) { 102062306a36Sopenharmony_ci /* Padding bytes or a valid padding node */ 102162306a36Sopenharmony_ci offs += ret; 102262306a36Sopenharmony_ci buf += ret; 102362306a36Sopenharmony_ci len -= ret; 102462306a36Sopenharmony_ci continue; 102562306a36Sopenharmony_ci } 102662306a36Sopenharmony_ci 102762306a36Sopenharmony_ci if (ret == SCANNED_EMPTY_SPACE) { 102862306a36Sopenharmony_ci ubifs_err(c, "unexpected empty space at %d:%d", 102962306a36Sopenharmony_ci lnum, offs); 103062306a36Sopenharmony_ci return -EUCLEAN; 103162306a36Sopenharmony_ci } 103262306a36Sopenharmony_ci 103362306a36Sopenharmony_ci if (quiet) { 103462306a36Sopenharmony_ci /* Redo the last scan but noisily */ 103562306a36Sopenharmony_ci quiet = 0; 103662306a36Sopenharmony_ci continue; 103762306a36Sopenharmony_ci } 103862306a36Sopenharmony_ci 103962306a36Sopenharmony_ci ubifs_scanned_corruption(c, lnum, offs, buf); 104062306a36Sopenharmony_ci return -EUCLEAN; 104162306a36Sopenharmony_ci } 104262306a36Sopenharmony_ci 104362306a36Sopenharmony_ci /* Pad to min_io_size */ 104462306a36Sopenharmony_ci len = ALIGN(ucleb->endpt, c->min_io_size); 104562306a36Sopenharmony_ci if (len > ucleb->endpt) { 104662306a36Sopenharmony_ci int pad_len = len - ALIGN(ucleb->endpt, 8); 104762306a36Sopenharmony_ci 104862306a36Sopenharmony_ci if (pad_len > 0) { 104962306a36Sopenharmony_ci buf = c->sbuf + len - pad_len; 105062306a36Sopenharmony_ci ubifs_pad(c, buf, pad_len); 105162306a36Sopenharmony_ci } 105262306a36Sopenharmony_ci } 105362306a36Sopenharmony_ci 105462306a36Sopenharmony_ci /* Write back the LEB atomically */ 105562306a36Sopenharmony_ci err = ubifs_leb_change(c, lnum, sbuf, len); 105662306a36Sopenharmony_ci if (err) 105762306a36Sopenharmony_ci return err; 105862306a36Sopenharmony_ci 105962306a36Sopenharmony_ci dbg_rcvry("cleaned LEB %d", lnum); 106062306a36Sopenharmony_ci 106162306a36Sopenharmony_ci return 0; 106262306a36Sopenharmony_ci} 106362306a36Sopenharmony_ci 106462306a36Sopenharmony_ci/** 106562306a36Sopenharmony_ci * ubifs_clean_lebs - clean LEBs recovered during read-only mount. 106662306a36Sopenharmony_ci * @c: UBIFS file-system description object 106762306a36Sopenharmony_ci * @sbuf: LEB-sized buffer to use 106862306a36Sopenharmony_ci * 106962306a36Sopenharmony_ci * This function cleans a LEB identified during recovery that needs to be 107062306a36Sopenharmony_ci * written but was not because UBIFS was mounted read-only. This happens when 107162306a36Sopenharmony_ci * remounting to read-write mode. 107262306a36Sopenharmony_ci * 107362306a36Sopenharmony_ci * This function returns %0 on success and a negative error code on failure. 107462306a36Sopenharmony_ci */ 107562306a36Sopenharmony_ciint ubifs_clean_lebs(struct ubifs_info *c, void *sbuf) 107662306a36Sopenharmony_ci{ 107762306a36Sopenharmony_ci dbg_rcvry("recovery"); 107862306a36Sopenharmony_ci while (!list_empty(&c->unclean_leb_list)) { 107962306a36Sopenharmony_ci struct ubifs_unclean_leb *ucleb; 108062306a36Sopenharmony_ci int err; 108162306a36Sopenharmony_ci 108262306a36Sopenharmony_ci ucleb = list_entry(c->unclean_leb_list.next, 108362306a36Sopenharmony_ci struct ubifs_unclean_leb, list); 108462306a36Sopenharmony_ci err = clean_an_unclean_leb(c, ucleb, sbuf); 108562306a36Sopenharmony_ci if (err) 108662306a36Sopenharmony_ci return err; 108762306a36Sopenharmony_ci list_del(&ucleb->list); 108862306a36Sopenharmony_ci kfree(ucleb); 108962306a36Sopenharmony_ci } 109062306a36Sopenharmony_ci return 0; 109162306a36Sopenharmony_ci} 109262306a36Sopenharmony_ci 109362306a36Sopenharmony_ci/** 109462306a36Sopenharmony_ci * grab_empty_leb - grab an empty LEB to use as GC LEB and run commit. 109562306a36Sopenharmony_ci * @c: UBIFS file-system description object 109662306a36Sopenharmony_ci * 109762306a36Sopenharmony_ci * This is a helper function for 'ubifs_rcvry_gc_commit()' which grabs an empty 109862306a36Sopenharmony_ci * LEB to be used as GC LEB (@c->gc_lnum), and then runs the commit. Returns 109962306a36Sopenharmony_ci * zero in case of success and a negative error code in case of failure. 110062306a36Sopenharmony_ci */ 110162306a36Sopenharmony_cistatic int grab_empty_leb(struct ubifs_info *c) 110262306a36Sopenharmony_ci{ 110362306a36Sopenharmony_ci int lnum, err; 110462306a36Sopenharmony_ci 110562306a36Sopenharmony_ci /* 110662306a36Sopenharmony_ci * Note, it is very important to first search for an empty LEB and then 110762306a36Sopenharmony_ci * run the commit, not vice-versa. The reason is that there might be 110862306a36Sopenharmony_ci * only one empty LEB at the moment, the one which has been the 110962306a36Sopenharmony_ci * @c->gc_lnum just before the power cut happened. During the regular 111062306a36Sopenharmony_ci * UBIFS operation (not now) @c->gc_lnum is marked as "taken", so no 111162306a36Sopenharmony_ci * one but GC can grab it. But at this moment this single empty LEB is 111262306a36Sopenharmony_ci * not marked as taken, so if we run commit - what happens? Right, the 111362306a36Sopenharmony_ci * commit will grab it and write the index there. Remember that the 111462306a36Sopenharmony_ci * index always expands as long as there is free space, and it only 111562306a36Sopenharmony_ci * starts consolidating when we run out of space. 111662306a36Sopenharmony_ci * 111762306a36Sopenharmony_ci * IOW, if we run commit now, we might not be able to find a free LEB 111862306a36Sopenharmony_ci * after this. 111962306a36Sopenharmony_ci */ 112062306a36Sopenharmony_ci lnum = ubifs_find_free_leb_for_idx(c); 112162306a36Sopenharmony_ci if (lnum < 0) { 112262306a36Sopenharmony_ci ubifs_err(c, "could not find an empty LEB"); 112362306a36Sopenharmony_ci ubifs_dump_lprops(c); 112462306a36Sopenharmony_ci ubifs_dump_budg(c, &c->bi); 112562306a36Sopenharmony_ci return lnum; 112662306a36Sopenharmony_ci } 112762306a36Sopenharmony_ci 112862306a36Sopenharmony_ci /* Reset the index flag */ 112962306a36Sopenharmony_ci err = ubifs_change_one_lp(c, lnum, LPROPS_NC, LPROPS_NC, 0, 113062306a36Sopenharmony_ci LPROPS_INDEX, 0); 113162306a36Sopenharmony_ci if (err) 113262306a36Sopenharmony_ci return err; 113362306a36Sopenharmony_ci 113462306a36Sopenharmony_ci c->gc_lnum = lnum; 113562306a36Sopenharmony_ci dbg_rcvry("found empty LEB %d, run commit", lnum); 113662306a36Sopenharmony_ci 113762306a36Sopenharmony_ci return ubifs_run_commit(c); 113862306a36Sopenharmony_ci} 113962306a36Sopenharmony_ci 114062306a36Sopenharmony_ci/** 114162306a36Sopenharmony_ci * ubifs_rcvry_gc_commit - recover the GC LEB number and run the commit. 114262306a36Sopenharmony_ci * @c: UBIFS file-system description object 114362306a36Sopenharmony_ci * 114462306a36Sopenharmony_ci * Out-of-place garbage collection requires always one empty LEB with which to 114562306a36Sopenharmony_ci * start garbage collection. The LEB number is recorded in c->gc_lnum and is 114662306a36Sopenharmony_ci * written to the master node on unmounting. In the case of an unclean unmount 114762306a36Sopenharmony_ci * the value of gc_lnum recorded in the master node is out of date and cannot 114862306a36Sopenharmony_ci * be used. Instead, recovery must allocate an empty LEB for this purpose. 114962306a36Sopenharmony_ci * However, there may not be enough empty space, in which case it must be 115062306a36Sopenharmony_ci * possible to GC the dirtiest LEB into the GC head LEB. 115162306a36Sopenharmony_ci * 115262306a36Sopenharmony_ci * This function also runs the commit which causes the TNC updates from 115362306a36Sopenharmony_ci * size-recovery and orphans to be written to the flash. That is important to 115462306a36Sopenharmony_ci * ensure correct replay order for subsequent mounts. 115562306a36Sopenharmony_ci * 115662306a36Sopenharmony_ci * This function returns %0 on success and a negative error code on failure. 115762306a36Sopenharmony_ci */ 115862306a36Sopenharmony_ciint ubifs_rcvry_gc_commit(struct ubifs_info *c) 115962306a36Sopenharmony_ci{ 116062306a36Sopenharmony_ci struct ubifs_wbuf *wbuf = &c->jheads[GCHD].wbuf; 116162306a36Sopenharmony_ci struct ubifs_lprops lp; 116262306a36Sopenharmony_ci int err; 116362306a36Sopenharmony_ci 116462306a36Sopenharmony_ci dbg_rcvry("GC head LEB %d, offs %d", wbuf->lnum, wbuf->offs); 116562306a36Sopenharmony_ci 116662306a36Sopenharmony_ci c->gc_lnum = -1; 116762306a36Sopenharmony_ci if (wbuf->lnum == -1 || wbuf->offs == c->leb_size) 116862306a36Sopenharmony_ci return grab_empty_leb(c); 116962306a36Sopenharmony_ci 117062306a36Sopenharmony_ci err = ubifs_find_dirty_leb(c, &lp, wbuf->offs, 2); 117162306a36Sopenharmony_ci if (err) { 117262306a36Sopenharmony_ci if (err != -ENOSPC) 117362306a36Sopenharmony_ci return err; 117462306a36Sopenharmony_ci 117562306a36Sopenharmony_ci dbg_rcvry("could not find a dirty LEB"); 117662306a36Sopenharmony_ci return grab_empty_leb(c); 117762306a36Sopenharmony_ci } 117862306a36Sopenharmony_ci 117962306a36Sopenharmony_ci ubifs_assert(c, !(lp.flags & LPROPS_INDEX)); 118062306a36Sopenharmony_ci ubifs_assert(c, lp.free + lp.dirty >= wbuf->offs); 118162306a36Sopenharmony_ci 118262306a36Sopenharmony_ci /* 118362306a36Sopenharmony_ci * We run the commit before garbage collection otherwise subsequent 118462306a36Sopenharmony_ci * mounts will see the GC and orphan deletion in a different order. 118562306a36Sopenharmony_ci */ 118662306a36Sopenharmony_ci dbg_rcvry("committing"); 118762306a36Sopenharmony_ci err = ubifs_run_commit(c); 118862306a36Sopenharmony_ci if (err) 118962306a36Sopenharmony_ci return err; 119062306a36Sopenharmony_ci 119162306a36Sopenharmony_ci dbg_rcvry("GC'ing LEB %d", lp.lnum); 119262306a36Sopenharmony_ci mutex_lock_nested(&wbuf->io_mutex, wbuf->jhead); 119362306a36Sopenharmony_ci err = ubifs_garbage_collect_leb(c, &lp); 119462306a36Sopenharmony_ci if (err >= 0) { 119562306a36Sopenharmony_ci int err2 = ubifs_wbuf_sync_nolock(wbuf); 119662306a36Sopenharmony_ci 119762306a36Sopenharmony_ci if (err2) 119862306a36Sopenharmony_ci err = err2; 119962306a36Sopenharmony_ci } 120062306a36Sopenharmony_ci mutex_unlock(&wbuf->io_mutex); 120162306a36Sopenharmony_ci if (err < 0) { 120262306a36Sopenharmony_ci ubifs_err(c, "GC failed, error %d", err); 120362306a36Sopenharmony_ci if (err == -EAGAIN) 120462306a36Sopenharmony_ci err = -EINVAL; 120562306a36Sopenharmony_ci return err; 120662306a36Sopenharmony_ci } 120762306a36Sopenharmony_ci 120862306a36Sopenharmony_ci ubifs_assert(c, err == LEB_RETAINED); 120962306a36Sopenharmony_ci if (err != LEB_RETAINED) 121062306a36Sopenharmony_ci return -EINVAL; 121162306a36Sopenharmony_ci 121262306a36Sopenharmony_ci err = ubifs_leb_unmap(c, c->gc_lnum); 121362306a36Sopenharmony_ci if (err) 121462306a36Sopenharmony_ci return err; 121562306a36Sopenharmony_ci 121662306a36Sopenharmony_ci dbg_rcvry("allocated LEB %d for GC", lp.lnum); 121762306a36Sopenharmony_ci return 0; 121862306a36Sopenharmony_ci} 121962306a36Sopenharmony_ci 122062306a36Sopenharmony_ci/** 122162306a36Sopenharmony_ci * struct size_entry - inode size information for recovery. 122262306a36Sopenharmony_ci * @rb: link in the RB-tree of sizes 122362306a36Sopenharmony_ci * @inum: inode number 122462306a36Sopenharmony_ci * @i_size: size on inode 122562306a36Sopenharmony_ci * @d_size: maximum size based on data nodes 122662306a36Sopenharmony_ci * @exists: indicates whether the inode exists 122762306a36Sopenharmony_ci * @inode: inode if pinned in memory awaiting rw mode to fix it 122862306a36Sopenharmony_ci */ 122962306a36Sopenharmony_cistruct size_entry { 123062306a36Sopenharmony_ci struct rb_node rb; 123162306a36Sopenharmony_ci ino_t inum; 123262306a36Sopenharmony_ci loff_t i_size; 123362306a36Sopenharmony_ci loff_t d_size; 123462306a36Sopenharmony_ci int exists; 123562306a36Sopenharmony_ci struct inode *inode; 123662306a36Sopenharmony_ci}; 123762306a36Sopenharmony_ci 123862306a36Sopenharmony_ci/** 123962306a36Sopenharmony_ci * add_ino - add an entry to the size tree. 124062306a36Sopenharmony_ci * @c: UBIFS file-system description object 124162306a36Sopenharmony_ci * @inum: inode number 124262306a36Sopenharmony_ci * @i_size: size on inode 124362306a36Sopenharmony_ci * @d_size: maximum size based on data nodes 124462306a36Sopenharmony_ci * @exists: indicates whether the inode exists 124562306a36Sopenharmony_ci */ 124662306a36Sopenharmony_cistatic int add_ino(struct ubifs_info *c, ino_t inum, loff_t i_size, 124762306a36Sopenharmony_ci loff_t d_size, int exists) 124862306a36Sopenharmony_ci{ 124962306a36Sopenharmony_ci struct rb_node **p = &c->size_tree.rb_node, *parent = NULL; 125062306a36Sopenharmony_ci struct size_entry *e; 125162306a36Sopenharmony_ci 125262306a36Sopenharmony_ci while (*p) { 125362306a36Sopenharmony_ci parent = *p; 125462306a36Sopenharmony_ci e = rb_entry(parent, struct size_entry, rb); 125562306a36Sopenharmony_ci if (inum < e->inum) 125662306a36Sopenharmony_ci p = &(*p)->rb_left; 125762306a36Sopenharmony_ci else 125862306a36Sopenharmony_ci p = &(*p)->rb_right; 125962306a36Sopenharmony_ci } 126062306a36Sopenharmony_ci 126162306a36Sopenharmony_ci e = kzalloc(sizeof(struct size_entry), GFP_KERNEL); 126262306a36Sopenharmony_ci if (!e) 126362306a36Sopenharmony_ci return -ENOMEM; 126462306a36Sopenharmony_ci 126562306a36Sopenharmony_ci e->inum = inum; 126662306a36Sopenharmony_ci e->i_size = i_size; 126762306a36Sopenharmony_ci e->d_size = d_size; 126862306a36Sopenharmony_ci e->exists = exists; 126962306a36Sopenharmony_ci 127062306a36Sopenharmony_ci rb_link_node(&e->rb, parent, p); 127162306a36Sopenharmony_ci rb_insert_color(&e->rb, &c->size_tree); 127262306a36Sopenharmony_ci 127362306a36Sopenharmony_ci return 0; 127462306a36Sopenharmony_ci} 127562306a36Sopenharmony_ci 127662306a36Sopenharmony_ci/** 127762306a36Sopenharmony_ci * find_ino - find an entry on the size tree. 127862306a36Sopenharmony_ci * @c: UBIFS file-system description object 127962306a36Sopenharmony_ci * @inum: inode number 128062306a36Sopenharmony_ci */ 128162306a36Sopenharmony_cistatic struct size_entry *find_ino(struct ubifs_info *c, ino_t inum) 128262306a36Sopenharmony_ci{ 128362306a36Sopenharmony_ci struct rb_node *p = c->size_tree.rb_node; 128462306a36Sopenharmony_ci struct size_entry *e; 128562306a36Sopenharmony_ci 128662306a36Sopenharmony_ci while (p) { 128762306a36Sopenharmony_ci e = rb_entry(p, struct size_entry, rb); 128862306a36Sopenharmony_ci if (inum < e->inum) 128962306a36Sopenharmony_ci p = p->rb_left; 129062306a36Sopenharmony_ci else if (inum > e->inum) 129162306a36Sopenharmony_ci p = p->rb_right; 129262306a36Sopenharmony_ci else 129362306a36Sopenharmony_ci return e; 129462306a36Sopenharmony_ci } 129562306a36Sopenharmony_ci return NULL; 129662306a36Sopenharmony_ci} 129762306a36Sopenharmony_ci 129862306a36Sopenharmony_ci/** 129962306a36Sopenharmony_ci * remove_ino - remove an entry from the size tree. 130062306a36Sopenharmony_ci * @c: UBIFS file-system description object 130162306a36Sopenharmony_ci * @inum: inode number 130262306a36Sopenharmony_ci */ 130362306a36Sopenharmony_cistatic void remove_ino(struct ubifs_info *c, ino_t inum) 130462306a36Sopenharmony_ci{ 130562306a36Sopenharmony_ci struct size_entry *e = find_ino(c, inum); 130662306a36Sopenharmony_ci 130762306a36Sopenharmony_ci if (!e) 130862306a36Sopenharmony_ci return; 130962306a36Sopenharmony_ci rb_erase(&e->rb, &c->size_tree); 131062306a36Sopenharmony_ci kfree(e); 131162306a36Sopenharmony_ci} 131262306a36Sopenharmony_ci 131362306a36Sopenharmony_ci/** 131462306a36Sopenharmony_ci * ubifs_destroy_size_tree - free resources related to the size tree. 131562306a36Sopenharmony_ci * @c: UBIFS file-system description object 131662306a36Sopenharmony_ci */ 131762306a36Sopenharmony_civoid ubifs_destroy_size_tree(struct ubifs_info *c) 131862306a36Sopenharmony_ci{ 131962306a36Sopenharmony_ci struct size_entry *e, *n; 132062306a36Sopenharmony_ci 132162306a36Sopenharmony_ci rbtree_postorder_for_each_entry_safe(e, n, &c->size_tree, rb) { 132262306a36Sopenharmony_ci iput(e->inode); 132362306a36Sopenharmony_ci kfree(e); 132462306a36Sopenharmony_ci } 132562306a36Sopenharmony_ci 132662306a36Sopenharmony_ci c->size_tree = RB_ROOT; 132762306a36Sopenharmony_ci} 132862306a36Sopenharmony_ci 132962306a36Sopenharmony_ci/** 133062306a36Sopenharmony_ci * ubifs_recover_size_accum - accumulate inode sizes for recovery. 133162306a36Sopenharmony_ci * @c: UBIFS file-system description object 133262306a36Sopenharmony_ci * @key: node key 133362306a36Sopenharmony_ci * @deletion: node is for a deletion 133462306a36Sopenharmony_ci * @new_size: inode size 133562306a36Sopenharmony_ci * 133662306a36Sopenharmony_ci * This function has two purposes: 133762306a36Sopenharmony_ci * 1) to ensure there are no data nodes that fall outside the inode size 133862306a36Sopenharmony_ci * 2) to ensure there are no data nodes for inodes that do not exist 133962306a36Sopenharmony_ci * To accomplish those purposes, a rb-tree is constructed containing an entry 134062306a36Sopenharmony_ci * for each inode number in the journal that has not been deleted, and recording 134162306a36Sopenharmony_ci * the size from the inode node, the maximum size of any data node (also altered 134262306a36Sopenharmony_ci * by truncations) and a flag indicating a inode number for which no inode node 134362306a36Sopenharmony_ci * was present in the journal. 134462306a36Sopenharmony_ci * 134562306a36Sopenharmony_ci * Note that there is still the possibility that there are data nodes that have 134662306a36Sopenharmony_ci * been committed that are beyond the inode size, however the only way to find 134762306a36Sopenharmony_ci * them would be to scan the entire index. Alternatively, some provision could 134862306a36Sopenharmony_ci * be made to record the size of inodes at the start of commit, which would seem 134962306a36Sopenharmony_ci * very cumbersome for a scenario that is quite unlikely and the only negative 135062306a36Sopenharmony_ci * consequence of which is wasted space. 135162306a36Sopenharmony_ci * 135262306a36Sopenharmony_ci * This functions returns %0 on success and a negative error code on failure. 135362306a36Sopenharmony_ci */ 135462306a36Sopenharmony_ciint ubifs_recover_size_accum(struct ubifs_info *c, union ubifs_key *key, 135562306a36Sopenharmony_ci int deletion, loff_t new_size) 135662306a36Sopenharmony_ci{ 135762306a36Sopenharmony_ci ino_t inum = key_inum(c, key); 135862306a36Sopenharmony_ci struct size_entry *e; 135962306a36Sopenharmony_ci int err; 136062306a36Sopenharmony_ci 136162306a36Sopenharmony_ci switch (key_type(c, key)) { 136262306a36Sopenharmony_ci case UBIFS_INO_KEY: 136362306a36Sopenharmony_ci if (deletion) 136462306a36Sopenharmony_ci remove_ino(c, inum); 136562306a36Sopenharmony_ci else { 136662306a36Sopenharmony_ci e = find_ino(c, inum); 136762306a36Sopenharmony_ci if (e) { 136862306a36Sopenharmony_ci e->i_size = new_size; 136962306a36Sopenharmony_ci e->exists = 1; 137062306a36Sopenharmony_ci } else { 137162306a36Sopenharmony_ci err = add_ino(c, inum, new_size, 0, 1); 137262306a36Sopenharmony_ci if (err) 137362306a36Sopenharmony_ci return err; 137462306a36Sopenharmony_ci } 137562306a36Sopenharmony_ci } 137662306a36Sopenharmony_ci break; 137762306a36Sopenharmony_ci case UBIFS_DATA_KEY: 137862306a36Sopenharmony_ci e = find_ino(c, inum); 137962306a36Sopenharmony_ci if (e) { 138062306a36Sopenharmony_ci if (new_size > e->d_size) 138162306a36Sopenharmony_ci e->d_size = new_size; 138262306a36Sopenharmony_ci } else { 138362306a36Sopenharmony_ci err = add_ino(c, inum, 0, new_size, 0); 138462306a36Sopenharmony_ci if (err) 138562306a36Sopenharmony_ci return err; 138662306a36Sopenharmony_ci } 138762306a36Sopenharmony_ci break; 138862306a36Sopenharmony_ci case UBIFS_TRUN_KEY: 138962306a36Sopenharmony_ci e = find_ino(c, inum); 139062306a36Sopenharmony_ci if (e) 139162306a36Sopenharmony_ci e->d_size = new_size; 139262306a36Sopenharmony_ci break; 139362306a36Sopenharmony_ci } 139462306a36Sopenharmony_ci return 0; 139562306a36Sopenharmony_ci} 139662306a36Sopenharmony_ci 139762306a36Sopenharmony_ci/** 139862306a36Sopenharmony_ci * fix_size_in_place - fix inode size in place on flash. 139962306a36Sopenharmony_ci * @c: UBIFS file-system description object 140062306a36Sopenharmony_ci * @e: inode size information for recovery 140162306a36Sopenharmony_ci */ 140262306a36Sopenharmony_cistatic int fix_size_in_place(struct ubifs_info *c, struct size_entry *e) 140362306a36Sopenharmony_ci{ 140462306a36Sopenharmony_ci struct ubifs_ino_node *ino = c->sbuf; 140562306a36Sopenharmony_ci unsigned char *p; 140662306a36Sopenharmony_ci union ubifs_key key; 140762306a36Sopenharmony_ci int err, lnum, offs, len; 140862306a36Sopenharmony_ci loff_t i_size; 140962306a36Sopenharmony_ci uint32_t crc; 141062306a36Sopenharmony_ci 141162306a36Sopenharmony_ci /* Locate the inode node LEB number and offset */ 141262306a36Sopenharmony_ci ino_key_init(c, &key, e->inum); 141362306a36Sopenharmony_ci err = ubifs_tnc_locate(c, &key, ino, &lnum, &offs); 141462306a36Sopenharmony_ci if (err) 141562306a36Sopenharmony_ci goto out; 141662306a36Sopenharmony_ci /* 141762306a36Sopenharmony_ci * If the size recorded on the inode node is greater than the size that 141862306a36Sopenharmony_ci * was calculated from nodes in the journal then don't change the inode. 141962306a36Sopenharmony_ci */ 142062306a36Sopenharmony_ci i_size = le64_to_cpu(ino->size); 142162306a36Sopenharmony_ci if (i_size >= e->d_size) 142262306a36Sopenharmony_ci return 0; 142362306a36Sopenharmony_ci /* Read the LEB */ 142462306a36Sopenharmony_ci err = ubifs_leb_read(c, lnum, c->sbuf, 0, c->leb_size, 1); 142562306a36Sopenharmony_ci if (err) 142662306a36Sopenharmony_ci goto out; 142762306a36Sopenharmony_ci /* Change the size field and recalculate the CRC */ 142862306a36Sopenharmony_ci ino = c->sbuf + offs; 142962306a36Sopenharmony_ci ino->size = cpu_to_le64(e->d_size); 143062306a36Sopenharmony_ci len = le32_to_cpu(ino->ch.len); 143162306a36Sopenharmony_ci crc = crc32(UBIFS_CRC32_INIT, (void *)ino + 8, len - 8); 143262306a36Sopenharmony_ci ino->ch.crc = cpu_to_le32(crc); 143362306a36Sopenharmony_ci /* Work out where data in the LEB ends and free space begins */ 143462306a36Sopenharmony_ci p = c->sbuf; 143562306a36Sopenharmony_ci len = c->leb_size - 1; 143662306a36Sopenharmony_ci while (p[len] == 0xff) 143762306a36Sopenharmony_ci len -= 1; 143862306a36Sopenharmony_ci len = ALIGN(len + 1, c->min_io_size); 143962306a36Sopenharmony_ci /* Atomically write the fixed LEB back again */ 144062306a36Sopenharmony_ci err = ubifs_leb_change(c, lnum, c->sbuf, len); 144162306a36Sopenharmony_ci if (err) 144262306a36Sopenharmony_ci goto out; 144362306a36Sopenharmony_ci dbg_rcvry("inode %lu at %d:%d size %lld -> %lld", 144462306a36Sopenharmony_ci (unsigned long)e->inum, lnum, offs, i_size, e->d_size); 144562306a36Sopenharmony_ci return 0; 144662306a36Sopenharmony_ci 144762306a36Sopenharmony_ciout: 144862306a36Sopenharmony_ci ubifs_warn(c, "inode %lu failed to fix size %lld -> %lld error %d", 144962306a36Sopenharmony_ci (unsigned long)e->inum, e->i_size, e->d_size, err); 145062306a36Sopenharmony_ci return err; 145162306a36Sopenharmony_ci} 145262306a36Sopenharmony_ci 145362306a36Sopenharmony_ci/** 145462306a36Sopenharmony_ci * inode_fix_size - fix inode size 145562306a36Sopenharmony_ci * @c: UBIFS file-system description object 145662306a36Sopenharmony_ci * @e: inode size information for recovery 145762306a36Sopenharmony_ci */ 145862306a36Sopenharmony_cistatic int inode_fix_size(struct ubifs_info *c, struct size_entry *e) 145962306a36Sopenharmony_ci{ 146062306a36Sopenharmony_ci struct inode *inode; 146162306a36Sopenharmony_ci struct ubifs_inode *ui; 146262306a36Sopenharmony_ci int err; 146362306a36Sopenharmony_ci 146462306a36Sopenharmony_ci if (c->ro_mount) 146562306a36Sopenharmony_ci ubifs_assert(c, !e->inode); 146662306a36Sopenharmony_ci 146762306a36Sopenharmony_ci if (e->inode) { 146862306a36Sopenharmony_ci /* Remounting rw, pick up inode we stored earlier */ 146962306a36Sopenharmony_ci inode = e->inode; 147062306a36Sopenharmony_ci } else { 147162306a36Sopenharmony_ci inode = ubifs_iget(c->vfs_sb, e->inum); 147262306a36Sopenharmony_ci if (IS_ERR(inode)) 147362306a36Sopenharmony_ci return PTR_ERR(inode); 147462306a36Sopenharmony_ci 147562306a36Sopenharmony_ci if (inode->i_size >= e->d_size) { 147662306a36Sopenharmony_ci /* 147762306a36Sopenharmony_ci * The original inode in the index already has a size 147862306a36Sopenharmony_ci * big enough, nothing to do 147962306a36Sopenharmony_ci */ 148062306a36Sopenharmony_ci iput(inode); 148162306a36Sopenharmony_ci return 0; 148262306a36Sopenharmony_ci } 148362306a36Sopenharmony_ci 148462306a36Sopenharmony_ci dbg_rcvry("ino %lu size %lld -> %lld", 148562306a36Sopenharmony_ci (unsigned long)e->inum, 148662306a36Sopenharmony_ci inode->i_size, e->d_size); 148762306a36Sopenharmony_ci 148862306a36Sopenharmony_ci ui = ubifs_inode(inode); 148962306a36Sopenharmony_ci 149062306a36Sopenharmony_ci inode->i_size = e->d_size; 149162306a36Sopenharmony_ci ui->ui_size = e->d_size; 149262306a36Sopenharmony_ci ui->synced_i_size = e->d_size; 149362306a36Sopenharmony_ci 149462306a36Sopenharmony_ci e->inode = inode; 149562306a36Sopenharmony_ci } 149662306a36Sopenharmony_ci 149762306a36Sopenharmony_ci /* 149862306a36Sopenharmony_ci * In readonly mode just keep the inode pinned in memory until we go 149962306a36Sopenharmony_ci * readwrite. In readwrite mode write the inode to the journal with the 150062306a36Sopenharmony_ci * fixed size. 150162306a36Sopenharmony_ci */ 150262306a36Sopenharmony_ci if (c->ro_mount) 150362306a36Sopenharmony_ci return 0; 150462306a36Sopenharmony_ci 150562306a36Sopenharmony_ci err = ubifs_jnl_write_inode(c, inode); 150662306a36Sopenharmony_ci 150762306a36Sopenharmony_ci iput(inode); 150862306a36Sopenharmony_ci 150962306a36Sopenharmony_ci if (err) 151062306a36Sopenharmony_ci return err; 151162306a36Sopenharmony_ci 151262306a36Sopenharmony_ci rb_erase(&e->rb, &c->size_tree); 151362306a36Sopenharmony_ci kfree(e); 151462306a36Sopenharmony_ci 151562306a36Sopenharmony_ci return 0; 151662306a36Sopenharmony_ci} 151762306a36Sopenharmony_ci 151862306a36Sopenharmony_ci/** 151962306a36Sopenharmony_ci * ubifs_recover_size - recover inode size. 152062306a36Sopenharmony_ci * @c: UBIFS file-system description object 152162306a36Sopenharmony_ci * @in_place: If true, do a in-place size fixup 152262306a36Sopenharmony_ci * 152362306a36Sopenharmony_ci * This function attempts to fix inode size discrepancies identified by the 152462306a36Sopenharmony_ci * 'ubifs_recover_size_accum()' function. 152562306a36Sopenharmony_ci * 152662306a36Sopenharmony_ci * This functions returns %0 on success and a negative error code on failure. 152762306a36Sopenharmony_ci */ 152862306a36Sopenharmony_ciint ubifs_recover_size(struct ubifs_info *c, bool in_place) 152962306a36Sopenharmony_ci{ 153062306a36Sopenharmony_ci struct rb_node *this = rb_first(&c->size_tree); 153162306a36Sopenharmony_ci 153262306a36Sopenharmony_ci while (this) { 153362306a36Sopenharmony_ci struct size_entry *e; 153462306a36Sopenharmony_ci int err; 153562306a36Sopenharmony_ci 153662306a36Sopenharmony_ci e = rb_entry(this, struct size_entry, rb); 153762306a36Sopenharmony_ci 153862306a36Sopenharmony_ci this = rb_next(this); 153962306a36Sopenharmony_ci 154062306a36Sopenharmony_ci if (!e->exists) { 154162306a36Sopenharmony_ci union ubifs_key key; 154262306a36Sopenharmony_ci 154362306a36Sopenharmony_ci ino_key_init(c, &key, e->inum); 154462306a36Sopenharmony_ci err = ubifs_tnc_lookup(c, &key, c->sbuf); 154562306a36Sopenharmony_ci if (err && err != -ENOENT) 154662306a36Sopenharmony_ci return err; 154762306a36Sopenharmony_ci if (err == -ENOENT) { 154862306a36Sopenharmony_ci /* Remove data nodes that have no inode */ 154962306a36Sopenharmony_ci dbg_rcvry("removing ino %lu", 155062306a36Sopenharmony_ci (unsigned long)e->inum); 155162306a36Sopenharmony_ci err = ubifs_tnc_remove_ino(c, e->inum); 155262306a36Sopenharmony_ci if (err) 155362306a36Sopenharmony_ci return err; 155462306a36Sopenharmony_ci } else { 155562306a36Sopenharmony_ci struct ubifs_ino_node *ino = c->sbuf; 155662306a36Sopenharmony_ci 155762306a36Sopenharmony_ci e->exists = 1; 155862306a36Sopenharmony_ci e->i_size = le64_to_cpu(ino->size); 155962306a36Sopenharmony_ci } 156062306a36Sopenharmony_ci } 156162306a36Sopenharmony_ci 156262306a36Sopenharmony_ci if (e->exists && e->i_size < e->d_size) { 156362306a36Sopenharmony_ci ubifs_assert(c, !(c->ro_mount && in_place)); 156462306a36Sopenharmony_ci 156562306a36Sopenharmony_ci /* 156662306a36Sopenharmony_ci * We found data that is outside the found inode size, 156762306a36Sopenharmony_ci * fixup the inode size 156862306a36Sopenharmony_ci */ 156962306a36Sopenharmony_ci 157062306a36Sopenharmony_ci if (in_place) { 157162306a36Sopenharmony_ci err = fix_size_in_place(c, e); 157262306a36Sopenharmony_ci if (err) 157362306a36Sopenharmony_ci return err; 157462306a36Sopenharmony_ci iput(e->inode); 157562306a36Sopenharmony_ci } else { 157662306a36Sopenharmony_ci err = inode_fix_size(c, e); 157762306a36Sopenharmony_ci if (err) 157862306a36Sopenharmony_ci return err; 157962306a36Sopenharmony_ci continue; 158062306a36Sopenharmony_ci } 158162306a36Sopenharmony_ci } 158262306a36Sopenharmony_ci 158362306a36Sopenharmony_ci rb_erase(&e->rb, &c->size_tree); 158462306a36Sopenharmony_ci kfree(e); 158562306a36Sopenharmony_ci } 158662306a36Sopenharmony_ci 158762306a36Sopenharmony_ci return 0; 158862306a36Sopenharmony_ci} 1589