18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * JFFS2 -- Journalling Flash File System, Version 2. 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Copyright © 2001-2007 Red Hat, Inc. 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * Created by David Woodhouse <dwmw2@infradead.org> 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci * For licensing information, see the file 'LICENCE' in this directory. 98c2ecf20Sopenharmony_ci * 108c2ecf20Sopenharmony_ci */ 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ci#include <linux/kernel.h> 158c2ecf20Sopenharmony_ci#include <linux/sched.h> 168c2ecf20Sopenharmony_ci#include <linux/slab.h> 178c2ecf20Sopenharmony_ci#include <linux/fs.h> 188c2ecf20Sopenharmony_ci#include <linux/crc32.h> 198c2ecf20Sopenharmony_ci#include <linux/pagemap.h> 208c2ecf20Sopenharmony_ci#include <linux/mtd/mtd.h> 218c2ecf20Sopenharmony_ci#include <linux/compiler.h> 228c2ecf20Sopenharmony_ci#include "nodelist.h" 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci/* 258c2ecf20Sopenharmony_ci * Check the data CRC of the node. 268c2ecf20Sopenharmony_ci * 278c2ecf20Sopenharmony_ci * Returns: 0 if the data CRC is correct; 288c2ecf20Sopenharmony_ci * 1 - if incorrect; 298c2ecf20Sopenharmony_ci * error code if an error occurred. 308c2ecf20Sopenharmony_ci */ 318c2ecf20Sopenharmony_cistatic int check_node_data(struct jffs2_sb_info *c, struct jffs2_tmp_dnode_info *tn) 328c2ecf20Sopenharmony_ci{ 338c2ecf20Sopenharmony_ci struct jffs2_raw_node_ref *ref = tn->fn->raw; 348c2ecf20Sopenharmony_ci int err = 0, pointed = 0; 358c2ecf20Sopenharmony_ci struct jffs2_eraseblock *jeb; 368c2ecf20Sopenharmony_ci unsigned char *buffer; 378c2ecf20Sopenharmony_ci uint32_t crc, ofs, len; 388c2ecf20Sopenharmony_ci size_t retlen; 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci BUG_ON(tn->csize == 0); 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci /* Calculate how many bytes were already checked */ 438c2ecf20Sopenharmony_ci ofs = ref_offset(ref) + sizeof(struct jffs2_raw_inode); 448c2ecf20Sopenharmony_ci len = tn->csize; 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci if (jffs2_is_writebuffered(c)) { 478c2ecf20Sopenharmony_ci int adj = ofs % c->wbuf_pagesize; 488c2ecf20Sopenharmony_ci if (likely(adj)) 498c2ecf20Sopenharmony_ci adj = c->wbuf_pagesize - adj; 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ci if (adj >= tn->csize) { 528c2ecf20Sopenharmony_ci dbg_readinode("no need to check node at %#08x, data length %u, data starts at %#08x - it has already been checked.\n", 538c2ecf20Sopenharmony_ci ref_offset(ref), tn->csize, ofs); 548c2ecf20Sopenharmony_ci goto adj_acc; 558c2ecf20Sopenharmony_ci } 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ci ofs += adj; 588c2ecf20Sopenharmony_ci len -= adj; 598c2ecf20Sopenharmony_ci } 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ci dbg_readinode("check node at %#08x, data length %u, partial CRC %#08x, correct CRC %#08x, data starts at %#08x, start checking from %#08x - %u bytes.\n", 628c2ecf20Sopenharmony_ci ref_offset(ref), tn->csize, tn->partial_crc, tn->data_crc, ofs - len, ofs, len); 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci#ifndef __ECOS 658c2ecf20Sopenharmony_ci /* TODO: instead, incapsulate point() stuff to jffs2_flash_read(), 668c2ecf20Sopenharmony_ci * adding and jffs2_flash_read_end() interface. */ 678c2ecf20Sopenharmony_ci err = mtd_point(c->mtd, ofs, len, &retlen, (void **)&buffer, NULL); 688c2ecf20Sopenharmony_ci if (!err && retlen < len) { 698c2ecf20Sopenharmony_ci JFFS2_WARNING("MTD point returned len too short: %zu instead of %u.\n", retlen, tn->csize); 708c2ecf20Sopenharmony_ci mtd_unpoint(c->mtd, ofs, retlen); 718c2ecf20Sopenharmony_ci } else if (err) { 728c2ecf20Sopenharmony_ci if (err != -EOPNOTSUPP) 738c2ecf20Sopenharmony_ci JFFS2_WARNING("MTD point failed: error code %d.\n", err); 748c2ecf20Sopenharmony_ci } else 758c2ecf20Sopenharmony_ci pointed = 1; /* succefully pointed to device */ 768c2ecf20Sopenharmony_ci#endif 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci if (!pointed) { 798c2ecf20Sopenharmony_ci buffer = kmalloc(len, GFP_KERNEL); 808c2ecf20Sopenharmony_ci if (unlikely(!buffer)) 818c2ecf20Sopenharmony_ci return -ENOMEM; 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci /* TODO: this is very frequent pattern, make it a separate 848c2ecf20Sopenharmony_ci * routine */ 858c2ecf20Sopenharmony_ci err = jffs2_flash_read(c, ofs, len, &retlen, buffer); 868c2ecf20Sopenharmony_ci if (err) { 878c2ecf20Sopenharmony_ci JFFS2_ERROR("can not read %d bytes from 0x%08x, error code: %d.\n", len, ofs, err); 888c2ecf20Sopenharmony_ci goto free_out; 898c2ecf20Sopenharmony_ci } 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ci if (retlen != len) { 928c2ecf20Sopenharmony_ci JFFS2_ERROR("short read at %#08x: %zd instead of %d.\n", ofs, retlen, len); 938c2ecf20Sopenharmony_ci err = -EIO; 948c2ecf20Sopenharmony_ci goto free_out; 958c2ecf20Sopenharmony_ci } 968c2ecf20Sopenharmony_ci } 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci /* Continue calculating CRC */ 998c2ecf20Sopenharmony_ci crc = crc32(tn->partial_crc, buffer, len); 1008c2ecf20Sopenharmony_ci if(!pointed) 1018c2ecf20Sopenharmony_ci kfree(buffer); 1028c2ecf20Sopenharmony_ci#ifndef __ECOS 1038c2ecf20Sopenharmony_ci else 1048c2ecf20Sopenharmony_ci mtd_unpoint(c->mtd, ofs, len); 1058c2ecf20Sopenharmony_ci#endif 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci if (crc != tn->data_crc) { 1088c2ecf20Sopenharmony_ci JFFS2_NOTICE("wrong data CRC in data node at 0x%08x: read %#08x, calculated %#08x.\n", 1098c2ecf20Sopenharmony_ci ref_offset(ref), tn->data_crc, crc); 1108c2ecf20Sopenharmony_ci return 1; 1118c2ecf20Sopenharmony_ci } 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_ciadj_acc: 1148c2ecf20Sopenharmony_ci jeb = &c->blocks[ref->flash_offset / c->sector_size]; 1158c2ecf20Sopenharmony_ci len = ref_totlen(c, jeb, ref); 1168c2ecf20Sopenharmony_ci /* If it should be REF_NORMAL, it'll get marked as such when 1178c2ecf20Sopenharmony_ci we build the fragtree, shortly. No need to worry about GC 1188c2ecf20Sopenharmony_ci moving it while it's marked REF_PRISTINE -- GC won't happen 1198c2ecf20Sopenharmony_ci till we've finished checking every inode anyway. */ 1208c2ecf20Sopenharmony_ci ref->flash_offset |= REF_PRISTINE; 1218c2ecf20Sopenharmony_ci /* 1228c2ecf20Sopenharmony_ci * Mark the node as having been checked and fix the 1238c2ecf20Sopenharmony_ci * accounting accordingly. 1248c2ecf20Sopenharmony_ci */ 1258c2ecf20Sopenharmony_ci spin_lock(&c->erase_completion_lock); 1268c2ecf20Sopenharmony_ci jeb->used_size += len; 1278c2ecf20Sopenharmony_ci jeb->unchecked_size -= len; 1288c2ecf20Sopenharmony_ci c->used_size += len; 1298c2ecf20Sopenharmony_ci c->unchecked_size -= len; 1308c2ecf20Sopenharmony_ci jffs2_dbg_acct_paranoia_check_nolock(c, jeb); 1318c2ecf20Sopenharmony_ci spin_unlock(&c->erase_completion_lock); 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_ci return 0; 1348c2ecf20Sopenharmony_ci 1358c2ecf20Sopenharmony_cifree_out: 1368c2ecf20Sopenharmony_ci if(!pointed) 1378c2ecf20Sopenharmony_ci kfree(buffer); 1388c2ecf20Sopenharmony_ci#ifndef __ECOS 1398c2ecf20Sopenharmony_ci else 1408c2ecf20Sopenharmony_ci mtd_unpoint(c->mtd, ofs, len); 1418c2ecf20Sopenharmony_ci#endif 1428c2ecf20Sopenharmony_ci return err; 1438c2ecf20Sopenharmony_ci} 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_ci/* 1468c2ecf20Sopenharmony_ci * Helper function for jffs2_add_older_frag_to_fragtree(). 1478c2ecf20Sopenharmony_ci * 1488c2ecf20Sopenharmony_ci * Checks the node if we are in the checking stage. 1498c2ecf20Sopenharmony_ci */ 1508c2ecf20Sopenharmony_cistatic int check_tn_node(struct jffs2_sb_info *c, struct jffs2_tmp_dnode_info *tn) 1518c2ecf20Sopenharmony_ci{ 1528c2ecf20Sopenharmony_ci int ret; 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci BUG_ON(ref_obsolete(tn->fn->raw)); 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_ci /* We only check the data CRC of unchecked nodes */ 1578c2ecf20Sopenharmony_ci if (ref_flags(tn->fn->raw) != REF_UNCHECKED) 1588c2ecf20Sopenharmony_ci return 0; 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci dbg_readinode("check node %#04x-%#04x, phys offs %#08x\n", 1618c2ecf20Sopenharmony_ci tn->fn->ofs, tn->fn->ofs + tn->fn->size, ref_offset(tn->fn->raw)); 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci ret = check_node_data(c, tn); 1648c2ecf20Sopenharmony_ci if (unlikely(ret < 0)) { 1658c2ecf20Sopenharmony_ci JFFS2_ERROR("check_node_data() returned error: %d.\n", 1668c2ecf20Sopenharmony_ci ret); 1678c2ecf20Sopenharmony_ci } else if (unlikely(ret > 0)) { 1688c2ecf20Sopenharmony_ci dbg_readinode("CRC error, mark it obsolete.\n"); 1698c2ecf20Sopenharmony_ci jffs2_mark_node_obsolete(c, tn->fn->raw); 1708c2ecf20Sopenharmony_ci } 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_ci return ret; 1738c2ecf20Sopenharmony_ci} 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_cistatic struct jffs2_tmp_dnode_info *jffs2_lookup_tn(struct rb_root *tn_root, uint32_t offset) 1768c2ecf20Sopenharmony_ci{ 1778c2ecf20Sopenharmony_ci struct rb_node *next; 1788c2ecf20Sopenharmony_ci struct jffs2_tmp_dnode_info *tn = NULL; 1798c2ecf20Sopenharmony_ci 1808c2ecf20Sopenharmony_ci dbg_readinode("root %p, offset %d\n", tn_root, offset); 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_ci next = tn_root->rb_node; 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_ci while (next) { 1858c2ecf20Sopenharmony_ci tn = rb_entry(next, struct jffs2_tmp_dnode_info, rb); 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_ci if (tn->fn->ofs < offset) 1888c2ecf20Sopenharmony_ci next = tn->rb.rb_right; 1898c2ecf20Sopenharmony_ci else if (tn->fn->ofs >= offset) 1908c2ecf20Sopenharmony_ci next = tn->rb.rb_left; 1918c2ecf20Sopenharmony_ci else 1928c2ecf20Sopenharmony_ci break; 1938c2ecf20Sopenharmony_ci } 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_ci return tn; 1968c2ecf20Sopenharmony_ci} 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_ci 1998c2ecf20Sopenharmony_cistatic void jffs2_kill_tn(struct jffs2_sb_info *c, struct jffs2_tmp_dnode_info *tn) 2008c2ecf20Sopenharmony_ci{ 2018c2ecf20Sopenharmony_ci jffs2_mark_node_obsolete(c, tn->fn->raw); 2028c2ecf20Sopenharmony_ci jffs2_free_full_dnode(tn->fn); 2038c2ecf20Sopenharmony_ci jffs2_free_tmp_dnode_info(tn); 2048c2ecf20Sopenharmony_ci} 2058c2ecf20Sopenharmony_ci/* 2068c2ecf20Sopenharmony_ci * This function is used when we read an inode. Data nodes arrive in 2078c2ecf20Sopenharmony_ci * arbitrary order -- they may be older or newer than the nodes which 2088c2ecf20Sopenharmony_ci * are already in the tree. Where overlaps occur, the older node can 2098c2ecf20Sopenharmony_ci * be discarded as long as the newer passes the CRC check. We don't 2108c2ecf20Sopenharmony_ci * bother to keep track of holes in this rbtree, and neither do we deal 2118c2ecf20Sopenharmony_ci * with frags -- we can have multiple entries starting at the same 2128c2ecf20Sopenharmony_ci * offset, and the one with the smallest length will come first in the 2138c2ecf20Sopenharmony_ci * ordering. 2148c2ecf20Sopenharmony_ci * 2158c2ecf20Sopenharmony_ci * Returns 0 if the node was handled (including marking it obsolete) 2168c2ecf20Sopenharmony_ci * < 0 an if error occurred 2178c2ecf20Sopenharmony_ci */ 2188c2ecf20Sopenharmony_cistatic int jffs2_add_tn_to_tree(struct jffs2_sb_info *c, 2198c2ecf20Sopenharmony_ci struct jffs2_readinode_info *rii, 2208c2ecf20Sopenharmony_ci struct jffs2_tmp_dnode_info *tn) 2218c2ecf20Sopenharmony_ci{ 2228c2ecf20Sopenharmony_ci uint32_t fn_end = tn->fn->ofs + tn->fn->size; 2238c2ecf20Sopenharmony_ci struct jffs2_tmp_dnode_info *this, *ptn; 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_ci dbg_readinode("insert fragment %#04x-%#04x, ver %u at %08x\n", tn->fn->ofs, fn_end, tn->version, ref_offset(tn->fn->raw)); 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_ci /* If a node has zero dsize, we only have to keep it if it might be the 2288c2ecf20Sopenharmony_ci node with highest version -- i.e. the one which will end up as f->metadata. 2298c2ecf20Sopenharmony_ci Note that such nodes won't be REF_UNCHECKED since there are no data to 2308c2ecf20Sopenharmony_ci check anyway. */ 2318c2ecf20Sopenharmony_ci if (!tn->fn->size) { 2328c2ecf20Sopenharmony_ci if (rii->mdata_tn) { 2338c2ecf20Sopenharmony_ci if (rii->mdata_tn->version < tn->version) { 2348c2ecf20Sopenharmony_ci /* We had a candidate mdata node already */ 2358c2ecf20Sopenharmony_ci dbg_readinode("kill old mdata with ver %d\n", rii->mdata_tn->version); 2368c2ecf20Sopenharmony_ci jffs2_kill_tn(c, rii->mdata_tn); 2378c2ecf20Sopenharmony_ci } else { 2388c2ecf20Sopenharmony_ci dbg_readinode("kill new mdata with ver %d (older than existing %d\n", 2398c2ecf20Sopenharmony_ci tn->version, rii->mdata_tn->version); 2408c2ecf20Sopenharmony_ci jffs2_kill_tn(c, tn); 2418c2ecf20Sopenharmony_ci return 0; 2428c2ecf20Sopenharmony_ci } 2438c2ecf20Sopenharmony_ci } 2448c2ecf20Sopenharmony_ci rii->mdata_tn = tn; 2458c2ecf20Sopenharmony_ci dbg_readinode("keep new mdata with ver %d\n", tn->version); 2468c2ecf20Sopenharmony_ci return 0; 2478c2ecf20Sopenharmony_ci } 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_ci /* Find the earliest node which _may_ be relevant to this one */ 2508c2ecf20Sopenharmony_ci this = jffs2_lookup_tn(&rii->tn_root, tn->fn->ofs); 2518c2ecf20Sopenharmony_ci if (this) { 2528c2ecf20Sopenharmony_ci /* If the node is coincident with another at a lower address, 2538c2ecf20Sopenharmony_ci back up until the other node is found. It may be relevant */ 2548c2ecf20Sopenharmony_ci while (this->overlapped) { 2558c2ecf20Sopenharmony_ci ptn = tn_prev(this); 2568c2ecf20Sopenharmony_ci if (!ptn) { 2578c2ecf20Sopenharmony_ci /* 2588c2ecf20Sopenharmony_ci * We killed a node which set the overlapped 2598c2ecf20Sopenharmony_ci * flags during the scan. Fix it up. 2608c2ecf20Sopenharmony_ci */ 2618c2ecf20Sopenharmony_ci this->overlapped = 0; 2628c2ecf20Sopenharmony_ci break; 2638c2ecf20Sopenharmony_ci } 2648c2ecf20Sopenharmony_ci this = ptn; 2658c2ecf20Sopenharmony_ci } 2668c2ecf20Sopenharmony_ci dbg_readinode("'this' found %#04x-%#04x (%s)\n", this->fn->ofs, this->fn->ofs + this->fn->size, this->fn ? "data" : "hole"); 2678c2ecf20Sopenharmony_ci } 2688c2ecf20Sopenharmony_ci 2698c2ecf20Sopenharmony_ci while (this) { 2708c2ecf20Sopenharmony_ci if (this->fn->ofs > fn_end) 2718c2ecf20Sopenharmony_ci break; 2728c2ecf20Sopenharmony_ci dbg_readinode("Ponder this ver %d, 0x%x-0x%x\n", 2738c2ecf20Sopenharmony_ci this->version, this->fn->ofs, this->fn->size); 2748c2ecf20Sopenharmony_ci 2758c2ecf20Sopenharmony_ci if (this->version == tn->version) { 2768c2ecf20Sopenharmony_ci /* Version number collision means REF_PRISTINE GC. Accept either of them 2778c2ecf20Sopenharmony_ci as long as the CRC is correct. Check the one we have already... */ 2788c2ecf20Sopenharmony_ci if (!check_tn_node(c, this)) { 2798c2ecf20Sopenharmony_ci /* The one we already had was OK. Keep it and throw away the new one */ 2808c2ecf20Sopenharmony_ci dbg_readinode("Like old node. Throw away new\n"); 2818c2ecf20Sopenharmony_ci jffs2_kill_tn(c, tn); 2828c2ecf20Sopenharmony_ci return 0; 2838c2ecf20Sopenharmony_ci } else { 2848c2ecf20Sopenharmony_ci /* Who cares if the new one is good; keep it for now anyway. */ 2858c2ecf20Sopenharmony_ci dbg_readinode("Like new node. Throw away old\n"); 2868c2ecf20Sopenharmony_ci rb_replace_node(&this->rb, &tn->rb, &rii->tn_root); 2878c2ecf20Sopenharmony_ci jffs2_kill_tn(c, this); 2888c2ecf20Sopenharmony_ci /* Same overlapping from in front and behind */ 2898c2ecf20Sopenharmony_ci return 0; 2908c2ecf20Sopenharmony_ci } 2918c2ecf20Sopenharmony_ci } 2928c2ecf20Sopenharmony_ci if (this->version < tn->version && 2938c2ecf20Sopenharmony_ci this->fn->ofs >= tn->fn->ofs && 2948c2ecf20Sopenharmony_ci this->fn->ofs + this->fn->size <= fn_end) { 2958c2ecf20Sopenharmony_ci /* New node entirely overlaps 'this' */ 2968c2ecf20Sopenharmony_ci if (check_tn_node(c, tn)) { 2978c2ecf20Sopenharmony_ci dbg_readinode("new node bad CRC\n"); 2988c2ecf20Sopenharmony_ci jffs2_kill_tn(c, tn); 2998c2ecf20Sopenharmony_ci return 0; 3008c2ecf20Sopenharmony_ci } 3018c2ecf20Sopenharmony_ci /* ... and is good. Kill 'this' and any subsequent nodes which are also overlapped */ 3028c2ecf20Sopenharmony_ci while (this && this->fn->ofs + this->fn->size <= fn_end) { 3038c2ecf20Sopenharmony_ci struct jffs2_tmp_dnode_info *next = tn_next(this); 3048c2ecf20Sopenharmony_ci if (this->version < tn->version) { 3058c2ecf20Sopenharmony_ci tn_erase(this, &rii->tn_root); 3068c2ecf20Sopenharmony_ci dbg_readinode("Kill overlapped ver %d, 0x%x-0x%x\n", 3078c2ecf20Sopenharmony_ci this->version, this->fn->ofs, 3088c2ecf20Sopenharmony_ci this->fn->ofs+this->fn->size); 3098c2ecf20Sopenharmony_ci jffs2_kill_tn(c, this); 3108c2ecf20Sopenharmony_ci } 3118c2ecf20Sopenharmony_ci this = next; 3128c2ecf20Sopenharmony_ci } 3138c2ecf20Sopenharmony_ci dbg_readinode("Done killing overlapped nodes\n"); 3148c2ecf20Sopenharmony_ci continue; 3158c2ecf20Sopenharmony_ci } 3168c2ecf20Sopenharmony_ci if (this->version > tn->version && 3178c2ecf20Sopenharmony_ci this->fn->ofs <= tn->fn->ofs && 3188c2ecf20Sopenharmony_ci this->fn->ofs+this->fn->size >= fn_end) { 3198c2ecf20Sopenharmony_ci /* New node entirely overlapped by 'this' */ 3208c2ecf20Sopenharmony_ci if (!check_tn_node(c, this)) { 3218c2ecf20Sopenharmony_ci dbg_readinode("Good CRC on old node. Kill new\n"); 3228c2ecf20Sopenharmony_ci jffs2_kill_tn(c, tn); 3238c2ecf20Sopenharmony_ci return 0; 3248c2ecf20Sopenharmony_ci } 3258c2ecf20Sopenharmony_ci /* ... but 'this' was bad. Replace it... */ 3268c2ecf20Sopenharmony_ci dbg_readinode("Bad CRC on old overlapping node. Kill it\n"); 3278c2ecf20Sopenharmony_ci tn_erase(this, &rii->tn_root); 3288c2ecf20Sopenharmony_ci jffs2_kill_tn(c, this); 3298c2ecf20Sopenharmony_ci break; 3308c2ecf20Sopenharmony_ci } 3318c2ecf20Sopenharmony_ci 3328c2ecf20Sopenharmony_ci this = tn_next(this); 3338c2ecf20Sopenharmony_ci } 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_ci /* We neither completely obsoleted nor were completely 3368c2ecf20Sopenharmony_ci obsoleted by an earlier node. Insert into the tree */ 3378c2ecf20Sopenharmony_ci { 3388c2ecf20Sopenharmony_ci struct rb_node *parent; 3398c2ecf20Sopenharmony_ci struct rb_node **link = &rii->tn_root.rb_node; 3408c2ecf20Sopenharmony_ci struct jffs2_tmp_dnode_info *insert_point = NULL; 3418c2ecf20Sopenharmony_ci 3428c2ecf20Sopenharmony_ci while (*link) { 3438c2ecf20Sopenharmony_ci parent = *link; 3448c2ecf20Sopenharmony_ci insert_point = rb_entry(parent, struct jffs2_tmp_dnode_info, rb); 3458c2ecf20Sopenharmony_ci if (tn->fn->ofs > insert_point->fn->ofs) 3468c2ecf20Sopenharmony_ci link = &insert_point->rb.rb_right; 3478c2ecf20Sopenharmony_ci else if (tn->fn->ofs < insert_point->fn->ofs || 3488c2ecf20Sopenharmony_ci tn->fn->size < insert_point->fn->size) 3498c2ecf20Sopenharmony_ci link = &insert_point->rb.rb_left; 3508c2ecf20Sopenharmony_ci else 3518c2ecf20Sopenharmony_ci link = &insert_point->rb.rb_right; 3528c2ecf20Sopenharmony_ci } 3538c2ecf20Sopenharmony_ci rb_link_node(&tn->rb, &insert_point->rb, link); 3548c2ecf20Sopenharmony_ci rb_insert_color(&tn->rb, &rii->tn_root); 3558c2ecf20Sopenharmony_ci } 3568c2ecf20Sopenharmony_ci 3578c2ecf20Sopenharmony_ci /* If there's anything behind that overlaps us, note it */ 3588c2ecf20Sopenharmony_ci this = tn_prev(tn); 3598c2ecf20Sopenharmony_ci if (this) { 3608c2ecf20Sopenharmony_ci while (1) { 3618c2ecf20Sopenharmony_ci if (this->fn->ofs + this->fn->size > tn->fn->ofs) { 3628c2ecf20Sopenharmony_ci dbg_readinode("Node is overlapped by %p (v %d, 0x%x-0x%x)\n", 3638c2ecf20Sopenharmony_ci this, this->version, this->fn->ofs, 3648c2ecf20Sopenharmony_ci this->fn->ofs+this->fn->size); 3658c2ecf20Sopenharmony_ci tn->overlapped = 1; 3668c2ecf20Sopenharmony_ci break; 3678c2ecf20Sopenharmony_ci } 3688c2ecf20Sopenharmony_ci if (!this->overlapped) 3698c2ecf20Sopenharmony_ci break; 3708c2ecf20Sopenharmony_ci 3718c2ecf20Sopenharmony_ci ptn = tn_prev(this); 3728c2ecf20Sopenharmony_ci if (!ptn) { 3738c2ecf20Sopenharmony_ci /* 3748c2ecf20Sopenharmony_ci * We killed a node which set the overlapped 3758c2ecf20Sopenharmony_ci * flags during the scan. Fix it up. 3768c2ecf20Sopenharmony_ci */ 3778c2ecf20Sopenharmony_ci this->overlapped = 0; 3788c2ecf20Sopenharmony_ci break; 3798c2ecf20Sopenharmony_ci } 3808c2ecf20Sopenharmony_ci this = ptn; 3818c2ecf20Sopenharmony_ci } 3828c2ecf20Sopenharmony_ci } 3838c2ecf20Sopenharmony_ci 3848c2ecf20Sopenharmony_ci /* If the new node overlaps anything ahead, note it */ 3858c2ecf20Sopenharmony_ci this = tn_next(tn); 3868c2ecf20Sopenharmony_ci while (this && this->fn->ofs < fn_end) { 3878c2ecf20Sopenharmony_ci this->overlapped = 1; 3888c2ecf20Sopenharmony_ci dbg_readinode("Node ver %d, 0x%x-0x%x is overlapped\n", 3898c2ecf20Sopenharmony_ci this->version, this->fn->ofs, 3908c2ecf20Sopenharmony_ci this->fn->ofs+this->fn->size); 3918c2ecf20Sopenharmony_ci this = tn_next(this); 3928c2ecf20Sopenharmony_ci } 3938c2ecf20Sopenharmony_ci return 0; 3948c2ecf20Sopenharmony_ci} 3958c2ecf20Sopenharmony_ci 3968c2ecf20Sopenharmony_ci/* Trivial function to remove the last node in the tree. Which by definition 3978c2ecf20Sopenharmony_ci has no right-hand child — so can be removed just by making its left-hand 3988c2ecf20Sopenharmony_ci child (if any) take its place under its parent. Since this is only done 3998c2ecf20Sopenharmony_ci when we're consuming the whole tree, there's no need to use rb_erase() 4008c2ecf20Sopenharmony_ci and let it worry about adjusting colours and balancing the tree. That 4018c2ecf20Sopenharmony_ci would just be a waste of time. */ 4028c2ecf20Sopenharmony_cistatic void eat_last(struct rb_root *root, struct rb_node *node) 4038c2ecf20Sopenharmony_ci{ 4048c2ecf20Sopenharmony_ci struct rb_node *parent = rb_parent(node); 4058c2ecf20Sopenharmony_ci struct rb_node **link; 4068c2ecf20Sopenharmony_ci 4078c2ecf20Sopenharmony_ci /* LAST! */ 4088c2ecf20Sopenharmony_ci BUG_ON(node->rb_right); 4098c2ecf20Sopenharmony_ci 4108c2ecf20Sopenharmony_ci if (!parent) 4118c2ecf20Sopenharmony_ci link = &root->rb_node; 4128c2ecf20Sopenharmony_ci else if (node == parent->rb_left) 4138c2ecf20Sopenharmony_ci link = &parent->rb_left; 4148c2ecf20Sopenharmony_ci else 4158c2ecf20Sopenharmony_ci link = &parent->rb_right; 4168c2ecf20Sopenharmony_ci 4178c2ecf20Sopenharmony_ci *link = node->rb_left; 4188c2ecf20Sopenharmony_ci if (node->rb_left) 4198c2ecf20Sopenharmony_ci node->rb_left->__rb_parent_color = node->__rb_parent_color; 4208c2ecf20Sopenharmony_ci} 4218c2ecf20Sopenharmony_ci 4228c2ecf20Sopenharmony_ci/* We put the version tree in reverse order, so we can use the same eat_last() 4238c2ecf20Sopenharmony_ci function that we use to consume the tmpnode tree (tn_root). */ 4248c2ecf20Sopenharmony_cistatic void ver_insert(struct rb_root *ver_root, struct jffs2_tmp_dnode_info *tn) 4258c2ecf20Sopenharmony_ci{ 4268c2ecf20Sopenharmony_ci struct rb_node **link = &ver_root->rb_node; 4278c2ecf20Sopenharmony_ci struct rb_node *parent = NULL; 4288c2ecf20Sopenharmony_ci struct jffs2_tmp_dnode_info *this_tn; 4298c2ecf20Sopenharmony_ci 4308c2ecf20Sopenharmony_ci while (*link) { 4318c2ecf20Sopenharmony_ci parent = *link; 4328c2ecf20Sopenharmony_ci this_tn = rb_entry(parent, struct jffs2_tmp_dnode_info, rb); 4338c2ecf20Sopenharmony_ci 4348c2ecf20Sopenharmony_ci if (tn->version > this_tn->version) 4358c2ecf20Sopenharmony_ci link = &parent->rb_left; 4368c2ecf20Sopenharmony_ci else 4378c2ecf20Sopenharmony_ci link = &parent->rb_right; 4388c2ecf20Sopenharmony_ci } 4398c2ecf20Sopenharmony_ci dbg_readinode("Link new node at %p (root is %p)\n", link, ver_root); 4408c2ecf20Sopenharmony_ci rb_link_node(&tn->rb, parent, link); 4418c2ecf20Sopenharmony_ci rb_insert_color(&tn->rb, ver_root); 4428c2ecf20Sopenharmony_ci} 4438c2ecf20Sopenharmony_ci 4448c2ecf20Sopenharmony_ci/* Build final, normal fragtree from tn tree. It doesn't matter which order 4458c2ecf20Sopenharmony_ci we add nodes to the real fragtree, as long as they don't overlap. And 4468c2ecf20Sopenharmony_ci having thrown away the majority of overlapped nodes as we went, there 4478c2ecf20Sopenharmony_ci really shouldn't be many sets of nodes which do overlap. If we start at 4488c2ecf20Sopenharmony_ci the end, we can use the overlap markers -- we can just eat nodes which 4498c2ecf20Sopenharmony_ci aren't overlapped, and when we encounter nodes which _do_ overlap we 4508c2ecf20Sopenharmony_ci sort them all into a temporary tree in version order before replaying them. */ 4518c2ecf20Sopenharmony_cistatic int jffs2_build_inode_fragtree(struct jffs2_sb_info *c, 4528c2ecf20Sopenharmony_ci struct jffs2_inode_info *f, 4538c2ecf20Sopenharmony_ci struct jffs2_readinode_info *rii) 4548c2ecf20Sopenharmony_ci{ 4558c2ecf20Sopenharmony_ci struct jffs2_tmp_dnode_info *pen, *last, *this; 4568c2ecf20Sopenharmony_ci struct rb_root ver_root = RB_ROOT; 4578c2ecf20Sopenharmony_ci uint32_t high_ver = 0; 4588c2ecf20Sopenharmony_ci 4598c2ecf20Sopenharmony_ci if (rii->mdata_tn) { 4608c2ecf20Sopenharmony_ci dbg_readinode("potential mdata is ver %d at %p\n", rii->mdata_tn->version, rii->mdata_tn); 4618c2ecf20Sopenharmony_ci high_ver = rii->mdata_tn->version; 4628c2ecf20Sopenharmony_ci rii->latest_ref = rii->mdata_tn->fn->raw; 4638c2ecf20Sopenharmony_ci } 4648c2ecf20Sopenharmony_ci#ifdef JFFS2_DBG_READINODE_MESSAGES 4658c2ecf20Sopenharmony_ci this = tn_last(&rii->tn_root); 4668c2ecf20Sopenharmony_ci while (this) { 4678c2ecf20Sopenharmony_ci dbg_readinode("tn %p ver %d range 0x%x-0x%x ov %d\n", this, this->version, this->fn->ofs, 4688c2ecf20Sopenharmony_ci this->fn->ofs+this->fn->size, this->overlapped); 4698c2ecf20Sopenharmony_ci this = tn_prev(this); 4708c2ecf20Sopenharmony_ci } 4718c2ecf20Sopenharmony_ci#endif 4728c2ecf20Sopenharmony_ci pen = tn_last(&rii->tn_root); 4738c2ecf20Sopenharmony_ci while ((last = pen)) { 4748c2ecf20Sopenharmony_ci pen = tn_prev(last); 4758c2ecf20Sopenharmony_ci 4768c2ecf20Sopenharmony_ci eat_last(&rii->tn_root, &last->rb); 4778c2ecf20Sopenharmony_ci ver_insert(&ver_root, last); 4788c2ecf20Sopenharmony_ci 4798c2ecf20Sopenharmony_ci if (unlikely(last->overlapped)) { 4808c2ecf20Sopenharmony_ci if (pen) 4818c2ecf20Sopenharmony_ci continue; 4828c2ecf20Sopenharmony_ci /* 4838c2ecf20Sopenharmony_ci * We killed a node which set the overlapped 4848c2ecf20Sopenharmony_ci * flags during the scan. Fix it up. 4858c2ecf20Sopenharmony_ci */ 4868c2ecf20Sopenharmony_ci last->overlapped = 0; 4878c2ecf20Sopenharmony_ci } 4888c2ecf20Sopenharmony_ci 4898c2ecf20Sopenharmony_ci /* Now we have a bunch of nodes in reverse version 4908c2ecf20Sopenharmony_ci order, in the tree at ver_root. Most of the time, 4918c2ecf20Sopenharmony_ci there'll actually be only one node in the 'tree', 4928c2ecf20Sopenharmony_ci in fact. */ 4938c2ecf20Sopenharmony_ci this = tn_last(&ver_root); 4948c2ecf20Sopenharmony_ci 4958c2ecf20Sopenharmony_ci while (this) { 4968c2ecf20Sopenharmony_ci struct jffs2_tmp_dnode_info *vers_next; 4978c2ecf20Sopenharmony_ci int ret; 4988c2ecf20Sopenharmony_ci vers_next = tn_prev(this); 4998c2ecf20Sopenharmony_ci eat_last(&ver_root, &this->rb); 5008c2ecf20Sopenharmony_ci if (check_tn_node(c, this)) { 5018c2ecf20Sopenharmony_ci dbg_readinode("node ver %d, 0x%x-0x%x failed CRC\n", 5028c2ecf20Sopenharmony_ci this->version, this->fn->ofs, 5038c2ecf20Sopenharmony_ci this->fn->ofs+this->fn->size); 5048c2ecf20Sopenharmony_ci jffs2_kill_tn(c, this); 5058c2ecf20Sopenharmony_ci } else { 5068c2ecf20Sopenharmony_ci if (this->version > high_ver) { 5078c2ecf20Sopenharmony_ci /* Note that this is different from the other 5088c2ecf20Sopenharmony_ci highest_version, because this one is only 5098c2ecf20Sopenharmony_ci counting _valid_ nodes which could give the 5108c2ecf20Sopenharmony_ci latest inode metadata */ 5118c2ecf20Sopenharmony_ci high_ver = this->version; 5128c2ecf20Sopenharmony_ci rii->latest_ref = this->fn->raw; 5138c2ecf20Sopenharmony_ci } 5148c2ecf20Sopenharmony_ci dbg_readinode("Add %p (v %d, 0x%x-0x%x, ov %d) to fragtree\n", 5158c2ecf20Sopenharmony_ci this, this->version, this->fn->ofs, 5168c2ecf20Sopenharmony_ci this->fn->ofs+this->fn->size, this->overlapped); 5178c2ecf20Sopenharmony_ci 5188c2ecf20Sopenharmony_ci ret = jffs2_add_full_dnode_to_inode(c, f, this->fn); 5198c2ecf20Sopenharmony_ci if (ret) { 5208c2ecf20Sopenharmony_ci /* Free the nodes in vers_root; let the caller 5218c2ecf20Sopenharmony_ci deal with the rest */ 5228c2ecf20Sopenharmony_ci JFFS2_ERROR("Add node to tree failed %d\n", ret); 5238c2ecf20Sopenharmony_ci while (1) { 5248c2ecf20Sopenharmony_ci vers_next = tn_prev(this); 5258c2ecf20Sopenharmony_ci if (check_tn_node(c, this)) 5268c2ecf20Sopenharmony_ci jffs2_mark_node_obsolete(c, this->fn->raw); 5278c2ecf20Sopenharmony_ci jffs2_free_full_dnode(this->fn); 5288c2ecf20Sopenharmony_ci jffs2_free_tmp_dnode_info(this); 5298c2ecf20Sopenharmony_ci this = vers_next; 5308c2ecf20Sopenharmony_ci if (!this) 5318c2ecf20Sopenharmony_ci break; 5328c2ecf20Sopenharmony_ci eat_last(&ver_root, &vers_next->rb); 5338c2ecf20Sopenharmony_ci } 5348c2ecf20Sopenharmony_ci return ret; 5358c2ecf20Sopenharmony_ci } 5368c2ecf20Sopenharmony_ci jffs2_free_tmp_dnode_info(this); 5378c2ecf20Sopenharmony_ci } 5388c2ecf20Sopenharmony_ci this = vers_next; 5398c2ecf20Sopenharmony_ci } 5408c2ecf20Sopenharmony_ci } 5418c2ecf20Sopenharmony_ci return 0; 5428c2ecf20Sopenharmony_ci} 5438c2ecf20Sopenharmony_ci 5448c2ecf20Sopenharmony_cistatic void jffs2_free_tmp_dnode_info_list(struct rb_root *list) 5458c2ecf20Sopenharmony_ci{ 5468c2ecf20Sopenharmony_ci struct jffs2_tmp_dnode_info *tn, *next; 5478c2ecf20Sopenharmony_ci 5488c2ecf20Sopenharmony_ci rbtree_postorder_for_each_entry_safe(tn, next, list, rb) { 5498c2ecf20Sopenharmony_ci jffs2_free_full_dnode(tn->fn); 5508c2ecf20Sopenharmony_ci jffs2_free_tmp_dnode_info(tn); 5518c2ecf20Sopenharmony_ci } 5528c2ecf20Sopenharmony_ci 5538c2ecf20Sopenharmony_ci *list = RB_ROOT; 5548c2ecf20Sopenharmony_ci} 5558c2ecf20Sopenharmony_ci 5568c2ecf20Sopenharmony_cistatic void jffs2_free_full_dirent_list(struct jffs2_full_dirent *fd) 5578c2ecf20Sopenharmony_ci{ 5588c2ecf20Sopenharmony_ci struct jffs2_full_dirent *next; 5598c2ecf20Sopenharmony_ci 5608c2ecf20Sopenharmony_ci while (fd) { 5618c2ecf20Sopenharmony_ci next = fd->next; 5628c2ecf20Sopenharmony_ci jffs2_free_full_dirent(fd); 5638c2ecf20Sopenharmony_ci fd = next; 5648c2ecf20Sopenharmony_ci } 5658c2ecf20Sopenharmony_ci} 5668c2ecf20Sopenharmony_ci 5678c2ecf20Sopenharmony_ci/* Returns first valid node after 'ref'. May return 'ref' */ 5688c2ecf20Sopenharmony_cistatic struct jffs2_raw_node_ref *jffs2_first_valid_node(struct jffs2_raw_node_ref *ref) 5698c2ecf20Sopenharmony_ci{ 5708c2ecf20Sopenharmony_ci while (ref && ref->next_in_ino) { 5718c2ecf20Sopenharmony_ci if (!ref_obsolete(ref)) 5728c2ecf20Sopenharmony_ci return ref; 5738c2ecf20Sopenharmony_ci dbg_noderef("node at 0x%08x is obsoleted. Ignoring.\n", ref_offset(ref)); 5748c2ecf20Sopenharmony_ci ref = ref->next_in_ino; 5758c2ecf20Sopenharmony_ci } 5768c2ecf20Sopenharmony_ci return NULL; 5778c2ecf20Sopenharmony_ci} 5788c2ecf20Sopenharmony_ci 5798c2ecf20Sopenharmony_ci/* 5808c2ecf20Sopenharmony_ci * Helper function for jffs2_get_inode_nodes(). 5818c2ecf20Sopenharmony_ci * It is called every time an directory entry node is found. 5828c2ecf20Sopenharmony_ci * 5838c2ecf20Sopenharmony_ci * Returns: 0 on success; 5848c2ecf20Sopenharmony_ci * negative error code on failure. 5858c2ecf20Sopenharmony_ci */ 5868c2ecf20Sopenharmony_cistatic inline int read_direntry(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref, 5878c2ecf20Sopenharmony_ci struct jffs2_raw_dirent *rd, size_t read, 5888c2ecf20Sopenharmony_ci struct jffs2_readinode_info *rii) 5898c2ecf20Sopenharmony_ci{ 5908c2ecf20Sopenharmony_ci struct jffs2_full_dirent *fd; 5918c2ecf20Sopenharmony_ci uint32_t crc; 5928c2ecf20Sopenharmony_ci 5938c2ecf20Sopenharmony_ci /* Obsoleted. This cannot happen, surely? dwmw2 20020308 */ 5948c2ecf20Sopenharmony_ci BUG_ON(ref_obsolete(ref)); 5958c2ecf20Sopenharmony_ci 5968c2ecf20Sopenharmony_ci crc = crc32(0, rd, sizeof(*rd) - 8); 5978c2ecf20Sopenharmony_ci if (unlikely(crc != je32_to_cpu(rd->node_crc))) { 5988c2ecf20Sopenharmony_ci JFFS2_NOTICE("header CRC failed on dirent node at %#08x: read %#08x, calculated %#08x\n", 5998c2ecf20Sopenharmony_ci ref_offset(ref), je32_to_cpu(rd->node_crc), crc); 6008c2ecf20Sopenharmony_ci jffs2_mark_node_obsolete(c, ref); 6018c2ecf20Sopenharmony_ci return 0; 6028c2ecf20Sopenharmony_ci } 6038c2ecf20Sopenharmony_ci 6048c2ecf20Sopenharmony_ci /* If we've never checked the CRCs on this node, check them now */ 6058c2ecf20Sopenharmony_ci if (ref_flags(ref) == REF_UNCHECKED) { 6068c2ecf20Sopenharmony_ci struct jffs2_eraseblock *jeb; 6078c2ecf20Sopenharmony_ci int len; 6088c2ecf20Sopenharmony_ci 6098c2ecf20Sopenharmony_ci /* Sanity check */ 6108c2ecf20Sopenharmony_ci if (unlikely(PAD((rd->nsize + sizeof(*rd))) != PAD(je32_to_cpu(rd->totlen)))) { 6118c2ecf20Sopenharmony_ci JFFS2_ERROR("illegal nsize in node at %#08x: nsize %#02x, totlen %#04x\n", 6128c2ecf20Sopenharmony_ci ref_offset(ref), rd->nsize, je32_to_cpu(rd->totlen)); 6138c2ecf20Sopenharmony_ci jffs2_mark_node_obsolete(c, ref); 6148c2ecf20Sopenharmony_ci return 0; 6158c2ecf20Sopenharmony_ci } 6168c2ecf20Sopenharmony_ci 6178c2ecf20Sopenharmony_ci jeb = &c->blocks[ref->flash_offset / c->sector_size]; 6188c2ecf20Sopenharmony_ci len = ref_totlen(c, jeb, ref); 6198c2ecf20Sopenharmony_ci 6208c2ecf20Sopenharmony_ci spin_lock(&c->erase_completion_lock); 6218c2ecf20Sopenharmony_ci jeb->used_size += len; 6228c2ecf20Sopenharmony_ci jeb->unchecked_size -= len; 6238c2ecf20Sopenharmony_ci c->used_size += len; 6248c2ecf20Sopenharmony_ci c->unchecked_size -= len; 6258c2ecf20Sopenharmony_ci ref->flash_offset = ref_offset(ref) | dirent_node_state(rd); 6268c2ecf20Sopenharmony_ci spin_unlock(&c->erase_completion_lock); 6278c2ecf20Sopenharmony_ci } 6288c2ecf20Sopenharmony_ci 6298c2ecf20Sopenharmony_ci fd = jffs2_alloc_full_dirent(rd->nsize + 1); 6308c2ecf20Sopenharmony_ci if (unlikely(!fd)) 6318c2ecf20Sopenharmony_ci return -ENOMEM; 6328c2ecf20Sopenharmony_ci 6338c2ecf20Sopenharmony_ci fd->raw = ref; 6348c2ecf20Sopenharmony_ci fd->version = je32_to_cpu(rd->version); 6358c2ecf20Sopenharmony_ci fd->ino = je32_to_cpu(rd->ino); 6368c2ecf20Sopenharmony_ci fd->type = rd->type; 6378c2ecf20Sopenharmony_ci 6388c2ecf20Sopenharmony_ci if (fd->version > rii->highest_version) 6398c2ecf20Sopenharmony_ci rii->highest_version = fd->version; 6408c2ecf20Sopenharmony_ci 6418c2ecf20Sopenharmony_ci /* Pick out the mctime of the latest dirent */ 6428c2ecf20Sopenharmony_ci if(fd->version > rii->mctime_ver && je32_to_cpu(rd->mctime)) { 6438c2ecf20Sopenharmony_ci rii->mctime_ver = fd->version; 6448c2ecf20Sopenharmony_ci rii->latest_mctime = je32_to_cpu(rd->mctime); 6458c2ecf20Sopenharmony_ci } 6468c2ecf20Sopenharmony_ci 6478c2ecf20Sopenharmony_ci /* 6488c2ecf20Sopenharmony_ci * Copy as much of the name as possible from the raw 6498c2ecf20Sopenharmony_ci * dirent we've already read from the flash. 6508c2ecf20Sopenharmony_ci */ 6518c2ecf20Sopenharmony_ci if (read > sizeof(*rd)) 6528c2ecf20Sopenharmony_ci memcpy(&fd->name[0], &rd->name[0], 6538c2ecf20Sopenharmony_ci min_t(uint32_t, rd->nsize, (read - sizeof(*rd)) )); 6548c2ecf20Sopenharmony_ci 6558c2ecf20Sopenharmony_ci /* Do we need to copy any more of the name directly from the flash? */ 6568c2ecf20Sopenharmony_ci if (rd->nsize + sizeof(*rd) > read) { 6578c2ecf20Sopenharmony_ci /* FIXME: point() */ 6588c2ecf20Sopenharmony_ci int err; 6598c2ecf20Sopenharmony_ci int already = read - sizeof(*rd); 6608c2ecf20Sopenharmony_ci 6618c2ecf20Sopenharmony_ci err = jffs2_flash_read(c, (ref_offset(ref)) + read, 6628c2ecf20Sopenharmony_ci rd->nsize - already, &read, &fd->name[already]); 6638c2ecf20Sopenharmony_ci if (unlikely(read != rd->nsize - already) && likely(!err)) { 6648c2ecf20Sopenharmony_ci jffs2_free_full_dirent(fd); 6658c2ecf20Sopenharmony_ci JFFS2_ERROR("short read: wanted %d bytes, got %zd\n", 6668c2ecf20Sopenharmony_ci rd->nsize - already, read); 6678c2ecf20Sopenharmony_ci return -EIO; 6688c2ecf20Sopenharmony_ci } 6698c2ecf20Sopenharmony_ci 6708c2ecf20Sopenharmony_ci if (unlikely(err)) { 6718c2ecf20Sopenharmony_ci JFFS2_ERROR("read remainder of name: error %d\n", err); 6728c2ecf20Sopenharmony_ci jffs2_free_full_dirent(fd); 6738c2ecf20Sopenharmony_ci return -EIO; 6748c2ecf20Sopenharmony_ci } 6758c2ecf20Sopenharmony_ci 6768c2ecf20Sopenharmony_ci#ifdef CONFIG_JFFS2_SUMMARY 6778c2ecf20Sopenharmony_ci /* 6788c2ecf20Sopenharmony_ci * we use CONFIG_JFFS2_SUMMARY because without it, we 6798c2ecf20Sopenharmony_ci * have checked it while mounting 6808c2ecf20Sopenharmony_ci */ 6818c2ecf20Sopenharmony_ci crc = crc32(0, fd->name, rd->nsize); 6828c2ecf20Sopenharmony_ci if (unlikely(crc != je32_to_cpu(rd->name_crc))) { 6838c2ecf20Sopenharmony_ci JFFS2_NOTICE("name CRC failed on dirent node at" 6848c2ecf20Sopenharmony_ci "%#08x: read %#08x,calculated %#08x\n", 6858c2ecf20Sopenharmony_ci ref_offset(ref), je32_to_cpu(rd->node_crc), crc); 6868c2ecf20Sopenharmony_ci jffs2_mark_node_obsolete(c, ref); 6878c2ecf20Sopenharmony_ci jffs2_free_full_dirent(fd); 6888c2ecf20Sopenharmony_ci return 0; 6898c2ecf20Sopenharmony_ci } 6908c2ecf20Sopenharmony_ci#endif 6918c2ecf20Sopenharmony_ci } 6928c2ecf20Sopenharmony_ci 6938c2ecf20Sopenharmony_ci fd->nhash = full_name_hash(NULL, fd->name, rd->nsize); 6948c2ecf20Sopenharmony_ci fd->next = NULL; 6958c2ecf20Sopenharmony_ci fd->name[rd->nsize] = '\0'; 6968c2ecf20Sopenharmony_ci 6978c2ecf20Sopenharmony_ci /* 6988c2ecf20Sopenharmony_ci * Wheee. We now have a complete jffs2_full_dirent structure, with 6998c2ecf20Sopenharmony_ci * the name in it and everything. Link it into the list 7008c2ecf20Sopenharmony_ci */ 7018c2ecf20Sopenharmony_ci jffs2_add_fd_to_list(c, fd, &rii->fds); 7028c2ecf20Sopenharmony_ci 7038c2ecf20Sopenharmony_ci return 0; 7048c2ecf20Sopenharmony_ci} 7058c2ecf20Sopenharmony_ci 7068c2ecf20Sopenharmony_ci/* 7078c2ecf20Sopenharmony_ci * Helper function for jffs2_get_inode_nodes(). 7088c2ecf20Sopenharmony_ci * It is called every time an inode node is found. 7098c2ecf20Sopenharmony_ci * 7108c2ecf20Sopenharmony_ci * Returns: 0 on success (possibly after marking a bad node obsolete); 7118c2ecf20Sopenharmony_ci * negative error code on failure. 7128c2ecf20Sopenharmony_ci */ 7138c2ecf20Sopenharmony_cistatic inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref, 7148c2ecf20Sopenharmony_ci struct jffs2_raw_inode *rd, int rdlen, 7158c2ecf20Sopenharmony_ci struct jffs2_readinode_info *rii) 7168c2ecf20Sopenharmony_ci{ 7178c2ecf20Sopenharmony_ci struct jffs2_tmp_dnode_info *tn; 7188c2ecf20Sopenharmony_ci uint32_t len, csize; 7198c2ecf20Sopenharmony_ci int ret = 0; 7208c2ecf20Sopenharmony_ci uint32_t crc; 7218c2ecf20Sopenharmony_ci 7228c2ecf20Sopenharmony_ci /* Obsoleted. This cannot happen, surely? dwmw2 20020308 */ 7238c2ecf20Sopenharmony_ci BUG_ON(ref_obsolete(ref)); 7248c2ecf20Sopenharmony_ci 7258c2ecf20Sopenharmony_ci crc = crc32(0, rd, sizeof(*rd) - 8); 7268c2ecf20Sopenharmony_ci if (unlikely(crc != je32_to_cpu(rd->node_crc))) { 7278c2ecf20Sopenharmony_ci JFFS2_NOTICE("node CRC failed on dnode at %#08x: read %#08x, calculated %#08x\n", 7288c2ecf20Sopenharmony_ci ref_offset(ref), je32_to_cpu(rd->node_crc), crc); 7298c2ecf20Sopenharmony_ci jffs2_mark_node_obsolete(c, ref); 7308c2ecf20Sopenharmony_ci return 0; 7318c2ecf20Sopenharmony_ci } 7328c2ecf20Sopenharmony_ci 7338c2ecf20Sopenharmony_ci tn = jffs2_alloc_tmp_dnode_info(); 7348c2ecf20Sopenharmony_ci if (!tn) { 7358c2ecf20Sopenharmony_ci JFFS2_ERROR("failed to allocate tn (%zu bytes).\n", sizeof(*tn)); 7368c2ecf20Sopenharmony_ci return -ENOMEM; 7378c2ecf20Sopenharmony_ci } 7388c2ecf20Sopenharmony_ci 7398c2ecf20Sopenharmony_ci tn->partial_crc = 0; 7408c2ecf20Sopenharmony_ci csize = je32_to_cpu(rd->csize); 7418c2ecf20Sopenharmony_ci 7428c2ecf20Sopenharmony_ci /* If we've never checked the CRCs on this node, check them now */ 7438c2ecf20Sopenharmony_ci if (ref_flags(ref) == REF_UNCHECKED) { 7448c2ecf20Sopenharmony_ci 7458c2ecf20Sopenharmony_ci /* Sanity checks */ 7468c2ecf20Sopenharmony_ci if (unlikely(je32_to_cpu(rd->offset) > je32_to_cpu(rd->isize)) || 7478c2ecf20Sopenharmony_ci unlikely(PAD(je32_to_cpu(rd->csize) + sizeof(*rd)) != PAD(je32_to_cpu(rd->totlen)))) { 7488c2ecf20Sopenharmony_ci JFFS2_WARNING("inode node header CRC is corrupted at %#08x\n", ref_offset(ref)); 7498c2ecf20Sopenharmony_ci jffs2_dbg_dump_node(c, ref_offset(ref)); 7508c2ecf20Sopenharmony_ci jffs2_mark_node_obsolete(c, ref); 7518c2ecf20Sopenharmony_ci goto free_out; 7528c2ecf20Sopenharmony_ci } 7538c2ecf20Sopenharmony_ci 7548c2ecf20Sopenharmony_ci if (jffs2_is_writebuffered(c) && csize != 0) { 7558c2ecf20Sopenharmony_ci /* At this point we are supposed to check the data CRC 7568c2ecf20Sopenharmony_ci * of our unchecked node. But thus far, we do not 7578c2ecf20Sopenharmony_ci * know whether the node is valid or obsolete. To 7588c2ecf20Sopenharmony_ci * figure this out, we need to walk all the nodes of 7598c2ecf20Sopenharmony_ci * the inode and build the inode fragtree. We don't 7608c2ecf20Sopenharmony_ci * want to spend time checking data of nodes which may 7618c2ecf20Sopenharmony_ci * later be found to be obsolete. So we put off the full 7628c2ecf20Sopenharmony_ci * data CRC checking until we have read all the inode 7638c2ecf20Sopenharmony_ci * nodes and have started building the fragtree. 7648c2ecf20Sopenharmony_ci * 7658c2ecf20Sopenharmony_ci * The fragtree is being built starting with nodes 7668c2ecf20Sopenharmony_ci * having the highest version number, so we'll be able 7678c2ecf20Sopenharmony_ci * to detect whether a node is valid (i.e., it is not 7688c2ecf20Sopenharmony_ci * overlapped by a node with higher version) or not. 7698c2ecf20Sopenharmony_ci * And we'll be able to check only those nodes, which 7708c2ecf20Sopenharmony_ci * are not obsolete. 7718c2ecf20Sopenharmony_ci * 7728c2ecf20Sopenharmony_ci * Of course, this optimization only makes sense in case 7738c2ecf20Sopenharmony_ci * of NAND flashes (or other flashes with 7748c2ecf20Sopenharmony_ci * !jffs2_can_mark_obsolete()), since on NOR flashes 7758c2ecf20Sopenharmony_ci * nodes are marked obsolete physically. 7768c2ecf20Sopenharmony_ci * 7778c2ecf20Sopenharmony_ci * Since NAND flashes (or other flashes with 7788c2ecf20Sopenharmony_ci * jffs2_is_writebuffered(c)) are anyway read by 7798c2ecf20Sopenharmony_ci * fractions of c->wbuf_pagesize, and we have just read 7808c2ecf20Sopenharmony_ci * the node header, it is likely that the starting part 7818c2ecf20Sopenharmony_ci * of the node data is also read when we read the 7828c2ecf20Sopenharmony_ci * header. So we don't mind to check the CRC of the 7838c2ecf20Sopenharmony_ci * starting part of the data of the node now, and check 7848c2ecf20Sopenharmony_ci * the second part later (in jffs2_check_node_data()). 7858c2ecf20Sopenharmony_ci * Of course, we will not need to re-read and re-check 7868c2ecf20Sopenharmony_ci * the NAND page which we have just read. This is why we 7878c2ecf20Sopenharmony_ci * read the whole NAND page at jffs2_get_inode_nodes(), 7888c2ecf20Sopenharmony_ci * while we needed only the node header. 7898c2ecf20Sopenharmony_ci */ 7908c2ecf20Sopenharmony_ci unsigned char *buf; 7918c2ecf20Sopenharmony_ci 7928c2ecf20Sopenharmony_ci /* 'buf' will point to the start of data */ 7938c2ecf20Sopenharmony_ci buf = (unsigned char *)rd + sizeof(*rd); 7948c2ecf20Sopenharmony_ci /* len will be the read data length */ 7958c2ecf20Sopenharmony_ci len = min_t(uint32_t, rdlen - sizeof(*rd), csize); 7968c2ecf20Sopenharmony_ci tn->partial_crc = crc32(0, buf, len); 7978c2ecf20Sopenharmony_ci 7988c2ecf20Sopenharmony_ci dbg_readinode("Calculates CRC (%#08x) for %d bytes, csize %d\n", tn->partial_crc, len, csize); 7998c2ecf20Sopenharmony_ci 8008c2ecf20Sopenharmony_ci /* If we actually calculated the whole data CRC 8018c2ecf20Sopenharmony_ci * and it is wrong, drop the node. */ 8028c2ecf20Sopenharmony_ci if (len >= csize && unlikely(tn->partial_crc != je32_to_cpu(rd->data_crc))) { 8038c2ecf20Sopenharmony_ci JFFS2_NOTICE("wrong data CRC in data node at 0x%08x: read %#08x, calculated %#08x.\n", 8048c2ecf20Sopenharmony_ci ref_offset(ref), tn->partial_crc, je32_to_cpu(rd->data_crc)); 8058c2ecf20Sopenharmony_ci jffs2_mark_node_obsolete(c, ref); 8068c2ecf20Sopenharmony_ci goto free_out; 8078c2ecf20Sopenharmony_ci } 8088c2ecf20Sopenharmony_ci 8098c2ecf20Sopenharmony_ci } else if (csize == 0) { 8108c2ecf20Sopenharmony_ci /* 8118c2ecf20Sopenharmony_ci * We checked the header CRC. If the node has no data, adjust 8128c2ecf20Sopenharmony_ci * the space accounting now. For other nodes this will be done 8138c2ecf20Sopenharmony_ci * later either when the node is marked obsolete or when its 8148c2ecf20Sopenharmony_ci * data is checked. 8158c2ecf20Sopenharmony_ci */ 8168c2ecf20Sopenharmony_ci struct jffs2_eraseblock *jeb; 8178c2ecf20Sopenharmony_ci 8188c2ecf20Sopenharmony_ci dbg_readinode("the node has no data.\n"); 8198c2ecf20Sopenharmony_ci jeb = &c->blocks[ref->flash_offset / c->sector_size]; 8208c2ecf20Sopenharmony_ci len = ref_totlen(c, jeb, ref); 8218c2ecf20Sopenharmony_ci 8228c2ecf20Sopenharmony_ci spin_lock(&c->erase_completion_lock); 8238c2ecf20Sopenharmony_ci jeb->used_size += len; 8248c2ecf20Sopenharmony_ci jeb->unchecked_size -= len; 8258c2ecf20Sopenharmony_ci c->used_size += len; 8268c2ecf20Sopenharmony_ci c->unchecked_size -= len; 8278c2ecf20Sopenharmony_ci ref->flash_offset = ref_offset(ref) | REF_NORMAL; 8288c2ecf20Sopenharmony_ci spin_unlock(&c->erase_completion_lock); 8298c2ecf20Sopenharmony_ci } 8308c2ecf20Sopenharmony_ci } 8318c2ecf20Sopenharmony_ci 8328c2ecf20Sopenharmony_ci tn->fn = jffs2_alloc_full_dnode(); 8338c2ecf20Sopenharmony_ci if (!tn->fn) { 8348c2ecf20Sopenharmony_ci JFFS2_ERROR("alloc fn failed\n"); 8358c2ecf20Sopenharmony_ci ret = -ENOMEM; 8368c2ecf20Sopenharmony_ci goto free_out; 8378c2ecf20Sopenharmony_ci } 8388c2ecf20Sopenharmony_ci 8398c2ecf20Sopenharmony_ci tn->version = je32_to_cpu(rd->version); 8408c2ecf20Sopenharmony_ci tn->fn->ofs = je32_to_cpu(rd->offset); 8418c2ecf20Sopenharmony_ci tn->data_crc = je32_to_cpu(rd->data_crc); 8428c2ecf20Sopenharmony_ci tn->csize = csize; 8438c2ecf20Sopenharmony_ci tn->fn->raw = ref; 8448c2ecf20Sopenharmony_ci tn->overlapped = 0; 8458c2ecf20Sopenharmony_ci 8468c2ecf20Sopenharmony_ci if (tn->version > rii->highest_version) 8478c2ecf20Sopenharmony_ci rii->highest_version = tn->version; 8488c2ecf20Sopenharmony_ci 8498c2ecf20Sopenharmony_ci /* There was a bug where we wrote hole nodes out with 8508c2ecf20Sopenharmony_ci csize/dsize swapped. Deal with it */ 8518c2ecf20Sopenharmony_ci if (rd->compr == JFFS2_COMPR_ZERO && !je32_to_cpu(rd->dsize) && csize) 8528c2ecf20Sopenharmony_ci tn->fn->size = csize; 8538c2ecf20Sopenharmony_ci else // normal case... 8548c2ecf20Sopenharmony_ci tn->fn->size = je32_to_cpu(rd->dsize); 8558c2ecf20Sopenharmony_ci 8568c2ecf20Sopenharmony_ci dbg_readinode2("dnode @%08x: ver %u, offset %#04x, dsize %#04x, csize %#04x\n", 8578c2ecf20Sopenharmony_ci ref_offset(ref), je32_to_cpu(rd->version), 8588c2ecf20Sopenharmony_ci je32_to_cpu(rd->offset), je32_to_cpu(rd->dsize), csize); 8598c2ecf20Sopenharmony_ci 8608c2ecf20Sopenharmony_ci ret = jffs2_add_tn_to_tree(c, rii, tn); 8618c2ecf20Sopenharmony_ci 8628c2ecf20Sopenharmony_ci if (ret) { 8638c2ecf20Sopenharmony_ci jffs2_free_full_dnode(tn->fn); 8648c2ecf20Sopenharmony_ci free_out: 8658c2ecf20Sopenharmony_ci jffs2_free_tmp_dnode_info(tn); 8668c2ecf20Sopenharmony_ci return ret; 8678c2ecf20Sopenharmony_ci } 8688c2ecf20Sopenharmony_ci#ifdef JFFS2_DBG_READINODE2_MESSAGES 8698c2ecf20Sopenharmony_ci dbg_readinode2("After adding ver %d:\n", je32_to_cpu(rd->version)); 8708c2ecf20Sopenharmony_ci tn = tn_first(&rii->tn_root); 8718c2ecf20Sopenharmony_ci while (tn) { 8728c2ecf20Sopenharmony_ci dbg_readinode2("%p: v %d r 0x%x-0x%x ov %d\n", 8738c2ecf20Sopenharmony_ci tn, tn->version, tn->fn->ofs, 8748c2ecf20Sopenharmony_ci tn->fn->ofs+tn->fn->size, tn->overlapped); 8758c2ecf20Sopenharmony_ci tn = tn_next(tn); 8768c2ecf20Sopenharmony_ci } 8778c2ecf20Sopenharmony_ci#endif 8788c2ecf20Sopenharmony_ci return 0; 8798c2ecf20Sopenharmony_ci} 8808c2ecf20Sopenharmony_ci 8818c2ecf20Sopenharmony_ci/* 8828c2ecf20Sopenharmony_ci * Helper function for jffs2_get_inode_nodes(). 8838c2ecf20Sopenharmony_ci * It is called every time an unknown node is found. 8848c2ecf20Sopenharmony_ci * 8858c2ecf20Sopenharmony_ci * Returns: 0 on success; 8868c2ecf20Sopenharmony_ci * negative error code on failure. 8878c2ecf20Sopenharmony_ci */ 8888c2ecf20Sopenharmony_cistatic inline int read_unknown(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref, struct jffs2_unknown_node *un) 8898c2ecf20Sopenharmony_ci{ 8908c2ecf20Sopenharmony_ci /* We don't mark unknown nodes as REF_UNCHECKED */ 8918c2ecf20Sopenharmony_ci if (ref_flags(ref) == REF_UNCHECKED) { 8928c2ecf20Sopenharmony_ci JFFS2_ERROR("REF_UNCHECKED but unknown node at %#08x\n", 8938c2ecf20Sopenharmony_ci ref_offset(ref)); 8948c2ecf20Sopenharmony_ci JFFS2_ERROR("Node is {%04x,%04x,%08x,%08x}. Please report this error.\n", 8958c2ecf20Sopenharmony_ci je16_to_cpu(un->magic), je16_to_cpu(un->nodetype), 8968c2ecf20Sopenharmony_ci je32_to_cpu(un->totlen), je32_to_cpu(un->hdr_crc)); 8978c2ecf20Sopenharmony_ci jffs2_mark_node_obsolete(c, ref); 8988c2ecf20Sopenharmony_ci return 0; 8998c2ecf20Sopenharmony_ci } 9008c2ecf20Sopenharmony_ci 9018c2ecf20Sopenharmony_ci un->nodetype = cpu_to_je16(JFFS2_NODE_ACCURATE | je16_to_cpu(un->nodetype)); 9028c2ecf20Sopenharmony_ci 9038c2ecf20Sopenharmony_ci switch(je16_to_cpu(un->nodetype) & JFFS2_COMPAT_MASK) { 9048c2ecf20Sopenharmony_ci 9058c2ecf20Sopenharmony_ci case JFFS2_FEATURE_INCOMPAT: 9068c2ecf20Sopenharmony_ci JFFS2_ERROR("unknown INCOMPAT nodetype %#04X at %#08x\n", 9078c2ecf20Sopenharmony_ci je16_to_cpu(un->nodetype), ref_offset(ref)); 9088c2ecf20Sopenharmony_ci /* EEP */ 9098c2ecf20Sopenharmony_ci BUG(); 9108c2ecf20Sopenharmony_ci break; 9118c2ecf20Sopenharmony_ci 9128c2ecf20Sopenharmony_ci case JFFS2_FEATURE_ROCOMPAT: 9138c2ecf20Sopenharmony_ci JFFS2_ERROR("unknown ROCOMPAT nodetype %#04X at %#08x\n", 9148c2ecf20Sopenharmony_ci je16_to_cpu(un->nodetype), ref_offset(ref)); 9158c2ecf20Sopenharmony_ci BUG_ON(!(c->flags & JFFS2_SB_FLAG_RO)); 9168c2ecf20Sopenharmony_ci break; 9178c2ecf20Sopenharmony_ci 9188c2ecf20Sopenharmony_ci case JFFS2_FEATURE_RWCOMPAT_COPY: 9198c2ecf20Sopenharmony_ci JFFS2_NOTICE("unknown RWCOMPAT_COPY nodetype %#04X at %#08x\n", 9208c2ecf20Sopenharmony_ci je16_to_cpu(un->nodetype), ref_offset(ref)); 9218c2ecf20Sopenharmony_ci break; 9228c2ecf20Sopenharmony_ci 9238c2ecf20Sopenharmony_ci case JFFS2_FEATURE_RWCOMPAT_DELETE: 9248c2ecf20Sopenharmony_ci JFFS2_NOTICE("unknown RWCOMPAT_DELETE nodetype %#04X at %#08x\n", 9258c2ecf20Sopenharmony_ci je16_to_cpu(un->nodetype), ref_offset(ref)); 9268c2ecf20Sopenharmony_ci jffs2_mark_node_obsolete(c, ref); 9278c2ecf20Sopenharmony_ci return 0; 9288c2ecf20Sopenharmony_ci } 9298c2ecf20Sopenharmony_ci 9308c2ecf20Sopenharmony_ci return 0; 9318c2ecf20Sopenharmony_ci} 9328c2ecf20Sopenharmony_ci 9338c2ecf20Sopenharmony_ci/* 9348c2ecf20Sopenharmony_ci * Helper function for jffs2_get_inode_nodes(). 9358c2ecf20Sopenharmony_ci * The function detects whether more data should be read and reads it if yes. 9368c2ecf20Sopenharmony_ci * 9378c2ecf20Sopenharmony_ci * Returns: 0 on success; 9388c2ecf20Sopenharmony_ci * negative error code on failure. 9398c2ecf20Sopenharmony_ci */ 9408c2ecf20Sopenharmony_cistatic int read_more(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref, 9418c2ecf20Sopenharmony_ci int needed_len, int *rdlen, unsigned char *buf) 9428c2ecf20Sopenharmony_ci{ 9438c2ecf20Sopenharmony_ci int err, to_read = needed_len - *rdlen; 9448c2ecf20Sopenharmony_ci size_t retlen; 9458c2ecf20Sopenharmony_ci uint32_t offs; 9468c2ecf20Sopenharmony_ci 9478c2ecf20Sopenharmony_ci if (jffs2_is_writebuffered(c)) { 9488c2ecf20Sopenharmony_ci int rem = to_read % c->wbuf_pagesize; 9498c2ecf20Sopenharmony_ci 9508c2ecf20Sopenharmony_ci if (rem) 9518c2ecf20Sopenharmony_ci to_read += c->wbuf_pagesize - rem; 9528c2ecf20Sopenharmony_ci } 9538c2ecf20Sopenharmony_ci 9548c2ecf20Sopenharmony_ci /* We need to read more data */ 9558c2ecf20Sopenharmony_ci offs = ref_offset(ref) + *rdlen; 9568c2ecf20Sopenharmony_ci 9578c2ecf20Sopenharmony_ci dbg_readinode("read more %d bytes\n", to_read); 9588c2ecf20Sopenharmony_ci 9598c2ecf20Sopenharmony_ci err = jffs2_flash_read(c, offs, to_read, &retlen, buf + *rdlen); 9608c2ecf20Sopenharmony_ci if (err) { 9618c2ecf20Sopenharmony_ci JFFS2_ERROR("can not read %d bytes from 0x%08x, " 9628c2ecf20Sopenharmony_ci "error code: %d.\n", to_read, offs, err); 9638c2ecf20Sopenharmony_ci return err; 9648c2ecf20Sopenharmony_ci } 9658c2ecf20Sopenharmony_ci 9668c2ecf20Sopenharmony_ci if (retlen < to_read) { 9678c2ecf20Sopenharmony_ci JFFS2_ERROR("short read at %#08x: %zu instead of %d.\n", 9688c2ecf20Sopenharmony_ci offs, retlen, to_read); 9698c2ecf20Sopenharmony_ci return -EIO; 9708c2ecf20Sopenharmony_ci } 9718c2ecf20Sopenharmony_ci 9728c2ecf20Sopenharmony_ci *rdlen += to_read; 9738c2ecf20Sopenharmony_ci return 0; 9748c2ecf20Sopenharmony_ci} 9758c2ecf20Sopenharmony_ci 9768c2ecf20Sopenharmony_ci/* Get tmp_dnode_info and full_dirent for all non-obsolete nodes associated 9778c2ecf20Sopenharmony_ci with this ino. Perform a preliminary ordering on data nodes, throwing away 9788c2ecf20Sopenharmony_ci those which are completely obsoleted by newer ones. The naïve approach we 9798c2ecf20Sopenharmony_ci use to take of just returning them _all_ in version order will cause us to 9808c2ecf20Sopenharmony_ci run out of memory in certain degenerate cases. */ 9818c2ecf20Sopenharmony_cistatic int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_info *f, 9828c2ecf20Sopenharmony_ci struct jffs2_readinode_info *rii) 9838c2ecf20Sopenharmony_ci{ 9848c2ecf20Sopenharmony_ci struct jffs2_raw_node_ref *ref, *valid_ref; 9858c2ecf20Sopenharmony_ci unsigned char *buf = NULL; 9868c2ecf20Sopenharmony_ci union jffs2_node_union *node; 9878c2ecf20Sopenharmony_ci size_t retlen; 9888c2ecf20Sopenharmony_ci int len, err; 9898c2ecf20Sopenharmony_ci 9908c2ecf20Sopenharmony_ci rii->mctime_ver = 0; 9918c2ecf20Sopenharmony_ci 9928c2ecf20Sopenharmony_ci dbg_readinode("ino #%u\n", f->inocache->ino); 9938c2ecf20Sopenharmony_ci 9948c2ecf20Sopenharmony_ci /* FIXME: in case of NOR and available ->point() this 9958c2ecf20Sopenharmony_ci * needs to be fixed. */ 9968c2ecf20Sopenharmony_ci len = sizeof(union jffs2_node_union) + c->wbuf_pagesize; 9978c2ecf20Sopenharmony_ci buf = kmalloc(len, GFP_KERNEL); 9988c2ecf20Sopenharmony_ci if (!buf) 9998c2ecf20Sopenharmony_ci return -ENOMEM; 10008c2ecf20Sopenharmony_ci 10018c2ecf20Sopenharmony_ci spin_lock(&c->erase_completion_lock); 10028c2ecf20Sopenharmony_ci valid_ref = jffs2_first_valid_node(f->inocache->nodes); 10038c2ecf20Sopenharmony_ci if (!valid_ref && f->inocache->ino != 1) 10048c2ecf20Sopenharmony_ci JFFS2_WARNING("Eep. No valid nodes for ino #%u.\n", f->inocache->ino); 10058c2ecf20Sopenharmony_ci while (valid_ref) { 10068c2ecf20Sopenharmony_ci /* We can hold a pointer to a non-obsolete node without the spinlock, 10078c2ecf20Sopenharmony_ci but _obsolete_ nodes may disappear at any time, if the block 10088c2ecf20Sopenharmony_ci they're in gets erased. So if we mark 'ref' obsolete while we're 10098c2ecf20Sopenharmony_ci not holding the lock, it can go away immediately. For that reason, 10108c2ecf20Sopenharmony_ci we find the next valid node first, before processing 'ref'. 10118c2ecf20Sopenharmony_ci */ 10128c2ecf20Sopenharmony_ci ref = valid_ref; 10138c2ecf20Sopenharmony_ci valid_ref = jffs2_first_valid_node(ref->next_in_ino); 10148c2ecf20Sopenharmony_ci spin_unlock(&c->erase_completion_lock); 10158c2ecf20Sopenharmony_ci 10168c2ecf20Sopenharmony_ci cond_resched(); 10178c2ecf20Sopenharmony_ci 10188c2ecf20Sopenharmony_ci /* 10198c2ecf20Sopenharmony_ci * At this point we don't know the type of the node we're going 10208c2ecf20Sopenharmony_ci * to read, so we do not know the size of its header. In order 10218c2ecf20Sopenharmony_ci * to minimize the amount of flash IO we assume the header is 10228c2ecf20Sopenharmony_ci * of size = JFFS2_MIN_NODE_HEADER. 10238c2ecf20Sopenharmony_ci */ 10248c2ecf20Sopenharmony_ci len = JFFS2_MIN_NODE_HEADER; 10258c2ecf20Sopenharmony_ci if (jffs2_is_writebuffered(c)) { 10268c2ecf20Sopenharmony_ci int end, rem; 10278c2ecf20Sopenharmony_ci 10288c2ecf20Sopenharmony_ci /* 10298c2ecf20Sopenharmony_ci * We are about to read JFFS2_MIN_NODE_HEADER bytes, 10308c2ecf20Sopenharmony_ci * but this flash has some minimal I/O unit. It is 10318c2ecf20Sopenharmony_ci * possible that we'll need to read more soon, so read 10328c2ecf20Sopenharmony_ci * up to the next min. I/O unit, in order not to 10338c2ecf20Sopenharmony_ci * re-read the same min. I/O unit twice. 10348c2ecf20Sopenharmony_ci */ 10358c2ecf20Sopenharmony_ci end = ref_offset(ref) + len; 10368c2ecf20Sopenharmony_ci rem = end % c->wbuf_pagesize; 10378c2ecf20Sopenharmony_ci if (rem) 10388c2ecf20Sopenharmony_ci end += c->wbuf_pagesize - rem; 10398c2ecf20Sopenharmony_ci len = end - ref_offset(ref); 10408c2ecf20Sopenharmony_ci } 10418c2ecf20Sopenharmony_ci 10428c2ecf20Sopenharmony_ci dbg_readinode("read %d bytes at %#08x(%d).\n", len, ref_offset(ref), ref_flags(ref)); 10438c2ecf20Sopenharmony_ci 10448c2ecf20Sopenharmony_ci /* FIXME: point() */ 10458c2ecf20Sopenharmony_ci err = jffs2_flash_read(c, ref_offset(ref), len, &retlen, buf); 10468c2ecf20Sopenharmony_ci if (err) { 10478c2ecf20Sopenharmony_ci JFFS2_ERROR("can not read %d bytes from 0x%08x, error code: %d.\n", len, ref_offset(ref), err); 10488c2ecf20Sopenharmony_ci goto free_out; 10498c2ecf20Sopenharmony_ci } 10508c2ecf20Sopenharmony_ci 10518c2ecf20Sopenharmony_ci if (retlen < len) { 10528c2ecf20Sopenharmony_ci JFFS2_ERROR("short read at %#08x: %zu instead of %d.\n", ref_offset(ref), retlen, len); 10538c2ecf20Sopenharmony_ci err = -EIO; 10548c2ecf20Sopenharmony_ci goto free_out; 10558c2ecf20Sopenharmony_ci } 10568c2ecf20Sopenharmony_ci 10578c2ecf20Sopenharmony_ci node = (union jffs2_node_union *)buf; 10588c2ecf20Sopenharmony_ci 10598c2ecf20Sopenharmony_ci /* No need to mask in the valid bit; it shouldn't be invalid */ 10608c2ecf20Sopenharmony_ci if (je32_to_cpu(node->u.hdr_crc) != crc32(0, node, sizeof(node->u)-4)) { 10618c2ecf20Sopenharmony_ci JFFS2_NOTICE("Node header CRC failed at %#08x. {%04x,%04x,%08x,%08x}\n", 10628c2ecf20Sopenharmony_ci ref_offset(ref), je16_to_cpu(node->u.magic), 10638c2ecf20Sopenharmony_ci je16_to_cpu(node->u.nodetype), 10648c2ecf20Sopenharmony_ci je32_to_cpu(node->u.totlen), 10658c2ecf20Sopenharmony_ci je32_to_cpu(node->u.hdr_crc)); 10668c2ecf20Sopenharmony_ci jffs2_dbg_dump_node(c, ref_offset(ref)); 10678c2ecf20Sopenharmony_ci jffs2_mark_node_obsolete(c, ref); 10688c2ecf20Sopenharmony_ci goto cont; 10698c2ecf20Sopenharmony_ci } 10708c2ecf20Sopenharmony_ci if (je16_to_cpu(node->u.magic) != JFFS2_MAGIC_BITMASK) { 10718c2ecf20Sopenharmony_ci /* Not a JFFS2 node, whinge and move on */ 10728c2ecf20Sopenharmony_ci JFFS2_NOTICE("Wrong magic bitmask 0x%04x in node header at %#08x.\n", 10738c2ecf20Sopenharmony_ci je16_to_cpu(node->u.magic), ref_offset(ref)); 10748c2ecf20Sopenharmony_ci jffs2_mark_node_obsolete(c, ref); 10758c2ecf20Sopenharmony_ci goto cont; 10768c2ecf20Sopenharmony_ci } 10778c2ecf20Sopenharmony_ci 10788c2ecf20Sopenharmony_ci switch (je16_to_cpu(node->u.nodetype)) { 10798c2ecf20Sopenharmony_ci 10808c2ecf20Sopenharmony_ci case JFFS2_NODETYPE_DIRENT: 10818c2ecf20Sopenharmony_ci 10828c2ecf20Sopenharmony_ci if (JFFS2_MIN_NODE_HEADER < sizeof(struct jffs2_raw_dirent) && 10838c2ecf20Sopenharmony_ci len < sizeof(struct jffs2_raw_dirent)) { 10848c2ecf20Sopenharmony_ci err = read_more(c, ref, sizeof(struct jffs2_raw_dirent), &len, buf); 10858c2ecf20Sopenharmony_ci if (unlikely(err)) 10868c2ecf20Sopenharmony_ci goto free_out; 10878c2ecf20Sopenharmony_ci } 10888c2ecf20Sopenharmony_ci 10898c2ecf20Sopenharmony_ci err = read_direntry(c, ref, &node->d, retlen, rii); 10908c2ecf20Sopenharmony_ci if (unlikely(err)) 10918c2ecf20Sopenharmony_ci goto free_out; 10928c2ecf20Sopenharmony_ci 10938c2ecf20Sopenharmony_ci break; 10948c2ecf20Sopenharmony_ci 10958c2ecf20Sopenharmony_ci case JFFS2_NODETYPE_INODE: 10968c2ecf20Sopenharmony_ci 10978c2ecf20Sopenharmony_ci if (JFFS2_MIN_NODE_HEADER < sizeof(struct jffs2_raw_inode) && 10988c2ecf20Sopenharmony_ci len < sizeof(struct jffs2_raw_inode)) { 10998c2ecf20Sopenharmony_ci err = read_more(c, ref, sizeof(struct jffs2_raw_inode), &len, buf); 11008c2ecf20Sopenharmony_ci if (unlikely(err)) 11018c2ecf20Sopenharmony_ci goto free_out; 11028c2ecf20Sopenharmony_ci } 11038c2ecf20Sopenharmony_ci 11048c2ecf20Sopenharmony_ci err = read_dnode(c, ref, &node->i, len, rii); 11058c2ecf20Sopenharmony_ci if (unlikely(err)) 11068c2ecf20Sopenharmony_ci goto free_out; 11078c2ecf20Sopenharmony_ci 11088c2ecf20Sopenharmony_ci break; 11098c2ecf20Sopenharmony_ci 11108c2ecf20Sopenharmony_ci default: 11118c2ecf20Sopenharmony_ci if (JFFS2_MIN_NODE_HEADER < sizeof(struct jffs2_unknown_node) && 11128c2ecf20Sopenharmony_ci len < sizeof(struct jffs2_unknown_node)) { 11138c2ecf20Sopenharmony_ci err = read_more(c, ref, sizeof(struct jffs2_unknown_node), &len, buf); 11148c2ecf20Sopenharmony_ci if (unlikely(err)) 11158c2ecf20Sopenharmony_ci goto free_out; 11168c2ecf20Sopenharmony_ci } 11178c2ecf20Sopenharmony_ci 11188c2ecf20Sopenharmony_ci err = read_unknown(c, ref, &node->u); 11198c2ecf20Sopenharmony_ci if (unlikely(err)) 11208c2ecf20Sopenharmony_ci goto free_out; 11218c2ecf20Sopenharmony_ci 11228c2ecf20Sopenharmony_ci } 11238c2ecf20Sopenharmony_ci cont: 11248c2ecf20Sopenharmony_ci spin_lock(&c->erase_completion_lock); 11258c2ecf20Sopenharmony_ci } 11268c2ecf20Sopenharmony_ci 11278c2ecf20Sopenharmony_ci spin_unlock(&c->erase_completion_lock); 11288c2ecf20Sopenharmony_ci kfree(buf); 11298c2ecf20Sopenharmony_ci 11308c2ecf20Sopenharmony_ci f->highest_version = rii->highest_version; 11318c2ecf20Sopenharmony_ci 11328c2ecf20Sopenharmony_ci dbg_readinode("nodes of inode #%u were read, the highest version is %u, latest_mctime %u, mctime_ver %u.\n", 11338c2ecf20Sopenharmony_ci f->inocache->ino, rii->highest_version, rii->latest_mctime, 11348c2ecf20Sopenharmony_ci rii->mctime_ver); 11358c2ecf20Sopenharmony_ci return 0; 11368c2ecf20Sopenharmony_ci 11378c2ecf20Sopenharmony_ci free_out: 11388c2ecf20Sopenharmony_ci jffs2_free_tmp_dnode_info_list(&rii->tn_root); 11398c2ecf20Sopenharmony_ci jffs2_free_full_dirent_list(rii->fds); 11408c2ecf20Sopenharmony_ci rii->fds = NULL; 11418c2ecf20Sopenharmony_ci kfree(buf); 11428c2ecf20Sopenharmony_ci return err; 11438c2ecf20Sopenharmony_ci} 11448c2ecf20Sopenharmony_ci 11458c2ecf20Sopenharmony_cistatic int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, 11468c2ecf20Sopenharmony_ci struct jffs2_inode_info *f, 11478c2ecf20Sopenharmony_ci struct jffs2_raw_inode *latest_node) 11488c2ecf20Sopenharmony_ci{ 11498c2ecf20Sopenharmony_ci struct jffs2_readinode_info rii; 11508c2ecf20Sopenharmony_ci uint32_t crc, new_size; 11518c2ecf20Sopenharmony_ci size_t retlen; 11528c2ecf20Sopenharmony_ci int ret; 11538c2ecf20Sopenharmony_ci 11548c2ecf20Sopenharmony_ci dbg_readinode("ino #%u pino/nlink is %d\n", f->inocache->ino, 11558c2ecf20Sopenharmony_ci f->inocache->pino_nlink); 11568c2ecf20Sopenharmony_ci 11578c2ecf20Sopenharmony_ci memset(&rii, 0, sizeof(rii)); 11588c2ecf20Sopenharmony_ci 11598c2ecf20Sopenharmony_ci /* Grab all nodes relevant to this ino */ 11608c2ecf20Sopenharmony_ci ret = jffs2_get_inode_nodes(c, f, &rii); 11618c2ecf20Sopenharmony_ci 11628c2ecf20Sopenharmony_ci if (ret) { 11638c2ecf20Sopenharmony_ci JFFS2_ERROR("cannot read nodes for ino %u, returned error is %d\n", f->inocache->ino, ret); 11648c2ecf20Sopenharmony_ci if (f->inocache->state == INO_STATE_READING) 11658c2ecf20Sopenharmony_ci jffs2_set_inocache_state(c, f->inocache, INO_STATE_CHECKEDABSENT); 11668c2ecf20Sopenharmony_ci return ret; 11678c2ecf20Sopenharmony_ci } 11688c2ecf20Sopenharmony_ci 11698c2ecf20Sopenharmony_ci ret = jffs2_build_inode_fragtree(c, f, &rii); 11708c2ecf20Sopenharmony_ci if (ret) { 11718c2ecf20Sopenharmony_ci JFFS2_ERROR("Failed to build final fragtree for inode #%u: error %d\n", 11728c2ecf20Sopenharmony_ci f->inocache->ino, ret); 11738c2ecf20Sopenharmony_ci if (f->inocache->state == INO_STATE_READING) 11748c2ecf20Sopenharmony_ci jffs2_set_inocache_state(c, f->inocache, INO_STATE_CHECKEDABSENT); 11758c2ecf20Sopenharmony_ci jffs2_free_tmp_dnode_info_list(&rii.tn_root); 11768c2ecf20Sopenharmony_ci /* FIXME: We could at least crc-check them all */ 11778c2ecf20Sopenharmony_ci if (rii.mdata_tn) { 11788c2ecf20Sopenharmony_ci jffs2_free_full_dnode(rii.mdata_tn->fn); 11798c2ecf20Sopenharmony_ci jffs2_free_tmp_dnode_info(rii.mdata_tn); 11808c2ecf20Sopenharmony_ci rii.mdata_tn = NULL; 11818c2ecf20Sopenharmony_ci } 11828c2ecf20Sopenharmony_ci return ret; 11838c2ecf20Sopenharmony_ci } 11848c2ecf20Sopenharmony_ci 11858c2ecf20Sopenharmony_ci if (rii.mdata_tn) { 11868c2ecf20Sopenharmony_ci if (rii.mdata_tn->fn->raw == rii.latest_ref) { 11878c2ecf20Sopenharmony_ci f->metadata = rii.mdata_tn->fn; 11888c2ecf20Sopenharmony_ci jffs2_free_tmp_dnode_info(rii.mdata_tn); 11898c2ecf20Sopenharmony_ci } else { 11908c2ecf20Sopenharmony_ci jffs2_kill_tn(c, rii.mdata_tn); 11918c2ecf20Sopenharmony_ci } 11928c2ecf20Sopenharmony_ci rii.mdata_tn = NULL; 11938c2ecf20Sopenharmony_ci } 11948c2ecf20Sopenharmony_ci 11958c2ecf20Sopenharmony_ci f->dents = rii.fds; 11968c2ecf20Sopenharmony_ci 11978c2ecf20Sopenharmony_ci jffs2_dbg_fragtree_paranoia_check_nolock(f); 11988c2ecf20Sopenharmony_ci 11998c2ecf20Sopenharmony_ci if (unlikely(!rii.latest_ref)) { 12008c2ecf20Sopenharmony_ci /* No data nodes for this inode. */ 12018c2ecf20Sopenharmony_ci if (f->inocache->ino != 1) { 12028c2ecf20Sopenharmony_ci JFFS2_WARNING("no data nodes found for ino #%u\n", f->inocache->ino); 12038c2ecf20Sopenharmony_ci if (!rii.fds) { 12048c2ecf20Sopenharmony_ci if (f->inocache->state == INO_STATE_READING) 12058c2ecf20Sopenharmony_ci jffs2_set_inocache_state(c, f->inocache, INO_STATE_CHECKEDABSENT); 12068c2ecf20Sopenharmony_ci return -EIO; 12078c2ecf20Sopenharmony_ci } 12088c2ecf20Sopenharmony_ci JFFS2_NOTICE("but it has children so we fake some modes for it\n"); 12098c2ecf20Sopenharmony_ci } 12108c2ecf20Sopenharmony_ci latest_node->mode = cpu_to_jemode(S_IFDIR|S_IRUGO|S_IWUSR|S_IXUGO); 12118c2ecf20Sopenharmony_ci latest_node->version = cpu_to_je32(0); 12128c2ecf20Sopenharmony_ci latest_node->atime = latest_node->ctime = latest_node->mtime = cpu_to_je32(0); 12138c2ecf20Sopenharmony_ci latest_node->isize = cpu_to_je32(0); 12148c2ecf20Sopenharmony_ci latest_node->gid = cpu_to_je16(0); 12158c2ecf20Sopenharmony_ci latest_node->uid = cpu_to_je16(0); 12168c2ecf20Sopenharmony_ci if (f->inocache->state == INO_STATE_READING) 12178c2ecf20Sopenharmony_ci jffs2_set_inocache_state(c, f->inocache, INO_STATE_PRESENT); 12188c2ecf20Sopenharmony_ci return 0; 12198c2ecf20Sopenharmony_ci } 12208c2ecf20Sopenharmony_ci 12218c2ecf20Sopenharmony_ci ret = jffs2_flash_read(c, ref_offset(rii.latest_ref), sizeof(*latest_node), &retlen, (void *)latest_node); 12228c2ecf20Sopenharmony_ci if (ret || retlen != sizeof(*latest_node)) { 12238c2ecf20Sopenharmony_ci JFFS2_ERROR("failed to read from flash: error %d, %zd of %zd bytes read\n", 12248c2ecf20Sopenharmony_ci ret, retlen, sizeof(*latest_node)); 12258c2ecf20Sopenharmony_ci /* FIXME: If this fails, there seems to be a memory leak. Find it. */ 12268c2ecf20Sopenharmony_ci return ret ? ret : -EIO; 12278c2ecf20Sopenharmony_ci } 12288c2ecf20Sopenharmony_ci 12298c2ecf20Sopenharmony_ci crc = crc32(0, latest_node, sizeof(*latest_node)-8); 12308c2ecf20Sopenharmony_ci if (crc != je32_to_cpu(latest_node->node_crc)) { 12318c2ecf20Sopenharmony_ci JFFS2_ERROR("CRC failed for read_inode of inode %u at physical location 0x%x\n", 12328c2ecf20Sopenharmony_ci f->inocache->ino, ref_offset(rii.latest_ref)); 12338c2ecf20Sopenharmony_ci return -EIO; 12348c2ecf20Sopenharmony_ci } 12358c2ecf20Sopenharmony_ci 12368c2ecf20Sopenharmony_ci switch(jemode_to_cpu(latest_node->mode) & S_IFMT) { 12378c2ecf20Sopenharmony_ci case S_IFDIR: 12388c2ecf20Sopenharmony_ci if (rii.mctime_ver > je32_to_cpu(latest_node->version)) { 12398c2ecf20Sopenharmony_ci /* The times in the latest_node are actually older than 12408c2ecf20Sopenharmony_ci mctime in the latest dirent. Cheat. */ 12418c2ecf20Sopenharmony_ci latest_node->ctime = latest_node->mtime = cpu_to_je32(rii.latest_mctime); 12428c2ecf20Sopenharmony_ci } 12438c2ecf20Sopenharmony_ci break; 12448c2ecf20Sopenharmony_ci 12458c2ecf20Sopenharmony_ci 12468c2ecf20Sopenharmony_ci case S_IFREG: 12478c2ecf20Sopenharmony_ci /* If it was a regular file, truncate it to the latest node's isize */ 12488c2ecf20Sopenharmony_ci new_size = jffs2_truncate_fragtree(c, &f->fragtree, je32_to_cpu(latest_node->isize)); 12498c2ecf20Sopenharmony_ci if (new_size != je32_to_cpu(latest_node->isize)) { 12508c2ecf20Sopenharmony_ci JFFS2_WARNING("Truncating ino #%u to %d bytes failed because it only had %d bytes to start with!\n", 12518c2ecf20Sopenharmony_ci f->inocache->ino, je32_to_cpu(latest_node->isize), new_size); 12528c2ecf20Sopenharmony_ci latest_node->isize = cpu_to_je32(new_size); 12538c2ecf20Sopenharmony_ci } 12548c2ecf20Sopenharmony_ci break; 12558c2ecf20Sopenharmony_ci 12568c2ecf20Sopenharmony_ci case S_IFLNK: 12578c2ecf20Sopenharmony_ci /* Hack to work around broken isize in old symlink code. 12588c2ecf20Sopenharmony_ci Remove this when dwmw2 comes to his senses and stops 12598c2ecf20Sopenharmony_ci symlinks from being an entirely gratuitous special 12608c2ecf20Sopenharmony_ci case. */ 12618c2ecf20Sopenharmony_ci if (!je32_to_cpu(latest_node->isize)) 12628c2ecf20Sopenharmony_ci latest_node->isize = latest_node->dsize; 12638c2ecf20Sopenharmony_ci 12648c2ecf20Sopenharmony_ci if (f->inocache->state != INO_STATE_CHECKING) { 12658c2ecf20Sopenharmony_ci /* Symlink's inode data is the target path. Read it and 12668c2ecf20Sopenharmony_ci * keep in RAM to facilitate quick follow symlink 12678c2ecf20Sopenharmony_ci * operation. */ 12688c2ecf20Sopenharmony_ci uint32_t csize = je32_to_cpu(latest_node->csize); 12698c2ecf20Sopenharmony_ci if (csize > JFFS2_MAX_NAME_LEN) 12708c2ecf20Sopenharmony_ci return -ENAMETOOLONG; 12718c2ecf20Sopenharmony_ci f->target = kmalloc(csize + 1, GFP_KERNEL); 12728c2ecf20Sopenharmony_ci if (!f->target) { 12738c2ecf20Sopenharmony_ci JFFS2_ERROR("can't allocate %u bytes of memory for the symlink target path cache\n", csize); 12748c2ecf20Sopenharmony_ci return -ENOMEM; 12758c2ecf20Sopenharmony_ci } 12768c2ecf20Sopenharmony_ci 12778c2ecf20Sopenharmony_ci ret = jffs2_flash_read(c, ref_offset(rii.latest_ref) + sizeof(*latest_node), 12788c2ecf20Sopenharmony_ci csize, &retlen, (char *)f->target); 12798c2ecf20Sopenharmony_ci 12808c2ecf20Sopenharmony_ci if (ret || retlen != csize) { 12818c2ecf20Sopenharmony_ci if (retlen != csize) 12828c2ecf20Sopenharmony_ci ret = -EIO; 12838c2ecf20Sopenharmony_ci kfree(f->target); 12848c2ecf20Sopenharmony_ci f->target = NULL; 12858c2ecf20Sopenharmony_ci return ret; 12868c2ecf20Sopenharmony_ci } 12878c2ecf20Sopenharmony_ci 12888c2ecf20Sopenharmony_ci f->target[csize] = '\0'; 12898c2ecf20Sopenharmony_ci dbg_readinode("symlink's target '%s' cached\n", f->target); 12908c2ecf20Sopenharmony_ci } 12918c2ecf20Sopenharmony_ci 12928c2ecf20Sopenharmony_ci fallthrough; 12938c2ecf20Sopenharmony_ci 12948c2ecf20Sopenharmony_ci case S_IFBLK: 12958c2ecf20Sopenharmony_ci case S_IFCHR: 12968c2ecf20Sopenharmony_ci /* Certain inode types should have only one data node, and it's 12978c2ecf20Sopenharmony_ci kept as the metadata node */ 12988c2ecf20Sopenharmony_ci if (f->metadata) { 12998c2ecf20Sopenharmony_ci JFFS2_ERROR("Argh. Special inode #%u with mode 0%o had metadata node\n", 13008c2ecf20Sopenharmony_ci f->inocache->ino, jemode_to_cpu(latest_node->mode)); 13018c2ecf20Sopenharmony_ci return -EIO; 13028c2ecf20Sopenharmony_ci } 13038c2ecf20Sopenharmony_ci if (!frag_first(&f->fragtree)) { 13048c2ecf20Sopenharmony_ci JFFS2_ERROR("Argh. Special inode #%u with mode 0%o has no fragments\n", 13058c2ecf20Sopenharmony_ci f->inocache->ino, jemode_to_cpu(latest_node->mode)); 13068c2ecf20Sopenharmony_ci return -EIO; 13078c2ecf20Sopenharmony_ci } 13088c2ecf20Sopenharmony_ci /* ASSERT: f->fraglist != NULL */ 13098c2ecf20Sopenharmony_ci if (frag_next(frag_first(&f->fragtree))) { 13108c2ecf20Sopenharmony_ci JFFS2_ERROR("Argh. Special inode #%u with mode 0x%x had more than one node\n", 13118c2ecf20Sopenharmony_ci f->inocache->ino, jemode_to_cpu(latest_node->mode)); 13128c2ecf20Sopenharmony_ci /* FIXME: Deal with it - check crc32, check for duplicate node, check times and discard the older one */ 13138c2ecf20Sopenharmony_ci return -EIO; 13148c2ecf20Sopenharmony_ci } 13158c2ecf20Sopenharmony_ci /* OK. We're happy */ 13168c2ecf20Sopenharmony_ci f->metadata = frag_first(&f->fragtree)->node; 13178c2ecf20Sopenharmony_ci jffs2_free_node_frag(frag_first(&f->fragtree)); 13188c2ecf20Sopenharmony_ci f->fragtree = RB_ROOT; 13198c2ecf20Sopenharmony_ci break; 13208c2ecf20Sopenharmony_ci } 13218c2ecf20Sopenharmony_ci if (f->inocache->state == INO_STATE_READING) 13228c2ecf20Sopenharmony_ci jffs2_set_inocache_state(c, f->inocache, INO_STATE_PRESENT); 13238c2ecf20Sopenharmony_ci 13248c2ecf20Sopenharmony_ci return 0; 13258c2ecf20Sopenharmony_ci} 13268c2ecf20Sopenharmony_ci 13278c2ecf20Sopenharmony_ci/* Scan the list of all nodes present for this ino, build map of versions, etc. */ 13288c2ecf20Sopenharmony_ciint jffs2_do_read_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, 13298c2ecf20Sopenharmony_ci uint32_t ino, struct jffs2_raw_inode *latest_node) 13308c2ecf20Sopenharmony_ci{ 13318c2ecf20Sopenharmony_ci dbg_readinode("read inode #%u\n", ino); 13328c2ecf20Sopenharmony_ci 13338c2ecf20Sopenharmony_ci retry_inocache: 13348c2ecf20Sopenharmony_ci spin_lock(&c->inocache_lock); 13358c2ecf20Sopenharmony_ci f->inocache = jffs2_get_ino_cache(c, ino); 13368c2ecf20Sopenharmony_ci 13378c2ecf20Sopenharmony_ci if (f->inocache) { 13388c2ecf20Sopenharmony_ci /* Check its state. We may need to wait before we can use it */ 13398c2ecf20Sopenharmony_ci switch(f->inocache->state) { 13408c2ecf20Sopenharmony_ci case INO_STATE_UNCHECKED: 13418c2ecf20Sopenharmony_ci case INO_STATE_CHECKEDABSENT: 13428c2ecf20Sopenharmony_ci f->inocache->state = INO_STATE_READING; 13438c2ecf20Sopenharmony_ci break; 13448c2ecf20Sopenharmony_ci 13458c2ecf20Sopenharmony_ci case INO_STATE_CHECKING: 13468c2ecf20Sopenharmony_ci case INO_STATE_GC: 13478c2ecf20Sopenharmony_ci /* If it's in either of these states, we need 13488c2ecf20Sopenharmony_ci to wait for whoever's got it to finish and 13498c2ecf20Sopenharmony_ci put it back. */ 13508c2ecf20Sopenharmony_ci dbg_readinode("waiting for ino #%u in state %d\n", ino, f->inocache->state); 13518c2ecf20Sopenharmony_ci sleep_on_spinunlock(&c->inocache_wq, &c->inocache_lock); 13528c2ecf20Sopenharmony_ci goto retry_inocache; 13538c2ecf20Sopenharmony_ci 13548c2ecf20Sopenharmony_ci case INO_STATE_READING: 13558c2ecf20Sopenharmony_ci case INO_STATE_PRESENT: 13568c2ecf20Sopenharmony_ci /* Eep. This should never happen. It can 13578c2ecf20Sopenharmony_ci happen if Linux calls read_inode() again 13588c2ecf20Sopenharmony_ci before clear_inode() has finished though. */ 13598c2ecf20Sopenharmony_ci JFFS2_ERROR("Eep. Trying to read_inode #%u when it's already in state %d!\n", ino, f->inocache->state); 13608c2ecf20Sopenharmony_ci /* Fail. That's probably better than allowing it to succeed */ 13618c2ecf20Sopenharmony_ci f->inocache = NULL; 13628c2ecf20Sopenharmony_ci break; 13638c2ecf20Sopenharmony_ci 13648c2ecf20Sopenharmony_ci default: 13658c2ecf20Sopenharmony_ci BUG(); 13668c2ecf20Sopenharmony_ci } 13678c2ecf20Sopenharmony_ci } 13688c2ecf20Sopenharmony_ci spin_unlock(&c->inocache_lock); 13698c2ecf20Sopenharmony_ci 13708c2ecf20Sopenharmony_ci if (!f->inocache && ino == 1) { 13718c2ecf20Sopenharmony_ci /* Special case - no root inode on medium */ 13728c2ecf20Sopenharmony_ci f->inocache = jffs2_alloc_inode_cache(); 13738c2ecf20Sopenharmony_ci if (!f->inocache) { 13748c2ecf20Sopenharmony_ci JFFS2_ERROR("cannot allocate inocache for root inode\n"); 13758c2ecf20Sopenharmony_ci return -ENOMEM; 13768c2ecf20Sopenharmony_ci } 13778c2ecf20Sopenharmony_ci dbg_readinode("creating inocache for root inode\n"); 13788c2ecf20Sopenharmony_ci memset(f->inocache, 0, sizeof(struct jffs2_inode_cache)); 13798c2ecf20Sopenharmony_ci f->inocache->ino = f->inocache->pino_nlink = 1; 13808c2ecf20Sopenharmony_ci f->inocache->nodes = (struct jffs2_raw_node_ref *)f->inocache; 13818c2ecf20Sopenharmony_ci f->inocache->state = INO_STATE_READING; 13828c2ecf20Sopenharmony_ci jffs2_add_ino_cache(c, f->inocache); 13838c2ecf20Sopenharmony_ci } 13848c2ecf20Sopenharmony_ci if (!f->inocache) { 13858c2ecf20Sopenharmony_ci JFFS2_ERROR("requested to read a nonexistent ino %u\n", ino); 13868c2ecf20Sopenharmony_ci return -ENOENT; 13878c2ecf20Sopenharmony_ci } 13888c2ecf20Sopenharmony_ci 13898c2ecf20Sopenharmony_ci return jffs2_do_read_inode_internal(c, f, latest_node); 13908c2ecf20Sopenharmony_ci} 13918c2ecf20Sopenharmony_ci 13928c2ecf20Sopenharmony_ciint jffs2_do_crccheck_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic) 13938c2ecf20Sopenharmony_ci{ 13948c2ecf20Sopenharmony_ci struct jffs2_raw_inode n; 13958c2ecf20Sopenharmony_ci struct jffs2_inode_info *f = kzalloc(sizeof(*f), GFP_KERNEL); 13968c2ecf20Sopenharmony_ci int ret; 13978c2ecf20Sopenharmony_ci 13988c2ecf20Sopenharmony_ci if (!f) 13998c2ecf20Sopenharmony_ci return -ENOMEM; 14008c2ecf20Sopenharmony_ci 14018c2ecf20Sopenharmony_ci mutex_init(&f->sem); 14028c2ecf20Sopenharmony_ci mutex_lock(&f->sem); 14038c2ecf20Sopenharmony_ci f->inocache = ic; 14048c2ecf20Sopenharmony_ci 14058c2ecf20Sopenharmony_ci ret = jffs2_do_read_inode_internal(c, f, &n); 14068c2ecf20Sopenharmony_ci mutex_unlock(&f->sem); 14078c2ecf20Sopenharmony_ci jffs2_do_clear_inode(c, f); 14088c2ecf20Sopenharmony_ci jffs2_xattr_do_crccheck_inode(c, ic); 14098c2ecf20Sopenharmony_ci kfree (f); 14108c2ecf20Sopenharmony_ci return ret; 14118c2ecf20Sopenharmony_ci} 14128c2ecf20Sopenharmony_ci 14138c2ecf20Sopenharmony_civoid jffs2_do_clear_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f) 14148c2ecf20Sopenharmony_ci{ 14158c2ecf20Sopenharmony_ci struct jffs2_full_dirent *fd, *fds; 14168c2ecf20Sopenharmony_ci int deleted; 14178c2ecf20Sopenharmony_ci 14188c2ecf20Sopenharmony_ci jffs2_xattr_delete_inode(c, f->inocache); 14198c2ecf20Sopenharmony_ci mutex_lock(&f->sem); 14208c2ecf20Sopenharmony_ci deleted = f->inocache && !f->inocache->pino_nlink; 14218c2ecf20Sopenharmony_ci 14228c2ecf20Sopenharmony_ci if (f->inocache && f->inocache->state != INO_STATE_CHECKING) 14238c2ecf20Sopenharmony_ci jffs2_set_inocache_state(c, f->inocache, INO_STATE_CLEARING); 14248c2ecf20Sopenharmony_ci 14258c2ecf20Sopenharmony_ci if (f->metadata) { 14268c2ecf20Sopenharmony_ci if (deleted) 14278c2ecf20Sopenharmony_ci jffs2_mark_node_obsolete(c, f->metadata->raw); 14288c2ecf20Sopenharmony_ci jffs2_free_full_dnode(f->metadata); 14298c2ecf20Sopenharmony_ci } 14308c2ecf20Sopenharmony_ci 14318c2ecf20Sopenharmony_ci jffs2_kill_fragtree(&f->fragtree, deleted?c:NULL); 14328c2ecf20Sopenharmony_ci 14338c2ecf20Sopenharmony_ci fds = f->dents; 14348c2ecf20Sopenharmony_ci while(fds) { 14358c2ecf20Sopenharmony_ci fd = fds; 14368c2ecf20Sopenharmony_ci fds = fd->next; 14378c2ecf20Sopenharmony_ci jffs2_free_full_dirent(fd); 14388c2ecf20Sopenharmony_ci } 14398c2ecf20Sopenharmony_ci 14408c2ecf20Sopenharmony_ci if (f->inocache && f->inocache->state != INO_STATE_CHECKING) { 14418c2ecf20Sopenharmony_ci jffs2_set_inocache_state(c, f->inocache, INO_STATE_CHECKEDABSENT); 14428c2ecf20Sopenharmony_ci if (f->inocache->nodes == (void *)f->inocache) 14438c2ecf20Sopenharmony_ci jffs2_del_ino_cache(c, f->inocache); 14448c2ecf20Sopenharmony_ci } 14458c2ecf20Sopenharmony_ci 14468c2ecf20Sopenharmony_ci mutex_unlock(&f->sem); 14478c2ecf20Sopenharmony_ci} 1448