11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * JFFS2 -- Journalling Flash File System, Version 2. 31da177e4SLinus Torvalds * 41da177e4SLinus Torvalds * Copyright (C) 2001-2003 Red Hat, Inc. 51da177e4SLinus Torvalds * 61da177e4SLinus Torvalds * Created by David Woodhouse <dwmw2@infradead.org> 71da177e4SLinus Torvalds * 81da177e4SLinus Torvalds * For licensing information, see the file 'LICENCE' in this directory. 91da177e4SLinus Torvalds * 10f97117d1SArtem B. Bityutskiy * $Id: readinode.c,v 1.131 2005/07/27 14:46:11 dedekind Exp $ 111da177e4SLinus Torvalds * 121da177e4SLinus Torvalds */ 131da177e4SLinus Torvalds 141da177e4SLinus Torvalds #include <linux/kernel.h> 151da177e4SLinus Torvalds #include <linux/slab.h> 161da177e4SLinus Torvalds #include <linux/fs.h> 171da177e4SLinus Torvalds #include <linux/crc32.h> 181da177e4SLinus Torvalds #include <linux/pagemap.h> 191da177e4SLinus Torvalds #include <linux/mtd/mtd.h> 201da177e4SLinus Torvalds #include <linux/compiler.h> 211da177e4SLinus Torvalds #include "nodelist.h" 221da177e4SLinus Torvalds 23f302cd02SArtem B. Bityutskiy void jffs2_truncate_fragtree (struct jffs2_sb_info *c, struct rb_root *list, uint32_t size) 241da177e4SLinus Torvalds { 251da177e4SLinus Torvalds struct jffs2_node_frag *frag = jffs2_lookup_node_frag(list, size); 261da177e4SLinus Torvalds 271da177e4SLinus Torvalds D1(printk(KERN_DEBUG "Truncating fraglist to 0x%08x bytes\n", size)); 281da177e4SLinus Torvalds 291da177e4SLinus Torvalds /* We know frag->ofs <= size. That's what lookup does for us */ 301da177e4SLinus Torvalds if (frag && frag->ofs != size) { 311da177e4SLinus Torvalds if (frag->ofs+frag->size >= size) { 321da177e4SLinus Torvalds D1(printk(KERN_DEBUG "Truncating frag 0x%08x-0x%08x\n", frag->ofs, frag->ofs+frag->size)); 331da177e4SLinus Torvalds frag->size = size - frag->ofs; 341da177e4SLinus Torvalds } 351da177e4SLinus Torvalds frag = frag_next(frag); 361da177e4SLinus Torvalds } 371da177e4SLinus Torvalds while (frag && frag->ofs >= size) { 381da177e4SLinus Torvalds struct jffs2_node_frag *next = frag_next(frag); 391da177e4SLinus Torvalds 401da177e4SLinus Torvalds D1(printk(KERN_DEBUG "Removing frag 0x%08x-0x%08x\n", frag->ofs, frag->ofs+frag->size)); 411da177e4SLinus Torvalds frag_erase(frag, list); 421da177e4SLinus Torvalds jffs2_obsolete_node_frag(c, frag); 431da177e4SLinus Torvalds frag = next; 441da177e4SLinus Torvalds } 451da177e4SLinus Torvalds } 461da177e4SLinus Torvalds 47f97117d1SArtem B. Bityutskiy /* 48f97117d1SArtem B. Bityutskiy * Put a new tmp_dnode_info into the temporaty RB-tree, keeping the list in 49f97117d1SArtem B. Bityutskiy * order of increasing version. 50f97117d1SArtem B. Bityutskiy */ 51f97117d1SArtem B. Bityutskiy static void jffs2_add_tn_to_tree(struct jffs2_tmp_dnode_info *tn, struct rb_root *list) 521da177e4SLinus Torvalds { 53f97117d1SArtem B. Bityutskiy struct rb_node **p = &list->rb_node; 54f97117d1SArtem B. Bityutskiy struct rb_node * parent = NULL; 55f97117d1SArtem B. Bityutskiy struct jffs2_tmp_dnode_info *this; 561da177e4SLinus Torvalds 57f97117d1SArtem B. Bityutskiy while (*p) { 58f97117d1SArtem B. Bityutskiy parent = *p; 59f97117d1SArtem B. Bityutskiy this = rb_entry(parent, struct jffs2_tmp_dnode_info, rb); 601da177e4SLinus Torvalds 61f97117d1SArtem B. Bityutskiy /* There may actually be a collision here, but it doesn't 62f97117d1SArtem B. Bityutskiy actually matter. As long as the two nodes with the same 63f97117d1SArtem B. Bityutskiy version are together, it's all fine. */ 64f97117d1SArtem B. Bityutskiy if (tn->version < this->version) 65f97117d1SArtem B. Bityutskiy p = &(*p)->rb_left; 66f97117d1SArtem B. Bityutskiy else 67f97117d1SArtem B. Bityutskiy p = &(*p)->rb_right; 68f97117d1SArtem B. Bityutskiy } 691da177e4SLinus Torvalds 70f97117d1SArtem B. Bityutskiy rb_link_node(&tn->rb, parent, p); 71f97117d1SArtem B. Bityutskiy rb_insert_color(&tn->rb, list); 72f97117d1SArtem B. Bityutskiy } 73f97117d1SArtem B. Bityutskiy 74f97117d1SArtem B. Bityutskiy static void jffs2_free_tmp_dnode_info_list(struct rb_root *list) 75f97117d1SArtem B. Bityutskiy { 76f97117d1SArtem B. Bityutskiy struct rb_node *this; 77f97117d1SArtem B. Bityutskiy struct jffs2_tmp_dnode_info *tn; 78f97117d1SArtem B. Bityutskiy 79f97117d1SArtem B. Bityutskiy this = list->rb_node; 80f97117d1SArtem B. Bityutskiy 81f97117d1SArtem B. Bityutskiy /* Now at bottom of tree */ 82f97117d1SArtem B. Bityutskiy while (this) { 83f97117d1SArtem B. Bityutskiy if (this->rb_left) 84f97117d1SArtem B. Bityutskiy this = this->rb_left; 85f97117d1SArtem B. Bityutskiy else if (this->rb_right) 86f97117d1SArtem B. Bityutskiy this = this->rb_right; 87f97117d1SArtem B. Bityutskiy else { 88f97117d1SArtem B. Bityutskiy tn = rb_entry(this, struct jffs2_tmp_dnode_info, rb); 89f97117d1SArtem B. Bityutskiy jffs2_free_full_dnode(tn->fn); 90f97117d1SArtem B. Bityutskiy jffs2_free_tmp_dnode_info(tn); 91f97117d1SArtem B. Bityutskiy 92f97117d1SArtem B. Bityutskiy this = this->rb_parent; 93f97117d1SArtem B. Bityutskiy if (!this) 941da177e4SLinus Torvalds break; 951da177e4SLinus Torvalds 96f97117d1SArtem B. Bityutskiy if (this->rb_left == &tn->rb) 97f97117d1SArtem B. Bityutskiy this->rb_left = NULL; 98f97117d1SArtem B. Bityutskiy else if (this->rb_right == &tn->rb) 99f97117d1SArtem B. Bityutskiy this->rb_right = NULL; 100f97117d1SArtem B. Bityutskiy else BUG(); 101f97117d1SArtem B. Bityutskiy } 102f97117d1SArtem B. Bityutskiy } 103f97117d1SArtem B. Bityutskiy list->rb_node = NULL; 104f97117d1SArtem B. Bityutskiy } 1051da177e4SLinus Torvalds 106f97117d1SArtem B. Bityutskiy static void jffs2_free_full_dirent_list(struct jffs2_full_dirent *fd) 107f97117d1SArtem B. Bityutskiy { 108f97117d1SArtem B. Bityutskiy struct jffs2_full_dirent *next; 109f97117d1SArtem B. Bityutskiy 110f97117d1SArtem B. Bityutskiy while (fd) { 111f97117d1SArtem B. Bityutskiy next = fd->next; 112f97117d1SArtem B. Bityutskiy jffs2_free_full_dirent(fd); 113f97117d1SArtem B. Bityutskiy fd = next; 114f97117d1SArtem B. Bityutskiy } 115f97117d1SArtem B. Bityutskiy } 116f97117d1SArtem B. Bityutskiy 117f97117d1SArtem B. Bityutskiy /* Returns first valid node after 'ref'. May return 'ref' */ 118f97117d1SArtem B. Bityutskiy static struct jffs2_raw_node_ref *jffs2_first_valid_node(struct jffs2_raw_node_ref *ref) 119f97117d1SArtem B. Bityutskiy { 120f97117d1SArtem B. Bityutskiy while (ref && ref->next_in_ino) { 121f97117d1SArtem B. Bityutskiy if (!ref_obsolete(ref)) 122f97117d1SArtem B. Bityutskiy return ref; 123f97117d1SArtem B. Bityutskiy D1(printk(KERN_DEBUG "node at 0x%08x is obsoleted. Ignoring.\n", ref_offset(ref))); 124f97117d1SArtem B. Bityutskiy ref = ref->next_in_ino; 125f97117d1SArtem B. Bityutskiy } 126f97117d1SArtem B. Bityutskiy return NULL; 127f97117d1SArtem B. Bityutskiy } 128f97117d1SArtem B. Bityutskiy 129f97117d1SArtem B. Bityutskiy /* 130f97117d1SArtem B. Bityutskiy * Helper function for jffs2_get_inode_nodes(). 131f97117d1SArtem B. Bityutskiy * It is called every time an directory entry node is found. 132f97117d1SArtem B. Bityutskiy * 133f97117d1SArtem B. Bityutskiy * Returns: 0 on succes; 134f97117d1SArtem B. Bityutskiy * 1 if the node should be marked obsolete; 135f97117d1SArtem B. Bityutskiy * negative error code on failure. 136f97117d1SArtem B. Bityutskiy */ 137f97117d1SArtem B. Bityutskiy static inline int 138f97117d1SArtem B. Bityutskiy read_direntry(struct jffs2_sb_info *c, 139f97117d1SArtem B. Bityutskiy struct jffs2_raw_node_ref *ref, 140f97117d1SArtem B. Bityutskiy struct jffs2_raw_dirent *rd, 141f97117d1SArtem B. Bityutskiy uint32_t read, 142f97117d1SArtem B. Bityutskiy struct jffs2_full_dirent **fdp, 143f97117d1SArtem B. Bityutskiy int32_t *latest_mctime, 144f97117d1SArtem B. Bityutskiy uint32_t *mctime_ver) 145f97117d1SArtem B. Bityutskiy { 146f97117d1SArtem B. Bityutskiy struct jffs2_full_dirent *fd; 147f97117d1SArtem B. Bityutskiy 148f97117d1SArtem B. Bityutskiy /* The direntry nodes are checked during the flash scanning */ 149f97117d1SArtem B. Bityutskiy BUG_ON(ref_flags(ref) == REF_UNCHECKED); 150f97117d1SArtem B. Bityutskiy /* Obsoleted. This cannot happen, surely? dwmw2 20020308 */ 151f97117d1SArtem B. Bityutskiy BUG_ON(ref_obsolete(ref)); 152f97117d1SArtem B. Bityutskiy 153f97117d1SArtem B. Bityutskiy /* Sanity check */ 154f97117d1SArtem B. Bityutskiy if (unlikely(PAD((rd->nsize + sizeof(*rd))) != PAD(je32_to_cpu(rd->totlen)))) { 155f97117d1SArtem B. Bityutskiy printk(KERN_ERR "Error! Illegal nsize in node at %#08x: nsize %#02x, totlen %#04x\n", 156f97117d1SArtem B. Bityutskiy ref_offset(ref), rd->nsize, je32_to_cpu(rd->totlen)); 157f97117d1SArtem B. Bityutskiy return 1; 158f97117d1SArtem B. Bityutskiy } 159f97117d1SArtem B. Bityutskiy 160f97117d1SArtem B. Bityutskiy fd = jffs2_alloc_full_dirent(rd->nsize + 1); 161f97117d1SArtem B. Bityutskiy if (unlikely(!fd)) 162f97117d1SArtem B. Bityutskiy return -ENOMEM; 163f97117d1SArtem B. Bityutskiy 164f97117d1SArtem B. Bityutskiy fd->raw = ref; 165f97117d1SArtem B. Bityutskiy fd->version = je32_to_cpu(rd->version); 166f97117d1SArtem B. Bityutskiy fd->ino = je32_to_cpu(rd->ino); 167f97117d1SArtem B. Bityutskiy fd->type = rd->type; 168f97117d1SArtem B. Bityutskiy 169f97117d1SArtem B. Bityutskiy /* Pick out the mctime of the latest dirent */ 170f97117d1SArtem B. Bityutskiy if(fd->version > *mctime_ver) { 171f97117d1SArtem B. Bityutskiy *mctime_ver = fd->version; 172f97117d1SArtem B. Bityutskiy *latest_mctime = je32_to_cpu(rd->mctime); 173f97117d1SArtem B. Bityutskiy } 174f97117d1SArtem B. Bityutskiy 175f97117d1SArtem B. Bityutskiy /* 176f97117d1SArtem B. Bityutskiy * Copy as much of the name as possible from the raw 177f97117d1SArtem B. Bityutskiy * dirent we've already read from the flash. 178f97117d1SArtem B. Bityutskiy */ 179f97117d1SArtem B. Bityutskiy if (read > sizeof(*rd)) 180f97117d1SArtem B. Bityutskiy memcpy(&fd->name[0], &rd->name[0], 181f97117d1SArtem B. Bityutskiy min_t(uint32_t, rd->nsize, (read - sizeof(*rd)) )); 182f97117d1SArtem B. Bityutskiy 183f97117d1SArtem B. Bityutskiy /* Do we need to copy any more of the name directly from the flash? */ 184f97117d1SArtem B. Bityutskiy if (rd->nsize + sizeof(*rd) > read) { 185f97117d1SArtem B. Bityutskiy /* FIXME: point() */ 186f97117d1SArtem B. Bityutskiy int err; 187f97117d1SArtem B. Bityutskiy int already = read - sizeof(*rd); 188f97117d1SArtem B. Bityutskiy 189f97117d1SArtem B. Bityutskiy err = jffs2_flash_read(c, (ref_offset(ref)) + read, 190f97117d1SArtem B. Bityutskiy rd->nsize - already, &read, &fd->name[already]); 191f97117d1SArtem B. Bityutskiy if (unlikely(read != rd->nsize - already) && likely(!err)) 192f97117d1SArtem B. Bityutskiy return -EIO; 193f97117d1SArtem B. Bityutskiy 194f97117d1SArtem B. Bityutskiy if (unlikely(err)) { 195f97117d1SArtem B. Bityutskiy printk(KERN_WARNING "Read remainder of name: error %d\n", err); 196f97117d1SArtem B. Bityutskiy jffs2_free_full_dirent(fd); 197f97117d1SArtem B. Bityutskiy return -EIO; 198f97117d1SArtem B. Bityutskiy } 199f97117d1SArtem B. Bityutskiy } 200f97117d1SArtem B. Bityutskiy 201f97117d1SArtem B. Bityutskiy fd->nhash = full_name_hash(fd->name, rd->nsize); 202f97117d1SArtem B. Bityutskiy fd->next = NULL; 203f97117d1SArtem B. Bityutskiy fd->name[rd->nsize] = '\0'; 204f97117d1SArtem B. Bityutskiy 205f97117d1SArtem B. Bityutskiy /* 206f97117d1SArtem B. Bityutskiy * Wheee. We now have a complete jffs2_full_dirent structure, with 207f97117d1SArtem B. Bityutskiy * the name in it and everything. Link it into the list 208f97117d1SArtem B. Bityutskiy */ 209f97117d1SArtem B. Bityutskiy D1(printk(KERN_DEBUG "Adding fd \"%s\", ino #%u\n", fd->name, fd->ino)); 210f97117d1SArtem B. Bityutskiy 211f97117d1SArtem B. Bityutskiy jffs2_add_fd_to_list(c, fd, fdp); 212f97117d1SArtem B. Bityutskiy 213f97117d1SArtem B. Bityutskiy return 0; 214f97117d1SArtem B. Bityutskiy } 215f97117d1SArtem B. Bityutskiy 216f97117d1SArtem B. Bityutskiy /* 217f97117d1SArtem B. Bityutskiy * Helper function for jffs2_get_inode_nodes(). 218f97117d1SArtem B. Bityutskiy * It is called every time an inode node is found. 219f97117d1SArtem B. Bityutskiy * 220f97117d1SArtem B. Bityutskiy * Returns: 0 on succes; 221f97117d1SArtem B. Bityutskiy * 1 if the node should be marked obsolete; 222f97117d1SArtem B. Bityutskiy * negative error code on failure. 223f97117d1SArtem B. Bityutskiy */ 224f97117d1SArtem B. Bityutskiy static inline int 225f97117d1SArtem B. Bityutskiy read_dnode(struct jffs2_sb_info *c, 226f97117d1SArtem B. Bityutskiy struct jffs2_raw_node_ref *ref, 227f97117d1SArtem B. Bityutskiy struct jffs2_raw_inode *rd, 228f97117d1SArtem B. Bityutskiy uint32_t read, 229f97117d1SArtem B. Bityutskiy struct rb_root *tnp, 230f97117d1SArtem B. Bityutskiy int32_t *latest_mctime, 231f97117d1SArtem B. Bityutskiy uint32_t *mctime_ver) 232f97117d1SArtem B. Bityutskiy { 233f97117d1SArtem B. Bityutskiy struct jffs2_eraseblock *jeb; 234f97117d1SArtem B. Bityutskiy struct jffs2_tmp_dnode_info *tn; 235f97117d1SArtem B. Bityutskiy 236f97117d1SArtem B. Bityutskiy /* Obsoleted. This cannot happen, surely? dwmw2 20020308 */ 237f97117d1SArtem B. Bityutskiy BUG_ON(ref_obsolete(ref)); 238f97117d1SArtem B. Bityutskiy 239f97117d1SArtem B. Bityutskiy /* If we've never checked the CRCs on this node, check them now */ 240f97117d1SArtem B. Bityutskiy if (ref_flags(ref) == REF_UNCHECKED) { 241f97117d1SArtem B. Bityutskiy uint32_t crc, len; 242f97117d1SArtem B. Bityutskiy 243f97117d1SArtem B. Bityutskiy crc = crc32(0, rd, sizeof(*rd) - 8); 244f97117d1SArtem B. Bityutskiy if (unlikely(crc != je32_to_cpu(rd->node_crc))) { 245f97117d1SArtem B. Bityutskiy printk(KERN_WARNING "Header CRC failed on node at %#08x: read %#08x, calculated %#08x\n", 246f97117d1SArtem B. Bityutskiy ref_offset(ref), je32_to_cpu(rd->node_crc), crc); 247f97117d1SArtem B. Bityutskiy return 1; 248f97117d1SArtem B. Bityutskiy } 249f97117d1SArtem B. Bityutskiy 250f97117d1SArtem B. Bityutskiy /* Sanity checks */ 251f97117d1SArtem B. Bityutskiy if (unlikely(je32_to_cpu(rd->offset) > je32_to_cpu(rd->isize)) || 252f97117d1SArtem B. Bityutskiy unlikely(PAD(je32_to_cpu(rd->csize) + sizeof(*rd)) != PAD(je32_to_cpu(rd->totlen)))) { 253f97117d1SArtem B. Bityutskiy printk(KERN_WARNING "Inode corrupted at %#08x, totlen %d, #ino %d, version %d, " 254f97117d1SArtem B. Bityutskiy "isize %d, csize %d, dsize %d \n", 255f97117d1SArtem B. Bityutskiy ref_offset(ref), je32_to_cpu(rd->totlen), je32_to_cpu(rd->ino), 256f97117d1SArtem B. Bityutskiy je32_to_cpu(rd->version), je32_to_cpu(rd->isize), 257f97117d1SArtem B. Bityutskiy je32_to_cpu(rd->csize), je32_to_cpu(rd->dsize)); 258f97117d1SArtem B. Bityutskiy return 1; 259f97117d1SArtem B. Bityutskiy } 260f97117d1SArtem B. Bityutskiy 261f97117d1SArtem B. Bityutskiy if (rd->compr != JFFS2_COMPR_ZERO && je32_to_cpu(rd->csize)) { 262f97117d1SArtem B. Bityutskiy unsigned char *buf = NULL; 263f97117d1SArtem B. Bityutskiy uint32_t pointed = 0; 264f97117d1SArtem B. Bityutskiy int err; 265f97117d1SArtem B. Bityutskiy #ifndef __ECOS 266f97117d1SArtem B. Bityutskiy if (c->mtd->point) { 267f97117d1SArtem B. Bityutskiy err = c->mtd->point (c->mtd, ref_offset(ref) + sizeof(*rd), je32_to_cpu(rd->csize), 268f97117d1SArtem B. Bityutskiy &read, &buf); 269f97117d1SArtem B. Bityutskiy if (unlikely(read < je32_to_cpu(rd->csize)) && likely(!err)) { 270f97117d1SArtem B. Bityutskiy D1(printk(KERN_DEBUG "MTD point returned len too short: 0x%zx\n", read)); 271f97117d1SArtem B. Bityutskiy c->mtd->unpoint(c->mtd, buf, ref_offset(ref) + sizeof(*rd), 272f97117d1SArtem B. Bityutskiy je32_to_cpu(rd->csize)); 273f97117d1SArtem B. Bityutskiy } else if (unlikely(err)){ 274f97117d1SArtem B. Bityutskiy D1(printk(KERN_DEBUG "MTD point failed %d\n", err)); 275f97117d1SArtem B. Bityutskiy } else 276f97117d1SArtem B. Bityutskiy pointed = 1; /* succefully pointed to device */ 277f97117d1SArtem B. Bityutskiy } 278f97117d1SArtem B. Bityutskiy #endif 279f97117d1SArtem B. Bityutskiy if(!pointed){ 280f97117d1SArtem B. Bityutskiy buf = kmalloc(je32_to_cpu(rd->csize), GFP_KERNEL); 281f97117d1SArtem B. Bityutskiy if (!buf) 282f97117d1SArtem B. Bityutskiy return -ENOMEM; 283f97117d1SArtem B. Bityutskiy 284f97117d1SArtem B. Bityutskiy err = jffs2_flash_read(c, ref_offset(ref) + sizeof(*rd), je32_to_cpu(rd->csize), 285f97117d1SArtem B. Bityutskiy &read, buf); 286f97117d1SArtem B. Bityutskiy if (unlikely(read != je32_to_cpu(rd->csize)) && likely(!err)) 287f97117d1SArtem B. Bityutskiy err = -EIO; 288f97117d1SArtem B. Bityutskiy if (err) { 289f97117d1SArtem B. Bityutskiy kfree(buf); 290f97117d1SArtem B. Bityutskiy return err; 291f97117d1SArtem B. Bityutskiy } 292f97117d1SArtem B. Bityutskiy } 293f97117d1SArtem B. Bityutskiy crc = crc32(0, buf, je32_to_cpu(rd->csize)); 294f97117d1SArtem B. Bityutskiy if(!pointed) 295f97117d1SArtem B. Bityutskiy kfree(buf); 296f97117d1SArtem B. Bityutskiy #ifndef __ECOS 297f97117d1SArtem B. Bityutskiy else 298f97117d1SArtem B. Bityutskiy c->mtd->unpoint(c->mtd, buf, ref_offset(ref) + sizeof(*rd), je32_to_cpu(rd->csize)); 299f97117d1SArtem B. Bityutskiy #endif 300f97117d1SArtem B. Bityutskiy 301f97117d1SArtem B. Bityutskiy if (crc != je32_to_cpu(rd->data_crc)) { 302f97117d1SArtem B. Bityutskiy printk(KERN_NOTICE "Data CRC failed on node at %#08x: read %#08x, calculated %#08x\n", 303f97117d1SArtem B. Bityutskiy ref_offset(ref), je32_to_cpu(rd->data_crc), crc); 304f97117d1SArtem B. Bityutskiy return 1; 305f97117d1SArtem B. Bityutskiy } 306f97117d1SArtem B. Bityutskiy 307f97117d1SArtem B. Bityutskiy } 308f97117d1SArtem B. Bityutskiy 309f97117d1SArtem B. Bityutskiy /* Mark the node as having been checked and fix the accounting accordingly */ 310f97117d1SArtem B. Bityutskiy jeb = &c->blocks[ref->flash_offset / c->sector_size]; 311f97117d1SArtem B. Bityutskiy len = ref_totlen(c, jeb, ref); 312f97117d1SArtem B. Bityutskiy 313f97117d1SArtem B. Bityutskiy spin_lock(&c->erase_completion_lock); 314f97117d1SArtem B. Bityutskiy jeb->used_size += len; 315f97117d1SArtem B. Bityutskiy jeb->unchecked_size -= len; 316f97117d1SArtem B. Bityutskiy c->used_size += len; 317f97117d1SArtem B. Bityutskiy c->unchecked_size -= len; 318f97117d1SArtem B. Bityutskiy 319f97117d1SArtem B. Bityutskiy /* If node covers at least a whole page, or if it starts at the 320f97117d1SArtem B. Bityutskiy beginning of a page and runs to the end of the file, or if 321f97117d1SArtem B. Bityutskiy it's a hole node, mark it REF_PRISTINE, else REF_NORMAL. 322f97117d1SArtem B. Bityutskiy 323f97117d1SArtem B. Bityutskiy If it's actually overlapped, it'll get made NORMAL (or OBSOLETE) 324f97117d1SArtem B. Bityutskiy when the overlapping node(s) get added to the tree anyway. 325f97117d1SArtem B. Bityutskiy */ 326f97117d1SArtem B. Bityutskiy if ((je32_to_cpu(rd->dsize) >= PAGE_CACHE_SIZE) || 327f97117d1SArtem B. Bityutskiy ( ((je32_to_cpu(rd->offset) & (PAGE_CACHE_SIZE-1))==0) && 328f97117d1SArtem B. Bityutskiy (je32_to_cpu(rd->dsize) + je32_to_cpu(rd->offset) == je32_to_cpu(rd->isize)))) { 329f97117d1SArtem B. Bityutskiy D1(printk(KERN_DEBUG "Marking node at %#08x REF_PRISTINE\n", ref_offset(ref))); 330f97117d1SArtem B. Bityutskiy ref->flash_offset = ref_offset(ref) | REF_PRISTINE; 331f97117d1SArtem B. Bityutskiy } else { 332f97117d1SArtem B. Bityutskiy D1(printk(KERN_DEBUG "Marking node at %#08x REF_NORMAL\n", ref_offset(ref))); 333f97117d1SArtem B. Bityutskiy ref->flash_offset = ref_offset(ref) | REF_NORMAL; 334f97117d1SArtem B. Bityutskiy } 335f97117d1SArtem B. Bityutskiy spin_unlock(&c->erase_completion_lock); 336f97117d1SArtem B. Bityutskiy } 337f97117d1SArtem B. Bityutskiy 338f97117d1SArtem B. Bityutskiy tn = jffs2_alloc_tmp_dnode_info(); 339f97117d1SArtem B. Bityutskiy if (!tn) { 340f97117d1SArtem B. Bityutskiy D1(printk(KERN_DEBUG "alloc tn failed\n")); 341f97117d1SArtem B. Bityutskiy return -ENOMEM; 342f97117d1SArtem B. Bityutskiy } 343f97117d1SArtem B. Bityutskiy 344f97117d1SArtem B. Bityutskiy tn->fn = jffs2_alloc_full_dnode(); 345f97117d1SArtem B. Bityutskiy if (!tn->fn) { 346f97117d1SArtem B. Bityutskiy D1(printk(KERN_DEBUG "alloc fn failed\n")); 347f97117d1SArtem B. Bityutskiy jffs2_free_tmp_dnode_info(tn); 348f97117d1SArtem B. Bityutskiy return -ENOMEM; 349f97117d1SArtem B. Bityutskiy } 350f97117d1SArtem B. Bityutskiy 351f97117d1SArtem B. Bityutskiy tn->version = je32_to_cpu(rd->version); 352f97117d1SArtem B. Bityutskiy tn->fn->ofs = je32_to_cpu(rd->offset); 353f97117d1SArtem B. Bityutskiy tn->fn->raw = ref; 354f97117d1SArtem B. Bityutskiy 355f97117d1SArtem B. Bityutskiy /* There was a bug where we wrote hole nodes out with 356f97117d1SArtem B. Bityutskiy csize/dsize swapped. Deal with it */ 357f97117d1SArtem B. Bityutskiy if (rd->compr == JFFS2_COMPR_ZERO && !je32_to_cpu(rd->dsize) && je32_to_cpu(rd->csize)) 358f97117d1SArtem B. Bityutskiy tn->fn->size = je32_to_cpu(rd->csize); 359f97117d1SArtem B. Bityutskiy else // normal case... 360f97117d1SArtem B. Bityutskiy tn->fn->size = je32_to_cpu(rd->dsize); 361f97117d1SArtem B. Bityutskiy 362f97117d1SArtem B. Bityutskiy D1(printk(KERN_DEBUG "dnode @%08x: ver %u, offset %#04x, dsize %#04x\n", 363f97117d1SArtem B. Bityutskiy ref_offset(ref), je32_to_cpu(rd->version), 364f97117d1SArtem B. Bityutskiy je32_to_cpu(rd->offset), je32_to_cpu(rd->dsize))); 365f97117d1SArtem B. Bityutskiy 366f97117d1SArtem B. Bityutskiy jffs2_add_tn_to_tree(tn, tnp); 367f97117d1SArtem B. Bityutskiy 368f97117d1SArtem B. Bityutskiy return 0; 369f97117d1SArtem B. Bityutskiy } 370f97117d1SArtem B. Bityutskiy 371f97117d1SArtem B. Bityutskiy /* 372f97117d1SArtem B. Bityutskiy * Helper function for jffs2_get_inode_nodes(). 373f97117d1SArtem B. Bityutskiy * It is called every time an unknown node is found. 374f97117d1SArtem B. Bityutskiy * 375f97117d1SArtem B. Bityutskiy * Returns: 0 on succes; 376f97117d1SArtem B. Bityutskiy * 1 if the node should be marked obsolete; 377f97117d1SArtem B. Bityutskiy * negative error code on failure. 378f97117d1SArtem B. Bityutskiy */ 379f97117d1SArtem B. Bityutskiy static inline int 380f97117d1SArtem B. Bityutskiy read_unknown(struct jffs2_sb_info *c, 381f97117d1SArtem B. Bityutskiy struct jffs2_raw_node_ref *ref, 382f97117d1SArtem B. Bityutskiy struct jffs2_unknown_node *un, 383f97117d1SArtem B. Bityutskiy uint32_t read) 384f97117d1SArtem B. Bityutskiy { 385f97117d1SArtem B. Bityutskiy /* We don't mark unknown nodes as REF_UNCHECKED */ 386f97117d1SArtem B. Bityutskiy BUG_ON(ref_flags(ref) == REF_UNCHECKED); 387f97117d1SArtem B. Bityutskiy 388f97117d1SArtem B. Bityutskiy un->nodetype = cpu_to_je16(JFFS2_NODE_ACCURATE | je16_to_cpu(un->nodetype)); 389f97117d1SArtem B. Bityutskiy 390f97117d1SArtem B. Bityutskiy if (crc32(0, un, sizeof(struct jffs2_unknown_node) - 4) != je32_to_cpu(un->hdr_crc)) { 391f97117d1SArtem B. Bityutskiy 392f97117d1SArtem B. Bityutskiy /* Hmmm. This should have been caught at scan time. */ 393f97117d1SArtem B. Bityutskiy printk(KERN_WARNING "Warning! Node header CRC failed at %#08x. " 394f97117d1SArtem B. Bityutskiy "But it must have been OK earlier.\n", ref_offset(ref)); 395f97117d1SArtem B. Bityutskiy D1(printk(KERN_DEBUG "Node was: { %#04x, %#04x, %#08x, %#08x }\n", 396f97117d1SArtem B. Bityutskiy je16_to_cpu(un->magic), je16_to_cpu(un->nodetype), 397f97117d1SArtem B. Bityutskiy je32_to_cpu(un->totlen), je32_to_cpu(un->hdr_crc))); 398f97117d1SArtem B. Bityutskiy return 1; 399f97117d1SArtem B. Bityutskiy } else { 400f97117d1SArtem B. Bityutskiy switch(je16_to_cpu(un->nodetype) & JFFS2_COMPAT_MASK) { 401f97117d1SArtem B. Bityutskiy 402f97117d1SArtem B. Bityutskiy case JFFS2_FEATURE_INCOMPAT: 403f97117d1SArtem B. Bityutskiy printk(KERN_NOTICE "Unknown INCOMPAT nodetype %#04X at %#08x\n", 404f97117d1SArtem B. Bityutskiy je16_to_cpu(un->nodetype), ref_offset(ref)); 405f97117d1SArtem B. Bityutskiy /* EEP */ 406f97117d1SArtem B. Bityutskiy BUG(); 407f97117d1SArtem B. Bityutskiy break; 408f97117d1SArtem B. Bityutskiy 409f97117d1SArtem B. Bityutskiy case JFFS2_FEATURE_ROCOMPAT: 410f97117d1SArtem B. Bityutskiy printk(KERN_NOTICE "Unknown ROCOMPAT nodetype %#04X at %#08x\n", 411f97117d1SArtem B. Bityutskiy je16_to_cpu(un->nodetype), ref_offset(ref)); 412f97117d1SArtem B. Bityutskiy BUG_ON(!(c->flags & JFFS2_SB_FLAG_RO)); 413f97117d1SArtem B. Bityutskiy break; 414f97117d1SArtem B. Bityutskiy 415f97117d1SArtem B. Bityutskiy case JFFS2_FEATURE_RWCOMPAT_COPY: 416f97117d1SArtem B. Bityutskiy printk(KERN_NOTICE "Unknown RWCOMPAT_COPY nodetype %#04X at %#08x\n", 417f97117d1SArtem B. Bityutskiy je16_to_cpu(un->nodetype), ref_offset(ref)); 418f97117d1SArtem B. Bityutskiy break; 419f97117d1SArtem B. Bityutskiy 420f97117d1SArtem B. Bityutskiy case JFFS2_FEATURE_RWCOMPAT_DELETE: 421f97117d1SArtem B. Bityutskiy printk(KERN_NOTICE "Unknown RWCOMPAT_DELETE nodetype %#04X at %#08x\n", 422f97117d1SArtem B. Bityutskiy je16_to_cpu(un->nodetype), ref_offset(ref)); 423f97117d1SArtem B. Bityutskiy return 1; 424f97117d1SArtem B. Bityutskiy } 425f97117d1SArtem B. Bityutskiy } 426f97117d1SArtem B. Bityutskiy 427f97117d1SArtem B. Bityutskiy return 0; 428f97117d1SArtem B. Bityutskiy } 429f97117d1SArtem B. Bityutskiy 430f97117d1SArtem B. Bityutskiy /* Get tmp_dnode_info and full_dirent for all non-obsolete nodes associated 431f97117d1SArtem B. Bityutskiy with this ino, returning the former in order of version */ 432f97117d1SArtem B. Bityutskiy 433f97117d1SArtem B. Bityutskiy static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_info *f, 434f97117d1SArtem B. Bityutskiy struct rb_root *tnp, struct jffs2_full_dirent **fdp, 435f97117d1SArtem B. Bityutskiy uint32_t *highest_version, uint32_t *latest_mctime, 436f97117d1SArtem B. Bityutskiy uint32_t *mctime_ver) 437f97117d1SArtem B. Bityutskiy { 438f97117d1SArtem B. Bityutskiy struct jffs2_raw_node_ref *ref, *valid_ref; 439f97117d1SArtem B. Bityutskiy struct rb_root ret_tn = RB_ROOT; 440f97117d1SArtem B. Bityutskiy struct jffs2_full_dirent *ret_fd = NULL; 441f97117d1SArtem B. Bityutskiy union jffs2_node_union node; 442f97117d1SArtem B. Bityutskiy size_t retlen; 443f97117d1SArtem B. Bityutskiy int err; 444f97117d1SArtem B. Bityutskiy 445f97117d1SArtem B. Bityutskiy *mctime_ver = 0; 446f97117d1SArtem B. Bityutskiy 447f97117d1SArtem B. Bityutskiy D1(printk(KERN_DEBUG "jffs2_get_inode_nodes(): ino #%u\n", f->inocache->ino)); 448f97117d1SArtem B. Bityutskiy 449f97117d1SArtem B. Bityutskiy spin_lock(&c->erase_completion_lock); 450f97117d1SArtem B. Bityutskiy 451f97117d1SArtem B. Bityutskiy valid_ref = jffs2_first_valid_node(f->inocache->nodes); 452f97117d1SArtem B. Bityutskiy 453f97117d1SArtem B. Bityutskiy if (!valid_ref && (f->inocache->ino != 1)) 454f97117d1SArtem B. Bityutskiy printk(KERN_WARNING "Eep. No valid nodes for ino #%u\n", f->inocache->ino); 455f97117d1SArtem B. Bityutskiy 456f97117d1SArtem B. Bityutskiy while (valid_ref) { 457f97117d1SArtem B. Bityutskiy /* We can hold a pointer to a non-obsolete node without the spinlock, 458f97117d1SArtem B. Bityutskiy but _obsolete_ nodes may disappear at any time, if the block 459f97117d1SArtem B. Bityutskiy they're in gets erased. So if we mark 'ref' obsolete while we're 460f97117d1SArtem B. Bityutskiy not holding the lock, it can go away immediately. For that reason, 461f97117d1SArtem B. Bityutskiy we find the next valid node first, before processing 'ref'. 462f97117d1SArtem B. Bityutskiy */ 463f97117d1SArtem B. Bityutskiy ref = valid_ref; 464f97117d1SArtem B. Bityutskiy valid_ref = jffs2_first_valid_node(ref->next_in_ino); 465f97117d1SArtem B. Bityutskiy spin_unlock(&c->erase_completion_lock); 466f97117d1SArtem B. Bityutskiy 467f97117d1SArtem B. Bityutskiy cond_resched(); 468f97117d1SArtem B. Bityutskiy 469f97117d1SArtem B. Bityutskiy /* FIXME: point() */ 470f97117d1SArtem B. Bityutskiy err = jffs2_flash_read(c, (ref_offset(ref)), 471f97117d1SArtem B. Bityutskiy min_t(uint32_t, ref_totlen(c, NULL, ref), sizeof(node)), 472f97117d1SArtem B. Bityutskiy &retlen, (void *)&node); 473f97117d1SArtem B. Bityutskiy if (err) { 474f97117d1SArtem B. Bityutskiy printk(KERN_WARNING "error %d reading node at 0x%08x in get_inode_nodes()\n", err, ref_offset(ref)); 475f97117d1SArtem B. Bityutskiy goto free_out; 476f97117d1SArtem B. Bityutskiy } 477f97117d1SArtem B. Bityutskiy 478f97117d1SArtem B. Bityutskiy switch (je16_to_cpu(node.u.nodetype)) { 479f97117d1SArtem B. Bityutskiy 480f97117d1SArtem B. Bityutskiy case JFFS2_NODETYPE_DIRENT: 481f97117d1SArtem B. Bityutskiy D1(printk(KERN_DEBUG "Node at %08x (%d) is a dirent node\n", ref_offset(ref), ref_flags(ref))); 482f97117d1SArtem B. Bityutskiy 483f97117d1SArtem B. Bityutskiy if (retlen < sizeof(node.d)) { 484f97117d1SArtem B. Bityutskiy printk(KERN_WARNING "Warning! Short read dirent at %#08x\n", ref_offset(ref)); 485f97117d1SArtem B. Bityutskiy err = -EIO; 486f97117d1SArtem B. Bityutskiy goto free_out; 487f97117d1SArtem B. Bityutskiy } 488f97117d1SArtem B. Bityutskiy 489f97117d1SArtem B. Bityutskiy err = read_direntry(c, ref, &node.d, retlen, &ret_fd, latest_mctime, mctime_ver); 490f97117d1SArtem B. Bityutskiy if (err == 1) { 491f97117d1SArtem B. Bityutskiy jffs2_mark_node_obsolete(c, ref); 492f97117d1SArtem B. Bityutskiy break; 493f97117d1SArtem B. Bityutskiy } else if (unlikely(err)) 494f97117d1SArtem B. Bityutskiy goto free_out; 495f97117d1SArtem B. Bityutskiy 496f97117d1SArtem B. Bityutskiy if (je32_to_cpu(node.d.version) > *highest_version) 497f97117d1SArtem B. Bityutskiy *highest_version = je32_to_cpu(node.d.version); 498f97117d1SArtem B. Bityutskiy 499f97117d1SArtem B. Bityutskiy break; 500f97117d1SArtem B. Bityutskiy 501f97117d1SArtem B. Bityutskiy case JFFS2_NODETYPE_INODE: 502f97117d1SArtem B. Bityutskiy D1(printk(KERN_DEBUG "Node at %08x (%d) is a data node\n", ref_offset(ref), ref_flags(ref))); 503f97117d1SArtem B. Bityutskiy 504f97117d1SArtem B. Bityutskiy if (retlen < sizeof(node.i)) { 505f97117d1SArtem B. Bityutskiy printk(KERN_WARNING "Warning! Short read dnode at %#08x\n", ref_offset(ref)); 506f97117d1SArtem B. Bityutskiy err = -EIO; 507f97117d1SArtem B. Bityutskiy goto free_out; 508f97117d1SArtem B. Bityutskiy } 509f97117d1SArtem B. Bityutskiy 510f97117d1SArtem B. Bityutskiy err = read_dnode(c, ref, &node.i, retlen, &ret_tn, latest_mctime, mctime_ver); 511f97117d1SArtem B. Bityutskiy if (err == 1) { 512f97117d1SArtem B. Bityutskiy jffs2_mark_node_obsolete(c, ref); 513f97117d1SArtem B. Bityutskiy break; 514f97117d1SArtem B. Bityutskiy } else if (unlikely(err)) 515f97117d1SArtem B. Bityutskiy goto free_out; 516f97117d1SArtem B. Bityutskiy 517f97117d1SArtem B. Bityutskiy if (je32_to_cpu(node.i.version) > *highest_version) 518f97117d1SArtem B. Bityutskiy *highest_version = je32_to_cpu(node.i.version); 519f97117d1SArtem B. Bityutskiy 520f97117d1SArtem B. Bityutskiy D1(printk(KERN_DEBUG "version %d, highest_version now %d\n", 521f97117d1SArtem B. Bityutskiy je32_to_cpu(node.i.version), *highest_version)); 522f97117d1SArtem B. Bityutskiy 5231da177e4SLinus Torvalds break; 5241da177e4SLinus Torvalds 5251da177e4SLinus Torvalds default: 526f97117d1SArtem B. Bityutskiy /* Check we've managed to read at least the common node header */ 527f97117d1SArtem B. Bityutskiy if (retlen < sizeof(struct jffs2_unknown_node)) { 528f97117d1SArtem B. Bityutskiy printk(KERN_WARNING "Warning! Short read unknown node at %#08x\n", 529f97117d1SArtem B. Bityutskiy ref_offset(ref)); 530f97117d1SArtem B. Bityutskiy return -EIO; 5311da177e4SLinus Torvalds } 5321da177e4SLinus Torvalds 533f97117d1SArtem B. Bityutskiy err = read_unknown(c, ref, &node.u, retlen); 534f97117d1SArtem B. Bityutskiy if (err == 1) { 535f97117d1SArtem B. Bityutskiy jffs2_mark_node_obsolete(c, ref); 536f97117d1SArtem B. Bityutskiy break; 537f97117d1SArtem B. Bityutskiy } else if (unlikely(err)) 538f97117d1SArtem B. Bityutskiy goto free_out; 539f97117d1SArtem B. Bityutskiy 5401da177e4SLinus Torvalds } 541f97117d1SArtem B. Bityutskiy spin_lock(&c->erase_completion_lock); 5421da177e4SLinus Torvalds 5431da177e4SLinus Torvalds } 544f97117d1SArtem B. Bityutskiy spin_unlock(&c->erase_completion_lock); 545f97117d1SArtem B. Bityutskiy *tnp = ret_tn; 546f97117d1SArtem B. Bityutskiy *fdp = ret_fd; 547f97117d1SArtem B. Bityutskiy 548f97117d1SArtem B. Bityutskiy return 0; 549f97117d1SArtem B. Bityutskiy 550f97117d1SArtem B. Bityutskiy free_out: 551f97117d1SArtem B. Bityutskiy jffs2_free_tmp_dnode_info_list(&ret_tn); 552f97117d1SArtem B. Bityutskiy jffs2_free_full_dirent_list(ret_fd); 553f97117d1SArtem B. Bityutskiy return err; 5541da177e4SLinus Torvalds } 5551da177e4SLinus Torvalds 5561da177e4SLinus Torvalds static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, 5571da177e4SLinus Torvalds struct jffs2_inode_info *f, 5581da177e4SLinus Torvalds struct jffs2_raw_inode *latest_node) 5591da177e4SLinus Torvalds { 5609dee7503SDavid Woodhouse struct jffs2_tmp_dnode_info *tn = NULL; 5619dee7503SDavid Woodhouse struct rb_root tn_list; 5629dee7503SDavid Woodhouse struct rb_node *rb, *repl_rb; 5631da177e4SLinus Torvalds struct jffs2_full_dirent *fd_list; 5641da177e4SLinus Torvalds struct jffs2_full_dnode *fn = NULL; 5651da177e4SLinus Torvalds uint32_t crc; 5661da177e4SLinus Torvalds uint32_t latest_mctime, mctime_ver; 5671da177e4SLinus Torvalds uint32_t mdata_ver = 0; 5681da177e4SLinus Torvalds size_t retlen; 5691da177e4SLinus Torvalds int ret; 5701da177e4SLinus Torvalds 5711da177e4SLinus Torvalds D1(printk(KERN_DEBUG "jffs2_do_read_inode_internal(): ino #%u nlink is %d\n", f->inocache->ino, f->inocache->nlink)); 5721da177e4SLinus Torvalds 5731da177e4SLinus Torvalds /* Grab all nodes relevant to this ino */ 5741da177e4SLinus Torvalds ret = jffs2_get_inode_nodes(c, f, &tn_list, &fd_list, &f->highest_version, &latest_mctime, &mctime_ver); 5751da177e4SLinus Torvalds 5761da177e4SLinus Torvalds if (ret) { 5771da177e4SLinus Torvalds printk(KERN_CRIT "jffs2_get_inode_nodes() for ino %u returned %d\n", f->inocache->ino, ret); 5781da177e4SLinus Torvalds if (f->inocache->state == INO_STATE_READING) 5791da177e4SLinus Torvalds jffs2_set_inocache_state(c, f->inocache, INO_STATE_CHECKEDABSENT); 5801da177e4SLinus Torvalds return ret; 5811da177e4SLinus Torvalds } 5821da177e4SLinus Torvalds f->dents = fd_list; 5831da177e4SLinus Torvalds 5849dee7503SDavid Woodhouse rb = rb_first(&tn_list); 5851da177e4SLinus Torvalds 5869dee7503SDavid Woodhouse while (rb) { 5879dee7503SDavid Woodhouse tn = rb_entry(rb, struct jffs2_tmp_dnode_info, rb); 5881da177e4SLinus Torvalds fn = tn->fn; 5891da177e4SLinus Torvalds 5901da177e4SLinus Torvalds if (f->metadata) { 5911da177e4SLinus Torvalds if (likely(tn->version >= mdata_ver)) { 5921da177e4SLinus Torvalds D1(printk(KERN_DEBUG "Obsoleting old metadata at 0x%08x\n", ref_offset(f->metadata->raw))); 5931da177e4SLinus Torvalds jffs2_mark_node_obsolete(c, f->metadata->raw); 5941da177e4SLinus Torvalds jffs2_free_full_dnode(f->metadata); 5951da177e4SLinus Torvalds f->metadata = NULL; 5961da177e4SLinus Torvalds 5971da177e4SLinus Torvalds mdata_ver = 0; 5981da177e4SLinus Torvalds } else { 5991da177e4SLinus Torvalds /* This should never happen. */ 6001da177e4SLinus Torvalds printk(KERN_WARNING "Er. New metadata at 0x%08x with ver %d is actually older than previous ver %d at 0x%08x\n", 6011da177e4SLinus Torvalds ref_offset(fn->raw), tn->version, mdata_ver, ref_offset(f->metadata->raw)); 6021da177e4SLinus Torvalds jffs2_mark_node_obsolete(c, fn->raw); 6031da177e4SLinus Torvalds jffs2_free_full_dnode(fn); 6041da177e4SLinus Torvalds /* Fill in latest_node from the metadata, not this one we're about to free... */ 6051da177e4SLinus Torvalds fn = f->metadata; 6061da177e4SLinus Torvalds goto next_tn; 6071da177e4SLinus Torvalds } 6081da177e4SLinus Torvalds } 6091da177e4SLinus Torvalds 6101da177e4SLinus Torvalds if (fn->size) { 6111da177e4SLinus Torvalds jffs2_add_full_dnode_to_inode(c, f, fn); 6121da177e4SLinus Torvalds } else { 6131da177e4SLinus Torvalds /* Zero-sized node at end of version list. Just a metadata update */ 6141da177e4SLinus Torvalds D1(printk(KERN_DEBUG "metadata @%08x: ver %d\n", ref_offset(fn->raw), tn->version)); 6151da177e4SLinus Torvalds f->metadata = fn; 6161da177e4SLinus Torvalds mdata_ver = tn->version; 6171da177e4SLinus Torvalds } 6181da177e4SLinus Torvalds next_tn: 6199dee7503SDavid Woodhouse BUG_ON(rb->rb_left); 6209dee7503SDavid Woodhouse if (rb->rb_parent && rb->rb_parent->rb_left == rb) { 6219dee7503SDavid Woodhouse /* We were then left-hand child of our parent. We need 6229dee7503SDavid Woodhouse to move our own right-hand child into our place. */ 6239dee7503SDavid Woodhouse repl_rb = rb->rb_right; 6249dee7503SDavid Woodhouse if (repl_rb) 6259dee7503SDavid Woodhouse repl_rb->rb_parent = rb->rb_parent; 6269dee7503SDavid Woodhouse } else 6279dee7503SDavid Woodhouse repl_rb = NULL; 6289dee7503SDavid Woodhouse 6299dee7503SDavid Woodhouse rb = rb_next(rb); 6309dee7503SDavid Woodhouse 6319dee7503SDavid Woodhouse /* Remove the spent tn from the tree; don't bother rebalancing 6329dee7503SDavid Woodhouse but put our right-hand child in our own place. */ 6339dee7503SDavid Woodhouse if (tn->rb.rb_parent) { 6349dee7503SDavid Woodhouse if (tn->rb.rb_parent->rb_left == &tn->rb) 6359dee7503SDavid Woodhouse tn->rb.rb_parent->rb_left = repl_rb; 6369dee7503SDavid Woodhouse else if (tn->rb.rb_parent->rb_right == &tn->rb) 6379dee7503SDavid Woodhouse tn->rb.rb_parent->rb_right = repl_rb; 6389dee7503SDavid Woodhouse else BUG(); 6399dee7503SDavid Woodhouse } else if (tn->rb.rb_right) 6409dee7503SDavid Woodhouse tn->rb.rb_right->rb_parent = NULL; 6419dee7503SDavid Woodhouse 6421da177e4SLinus Torvalds jffs2_free_tmp_dnode_info(tn); 6431da177e4SLinus Torvalds } 644e0c8e42fSArtem B. Bityutskiy jffs2_dbg_fragtree_paranoia_check_nolock(f); 6451da177e4SLinus Torvalds 6461da177e4SLinus Torvalds if (!fn) { 6471da177e4SLinus Torvalds /* No data nodes for this inode. */ 6481da177e4SLinus Torvalds if (f->inocache->ino != 1) { 6491da177e4SLinus Torvalds printk(KERN_WARNING "jffs2_do_read_inode(): No data nodes found for ino #%u\n", f->inocache->ino); 6501da177e4SLinus Torvalds if (!fd_list) { 6511da177e4SLinus Torvalds if (f->inocache->state == INO_STATE_READING) 6521da177e4SLinus Torvalds jffs2_set_inocache_state(c, f->inocache, INO_STATE_CHECKEDABSENT); 6531da177e4SLinus Torvalds return -EIO; 6541da177e4SLinus Torvalds } 6551da177e4SLinus Torvalds printk(KERN_WARNING "jffs2_do_read_inode(): But it has children so we fake some modes for it\n"); 6561da177e4SLinus Torvalds } 6571da177e4SLinus Torvalds latest_node->mode = cpu_to_jemode(S_IFDIR|S_IRUGO|S_IWUSR|S_IXUGO); 6581da177e4SLinus Torvalds latest_node->version = cpu_to_je32(0); 6591da177e4SLinus Torvalds latest_node->atime = latest_node->ctime = latest_node->mtime = cpu_to_je32(0); 6601da177e4SLinus Torvalds latest_node->isize = cpu_to_je32(0); 6611da177e4SLinus Torvalds latest_node->gid = cpu_to_je16(0); 6621da177e4SLinus Torvalds latest_node->uid = cpu_to_je16(0); 6631da177e4SLinus Torvalds if (f->inocache->state == INO_STATE_READING) 6641da177e4SLinus Torvalds jffs2_set_inocache_state(c, f->inocache, INO_STATE_PRESENT); 6651da177e4SLinus Torvalds return 0; 6661da177e4SLinus Torvalds } 6671da177e4SLinus Torvalds 6681da177e4SLinus Torvalds ret = jffs2_flash_read(c, ref_offset(fn->raw), sizeof(*latest_node), &retlen, (void *)latest_node); 6691da177e4SLinus Torvalds if (ret || retlen != sizeof(*latest_node)) { 6701da177e4SLinus Torvalds printk(KERN_NOTICE "MTD read in jffs2_do_read_inode() failed: Returned %d, %zd of %zd bytes read\n", 6711da177e4SLinus Torvalds ret, retlen, sizeof(*latest_node)); 6721da177e4SLinus Torvalds /* FIXME: If this fails, there seems to be a memory leak. Find it. */ 6731da177e4SLinus Torvalds up(&f->sem); 6741da177e4SLinus Torvalds jffs2_do_clear_inode(c, f); 6751da177e4SLinus Torvalds return ret?ret:-EIO; 6761da177e4SLinus Torvalds } 6771da177e4SLinus Torvalds 6781da177e4SLinus Torvalds crc = crc32(0, latest_node, sizeof(*latest_node)-8); 6791da177e4SLinus Torvalds if (crc != je32_to_cpu(latest_node->node_crc)) { 6801da177e4SLinus Torvalds printk(KERN_NOTICE "CRC failed for read_inode of inode %u at physical location 0x%x\n", f->inocache->ino, ref_offset(fn->raw)); 6811da177e4SLinus Torvalds up(&f->sem); 6821da177e4SLinus Torvalds jffs2_do_clear_inode(c, f); 6831da177e4SLinus Torvalds return -EIO; 6841da177e4SLinus Torvalds } 6851da177e4SLinus Torvalds 6861da177e4SLinus Torvalds switch(jemode_to_cpu(latest_node->mode) & S_IFMT) { 6871da177e4SLinus Torvalds case S_IFDIR: 6881da177e4SLinus Torvalds if (mctime_ver > je32_to_cpu(latest_node->version)) { 6891da177e4SLinus Torvalds /* The times in the latest_node are actually older than 6901da177e4SLinus Torvalds mctime in the latest dirent. Cheat. */ 6911da177e4SLinus Torvalds latest_node->ctime = latest_node->mtime = cpu_to_je32(latest_mctime); 6921da177e4SLinus Torvalds } 6931da177e4SLinus Torvalds break; 6941da177e4SLinus Torvalds 6951da177e4SLinus Torvalds 6961da177e4SLinus Torvalds case S_IFREG: 6971da177e4SLinus Torvalds /* If it was a regular file, truncate it to the latest node's isize */ 698f302cd02SArtem B. Bityutskiy jffs2_truncate_fragtree(c, &f->fragtree, je32_to_cpu(latest_node->isize)); 6991da177e4SLinus Torvalds break; 7001da177e4SLinus Torvalds 7011da177e4SLinus Torvalds case S_IFLNK: 7021da177e4SLinus Torvalds /* Hack to work around broken isize in old symlink code. 7031da177e4SLinus Torvalds Remove this when dwmw2 comes to his senses and stops 7041da177e4SLinus Torvalds symlinks from being an entirely gratuitous special 7051da177e4SLinus Torvalds case. */ 7061da177e4SLinus Torvalds if (!je32_to_cpu(latest_node->isize)) 7071da177e4SLinus Torvalds latest_node->isize = latest_node->dsize; 70832f1a95dSArtem B. Bityuckiy 70932f1a95dSArtem B. Bityuckiy if (f->inocache->state != INO_STATE_CHECKING) { 71032f1a95dSArtem B. Bityuckiy /* Symlink's inode data is the target path. Read it and 7112b79adccSArtem B. Bityutskiy * keep in RAM to facilitate quick follow symlink 7122b79adccSArtem B. Bityutskiy * operation. */ 7132b79adccSArtem B. Bityutskiy f->target = kmalloc(je32_to_cpu(latest_node->csize) + 1, GFP_KERNEL); 7142b79adccSArtem B. Bityutskiy if (!f->target) { 71532f1a95dSArtem B. Bityuckiy printk(KERN_WARNING "Can't allocate %d bytes of memory " 71632f1a95dSArtem B. Bityuckiy "for the symlink target path cache\n", 71732f1a95dSArtem B. Bityuckiy je32_to_cpu(latest_node->csize)); 71832f1a95dSArtem B. Bityuckiy up(&f->sem); 71932f1a95dSArtem B. Bityuckiy jffs2_do_clear_inode(c, f); 72032f1a95dSArtem B. Bityuckiy return -ENOMEM; 72132f1a95dSArtem B. Bityuckiy } 72232f1a95dSArtem B. Bityuckiy 72332f1a95dSArtem B. Bityuckiy ret = jffs2_flash_read(c, ref_offset(fn->raw) + sizeof(*latest_node), 7242b79adccSArtem B. Bityutskiy je32_to_cpu(latest_node->csize), &retlen, (char *)f->target); 72532f1a95dSArtem B. Bityuckiy 72632f1a95dSArtem B. Bityuckiy if (ret || retlen != je32_to_cpu(latest_node->csize)) { 72732f1a95dSArtem B. Bityuckiy if (retlen != je32_to_cpu(latest_node->csize)) 72832f1a95dSArtem B. Bityuckiy ret = -EIO; 7292b79adccSArtem B. Bityutskiy kfree(f->target); 7302b79adccSArtem B. Bityutskiy f->target = NULL; 73132f1a95dSArtem B. Bityuckiy up(&f->sem); 73232f1a95dSArtem B. Bityuckiy jffs2_do_clear_inode(c, f); 73332f1a95dSArtem B. Bityuckiy return -ret; 73432f1a95dSArtem B. Bityuckiy } 73532f1a95dSArtem B. Bityuckiy 7362b79adccSArtem B. Bityutskiy f->target[je32_to_cpu(latest_node->csize)] = '\0'; 73732f1a95dSArtem B. Bityuckiy D1(printk(KERN_DEBUG "jffs2_do_read_inode(): symlink's target '%s' cached\n", 7382b79adccSArtem B. Bityutskiy f->target)); 73932f1a95dSArtem B. Bityuckiy } 74032f1a95dSArtem B. Bityuckiy 7411da177e4SLinus Torvalds /* fall through... */ 7421da177e4SLinus Torvalds 7431da177e4SLinus Torvalds case S_IFBLK: 7441da177e4SLinus Torvalds case S_IFCHR: 7451da177e4SLinus Torvalds /* Certain inode types should have only one data node, and it's 7461da177e4SLinus Torvalds kept as the metadata node */ 7471da177e4SLinus Torvalds if (f->metadata) { 7481da177e4SLinus Torvalds printk(KERN_WARNING "Argh. Special inode #%u with mode 0%o had metadata node\n", 7491da177e4SLinus Torvalds f->inocache->ino, jemode_to_cpu(latest_node->mode)); 7501da177e4SLinus Torvalds up(&f->sem); 7511da177e4SLinus Torvalds jffs2_do_clear_inode(c, f); 7521da177e4SLinus Torvalds return -EIO; 7531da177e4SLinus Torvalds } 7541da177e4SLinus Torvalds if (!frag_first(&f->fragtree)) { 7551da177e4SLinus Torvalds printk(KERN_WARNING "Argh. Special inode #%u with mode 0%o has no fragments\n", 7561da177e4SLinus Torvalds f->inocache->ino, jemode_to_cpu(latest_node->mode)); 7571da177e4SLinus Torvalds up(&f->sem); 7581da177e4SLinus Torvalds jffs2_do_clear_inode(c, f); 7591da177e4SLinus Torvalds return -EIO; 7601da177e4SLinus Torvalds } 7611da177e4SLinus Torvalds /* ASSERT: f->fraglist != NULL */ 7621da177e4SLinus Torvalds if (frag_next(frag_first(&f->fragtree))) { 7631da177e4SLinus Torvalds printk(KERN_WARNING "Argh. Special inode #%u with mode 0x%x had more than one node\n", 7641da177e4SLinus Torvalds f->inocache->ino, jemode_to_cpu(latest_node->mode)); 7651da177e4SLinus Torvalds /* FIXME: Deal with it - check crc32, check for duplicate node, check times and discard the older one */ 7661da177e4SLinus Torvalds up(&f->sem); 7671da177e4SLinus Torvalds jffs2_do_clear_inode(c, f); 7681da177e4SLinus Torvalds return -EIO; 7691da177e4SLinus Torvalds } 7701da177e4SLinus Torvalds /* OK. We're happy */ 7711da177e4SLinus Torvalds f->metadata = frag_first(&f->fragtree)->node; 7721da177e4SLinus Torvalds jffs2_free_node_frag(frag_first(&f->fragtree)); 7731da177e4SLinus Torvalds f->fragtree = RB_ROOT; 7741da177e4SLinus Torvalds break; 7751da177e4SLinus Torvalds } 7761da177e4SLinus Torvalds if (f->inocache->state == INO_STATE_READING) 7771da177e4SLinus Torvalds jffs2_set_inocache_state(c, f->inocache, INO_STATE_PRESENT); 7781da177e4SLinus Torvalds 7791da177e4SLinus Torvalds return 0; 7801da177e4SLinus Torvalds } 7811da177e4SLinus Torvalds 782f97117d1SArtem B. Bityutskiy /* Scan the list of all nodes present for this ino, build map of versions, etc. */ 783f97117d1SArtem B. Bityutskiy int jffs2_do_read_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, 784f97117d1SArtem B. Bityutskiy uint32_t ino, struct jffs2_raw_inode *latest_node) 785f97117d1SArtem B. Bityutskiy { 786f97117d1SArtem B. Bityutskiy D2(printk(KERN_DEBUG "jffs2_do_read_inode(): getting inocache\n")); 787f97117d1SArtem B. Bityutskiy 788f97117d1SArtem B. Bityutskiy retry_inocache: 789f97117d1SArtem B. Bityutskiy spin_lock(&c->inocache_lock); 790f97117d1SArtem B. Bityutskiy f->inocache = jffs2_get_ino_cache(c, ino); 791f97117d1SArtem B. Bityutskiy 792f97117d1SArtem B. Bityutskiy D2(printk(KERN_DEBUG "jffs2_do_read_inode(): Got inocache at %p\n", f->inocache)); 793f97117d1SArtem B. Bityutskiy 794f97117d1SArtem B. Bityutskiy if (f->inocache) { 795f97117d1SArtem B. Bityutskiy /* Check its state. We may need to wait before we can use it */ 796f97117d1SArtem B. Bityutskiy switch(f->inocache->state) { 797f97117d1SArtem B. Bityutskiy case INO_STATE_UNCHECKED: 798f97117d1SArtem B. Bityutskiy case INO_STATE_CHECKEDABSENT: 799f97117d1SArtem B. Bityutskiy f->inocache->state = INO_STATE_READING; 800f97117d1SArtem B. Bityutskiy break; 801f97117d1SArtem B. Bityutskiy 802f97117d1SArtem B. Bityutskiy case INO_STATE_CHECKING: 803f97117d1SArtem B. Bityutskiy case INO_STATE_GC: 804f97117d1SArtem B. Bityutskiy /* If it's in either of these states, we need 805f97117d1SArtem B. Bityutskiy to wait for whoever's got it to finish and 806f97117d1SArtem B. Bityutskiy put it back. */ 807f97117d1SArtem B. Bityutskiy D1(printk(KERN_DEBUG "jffs2_get_ino_cache_read waiting for ino #%u in state %d\n", 808f97117d1SArtem B. Bityutskiy ino, f->inocache->state)); 809f97117d1SArtem B. Bityutskiy sleep_on_spinunlock(&c->inocache_wq, &c->inocache_lock); 810f97117d1SArtem B. Bityutskiy goto retry_inocache; 811f97117d1SArtem B. Bityutskiy 812f97117d1SArtem B. Bityutskiy case INO_STATE_READING: 813f97117d1SArtem B. Bityutskiy case INO_STATE_PRESENT: 814f97117d1SArtem B. Bityutskiy /* Eep. This should never happen. It can 815f97117d1SArtem B. Bityutskiy happen if Linux calls read_inode() again 816f97117d1SArtem B. Bityutskiy before clear_inode() has finished though. */ 817f97117d1SArtem B. Bityutskiy printk(KERN_WARNING "Eep. Trying to read_inode #%u when it's already in state %d!\n", ino, f->inocache->state); 818f97117d1SArtem B. Bityutskiy /* Fail. That's probably better than allowing it to succeed */ 819f97117d1SArtem B. Bityutskiy f->inocache = NULL; 820f97117d1SArtem B. Bityutskiy break; 821f97117d1SArtem B. Bityutskiy 822f97117d1SArtem B. Bityutskiy default: 823f97117d1SArtem B. Bityutskiy BUG(); 824f97117d1SArtem B. Bityutskiy } 825f97117d1SArtem B. Bityutskiy } 826f97117d1SArtem B. Bityutskiy spin_unlock(&c->inocache_lock); 827f97117d1SArtem B. Bityutskiy 828f97117d1SArtem B. Bityutskiy if (!f->inocache && ino == 1) { 829f97117d1SArtem B. Bityutskiy /* Special case - no root inode on medium */ 830f97117d1SArtem B. Bityutskiy f->inocache = jffs2_alloc_inode_cache(); 831f97117d1SArtem B. Bityutskiy if (!f->inocache) { 832f97117d1SArtem B. Bityutskiy printk(KERN_CRIT "jffs2_do_read_inode(): Cannot allocate inocache for root inode\n"); 833f97117d1SArtem B. Bityutskiy return -ENOMEM; 834f97117d1SArtem B. Bityutskiy } 835f97117d1SArtem B. Bityutskiy D1(printk(KERN_DEBUG "jffs2_do_read_inode(): Creating inocache for root inode\n")); 836f97117d1SArtem B. Bityutskiy memset(f->inocache, 0, sizeof(struct jffs2_inode_cache)); 837f97117d1SArtem B. Bityutskiy f->inocache->ino = f->inocache->nlink = 1; 838f97117d1SArtem B. Bityutskiy f->inocache->nodes = (struct jffs2_raw_node_ref *)f->inocache; 839f97117d1SArtem B. Bityutskiy f->inocache->state = INO_STATE_READING; 840f97117d1SArtem B. Bityutskiy jffs2_add_ino_cache(c, f->inocache); 841f97117d1SArtem B. Bityutskiy } 842f97117d1SArtem B. Bityutskiy if (!f->inocache) { 843f97117d1SArtem B. Bityutskiy printk(KERN_WARNING "jffs2_do_read_inode() on nonexistent ino %u\n", ino); 844f97117d1SArtem B. Bityutskiy return -ENOENT; 845f97117d1SArtem B. Bityutskiy } 846f97117d1SArtem B. Bityutskiy 847f97117d1SArtem B. Bityutskiy return jffs2_do_read_inode_internal(c, f, latest_node); 848f97117d1SArtem B. Bityutskiy } 849f97117d1SArtem B. Bityutskiy 850f97117d1SArtem B. Bityutskiy int jffs2_do_crccheck_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic) 851f97117d1SArtem B. Bityutskiy { 852f97117d1SArtem B. Bityutskiy struct jffs2_raw_inode n; 853f97117d1SArtem B. Bityutskiy struct jffs2_inode_info *f = kmalloc(sizeof(*f), GFP_KERNEL); 854f97117d1SArtem B. Bityutskiy int ret; 855f97117d1SArtem B. Bityutskiy 856f97117d1SArtem B. Bityutskiy if (!f) 857f97117d1SArtem B. Bityutskiy return -ENOMEM; 858f97117d1SArtem B. Bityutskiy 859f97117d1SArtem B. Bityutskiy memset(f, 0, sizeof(*f)); 860f97117d1SArtem B. Bityutskiy init_MUTEX_LOCKED(&f->sem); 861f97117d1SArtem B. Bityutskiy f->inocache = ic; 862f97117d1SArtem B. Bityutskiy 863f97117d1SArtem B. Bityutskiy ret = jffs2_do_read_inode_internal(c, f, &n); 864f97117d1SArtem B. Bityutskiy if (!ret) { 865f97117d1SArtem B. Bityutskiy up(&f->sem); 866f97117d1SArtem B. Bityutskiy jffs2_do_clear_inode(c, f); 867f97117d1SArtem B. Bityutskiy } 868f97117d1SArtem B. Bityutskiy kfree (f); 869f97117d1SArtem B. Bityutskiy return ret; 870f97117d1SArtem B. Bityutskiy } 871f97117d1SArtem B. Bityutskiy 8721da177e4SLinus Torvalds void jffs2_do_clear_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f) 8731da177e4SLinus Torvalds { 8741da177e4SLinus Torvalds struct jffs2_full_dirent *fd, *fds; 8751da177e4SLinus Torvalds int deleted; 8761da177e4SLinus Torvalds 8771da177e4SLinus Torvalds down(&f->sem); 8781da177e4SLinus Torvalds deleted = f->inocache && !f->inocache->nlink; 8791da177e4SLinus Torvalds 88067e345d1SDavid Woodhouse if (f->inocache && f->inocache->state != INO_STATE_CHECKING) 88167e345d1SDavid Woodhouse jffs2_set_inocache_state(c, f->inocache, INO_STATE_CLEARING); 88267e345d1SDavid Woodhouse 8831da177e4SLinus Torvalds if (f->metadata) { 8841da177e4SLinus Torvalds if (deleted) 8851da177e4SLinus Torvalds jffs2_mark_node_obsolete(c, f->metadata->raw); 8861da177e4SLinus Torvalds jffs2_free_full_dnode(f->metadata); 8871da177e4SLinus Torvalds } 8881da177e4SLinus Torvalds 8891da177e4SLinus Torvalds jffs2_kill_fragtree(&f->fragtree, deleted?c:NULL); 8901da177e4SLinus Torvalds 8912b79adccSArtem B. Bityutskiy if (f->target) { 8922b79adccSArtem B. Bityutskiy kfree(f->target); 8932b79adccSArtem B. Bityutskiy f->target = NULL; 89432f1a95dSArtem B. Bityuckiy } 8951da177e4SLinus Torvalds 8962b79adccSArtem B. Bityutskiy fds = f->dents; 8971da177e4SLinus Torvalds while(fds) { 8981da177e4SLinus Torvalds fd = fds; 8991da177e4SLinus Torvalds fds = fd->next; 9001da177e4SLinus Torvalds jffs2_free_full_dirent(fd); 9011da177e4SLinus Torvalds } 9021da177e4SLinus Torvalds 90367e345d1SDavid Woodhouse if (f->inocache && f->inocache->state != INO_STATE_CHECKING) { 9041da177e4SLinus Torvalds jffs2_set_inocache_state(c, f->inocache, INO_STATE_CHECKEDABSENT); 90567e345d1SDavid Woodhouse if (f->inocache->nodes == (void *)f->inocache) 90667e345d1SDavid Woodhouse jffs2_del_ino_cache(c, f->inocache); 90767e345d1SDavid Woodhouse } 9081da177e4SLinus Torvalds 9091da177e4SLinus Torvalds up(&f->sem); 9101da177e4SLinus Torvalds } 911