/ipc/

aging The LITMUS^RT kernel.Bjoern Brandenburg
aboutsummaryrefslogblamecommitdiffstats
path: root/fs/jffs2/readinode.c
blob: 2ab1a0d91210b4903a976cd58cae63f06ad58f6e (plain) (tree)
1
2
3
4
5
6
7
8
9


                                                     
                                       




                                                                       


                         
                        







                           
  



                                         
                                            











                                                                                    

                                                               
                        
 



                                                     
 








                                                                                                                                              







                                                                                                                                                                 

                                                              
                                           
                                                                                                                   
                                                             
































                                                                                                           
                                                  



                                                                                                      
                                                                 





























                                                                      
                                                  









































































                                                                                             
                                                                    
                                 
   




                                                                 
                                                
 
                                                                                                                                  






                                                                                      









                                                                                                      







                                                                           


                                                                               











                                                                            

                                                                                                                                            
















                                                                                                       
                                                                                 
                                                                                   
                                                       

                                                                               










                                                                    
                                                                                                             
                                                                                  









                                                                                            
                                                                         
                                 










                                                                                  
                                                                                    
                                                      
                                               
                              
                 


                                     
 
                                                              
                                                                
         

                                                              
                                                                 














                                                                                         
 












                                                                                             










                                                                            


















                                                                            
 































                                                                                 
                    
                                                 
         



                                                                            
 























                                                                                                          
                                                                              









                                                   








                                                                    












                                                                    
                                                                                    











                                                                                      
                                                                                              


























                                                                                                   
 
 

















                                                                             
                                               









                                                           
                        
 
 


                                                                     
 





                                           
 





                                                                                        
                                                                                         



                                       
 



                                                            
                         

                                           
                                                                                        

                                                                         

                                     
                     
 

                                                                   
 



                                                                                                         

                                                 
         
 








                                                                                                  

                                                         









                                                                     
                                                                            


                                                       


                                                    
 



                                               
 


                                                   
                                                      


                                                                      

         
          





                                                                          
 




                                                                              

                                                                   


                                                                                
 
                                    
                                                                               

                                                   

                 
 


                                                        
 

                                                                          
                                                               
           
                                               
 


                 



                                                  
                                                                      

                                           
                                                                                     

                                                                   
 
                                        
                            
                    
                     
 


                                                                   



                                                                                                 

                                                 

         

                                          
                                                                                 




                                       
 

                                                                          
 


                                                                                                          


                                                                                                        
                                      

                 


















                                                                                
                                                                 





















                                                                                

                                                             
                                                                                                                      


                                                                       
                                                                                                     

                                                                                                                      
                                                                 
                                              
                         
 








                                                                                      
                                                                 







                                                                             
                                                                         
                                                               
                 
         
 

                                          
                                                 

                              
         
 

                                               

                                                 
                          



                                                   
 

                                                             

                                                                              


                                                      


                                                                                       
 
                                               
 





                                              

                                                                           

                                     


                                                                         


                                 


                 



                                                    
                         

                                           
                                                                                                                      
 
                                                          



                                                                                         

                                                                               

                                                 
         
 
                                                                                    
 






















                                                                                 

                                                 
         
 
                 

 



                                                                             
                         


                                                                             
                                                                    
 
                                               



                                        
                                                     
 


                                                          


                                        
 
                                                       
 
                                                                        

                                                                 
                                                                 

                           
 
                               
                                                                        
                                                       


                            
                          


                 
                                                                           



                                                                             
                                                                                     
                                                                  
 
                                                   

                                     
                      
                     
 
                            
 
                                                     
 

                                                             
                                                                


                                       
 
                                             
                                                               

                                                                                      












                                                                                     


                                                                               

                                                                             
                   
                                            
                                                

                                     
                          




                                                                              
                           




                                                              

                 
                                                                                                     
 
                                    
                                                                              
                          


                                                                                                                          
 
                                   
                                                                                                               
                                   

                                      
 
                                                     
 










                                                                                                



                                                                                             


                                                         
 
                                                        
 
                                           
 

                                                                                      
                                                                                                    


                                                      
 

                                                                           
                                              
 

                              
                                          
 

                                                                                     
                                                                                                   

                                                      
                         
 

                                                                     
                                              
 
                              
 
                        

                                                                                        
                                                                                                      

                                                      
                         
 
                                                             
                                          


                                              
             
                                                     
         
 
                                               
                   
 

                                                  
                                                                                                                    

                                                                                 


                 


                                                      
                   
                   

 
                                                                


                                                                            
                                        
                               


                      

                                                                     
 

                                     
                                                 
                                                

                  
                                                                                                           



                                                                                          
 














                                                                                          
 





                                                                
                 
                                    
         
 


                                                    
 
                                        

                                                   
                                                                                             
                                       



                                                                                                          
                                                                                           











                                                                                              
                                                                                                                  
                                                    

                                                                                           
                                                                                     
                                      





                                                            
                                                                                                
                                                                      
                                      





                                                           
                                                                         

                                                                               
                                                                                                 


                      
 

                                                                                      





                                                                                                                            








                                                                        


                                                                               



                                                                                             
                                                                                                                                                      
                                                      


                                                           
 
                                                                                                    
                                                                                                             
 


                                                                                

                                                 
                                                      
                                                           
                                           

                         
                                                                          
                                                                                   
                 
 






                                                                               
                                                                                                
                                                                                   
                                              



                                                   
                                                                                               
                                                                                   
                                              




                                                          
                                                                                                      

                                                                                                                                
                                              














                                                                            
                                                                                  
                                                                            

                                                                          
                                               




                                                  






                                                                               
 




                                                                     
                                                                                                    







                                                                                
                                                                                                                               













                                                                                      
                                                                                 

                                       
                                                                    
                                                                         
                                                               




                                                                              
                                                                               








                                                                                  
                                                                     




                               

                            



                                                     
                                      





                                           




                                                                              
                                                 
                            
                                                          
 


                                                                             







                                                                      



                                 
 




                                           

         
                                                                      
                                                                                  


                                                              
 
                              
 
/*
 * JFFS2 -- Journalling Flash File System, Version 2.
 *
 * Copyright © 2001-2007 Red Hat, Inc.
 *
 * Created by David Woodhouse <dwmw2@infradead.org>
 *
 * For licensing information, see the file 'LICENCE' in this directory.
 *
 */

#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/fs.h>
#include <linux/crc32.h>
#include <linux/pagemap.h>
#include <linux/mtd/mtd.h>
#include <linux/compiler.h>
#include "nodelist.h"

/*
 * Check the data CRC of the node.
 *
 * Returns: 0 if the data CRC is correct;
 * 	    1 - if incorrect;
 *	    error code if an error occurred.
 */
static int check_node_data(struct jffs2_sb_info *c, struct jffs2_tmp_dnode_info *tn)
{
	struct jffs2_raw_node_ref *ref = tn->fn->raw;
	int err = 0, pointed = 0;
	struct jffs2_eraseblock *jeb;
	unsigned char *buffer;
	uint32_t crc, ofs, len;
	size_t retlen;

	BUG_ON(tn->csize == 0);

	/* Calculate how many bytes were already checked */
	ofs = ref_offset(ref) + sizeof(struct jffs2_raw_inode);
	len = tn->csize;

	if (jffs2_is_writebuffered(c)) {
		int adj = ofs % c->wbuf_pagesize;
		if (likely(adj))
			adj = c->wbuf_pagesize - adj;

		if (adj >= tn->csize) {
			dbg_readinode("no need to check node at %#08x, data length %u, data starts at %#08x - it has already been checked.\n",
				      ref_offset(ref), tn->csize, ofs);
			goto adj_acc;
		}

		ofs += adj;
		len -= adj;
	}

	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",
		ref_offset(ref), tn->csize, tn->partial_crc, tn->data_crc, ofs - len, ofs, len);

#ifndef __ECOS
	/* TODO: instead, incapsulate point() stuff to jffs2_flash_read(),
	 * adding and jffs2_flash_read_end() interface. */
	if (c->mtd->point) {
		err = c->mtd->point(c->mtd, ofs, len, &retlen,
				    (void **)&buffer, NULL);
		if (!err && retlen < len) {
			JFFS2_WARNING("MTD point returned len too short: %zu instead of %u.\n", retlen, tn->csize);
			c->mtd->unpoint(c->mtd, ofs, retlen);
		} else if (err)
			JFFS2_WARNING("MTD point failed: error code %d.\n", err);
		else
			pointed = 1; /* succefully pointed to device */
	}
#endif

	if (!pointed) {
		buffer = kmalloc(len, GFP_KERNEL);
		if (unlikely(!buffer))
			return -ENOMEM;

		/* TODO: this is very frequent pattern, make it a separate
		 * routine */
		err = jffs2_flash_read(c, ofs, len, &retlen, buffer);
		if (err) {
			JFFS2_ERROR("can not read %d bytes from 0x%08x, error code: %d.\n", len, ofs, err);
			goto free_out;
		}

		if (retlen != len) {
			JFFS2_ERROR("short read at %#08x: %zd instead of %d.\n", ofs, retlen, len);
			err = -EIO;
			goto free_out;
		}
	}

	/* Continue calculating CRC */
	crc = crc32(tn->partial_crc, buffer, len);
	if(!pointed)
		kfree(buffer);
#ifndef __ECOS
	else
		c->mtd->unpoint(c->mtd, ofs, len);
#endif

	if (crc != tn->data_crc) {
		JFFS2_NOTICE("wrong data CRC in data node at 0x%08x: read %#08x, calculated %#08x.\n",
			     ref_offset(ref), tn->data_crc, crc);
		return 1;
	}

adj_acc:
	jeb = &c->blocks[ref->flash_offset / c->sector_size];
	len = ref_totlen(c, jeb, ref);
	/* If it should be REF_NORMAL, it'll get marked as such when
	   we build the fragtree, shortly. No need to worry about GC
	   moving it while it's marked REF_PRISTINE -- GC won't happen
	   till we've finished checking every inode anyway. */
	ref->flash_offset |= REF_PRISTINE;
	/*
	 * Mark the node as having been checked and fix the
	 * accounting accordingly.
	 */
	spin_lock(&c->erase_completion_lock);
	jeb->used_size += len;
	jeb->unchecked_size -= len;
	c->used_size += len;
	c->unchecked_size -= len;
	jffs2_dbg_acct_paranoia_check_nolock(c, jeb);
	spin_unlock(&c->erase_completion_lock);

	return 0;

free_out:
	if(!pointed)
		kfree(buffer);
#ifndef __ECOS
	else
		c->mtd->unpoint(c->mtd, ofs, len);
#endif
	return err;
}

/*
 * Helper function for jffs2_add_older_frag_to_fragtree().
 *
 * Checks the node if we are in the checking stage.
 */
static int check_tn_node(struct jffs2_sb_info *c, struct jffs2_tmp_dnode_info *tn)
{
	int ret;

	BUG_ON(ref_obsolete(tn->fn->raw));

	/* We only check the data CRC of unchecked nodes */
	if (ref_flags(tn->fn->raw) != REF_UNCHECKED)
		return 0;

	dbg_readinode("check node %#04x-%#04x, phys offs %#08x\n",
		      tn->fn->ofs, tn->fn->ofs + tn->fn->size, ref_offset(tn->fn->raw));

	ret = check_node_data(c, tn);
	if (unlikely(ret < 0)) {
		JFFS2_ERROR("check_node_data() returned error: %d.\n",
			ret);
	} else if (unlikely(ret > 0)) {
		dbg_readinode("CRC error, mark it obsolete.\n");
		jffs2_mark_node_obsolete(c, tn->fn->raw);
	}

	return ret;
}

static struct jffs2_tmp_dnode_info *jffs2_lookup_tn(struct rb_root *tn_root, uint32_t offset)
{
	struct rb_node *next;
	struct jffs2_tmp_dnode_info *tn = NULL;

	dbg_readinode("root %p, offset %d\n", tn_root, offset);

	next = tn_root->rb_node;

	while (next) {
		tn = rb_entry(next, struct jffs2_tmp_dnode_info, rb);

		if (tn->fn->ofs < offset)
			next = tn->rb.rb_right;
		else if (tn->fn->ofs >= offset)
			next = tn->rb.rb_left;
		else
			break;
	}

	return tn;
}


static void jffs2_kill_tn(struct jffs2_sb_info *c, struct jffs2_tmp_dnode_info *tn)
{
	jffs2_mark_node_obsolete(c, tn->fn->raw);
	jffs2_free_full_dnode(tn->fn);
	jffs2_free_tmp_dnode_info(tn);
}
/*
 * This function is used when we read an inode. Data nodes arrive in
 * arbitrary order -- they may be older or newer than the nodes which
 * are already in the tree. Where overlaps occur, the older node can
 * be discarded as long as the newer passes the CRC check. We don't
 * bother to keep track of holes in this rbtree, and neither do we deal
 * with frags -- we can have multiple entries starting at the same
 * offset, and the one with the smallest length will come first in the
 * ordering.
 *
 * Returns 0 if the node was handled (including marking it obsolete)
 *	 < 0 an if error occurred
 */
static int jffs2_add_tn_to_tree(struct jffs2_sb_info *c,
				struct jffs2_readinode_info *rii,
				struct jffs2_tmp_dnode_info *tn)
{
	uint32_t fn_end = tn->fn->ofs + tn->fn->size;
	struct jffs2_tmp_dnode_info *this, *ptn;