2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								/*
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  JFFS2  - -  Journalling  Flash  File  System ,  Version  2. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
									
										
										
										
											2007-04-25 14:16:47 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  Copyright  ©  2001 - 2007  Red  Hat ,  Inc . 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Created  by  David  Woodhouse  < dwmw2 @ infradead . org > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  For  licensing  information ,  see  the  file  ' LICENCE '  in  this  directory . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
									
										
										
										
											2012-02-15 15:56:45 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 
  
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <linux/kernel.h> 
  
						 
					
						
							
								
									
										
										
										
											2005-07-30 16:29:30 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# include  <linux/sched.h> 
  
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								# 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" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-08-01 13:05:22 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*
  
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] Improve read_inode memory usage, v2.
We originally used to read every node and allocate a jffs2_tmp_dnode_info
structure for each, before processing them in (reverse) version order
and discarding the ones which are obsoleted by later nodes.
With huge logfiles, this behaviour caused memory problems. For example, a
file involved in OLPC trac #1292 has 1822391 nodes, and would cause the XO
machine to run out of memory during the first stage of read_inode().
Instead of just inserting nodes into a tree in version order as we find
them, we now put them into a tree in order of their offset within the
file, which allows us to immediately discard nodes which are completely
obsoleted.
We don't use a full tree with 'fragments' pointing to the real data
structure, as we do in the normal fragtree. We sort only on the start
address, and add an 'overlapped' flag to the tmp_dnode_info to indicate
that the node in question is (partially) overlapped by another.
When the scan is complete, we start at the end of the file, adding each
node to a real fragtree as before. Where the node is non-overlapped, we
just add it (it doesn't matter that it's not the latest version; there is
no overlap). When the node at the end of the tree _is_ overlapped, we sort
it and all its overlapping nodes into version order and then add them to
the fragtree in that order.
This 'early discard' reduces the peak allocation of tmp_dnode_info
structures from 1.8M to a mere 62872 (3.5%) in the degenerate case
referenced above.
This version of the patch also correctly rememembers the highest node
version# seen for an inode when it's scanned.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-25 03:23:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  Check  the  data  CRC  of  the  node . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Returns :  0  if  the  data  CRC  is  correct ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  	    1  -  if  incorrect ; 
							 
						 
					
						
							
								
									
										
										
										
											2011-03-30 22:57:33 -03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 * 	    error  code  if  an  error  occurred . 
							 
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] Improve read_inode memory usage, v2.
We originally used to read every node and allocate a jffs2_tmp_dnode_info
structure for each, before processing them in (reverse) version order
and discarding the ones which are obsoleted by later nodes.
With huge logfiles, this behaviour caused memory problems. For example, a
file involved in OLPC trac #1292 has 1822391 nodes, and would cause the XO
machine to run out of memory during the first stage of read_inode().
Instead of just inserting nodes into a tree in version order as we find
them, we now put them into a tree in order of their offset within the
file, which allows us to immediately discard nodes which are completely
obsoleted.
We don't use a full tree with 'fragments' pointing to the real data
structure, as we do in the normal fragtree. We sort only on the start
address, and add an 'overlapped' flag to the tmp_dnode_info to indicate
that the node in question is (partially) overlapped by another.
When the scan is complete, we start at the end of the file, adding each
node to a real fragtree as before. Where the node is non-overlapped, we
just add it (it doesn't matter that it's not the latest version; there is
no overlap). When the node at the end of the tree _is_ overlapped, we sort
it and all its overlapping nodes into version order and then add them to
the fragtree in that order.
This 'early discard' reduces the peak allocation of tmp_dnode_info
structures from 1.8M to a mere 62872 (3.5%) in the degenerate case
referenced above.
This version of the patch also correctly rememembers the highest node
version# seen for an inode when it's scanned.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-25 03:23:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								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 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2007-11-21 12:08:16 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									len  =  tn - > csize ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] Improve read_inode memory usage, v2.
We originally used to read every node and allocate a jffs2_tmp_dnode_info
structure for each, before processing them in (reverse) version order
and discarding the ones which are obsoleted by later nodes.
With huge logfiles, this behaviour caused memory problems. For example, a
file involved in OLPC trac #1292 has 1822391 nodes, and would cause the XO
machine to run out of memory during the first stage of read_inode().
Instead of just inserting nodes into a tree in version order as we find
them, we now put them into a tree in order of their offset within the
file, which allows us to immediately discard nodes which are completely
obsoleted.
We don't use a full tree with 'fragments' pointing to the real data
structure, as we do in the normal fragtree. We sort only on the start
address, and add an 'overlapped' flag to the tmp_dnode_info to indicate
that the node in question is (partially) overlapped by another.
When the scan is complete, we start at the end of the file, adding each
node to a real fragtree as before. Where the node is non-overlapped, we
just add it (it doesn't matter that it's not the latest version; there is
no overlap). When the node at the end of the tree _is_ overlapped, we sort
it and all its overlapping nodes into version order and then add them to
the fragtree in that order.
This 'early discard' reduces the peak allocation of tmp_dnode_info
structures from 1.8M to a mere 62872 (3.5%) in the degenerate case
referenced above.
This version of the patch also correctly rememembers the highest node
version# seen for an inode when it's scanned.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-25 03:23:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2007-11-21 12:08:16 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( jffs2_is_writebuffered ( c ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										int  adj  =  ofs  %  c - > wbuf_pagesize ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( likely ( adj ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											adj  =  c - > wbuf_pagesize  -  adj ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] Improve read_inode memory usage, v2.
We originally used to read every node and allocate a jffs2_tmp_dnode_info
structure for each, before processing them in (reverse) version order
and discarding the ones which are obsoleted by later nodes.
With huge logfiles, this behaviour caused memory problems. For example, a
file involved in OLPC trac #1292 has 1822391 nodes, and would cause the XO
machine to run out of memory during the first stage of read_inode().
Instead of just inserting nodes into a tree in version order as we find
them, we now put them into a tree in order of their offset within the
file, which allows us to immediately discard nodes which are completely
obsoleted.
We don't use a full tree with 'fragments' pointing to the real data
structure, as we do in the normal fragtree. We sort only on the start
address, and add an 'overlapped' flag to the tmp_dnode_info to indicate
that the node in question is (partially) overlapped by another.
When the scan is complete, we start at the end of the file, adding each
node to a real fragtree as before. Where the node is non-overlapped, we
just add it (it doesn't matter that it's not the latest version; there is
no overlap). When the node at the end of the tree _is_ overlapped, we sort
it and all its overlapping nodes into version order and then add them to
the fragtree in that order.
This 'early discard' reduces the peak allocation of tmp_dnode_info
structures from 1.8M to a mere 62872 (3.5%) in the degenerate case
referenced above.
This version of the patch also correctly rememembers the highest node
version# seen for an inode when it's scanned.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-25 03:23:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2007-11-21 12:08:16 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										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 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] Improve read_inode memory usage, v2.
We originally used to read every node and allocate a jffs2_tmp_dnode_info
structure for each, before processing them in (reverse) version order
and discarding the ones which are obsoleted by later nodes.
With huge logfiles, this behaviour caused memory problems. For example, a
file involved in OLPC trac #1292 has 1822391 nodes, and would cause the XO
machine to run out of memory during the first stage of read_inode().
Instead of just inserting nodes into a tree in version order as we find
them, we now put them into a tree in order of their offset within the
file, which allows us to immediately discard nodes which are completely
obsoleted.
We don't use a full tree with 'fragments' pointing to the real data
structure, as we do in the normal fragtree. We sort only on the start
address, and add an 'overlapped' flag to the tmp_dnode_info to indicate
that the node in question is (partially) overlapped by another.
When the scan is complete, we start at the end of the file, adding each
node to a real fragtree as before. Where the node is non-overlapped, we
just add it (it doesn't matter that it's not the latest version; there is
no overlap). When the node at the end of the tree _is_ overlapped, we sort
it and all its overlapping nodes into version order and then add them to
the fragtree in that order.
This 'early discard' reduces the peak allocation of tmp_dnode_info
structures from 1.8M to a mere 62872 (3.5%) in the degenerate case
referenced above.
This version of the patch also correctly rememembers the highest node
version# seen for an inode when it's scanned.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-25 03:23:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									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 .  */ 
							 
						 
					
						
							
								
									
										
										
										
											2011-12-28 15:55:42 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									err  =  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 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										mtd_unpoint ( c - > mtd ,  ofs ,  retlen ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  else  if  ( err )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( err  ! =  - EOPNOTSUPP ) 
							 
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] Improve read_inode memory usage, v2.
We originally used to read every node and allocate a jffs2_tmp_dnode_info
structure for each, before processing them in (reverse) version order
and discarding the ones which are obsoleted by later nodes.
With huge logfiles, this behaviour caused memory problems. For example, a
file involved in OLPC trac #1292 has 1822391 nodes, and would cause the XO
machine to run out of memory during the first stage of read_inode().
Instead of just inserting nodes into a tree in version order as we find
them, we now put them into a tree in order of their offset within the
file, which allows us to immediately discard nodes which are completely
obsoleted.
We don't use a full tree with 'fragments' pointing to the real data
structure, as we do in the normal fragtree. We sort only on the start
address, and add an 'overlapped' flag to the tmp_dnode_info to indicate
that the node in question is (partially) overlapped by another.
When the scan is complete, we start at the end of the file, adding each
node to a real fragtree as before. Where the node is non-overlapped, we
just add it (it doesn't matter that it's not the latest version; there is
no overlap). When the node at the end of the tree _is_ overlapped, we sort
it and all its overlapping nodes into version order and then add them to
the fragtree in that order.
This 'early discard' reduces the peak allocation of tmp_dnode_info
structures from 1.8M to a mere 62872 (3.5%) in the degenerate case
referenced above.
This version of the patch also correctly rememembers the highest node
version# seen for an inode when it's scanned.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-25 03:23:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											JFFS2_WARNING ( " MTD point failed: error code %d. \n " ,  err ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2011-12-28 15:55:42 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									}  else 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										pointed  =  1 ;  /* succefully pointed to device */ 
							 
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] Improve read_inode memory usage, v2.
We originally used to read every node and allocate a jffs2_tmp_dnode_info
structure for each, before processing them in (reverse) version order
and discarding the ones which are obsoleted by later nodes.
With huge logfiles, this behaviour caused memory problems. For example, a
file involved in OLPC trac #1292 has 1822391 nodes, and would cause the XO
machine to run out of memory during the first stage of read_inode().
Instead of just inserting nodes into a tree in version order as we find
them, we now put them into a tree in order of their offset within the
file, which allows us to immediately discard nodes which are completely
obsoleted.
We don't use a full tree with 'fragments' pointing to the real data
structure, as we do in the normal fragtree. We sort only on the start
address, and add an 'overlapped' flag to the tmp_dnode_info to indicate
that the node in question is (partially) overlapped by another.
When the scan is complete, we start at the end of the file, adding each
node to a real fragtree as before. Where the node is non-overlapped, we
just add it (it doesn't matter that it's not the latest version; there is
no overlap). When the node at the end of the tree _is_ overlapped, we sort
it and all its overlapping nodes into version order and then add them to
the fragtree in that order.
This 'early discard' reduces the peak allocation of tmp_dnode_info
structures from 1.8M to a mere 62872 (3.5%) in the degenerate case
referenced above.
This version of the patch also correctly rememembers the highest node
version# seen for an inode when it's scanned.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-25 03:23:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# 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 
							 
						 
					
						
							
								
									
										
										
										
											2011-12-23 17:05:52 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										mtd_unpoint ( c - > mtd ,  ofs ,  len ) ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] Improve read_inode memory usage, v2.
We originally used to read every node and allocate a jffs2_tmp_dnode_info
structure for each, before processing them in (reverse) version order
and discarding the ones which are obsoleted by later nodes.
With huge logfiles, this behaviour caused memory problems. For example, a
file involved in OLPC trac #1292 has 1822391 nodes, and would cause the XO
machine to run out of memory during the first stage of read_inode().
Instead of just inserting nodes into a tree in version order as we find
them, we now put them into a tree in order of their offset within the
file, which allows us to immediately discard nodes which are completely
obsoleted.
We don't use a full tree with 'fragments' pointing to the real data
structure, as we do in the normal fragtree. We sort only on the start
address, and add an 'overlapped' flag to the tmp_dnode_info to indicate
that the node in question is (partially) overlapped by another.
When the scan is complete, we start at the end of the file, adding each
node to a real fragtree as before. Where the node is non-overlapped, we
just add it (it doesn't matter that it's not the latest version; there is
no overlap). When the node at the end of the tree _is_ overlapped, we sort
it and all its overlapping nodes into version order and then add them to
the fragtree in that order.
This 'early discard' reduces the peak allocation of tmp_dnode_info
structures from 1.8M to a mere 62872 (3.5%) in the degenerate case
referenced above.
This version of the patch also correctly rememembers the highest node
version# seen for an inode when it's scanned.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-25 03:23:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( crc  ! =  tn - > data_crc )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										JFFS2_NOTICE ( " wrong data CRC in data node at 0x%08x: read %#08x, calculated %#08x. \n " , 
							 
						 
					
						
							
								
									
										
										
										
											2007-07-05 01:57:26 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											     ref_offset ( ref ) ,  tn - > data_crc ,  crc ) ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] Improve read_inode memory usage, v2.
We originally used to read every node and allocate a jffs2_tmp_dnode_info
structure for each, before processing them in (reverse) version order
and discarding the ones which are obsoleted by later nodes.
With huge logfiles, this behaviour caused memory problems. For example, a
file involved in OLPC trac #1292 has 1822391 nodes, and would cause the XO
machine to run out of memory during the first stage of read_inode().
Instead of just inserting nodes into a tree in version order as we find
them, we now put them into a tree in order of their offset within the
file, which allows us to immediately discard nodes which are completely
obsoleted.
We don't use a full tree with 'fragments' pointing to the real data
structure, as we do in the normal fragtree. We sort only on the start
address, and add an 'overlapped' flag to the tmp_dnode_info to indicate
that the node in question is (partially) overlapped by another.
When the scan is complete, we start at the end of the file, adding each
node to a real fragtree as before. Where the node is non-overlapped, we
just add it (it doesn't matter that it's not the latest version; there is
no overlap). When the node at the end of the tree _is_ overlapped, we sort
it and all its overlapping nodes into version order and then add them to
the fragtree in that order.
This 'early discard' reduces the peak allocation of tmp_dnode_info
structures from 1.8M to a mere 62872 (3.5%) in the degenerate case
referenced above.
This version of the patch also correctly rememembers the highest node
version# seen for an inode when it's scanned.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-25 03:23:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										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 
							 
						 
					
						
							
								
									
										
										
										
											2011-12-23 17:05:52 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										mtd_unpoint ( c - > mtd ,  ofs ,  len ) ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] Improve read_inode memory usage, v2.
We originally used to read every node and allocate a jffs2_tmp_dnode_info
structure for each, before processing them in (reverse) version order
and discarding the ones which are obsoleted by later nodes.
With huge logfiles, this behaviour caused memory problems. For example, a
file involved in OLPC trac #1292 has 1822391 nodes, and would cause the XO
machine to run out of memory during the first stage of read_inode().
Instead of just inserting nodes into a tree in version order as we find
them, we now put them into a tree in order of their offset within the
file, which allows us to immediately discard nodes which are completely
obsoleted.
We don't use a full tree with 'fragments' pointing to the real data
structure, as we do in the normal fragtree. We sort only on the start
address, and add an 'overlapped' flag to the tmp_dnode_info to indicate
that the node in question is (partially) overlapped by another.
When the scan is complete, we start at the end of the file, adding each
node to a real fragtree as before. Where the node is non-overlapped, we
just add it (it doesn't matter that it's not the latest version; there is
no overlap). When the node at the end of the tree _is_ overlapped, we sort
it and all its overlapping nodes into version order and then add them to
the fragtree in that order.
This 'early discard' reduces the peak allocation of tmp_dnode_info
structures from 1.8M to a mere 62872 (3.5%) in the degenerate case
referenced above.
This version of the patch also correctly rememembers the highest node
version# seen for an inode when it's scanned.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-25 03:23:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# 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 . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
									
										
										
										
											2007-07-03 16:51:19 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  Returns  0  if  the  node  was  handled  ( including  marking  it  obsolete ) 
							 
						 
					
						
							
								
									
										
										
										
											2007-07-10 10:01:22 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 * 	 <  0  an  if  error  occurred 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] Improve read_inode memory usage, v2.
We originally used to read every node and allocate a jffs2_tmp_dnode_info
structure for each, before processing them in (reverse) version order
and discarding the ones which are obsoleted by later nodes.
With huge logfiles, this behaviour caused memory problems. For example, a
file involved in OLPC trac #1292 has 1822391 nodes, and would cause the XO
machine to run out of memory during the first stage of read_inode().
Instead of just inserting nodes into a tree in version order as we find
them, we now put them into a tree in order of their offset within the
file, which allows us to immediately discard nodes which are completely
obsoleted.
We don't use a full tree with 'fragments' pointing to the real data
structure, as we do in the normal fragtree. We sort only on the start
address, and add an 'overlapped' flag to the tmp_dnode_info to indicate
that the node in question is (partially) overlapped by another.
When the scan is complete, we start at the end of the file, adding each
node to a real fragtree as before. Where the node is non-overlapped, we
just add it (it doesn't matter that it's not the latest version; there is
no overlap). When the node at the end of the tree _is_ overlapped, we sort
it and all its overlapping nodes into version order and then add them to
the fragtree in that order.
This 'early discard' reduces the peak allocation of tmp_dnode_info
structures from 1.8M to a mere 62872 (3.5%) in the degenerate case
referenced above.
This version of the patch also correctly rememembers the highest node
version# seen for an inode when it's scanned.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-25 03:23:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								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 ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-02-16 21:29:31 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  jffs2_tmp_dnode_info  * this ,  * ptn ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] Improve read_inode memory usage, v2.
We originally used to read every node and allocate a jffs2_tmp_dnode_info
structure for each, before processing them in (reverse) version order
and discarding the ones which are obsoleted by later nodes.
With huge logfiles, this behaviour caused memory problems. For example, a
file involved in OLPC trac #1292 has 1822391 nodes, and would cause the XO
machine to run out of memory during the first stage of read_inode().
Instead of just inserting nodes into a tree in version order as we find
them, we now put them into a tree in order of their offset within the
file, which allows us to immediately discard nodes which are completely
obsoleted.
We don't use a full tree with 'fragments' pointing to the real data
structure, as we do in the normal fragtree. We sort only on the start
address, and add an 'overlapped' flag to the tmp_dnode_info to indicate
that the node in question is (partially) overlapped by another.
When the scan is complete, we start at the end of the file, adding each
node to a real fragtree as before. Where the node is non-overlapped, we
just add it (it doesn't matter that it's not the latest version; there is
no overlap). When the node at the end of the tree _is_ overlapped, we sort
it and all its overlapping nodes into version order and then add them to
the fragtree in that order.
This 'early discard' reduces the peak allocation of tmp_dnode_info
structures from 1.8M to a mere 62872 (3.5%) in the degenerate case
referenced above.
This version of the patch also correctly rememembers the highest node
version# seen for an inode when it's scanned.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-25 03:23:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2007-05-07 13:16:13 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									dbg_readinode ( " insert fragment %#04x-%#04x, ver %u at %08x \n " ,  tn - > fn - > ofs ,  fn_end ,  tn - > version ,  ref_offset ( tn - > fn - > raw ) ) ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] Improve read_inode memory usage, v2.
We originally used to read every node and allocate a jffs2_tmp_dnode_info
structure for each, before processing them in (reverse) version order
and discarding the ones which are obsoleted by later nodes.
With huge logfiles, this behaviour caused memory problems. For example, a
file involved in OLPC trac #1292 has 1822391 nodes, and would cause the XO
machine to run out of memory during the first stage of read_inode().
Instead of just inserting nodes into a tree in version order as we find
them, we now put them into a tree in order of their offset within the
file, which allows us to immediately discard nodes which are completely
obsoleted.
We don't use a full tree with 'fragments' pointing to the real data
structure, as we do in the normal fragtree. We sort only on the start
address, and add an 'overlapped' flag to the tmp_dnode_info to indicate
that the node in question is (partially) overlapped by another.
When the scan is complete, we start at the end of the file, adding each
node to a real fragtree as before. Where the node is non-overlapped, we
just add it (it doesn't matter that it's not the latest version; there is
no overlap). When the node at the end of the tree _is_ overlapped, we sort
it and all its overlapping nodes into version order and then add them to
the fragtree in that order.
This 'early discard' reduces the peak allocation of tmp_dnode_info
structures from 1.8M to a mere 62872 (3.5%) in the degenerate case
referenced above.
This version of the patch also correctly rememembers the highest node
version# seen for an inode when it's scanned.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-25 03:23:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* If a node has zero dsize, we only have to keep if it if it might be the
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									   node  with  highest  version  - -  i . e .  the  one  which  will  end  up  as  f - > metadata . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									   Note  that  such  nodes  won ' t  be  REF_UNCHECKED  since  there  are  no  data  to 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									   check  anyway .  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! tn - > fn - > size )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( rii - > mdata_tn )  { 
							 
						 
					
						
							
								
									
										
										
										
											2007-06-01 20:04:43 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											if  ( rii - > mdata_tn - > version  <  tn - > version )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												/* We had a candidate mdata node already */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												dbg_readinode ( " kill old mdata with ver %d \n " ,  rii - > mdata_tn - > version ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												jffs2_kill_tn ( c ,  rii - > mdata_tn ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												dbg_readinode ( " kill new mdata with ver %d (older than existing %d \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													      tn - > version ,  rii - > mdata_tn - > version ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												jffs2_kill_tn ( c ,  tn ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] Improve read_inode memory usage, v2.
We originally used to read every node and allocate a jffs2_tmp_dnode_info
structure for each, before processing them in (reverse) version order
and discarding the ones which are obsoleted by later nodes.
With huge logfiles, this behaviour caused memory problems. For example, a
file involved in OLPC trac #1292 has 1822391 nodes, and would cause the XO
machine to run out of memory during the first stage of read_inode().
Instead of just inserting nodes into a tree in version order as we find
them, we now put them into a tree in order of their offset within the
file, which allows us to immediately discard nodes which are completely
obsoleted.
We don't use a full tree with 'fragments' pointing to the real data
structure, as we do in the normal fragtree. We sort only on the start
address, and add an 'overlapped' flag to the tmp_dnode_info to indicate
that the node in question is (partially) overlapped by another.
When the scan is complete, we start at the end of the file, adding each
node to a real fragtree as before. Where the node is non-overlapped, we
just add it (it doesn't matter that it's not the latest version; there is
no overlap). When the node at the end of the tree _is_ overlapped, we sort
it and all its overlapping nodes into version order and then add them to
the fragtree in that order.
This 'early discard' reduces the peak allocation of tmp_dnode_info
structures from 1.8M to a mere 62872 (3.5%) in the degenerate case
referenced above.
This version of the patch also correctly rememembers the highest node
version# seen for an inode when it's scanned.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-25 03:23:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										rii - > mdata_tn  =  tn ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										dbg_readinode ( " keep new mdata with ver %d \n " ,  tn - > version ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Find the earliest node which _may_ be relevant to this one */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									this  =  jffs2_lookup_tn ( & rii - > tn_root ,  tn - > fn - > ofs ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2007-05-08 00:19:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( this )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* If the node is coincident with another at a lower address,
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										   back  up  until  the  other  node  is  found .  It  may  be  relevant  */ 
							 
						 
					
						
							
								
									
										
										
										
											2009-02-16 21:29:31 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										while  ( this - > overlapped )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ptn  =  tn_prev ( this ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( ! ptn )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												/*
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												 *  We  killed  a  node  which  set  the  overlapped 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												 *  flags  during  the  scan .  Fix  it  up . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												this - > overlapped  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											this  =  ptn ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2007-05-08 00:19:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										dbg_readinode ( " 'this' found %#04x-%#04x (%s) \n " ,  this - > fn - > ofs ,  this - > fn - > ofs  +  this - > fn - > size ,  this - > fn  ?  " data "  :  " hole " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] Improve read_inode memory usage, v2.
We originally used to read every node and allocate a jffs2_tmp_dnode_info
structure for each, before processing them in (reverse) version order
and discarding the ones which are obsoleted by later nodes.
With huge logfiles, this behaviour caused memory problems. For example, a
file involved in OLPC trac #1292 has 1822391 nodes, and would cause the XO
machine to run out of memory during the first stage of read_inode().
Instead of just inserting nodes into a tree in version order as we find
them, we now put them into a tree in order of their offset within the
file, which allows us to immediately discard nodes which are completely
obsoleted.
We don't use a full tree with 'fragments' pointing to the real data
structure, as we do in the normal fragtree. We sort only on the start
address, and add an 'overlapped' flag to the tmp_dnode_info to indicate
that the node in question is (partially) overlapped by another.
When the scan is complete, we start at the end of the file, adding each
node to a real fragtree as before. Where the node is non-overlapped, we
just add it (it doesn't matter that it's not the latest version; there is
no overlap). When the node at the end of the tree _is_ overlapped, we sort
it and all its overlapping nodes into version order and then add them to
the fragtree in that order.
This 'early discard' reduces the peak allocation of tmp_dnode_info
structures from 1.8M to a mere 62872 (3.5%) in the degenerate case
referenced above.
This version of the patch also correctly rememembers the highest node
version# seen for an inode when it's scanned.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-25 03:23:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									while  ( this )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( this - > fn - > ofs  >  fn_end ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										dbg_readinode ( " Ponder this ver %d, 0x%x-0x%x \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											      this - > version ,  this - > fn - > ofs ,  this - > fn - > size ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( this - > version  = =  tn - > version )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											/* Version number collision means REF_PRISTINE GC. Accept either of them
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											   as  long  as  the  CRC  is  correct .  Check  the  one  we  have  already . . .   */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( ! check_tn_node ( c ,  this ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												/* The one we already had was OK. Keep it and throw away the new one */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												dbg_readinode ( " Like old node. Throw away new \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												jffs2_kill_tn ( c ,  tn ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												/* Who cares if the new one is good; keep it for now anyway. */ 
							 
						 
					
						
							
								
									
										
										
										
											2007-05-07 13:16:13 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												dbg_readinode ( " Like new node. Throw away old \n " ) ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] Improve read_inode memory usage, v2.
We originally used to read every node and allocate a jffs2_tmp_dnode_info
structure for each, before processing them in (reverse) version order
and discarding the ones which are obsoleted by later nodes.
With huge logfiles, this behaviour caused memory problems. For example, a
file involved in OLPC trac #1292 has 1822391 nodes, and would cause the XO
machine to run out of memory during the first stage of read_inode().
Instead of just inserting nodes into a tree in version order as we find
them, we now put them into a tree in order of their offset within the
file, which allows us to immediately discard nodes which are completely
obsoleted.
We don't use a full tree with 'fragments' pointing to the real data
structure, as we do in the normal fragtree. We sort only on the start
address, and add an 'overlapped' flag to the tmp_dnode_info to indicate
that the node in question is (partially) overlapped by another.
When the scan is complete, we start at the end of the file, adding each
node to a real fragtree as before. Where the node is non-overlapped, we
just add it (it doesn't matter that it's not the latest version; there is
no overlap). When the node at the end of the tree _is_ overlapped, we sort
it and all its overlapping nodes into version order and then add them to
the fragtree in that order.
This 'early discard' reduces the peak allocation of tmp_dnode_info
structures from 1.8M to a mere 62872 (3.5%) in the degenerate case
referenced above.
This version of the patch also correctly rememembers the highest node
version# seen for an inode when it's scanned.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-25 03:23:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												rb_replace_node ( & this - > rb ,  & tn - > rb ,  & rii - > tn_root ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												jffs2_kill_tn ( c ,  this ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2007-05-07 13:16:13 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												/* Same overlapping from in front and behind */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return  0 ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] Improve read_inode memory usage, v2.
We originally used to read every node and allocate a jffs2_tmp_dnode_info
structure for each, before processing them in (reverse) version order
and discarding the ones which are obsoleted by later nodes.
With huge logfiles, this behaviour caused memory problems. For example, a
file involved in OLPC trac #1292 has 1822391 nodes, and would cause the XO
machine to run out of memory during the first stage of read_inode().
Instead of just inserting nodes into a tree in version order as we find
them, we now put them into a tree in order of their offset within the
file, which allows us to immediately discard nodes which are completely
obsoleted.
We don't use a full tree with 'fragments' pointing to the real data
structure, as we do in the normal fragtree. We sort only on the start
address, and add an 'overlapped' flag to the tmp_dnode_info to indicate
that the node in question is (partially) overlapped by another.
When the scan is complete, we start at the end of the file, adding each
node to a real fragtree as before. Where the node is non-overlapped, we
just add it (it doesn't matter that it's not the latest version; there is
no overlap). When the node at the end of the tree _is_ overlapped, we sort
it and all its overlapping nodes into version order and then add them to
the fragtree in that order.
This 'early discard' reduces the peak allocation of tmp_dnode_info
structures from 1.8M to a mere 62872 (3.5%) in the degenerate case
referenced above.
This version of the patch also correctly rememembers the highest node
version# seen for an inode when it's scanned.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-25 03:23:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( this - > version  <  tn - > version  & & 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										    this - > fn - > ofs  > =  tn - > fn - > ofs  & & 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										    this - > fn - > ofs  +  this - > fn - > size  < =  fn_end )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											/* New node entirely overlaps 'this' */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( check_tn_node ( c ,  tn ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												dbg_readinode ( " new node bad CRC \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												jffs2_kill_tn ( c ,  tn ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2007-05-07 13:16:13 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											/* ... and is good. Kill 'this' and any subsequent nodes which are also overlapped */ 
							 
						 
					
						
							
								
									
										
										
										
											2007-05-08 00:19:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											while  ( this  & &  this - > fn - > ofs  +  this - > fn - > size  < =  fn_end )  { 
							 
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] Improve read_inode memory usage, v2.
We originally used to read every node and allocate a jffs2_tmp_dnode_info
structure for each, before processing them in (reverse) version order
and discarding the ones which are obsoleted by later nodes.
With huge logfiles, this behaviour caused memory problems. For example, a
file involved in OLPC trac #1292 has 1822391 nodes, and would cause the XO
machine to run out of memory during the first stage of read_inode().
Instead of just inserting nodes into a tree in version order as we find
them, we now put them into a tree in order of their offset within the
file, which allows us to immediately discard nodes which are completely
obsoleted.
We don't use a full tree with 'fragments' pointing to the real data
structure, as we do in the normal fragtree. We sort only on the start
address, and add an 'overlapped' flag to the tmp_dnode_info to indicate
that the node in question is (partially) overlapped by another.
When the scan is complete, we start at the end of the file, adding each
node to a real fragtree as before. Where the node is non-overlapped, we
just add it (it doesn't matter that it's not the latest version; there is
no overlap). When the node at the end of the tree _is_ overlapped, we sort
it and all its overlapping nodes into version order and then add them to
the fragtree in that order.
This 'early discard' reduces the peak allocation of tmp_dnode_info
structures from 1.8M to a mere 62872 (3.5%) in the degenerate case
referenced above.
This version of the patch also correctly rememembers the highest node
version# seen for an inode when it's scanned.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-25 03:23:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												struct  jffs2_tmp_dnode_info  * next  =  tn_next ( this ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  ( this - > version  <  tn - > version )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													tn_erase ( this ,  & rii - > tn_root ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													dbg_readinode ( " Kill overlapped ver %d, 0x%x-0x%x \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														      this - > version ,  this - > fn - > ofs , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														      this - > fn - > ofs + this - > fn - > size ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													jffs2_kill_tn ( c ,  this ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												this  =  next ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2007-05-07 13:16:13 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											dbg_readinode ( " Done killing overlapped nodes \n " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2007-05-08 00:19:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											continue ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] Improve read_inode memory usage, v2.
We originally used to read every node and allocate a jffs2_tmp_dnode_info
structure for each, before processing them in (reverse) version order
and discarding the ones which are obsoleted by later nodes.
With huge logfiles, this behaviour caused memory problems. For example, a
file involved in OLPC trac #1292 has 1822391 nodes, and would cause the XO
machine to run out of memory during the first stage of read_inode().
Instead of just inserting nodes into a tree in version order as we find
them, we now put them into a tree in order of their offset within the
file, which allows us to immediately discard nodes which are completely
obsoleted.
We don't use a full tree with 'fragments' pointing to the real data
structure, as we do in the normal fragtree. We sort only on the start
address, and add an 'overlapped' flag to the tmp_dnode_info to indicate
that the node in question is (partially) overlapped by another.
When the scan is complete, we start at the end of the file, adding each
node to a real fragtree as before. Where the node is non-overlapped, we
just add it (it doesn't matter that it's not the latest version; there is
no overlap). When the node at the end of the tree _is_ overlapped, we sort
it and all its overlapping nodes into version order and then add them to
the fragtree in that order.
This 'early discard' reduces the peak allocation of tmp_dnode_info
structures from 1.8M to a mere 62872 (3.5%) in the degenerate case
referenced above.
This version of the patch also correctly rememembers the highest node
version# seen for an inode when it's scanned.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-25 03:23:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( this - > version  >  tn - > version  & & 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										    this - > fn - > ofs  < =  tn - > fn - > ofs  & & 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										    this - > fn - > ofs + this - > fn - > size  > =  fn_end )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											/* New node entirely overlapped by 'this' */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( ! check_tn_node ( c ,  this ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												dbg_readinode ( " Good CRC on old node. Kill new \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												jffs2_kill_tn ( c ,  tn ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											/* ... but 'this' was bad. Replace it... */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											dbg_readinode ( " Bad CRC on old overlapping node. Kill it \n " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2007-05-07 13:16:13 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											tn_erase ( this ,  & rii - > tn_root ) ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] Improve read_inode memory usage, v2.
We originally used to read every node and allocate a jffs2_tmp_dnode_info
structure for each, before processing them in (reverse) version order
and discarding the ones which are obsoleted by later nodes.
With huge logfiles, this behaviour caused memory problems. For example, a
file involved in OLPC trac #1292 has 1822391 nodes, and would cause the XO
machine to run out of memory during the first stage of read_inode().
Instead of just inserting nodes into a tree in version order as we find
them, we now put them into a tree in order of their offset within the
file, which allows us to immediately discard nodes which are completely
obsoleted.
We don't use a full tree with 'fragments' pointing to the real data
structure, as we do in the normal fragtree. We sort only on the start
address, and add an 'overlapped' flag to the tmp_dnode_info to indicate
that the node in question is (partially) overlapped by another.
When the scan is complete, we start at the end of the file, adding each
node to a real fragtree as before. Where the node is non-overlapped, we
just add it (it doesn't matter that it's not the latest version; there is
no overlap). When the node at the end of the tree _is_ overlapped, we sort
it and all its overlapping nodes into version order and then add them to
the fragtree in that order.
This 'early discard' reduces the peak allocation of tmp_dnode_info
structures from 1.8M to a mere 62872 (3.5%) in the degenerate case
referenced above.
This version of the patch also correctly rememembers the highest node
version# seen for an inode when it's scanned.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-25 03:23:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											jffs2_kill_tn ( c ,  this ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2007-05-07 13:16:13 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											break ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] Improve read_inode memory usage, v2.
We originally used to read every node and allocate a jffs2_tmp_dnode_info
structure for each, before processing them in (reverse) version order
and discarding the ones which are obsoleted by later nodes.
With huge logfiles, this behaviour caused memory problems. For example, a
file involved in OLPC trac #1292 has 1822391 nodes, and would cause the XO
machine to run out of memory during the first stage of read_inode().
Instead of just inserting nodes into a tree in version order as we find
them, we now put them into a tree in order of their offset within the
file, which allows us to immediately discard nodes which are completely
obsoleted.
We don't use a full tree with 'fragments' pointing to the real data
structure, as we do in the normal fragtree. We sort only on the start
address, and add an 'overlapped' flag to the tmp_dnode_info to indicate
that the node in question is (partially) overlapped by another.
When the scan is complete, we start at the end of the file, adding each
node to a real fragtree as before. Where the node is non-overlapped, we
just add it (it doesn't matter that it's not the latest version; there is
no overlap). When the node at the end of the tree _is_ overlapped, we sort
it and all its overlapping nodes into version order and then add them to
the fragtree in that order.
This 'early discard' reduces the peak allocation of tmp_dnode_info
structures from 1.8M to a mere 62872 (3.5%) in the degenerate case
referenced above.
This version of the patch also correctly rememembers the highest node
version# seen for an inode when it's scanned.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-25 03:23:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										this  =  tn_next ( this ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2007-05-06 14:41:40 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] Improve read_inode memory usage, v2.
We originally used to read every node and allocate a jffs2_tmp_dnode_info
structure for each, before processing them in (reverse) version order
and discarding the ones which are obsoleted by later nodes.
With huge logfiles, this behaviour caused memory problems. For example, a
file involved in OLPC trac #1292 has 1822391 nodes, and would cause the XO
machine to run out of memory during the first stage of read_inode().
Instead of just inserting nodes into a tree in version order as we find
them, we now put them into a tree in order of their offset within the
file, which allows us to immediately discard nodes which are completely
obsoleted.
We don't use a full tree with 'fragments' pointing to the real data
structure, as we do in the normal fragtree. We sort only on the start
address, and add an 'overlapped' flag to the tmp_dnode_info to indicate
that the node in question is (partially) overlapped by another.
When the scan is complete, we start at the end of the file, adding each
node to a real fragtree as before. Where the node is non-overlapped, we
just add it (it doesn't matter that it's not the latest version; there is
no overlap). When the node at the end of the tree _is_ overlapped, we sort
it and all its overlapping nodes into version order and then add them to
the fragtree in that order.
This 'early discard' reduces the peak allocation of tmp_dnode_info
structures from 1.8M to a mere 62872 (3.5%) in the degenerate case
referenced above.
This version of the patch also correctly rememembers the highest node
version# seen for an inode when it's scanned.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-25 03:23:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* We neither completely obsoleted nor were completely
 
							 
						 
					
						
							
								
									
										
										
										
											2007-05-06 14:41:40 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									   obsoleted  by  an  earlier  node .  Insert  into  the  tree  */ 
							 
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] Improve read_inode memory usage, v2.
We originally used to read every node and allocate a jffs2_tmp_dnode_info
structure for each, before processing them in (reverse) version order
and discarding the ones which are obsoleted by later nodes.
With huge logfiles, this behaviour caused memory problems. For example, a
file involved in OLPC trac #1292 has 1822391 nodes, and would cause the XO
machine to run out of memory during the first stage of read_inode().
Instead of just inserting nodes into a tree in version order as we find
them, we now put them into a tree in order of their offset within the
file, which allows us to immediately discard nodes which are completely
obsoleted.
We don't use a full tree with 'fragments' pointing to the real data
structure, as we do in the normal fragtree. We sort only on the start
address, and add an 'overlapped' flag to the tmp_dnode_info to indicate
that the node in question is (partially) overlapped by another.
When the scan is complete, we start at the end of the file, adding each
node to a real fragtree as before. Where the node is non-overlapped, we
just add it (it doesn't matter that it's not the latest version; there is
no overlap). When the node at the end of the tree _is_ overlapped, we sort
it and all its overlapping nodes into version order and then add them to
the fragtree in that order.
This 'early discard' reduces the peak allocation of tmp_dnode_info
structures from 1.8M to a mere 62872 (3.5%) in the degenerate case
referenced above.
This version of the patch also correctly rememembers the highest node
version# seen for an inode when it's scanned.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-25 03:23:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									{ 
							 
						 
					
						
							
								
									
										
										
										
											2007-05-06 14:41:40 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										struct  rb_node  * parent ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										struct  rb_node  * * link  =  & rii - > tn_root . rb_node ; 
							 
						 
					
						
							
								
									
										
										
										
											2007-05-08 00:19:54 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										struct  jffs2_tmp_dnode_info  * insert_point  =  NULL ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] Improve read_inode memory usage, v2.
We originally used to read every node and allocate a jffs2_tmp_dnode_info
structure for each, before processing them in (reverse) version order
and discarding the ones which are obsoleted by later nodes.
With huge logfiles, this behaviour caused memory problems. For example, a
file involved in OLPC trac #1292 has 1822391 nodes, and would cause the XO
machine to run out of memory during the first stage of read_inode().
Instead of just inserting nodes into a tree in version order as we find
them, we now put them into a tree in order of their offset within the
file, which allows us to immediately discard nodes which are completely
obsoleted.
We don't use a full tree with 'fragments' pointing to the real data
structure, as we do in the normal fragtree. We sort only on the start
address, and add an 'overlapped' flag to the tmp_dnode_info to indicate
that the node in question is (partially) overlapped by another.
When the scan is complete, we start at the end of the file, adding each
node to a real fragtree as before. Where the node is non-overlapped, we
just add it (it doesn't matter that it's not the latest version; there is
no overlap). When the node at the end of the tree _is_ overlapped, we sort
it and all its overlapping nodes into version order and then add them to
the fragtree in that order.
This 'early discard' reduces the peak allocation of tmp_dnode_info
structures from 1.8M to a mere 62872 (3.5%) in the degenerate case
referenced above.
This version of the patch also correctly rememembers the highest node
version# seen for an inode when it's scanned.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-25 03:23:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										while  ( * link )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											parent  =  * link ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											insert_point  =  rb_entry ( parent ,  struct  jffs2_tmp_dnode_info ,  rb ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( tn - > fn - > ofs  >  insert_point - > fn - > ofs ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												link  =  & insert_point - > rb . rb_right ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											else  if  ( tn - > fn - > ofs  <  insert_point - > fn - > ofs  | | 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												 tn - > fn - > size  <  insert_point - > fn - > size ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												link  =  & insert_point - > rb . rb_left ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											else 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												link  =  & insert_point - > rb . rb_right ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										rb_link_node ( & tn - > rb ,  & insert_point - > rb ,  link ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										rb_insert_color ( & tn - > rb ,  & rii - > tn_root ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2007-05-05 16:29:34 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] Improve read_inode memory usage, v2.
We originally used to read every node and allocate a jffs2_tmp_dnode_info
structure for each, before processing them in (reverse) version order
and discarding the ones which are obsoleted by later nodes.
With huge logfiles, this behaviour caused memory problems. For example, a
file involved in OLPC trac #1292 has 1822391 nodes, and would cause the XO
machine to run out of memory during the first stage of read_inode().
Instead of just inserting nodes into a tree in version order as we find
them, we now put them into a tree in order of their offset within the
file, which allows us to immediately discard nodes which are completely
obsoleted.
We don't use a full tree with 'fragments' pointing to the real data
structure, as we do in the normal fragtree. We sort only on the start
address, and add an 'overlapped' flag to the tmp_dnode_info to indicate
that the node in question is (partially) overlapped by another.
When the scan is complete, we start at the end of the file, adding each
node to a real fragtree as before. Where the node is non-overlapped, we
just add it (it doesn't matter that it's not the latest version; there is
no overlap). When the node at the end of the tree _is_ overlapped, we sort
it and all its overlapping nodes into version order and then add them to
the fragtree in that order.
This 'early discard' reduces the peak allocation of tmp_dnode_info
structures from 1.8M to a mere 62872 (3.5%) in the degenerate case
referenced above.
This version of the patch also correctly rememembers the highest node
version# seen for an inode when it's scanned.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-25 03:23:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* If there's anything behind that overlaps us, note it */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									this  =  tn_prev ( tn ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( this )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										while  ( 1 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( this - > fn - > ofs  +  this - > fn - > size  >  tn - > fn - > ofs )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												dbg_readinode ( " Node is overlapped by %p (v %d, 0x%x-0x%x) \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													      this ,  this - > version ,  this - > fn - > ofs , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													      this - > fn - > ofs + this - > fn - > size ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												tn - > overlapped  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( ! this - > overlapped ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												break ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-02-16 21:29:31 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ptn  =  tn_prev ( this ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( ! ptn )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												/*
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												 *  We  killed  a  node  which  set  the  overlapped 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												 *  flags  during  the  scan .  Fix  it  up . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												this - > overlapped  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											this  =  ptn ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] Improve read_inode memory usage, v2.
We originally used to read every node and allocate a jffs2_tmp_dnode_info
structure for each, before processing them in (reverse) version order
and discarding the ones which are obsoleted by later nodes.
With huge logfiles, this behaviour caused memory problems. For example, a
file involved in OLPC trac #1292 has 1822391 nodes, and would cause the XO
machine to run out of memory during the first stage of read_inode().
Instead of just inserting nodes into a tree in version order as we find
them, we now put them into a tree in order of their offset within the
file, which allows us to immediately discard nodes which are completely
obsoleted.
We don't use a full tree with 'fragments' pointing to the real data
structure, as we do in the normal fragtree. We sort only on the start
address, and add an 'overlapped' flag to the tmp_dnode_info to indicate
that the node in question is (partially) overlapped by another.
When the scan is complete, we start at the end of the file, adding each
node to a real fragtree as before. Where the node is non-overlapped, we
just add it (it doesn't matter that it's not the latest version; there is
no overlap). When the node at the end of the tree _is_ overlapped, we sort
it and all its overlapping nodes into version order and then add them to
the fragtree in that order.
This 'early discard' reduces the peak allocation of tmp_dnode_info
structures from 1.8M to a mere 62872 (3.5%) in the degenerate case
referenced above.
This version of the patch also correctly rememembers the highest node
version# seen for an inode when it's scanned.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-25 03:23:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* If the new node overlaps anything ahead, note it */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									this  =  tn_next ( tn ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									while  ( this  & &  this - > fn - > ofs  <  fn_end )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										this - > overlapped  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										dbg_readinode ( " Node ver %d, 0x%x-0x%x is overlapped \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											      this - > version ,  this - > fn - > ofs , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											      this - > fn - > ofs + this - > fn - > size ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										this  =  tn_next ( this ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* Trivial function to remove the last node in the tree. Which by definition
  
						 
					
						
							
								
									
										
										
										
											2012-10-08 16:30:37 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								   has  no  right - hand  child  —  so  can  be  removed  just  by  making  its  left - hand 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								   child  ( if  any )  take  its  place  under  its  parent .  Since  this  is  only  done 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								   when  we ' re  consuming  the  whole  tree ,  there ' s  no  need  to  use  rb_erase ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								   and  let  it  worry  about  adjusting  colours  and  balancing  the  tree .  That 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								   would  just  be  a  waste  of  time .  */ 
							 
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] Improve read_inode memory usage, v2.
We originally used to read every node and allocate a jffs2_tmp_dnode_info
structure for each, before processing them in (reverse) version order
and discarding the ones which are obsoleted by later nodes.
With huge logfiles, this behaviour caused memory problems. For example, a
file involved in OLPC trac #1292 has 1822391 nodes, and would cause the XO
machine to run out of memory during the first stage of read_inode().
Instead of just inserting nodes into a tree in version order as we find
them, we now put them into a tree in order of their offset within the
file, which allows us to immediately discard nodes which are completely
obsoleted.
We don't use a full tree with 'fragments' pointing to the real data
structure, as we do in the normal fragtree. We sort only on the start
address, and add an 'overlapped' flag to the tmp_dnode_info to indicate
that the node in question is (partially) overlapped by another.
When the scan is complete, we start at the end of the file, adding each
node to a real fragtree as before. Where the node is non-overlapped, we
just add it (it doesn't matter that it's not the latest version; there is
no overlap). When the node at the end of the tree _is_ overlapped, we sort
it and all its overlapping nodes into version order and then add them to
the fragtree in that order.
This 'early discard' reduces the peak allocation of tmp_dnode_info
structures from 1.8M to a mere 62872 (3.5%) in the degenerate case
referenced above.
This version of the patch also correctly rememembers the highest node
version# seen for an inode when it's scanned.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-25 03:23:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  void  eat_last ( struct  rb_root  * root ,  struct  rb_node  * node )  
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] Improve read_inode memory usage, v2.
We originally used to read every node and allocate a jffs2_tmp_dnode_info
structure for each, before processing them in (reverse) version order
and discarding the ones which are obsoleted by later nodes.
With huge logfiles, this behaviour caused memory problems. For example, a
file involved in OLPC trac #1292 has 1822391 nodes, and would cause the XO
machine to run out of memory during the first stage of read_inode().
Instead of just inserting nodes into a tree in version order as we find
them, we now put them into a tree in order of their offset within the
file, which allows us to immediately discard nodes which are completely
obsoleted.
We don't use a full tree with 'fragments' pointing to the real data
structure, as we do in the normal fragtree. We sort only on the start
address, and add an 'overlapped' flag to the tmp_dnode_info to indicate
that the node in question is (partially) overlapped by another.
When the scan is complete, we start at the end of the file, adding each
node to a real fragtree as before. Where the node is non-overlapped, we
just add it (it doesn't matter that it's not the latest version; there is
no overlap). When the node at the end of the tree _is_ overlapped, we sort
it and all its overlapping nodes into version order and then add them to
the fragtree in that order.
This 'early discard' reduces the peak allocation of tmp_dnode_info
structures from 1.8M to a mere 62872 (3.5%) in the degenerate case
referenced above.
This version of the patch also correctly rememembers the highest node
version# seen for an inode when it's scanned.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-25 03:23:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  rb_node  * parent  =  rb_parent ( node ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  rb_node  * * link ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* LAST! */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									BUG_ON ( node - > rb_right ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! parent ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										link  =  & root - > rb_node ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									else  if  ( node  = =  parent - > rb_left ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										link  =  & parent - > rb_left ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									else 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										link  =  & parent - > rb_right ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									* link  =  node - > rb_left ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( node - > rb_left ) 
							 
						 
					
						
							
								
									
										
										
										
											2012-10-08 16:30:37 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										node - > rb_left - > __rb_parent_color  =  node - > __rb_parent_color ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] Improve read_inode memory usage, v2.
We originally used to read every node and allocate a jffs2_tmp_dnode_info
structure for each, before processing them in (reverse) version order
and discarding the ones which are obsoleted by later nodes.
With huge logfiles, this behaviour caused memory problems. For example, a
file involved in OLPC trac #1292 has 1822391 nodes, and would cause the XO
machine to run out of memory during the first stage of read_inode().
Instead of just inserting nodes into a tree in version order as we find
them, we now put them into a tree in order of their offset within the
file, which allows us to immediately discard nodes which are completely
obsoleted.
We don't use a full tree with 'fragments' pointing to the real data
structure, as we do in the normal fragtree. We sort only on the start
address, and add an 'overlapped' flag to the tmp_dnode_info to indicate
that the node in question is (partially) overlapped by another.
When the scan is complete, we start at the end of the file, adding each
node to a real fragtree as before. Where the node is non-overlapped, we
just add it (it doesn't matter that it's not the latest version; there is
no overlap). When the node at the end of the tree _is_ overlapped, we sort
it and all its overlapping nodes into version order and then add them to
the fragtree in that order.
This 'early discard' reduces the peak allocation of tmp_dnode_info
structures from 1.8M to a mere 62872 (3.5%) in the degenerate case
referenced above.
This version of the patch also correctly rememembers the highest node
version# seen for an inode when it's scanned.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-25 03:23:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2012-10-08 16:30:37 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/* We put the version tree in reverse order, so we can use the same eat_last()
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								   function  that  we  use  to  consume  the  tmpnode  tree  ( tn_root ) .  */ 
							 
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] Improve read_inode memory usage, v2.
We originally used to read every node and allocate a jffs2_tmp_dnode_info
structure for each, before processing them in (reverse) version order
and discarding the ones which are obsoleted by later nodes.
With huge logfiles, this behaviour caused memory problems. For example, a
file involved in OLPC trac #1292 has 1822391 nodes, and would cause the XO
machine to run out of memory during the first stage of read_inode().
Instead of just inserting nodes into a tree in version order as we find
them, we now put them into a tree in order of their offset within the
file, which allows us to immediately discard nodes which are completely
obsoleted.
We don't use a full tree with 'fragments' pointing to the real data
structure, as we do in the normal fragtree. We sort only on the start
address, and add an 'overlapped' flag to the tmp_dnode_info to indicate
that the node in question is (partially) overlapped by another.
When the scan is complete, we start at the end of the file, adding each
node to a real fragtree as before. Where the node is non-overlapped, we
just add it (it doesn't matter that it's not the latest version; there is
no overlap). When the node at the end of the tree _is_ overlapped, we sort
it and all its overlapping nodes into version order and then add them to
the fragtree in that order.
This 'early discard' reduces the peak allocation of tmp_dnode_info
structures from 1.8M to a mere 62872 (3.5%) in the degenerate case
referenced above.
This version of the patch also correctly rememembers the highest node
version# seen for an inode when it's scanned.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-25 03:23:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  void  ver_insert ( struct  rb_root  * ver_root ,  struct  jffs2_tmp_dnode_info  * tn )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  rb_node  * * link  =  & ver_root - > rb_node ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  rb_node  * parent  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  jffs2_tmp_dnode_info  * this_tn ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									while  ( * link )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										parent  =  * link ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										this_tn  =  rb_entry ( parent ,  struct  jffs2_tmp_dnode_info ,  rb ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( tn - > version  >  this_tn - > version ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											link  =  & parent - > rb_left ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-07-27 15:46:14 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										else 
							 
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] Improve read_inode memory usage, v2.
We originally used to read every node and allocate a jffs2_tmp_dnode_info
structure for each, before processing them in (reverse) version order
and discarding the ones which are obsoleted by later nodes.
With huge logfiles, this behaviour caused memory problems. For example, a
file involved in OLPC trac #1292 has 1822391 nodes, and would cause the XO
machine to run out of memory during the first stage of read_inode().
Instead of just inserting nodes into a tree in version order as we find
them, we now put them into a tree in order of their offset within the
file, which allows us to immediately discard nodes which are completely
obsoleted.
We don't use a full tree with 'fragments' pointing to the real data
structure, as we do in the normal fragtree. We sort only on the start
address, and add an 'overlapped' flag to the tmp_dnode_info to indicate
that the node in question is (partially) overlapped by another.
When the scan is complete, we start at the end of the file, adding each
node to a real fragtree as before. Where the node is non-overlapped, we
just add it (it doesn't matter that it's not the latest version; there is
no overlap). When the node at the end of the tree _is_ overlapped, we sort
it and all its overlapping nodes into version order and then add them to
the fragtree in that order.
This 'early discard' reduces the peak allocation of tmp_dnode_info
structures from 1.8M to a mere 62872 (3.5%) in the degenerate case
referenced above.
This version of the patch also correctly rememembers the highest node
version# seen for an inode when it's scanned.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-25 03:23:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											link  =  & parent - > rb_right ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-08-01 13:05:22 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] Improve read_inode memory usage, v2.
We originally used to read every node and allocate a jffs2_tmp_dnode_info
structure for each, before processing them in (reverse) version order
and discarding the ones which are obsoleted by later nodes.
With huge logfiles, this behaviour caused memory problems. For example, a
file involved in OLPC trac #1292 has 1822391 nodes, and would cause the XO
machine to run out of memory during the first stage of read_inode().
Instead of just inserting nodes into a tree in version order as we find
them, we now put them into a tree in order of their offset within the
file, which allows us to immediately discard nodes which are completely
obsoleted.
We don't use a full tree with 'fragments' pointing to the real data
structure, as we do in the normal fragtree. We sort only on the start
address, and add an 'overlapped' flag to the tmp_dnode_info to indicate
that the node in question is (partially) overlapped by another.
When the scan is complete, we start at the end of the file, adding each
node to a real fragtree as before. Where the node is non-overlapped, we
just add it (it doesn't matter that it's not the latest version; there is
no overlap). When the node at the end of the tree _is_ overlapped, we sort
it and all its overlapping nodes into version order and then add them to
the fragtree in that order.
This 'early discard' reduces the peak allocation of tmp_dnode_info
structures from 1.8M to a mere 62872 (3.5%) in the degenerate case
referenced above.
This version of the patch also correctly rememembers the highest node
version# seen for an inode when it's scanned.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-25 03:23:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									dbg_readinode ( " Link new node at %p (root is %p) \n " ,  link ,  ver_root ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									rb_link_node ( & tn - > rb ,  parent ,  link ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									rb_insert_color ( & tn - > rb ,  ver_root ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2005-07-27 15:46:14 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] Improve read_inode memory usage, v2.
We originally used to read every node and allocate a jffs2_tmp_dnode_info
structure for each, before processing them in (reverse) version order
and discarding the ones which are obsoleted by later nodes.
With huge logfiles, this behaviour caused memory problems. For example, a
file involved in OLPC trac #1292 has 1822391 nodes, and would cause the XO
machine to run out of memory during the first stage of read_inode().
Instead of just inserting nodes into a tree in version order as we find
them, we now put them into a tree in order of their offset within the
file, which allows us to immediately discard nodes which are completely
obsoleted.
We don't use a full tree with 'fragments' pointing to the real data
structure, as we do in the normal fragtree. We sort only on the start
address, and add an 'overlapped' flag to the tmp_dnode_info to indicate
that the node in question is (partially) overlapped by another.
When the scan is complete, we start at the end of the file, adding each
node to a real fragtree as before. Where the node is non-overlapped, we
just add it (it doesn't matter that it's not the latest version; there is
no overlap). When the node at the end of the tree _is_ overlapped, we sort
it and all its overlapping nodes into version order and then add them to
the fragtree in that order.
This 'early discard' reduces the peak allocation of tmp_dnode_info
structures from 1.8M to a mere 62872 (3.5%) in the degenerate case
referenced above.
This version of the patch also correctly rememembers the highest node
version# seen for an inode when it's scanned.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-25 03:23:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/* Build final, normal fragtree from tn tree. It doesn't matter which order
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								   we  add  nodes  to  the  real  fragtree ,  as  long  as  they  don ' t  overlap .  And 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								   having  thrown  away  the  majority  of  overlapped  nodes  as  we  went ,  there 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								   really  shouldn ' t  be  many  sets  of  nodes  which  do  overlap .  If  we  start  at 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								   the  end ,  we  can  use  the  overlap  markers  - -  we  can  just  eat  nodes  which 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								   aren ' t  overlapped ,  and  when  we  encounter  nodes  which  _do_  overlap  we 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								   sort  them  all  into  a  temporary  tree  in  version  order  before  replaying  them .  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  jffs2_build_inode_fragtree ( struct  jffs2_sb_info  * c ,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												      struct  jffs2_inode_info  * f , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												      struct  jffs2_readinode_info  * rii ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  jffs2_tmp_dnode_info  * pen ,  * last ,  * this ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  rb_root  ver_root  =  RB_ROOT ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									uint32_t  high_ver  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( rii - > mdata_tn )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										dbg_readinode ( " potential mdata is ver %d at %p \n " ,  rii - > mdata_tn - > version ,  rii - > mdata_tn ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										high_ver  =  rii - > mdata_tn - > version ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										rii - > latest_ref  =  rii - > mdata_tn - > fn - > raw ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# ifdef JFFS2_DBG_READINODE_MESSAGES 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									this  =  tn_last ( & rii - > tn_root ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									while  ( this )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										dbg_readinode ( " tn %p ver %d range 0x%x-0x%x ov %d \n " ,  this ,  this - > version ,  this - > fn - > ofs , 
							 
						 
					
						
							
								
									
										
										
										
											2007-05-06 14:41:40 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											      this - > fn - > ofs + this - > fn - > size ,  this - > overlapped ) ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] Improve read_inode memory usage, v2.
We originally used to read every node and allocate a jffs2_tmp_dnode_info
structure for each, before processing them in (reverse) version order
and discarding the ones which are obsoleted by later nodes.
With huge logfiles, this behaviour caused memory problems. For example, a
file involved in OLPC trac #1292 has 1822391 nodes, and would cause the XO
machine to run out of memory during the first stage of read_inode().
Instead of just inserting nodes into a tree in version order as we find
them, we now put them into a tree in order of their offset within the
file, which allows us to immediately discard nodes which are completely
obsoleted.
We don't use a full tree with 'fragments' pointing to the real data
structure, as we do in the normal fragtree. We sort only on the start
address, and add an 'overlapped' flag to the tmp_dnode_info to indicate
that the node in question is (partially) overlapped by another.
When the scan is complete, we start at the end of the file, adding each
node to a real fragtree as before. Where the node is non-overlapped, we
just add it (it doesn't matter that it's not the latest version; there is
no overlap). When the node at the end of the tree _is_ overlapped, we sort
it and all its overlapping nodes into version order and then add them to
the fragtree in that order.
This 'early discard' reduces the peak allocation of tmp_dnode_info
structures from 1.8M to a mere 62872 (3.5%) in the degenerate case
referenced above.
This version of the patch also correctly rememembers the highest node
version# seen for an inode when it's scanned.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-25 03:23:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										this  =  tn_prev ( this ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									pen  =  tn_last ( & rii - > tn_root ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									while  ( ( last  =  pen ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										pen  =  tn_prev ( last ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										eat_last ( & rii - > tn_root ,  & last - > rb ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ver_insert ( & ver_root ,  last ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2009-02-16 21:29:31 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( unlikely ( last - > overlapped ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( pen ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											/*
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  We  killed  a  node  which  set  the  overlapped 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  flags  during  the  scan .  Fix  it  up . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											last - > overlapped  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] Improve read_inode memory usage, v2.
We originally used to read every node and allocate a jffs2_tmp_dnode_info
structure for each, before processing them in (reverse) version order
and discarding the ones which are obsoleted by later nodes.
With huge logfiles, this behaviour caused memory problems. For example, a
file involved in OLPC trac #1292 has 1822391 nodes, and would cause the XO
machine to run out of memory during the first stage of read_inode().
Instead of just inserting nodes into a tree in version order as we find
them, we now put them into a tree in order of their offset within the
file, which allows us to immediately discard nodes which are completely
obsoleted.
We don't use a full tree with 'fragments' pointing to the real data
structure, as we do in the normal fragtree. We sort only on the start
address, and add an 'overlapped' flag to the tmp_dnode_info to indicate
that the node in question is (partially) overlapped by another.
When the scan is complete, we start at the end of the file, adding each
node to a real fragtree as before. Where the node is non-overlapped, we
just add it (it doesn't matter that it's not the latest version; there is
no overlap). When the node at the end of the tree _is_ overlapped, we sort
it and all its overlapping nodes into version order and then add them to
the fragtree in that order.
This 'early discard' reduces the peak allocation of tmp_dnode_info
structures from 1.8M to a mere 62872 (3.5%) in the degenerate case
referenced above.
This version of the patch also correctly rememembers the highest node
version# seen for an inode when it's scanned.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-25 03:23:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Now we have a bunch of nodes in reverse version
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										   order ,  in  the  tree  at  ver_root .  Most  of  the  time , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										   there ' ll  actually  be  only  one  node  in  the  ' tree ' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										   in  fact .  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										this  =  tn_last ( & ver_root ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										while  ( this )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											struct  jffs2_tmp_dnode_info  * vers_next ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											int  ret ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											vers_next  =  tn_prev ( this ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											eat_last ( & ver_root ,  & this - > rb ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( check_tn_node ( c ,  this ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2007-05-05 16:29:34 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												dbg_readinode ( " node ver %d, 0x%x-0x%x failed CRC \n " , 
							 
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] Improve read_inode memory usage, v2.
We originally used to read every node and allocate a jffs2_tmp_dnode_info
structure for each, before processing them in (reverse) version order
and discarding the ones which are obsoleted by later nodes.
With huge logfiles, this behaviour caused memory problems. For example, a
file involved in OLPC trac #1292 has 1822391 nodes, and would cause the XO
machine to run out of memory during the first stage of read_inode().
Instead of just inserting nodes into a tree in version order as we find
them, we now put them into a tree in order of their offset within the
file, which allows us to immediately discard nodes which are completely
obsoleted.
We don't use a full tree with 'fragments' pointing to the real data
structure, as we do in the normal fragtree. We sort only on the start
address, and add an 'overlapped' flag to the tmp_dnode_info to indicate
that the node in question is (partially) overlapped by another.
When the scan is complete, we start at the end of the file, adding each
node to a real fragtree as before. Where the node is non-overlapped, we
just add it (it doesn't matter that it's not the latest version; there is
no overlap). When the node at the end of the tree _is_ overlapped, we sort
it and all its overlapping nodes into version order and then add them to
the fragtree in that order.
This 'early discard' reduces the peak allocation of tmp_dnode_info
structures from 1.8M to a mere 62872 (3.5%) in the degenerate case
referenced above.
This version of the patch also correctly rememembers the highest node
version# seen for an inode when it's scanned.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-25 03:23:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
													     this - > version ,  this - > fn - > ofs , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													     this - > fn - > ofs + this - > fn - > size ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												jffs2_kill_tn ( c ,  this ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  ( this - > version  >  high_ver )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													/* Note that this is different from the other
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													   highest_version ,  because  this  one  is  only 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													   counting  _valid_  nodes  which  could  give  the 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													   latest  inode  metadata  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													high_ver  =  this - > version ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													rii - > latest_ref  =  this - > fn - > raw ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
									
										
										
										
											2007-05-05 16:29:34 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												dbg_readinode ( " Add %p (v %d, 0x%x-0x%x, ov %d) to fragtree \n " , 
							 
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] Improve read_inode memory usage, v2.
We originally used to read every node and allocate a jffs2_tmp_dnode_info
structure for each, before processing them in (reverse) version order
and discarding the ones which are obsoleted by later nodes.
With huge logfiles, this behaviour caused memory problems. For example, a
file involved in OLPC trac #1292 has 1822391 nodes, and would cause the XO
machine to run out of memory during the first stage of read_inode().
Instead of just inserting nodes into a tree in version order as we find
them, we now put them into a tree in order of their offset within the
file, which allows us to immediately discard nodes which are completely
obsoleted.
We don't use a full tree with 'fragments' pointing to the real data
structure, as we do in the normal fragtree. We sort only on the start
address, and add an 'overlapped' flag to the tmp_dnode_info to indicate
that the node in question is (partially) overlapped by another.
When the scan is complete, we start at the end of the file, adding each
node to a real fragtree as before. Where the node is non-overlapped, we
just add it (it doesn't matter that it's not the latest version; there is
no overlap). When the node at the end of the tree _is_ overlapped, we sort
it and all its overlapping nodes into version order and then add them to
the fragtree in that order.
This 'early discard' reduces the peak allocation of tmp_dnode_info
structures from 1.8M to a mere 62872 (3.5%) in the degenerate case
referenced above.
This version of the patch also correctly rememembers the highest node
version# seen for an inode when it's scanned.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-25 03:23:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
													     this ,  this - > version ,  this - > fn - > ofs , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													     this - > fn - > ofs + this - > fn - > size ,  this - > overlapped ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												ret  =  jffs2_add_full_dnode_to_inode ( c ,  f ,  this - > fn ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  ( ret )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													/* Free the nodes in vers_root; let the caller
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													   deal  with  the  rest  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													JFFS2_ERROR ( " Add node to tree failed %d \n " ,  ret ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													while  ( 1 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														vers_next  =  tn_prev ( this ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														if  ( check_tn_node ( c ,  this ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
															jffs2_mark_node_obsolete ( c ,  this - > fn - > raw ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														jffs2_free_full_dnode ( this - > fn ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														jffs2_free_tmp_dnode_info ( this ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														this  =  vers_next ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														if  ( ! this ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
															break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														eat_last ( & ver_root ,  & vers_next - > rb ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													return  ret ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												jffs2_free_tmp_dnode_info ( this ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											this  =  vers_next ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-07-27 15:46:14 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-27 15:46:14 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  void  jffs2_free_tmp_dnode_info_list ( struct  rb_root  * list )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  rb_node  * this ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  jffs2_tmp_dnode_info  * tn ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									this  =  list - > rb_node ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Now at bottom of tree */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									while  ( this )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( this - > rb_left ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											this  =  this - > rb_left ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										else  if  ( this - > rb_right ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											this  =  this - > rb_right ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											tn  =  rb_entry ( this ,  struct  jffs2_tmp_dnode_info ,  rb ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											jffs2_free_full_dnode ( tn - > fn ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											jffs2_free_tmp_dnode_info ( tn ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2006-04-21 13:17:57 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											this  =  rb_parent ( this ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-07-27 15:46:14 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											if  ( ! this ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( this - > rb_left  = =  & tn - > rb ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												this - > rb_left  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											else  if  ( this - > rb_right  = =  & tn - > rb ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												this - > rb_right  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											else  BUG ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2010-03-15 00:34:59 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									* list  =  RB_ROOT ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-07-27 15:46:14 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-27 15:46:14 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  void  jffs2_free_full_dirent_list ( struct  jffs2_full_dirent  * fd )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  jffs2_full_dirent  * next ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-07-07 16:45:32 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-27 15:46:14 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									while  ( fd )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										next  =  fd - > next ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										jffs2_free_full_dirent ( fd ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										fd  =  next ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-27 15:46:14 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/* Returns first valid node after 'ref'. May return 'ref' */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  struct  jffs2_raw_node_ref  * jffs2_first_valid_node ( struct  jffs2_raw_node_ref  * ref )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									while  ( ref  & &  ref - > next_in_ino )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! ref_obsolete ( ref ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  ref ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-09-22 12:25:00 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										dbg_noderef ( " node at 0x%08x is obsoleted. Ignoring. \n " ,  ref_offset ( ref ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-07-27 15:46:14 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ref  =  ref - > next_in_ino ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-27 15:46:14 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Helper  function  for  jffs2_get_inode_nodes ( ) . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  It  is  called  every  time  an  directory  entry  node  is  found . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
									
										
										
										
											2007-07-03 16:51:19 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  Returns :  0  on  success ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-07-27 15:46:14 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  	    negative  error  code  on  failure . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
									
										
										
										
											2005-08-01 13:05:22 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  inline  int  read_direntry ( struct  jffs2_sb_info  * c ,  struct  jffs2_raw_node_ref  * ref ,  
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] Improve read_inode memory usage, v2.
We originally used to read every node and allocate a jffs2_tmp_dnode_info
structure for each, before processing them in (reverse) version order
and discarding the ones which are obsoleted by later nodes.
With huge logfiles, this behaviour caused memory problems. For example, a
file involved in OLPC trac #1292 has 1822391 nodes, and would cause the XO
machine to run out of memory during the first stage of read_inode().
Instead of just inserting nodes into a tree in version order as we find
them, we now put them into a tree in order of their offset within the
file, which allows us to immediately discard nodes which are completely
obsoleted.
We don't use a full tree with 'fragments' pointing to the real data
structure, as we do in the normal fragtree. We sort only on the start
address, and add an 'overlapped' flag to the tmp_dnode_info to indicate
that the node in question is (partially) overlapped by another.
When the scan is complete, we start at the end of the file, adding each
node to a real fragtree as before. Where the node is non-overlapped, we
just add it (it doesn't matter that it's not the latest version; there is
no overlap). When the node at the end of the tree _is_ overlapped, we sort
it and all its overlapping nodes into version order and then add them to
the fragtree in that order.
This 'early discard' reduces the peak allocation of tmp_dnode_info
structures from 1.8M to a mere 62872 (3.5%) in the degenerate case
referenced above.
This version of the patch also correctly rememembers the highest node
version# seen for an inode when it's scanned.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-25 03:23:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												struct  jffs2_raw_dirent  * rd ,  size_t  read , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												struct  jffs2_readinode_info  * rii ) 
							 
						 
					
						
							
								
									
										
										
										
											2005-07-27 15:46:14 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  jffs2_full_dirent  * fd ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-06-18 22:44:21 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									uint32_t  crc ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-11-07 11:16:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-27 15:46:14 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* Obsoleted. This cannot happen, surely? dwmw2 20020308 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									BUG_ON ( ref_obsolete ( ref ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-11-07 11:16:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2006-06-18 22:44:21 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									crc  =  crc32 ( 0 ,  rd ,  sizeof ( * rd )  -  8 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( unlikely ( crc  ! =  je32_to_cpu ( rd - > node_crc ) ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										JFFS2_NOTICE ( " header CRC failed on dirent node at %#08x: read %#08x, calculated %#08x \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											     ref_offset ( ref ) ,  je32_to_cpu ( rd - > node_crc ) ,  crc ) ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] Improve read_inode memory usage, v2.
We originally used to read every node and allocate a jffs2_tmp_dnode_info
structure for each, before processing them in (reverse) version order
and discarding the ones which are obsoleted by later nodes.
With huge logfiles, this behaviour caused memory problems. For example, a
file involved in OLPC trac #1292 has 1822391 nodes, and would cause the XO
machine to run out of memory during the first stage of read_inode().
Instead of just inserting nodes into a tree in version order as we find
them, we now put them into a tree in order of their offset within the
file, which allows us to immediately discard nodes which are completely
obsoleted.
We don't use a full tree with 'fragments' pointing to the real data
structure, as we do in the normal fragtree. We sort only on the start
address, and add an 'overlapped' flag to the tmp_dnode_info to indicate
that the node in question is (partially) overlapped by another.
When the scan is complete, we start at the end of the file, adding each
node to a real fragtree as before. Where the node is non-overlapped, we
just add it (it doesn't matter that it's not the latest version; there is
no overlap). When the node at the end of the tree _is_ overlapped, we sort
it and all its overlapping nodes into version order and then add them to
the fragtree in that order.
This 'early discard' reduces the peak allocation of tmp_dnode_info
structures from 1.8M to a mere 62872 (3.5%) in the degenerate case
referenced above.
This version of the patch also correctly rememembers the highest node
version# seen for an inode when it's scanned.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-25 03:23:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										jffs2_mark_node_obsolete ( c ,  ref ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-07-27 15:46:14 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2005-11-07 11:16:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2006-06-18 22:44:21 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* If we've never checked the CRCs on this node, check them now */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ref_flags ( ref )  = =  REF_UNCHECKED )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										struct  jffs2_eraseblock  * jeb ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										int  len ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Sanity check */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( unlikely ( PAD ( ( rd - > nsize  +  sizeof ( * rd ) ) )  ! =  PAD ( je32_to_cpu ( rd - > totlen ) ) ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											JFFS2_ERROR ( " illegal nsize in node at %#08x: nsize %#02x, totlen %#04x \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												    ref_offset ( ref ) ,  rd - > nsize ,  je32_to_cpu ( rd - > totlen ) ) ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] Improve read_inode memory usage, v2.
We originally used to read every node and allocate a jffs2_tmp_dnode_info
structure for each, before processing them in (reverse) version order
and discarding the ones which are obsoleted by later nodes.
With huge logfiles, this behaviour caused memory problems. For example, a
file involved in OLPC trac #1292 has 1822391 nodes, and would cause the XO
machine to run out of memory during the first stage of read_inode().
Instead of just inserting nodes into a tree in version order as we find
them, we now put them into a tree in order of their offset within the
file, which allows us to immediately discard nodes which are completely
obsoleted.
We don't use a full tree with 'fragments' pointing to the real data
structure, as we do in the normal fragtree. We sort only on the start
address, and add an 'overlapped' flag to the tmp_dnode_info to indicate
that the node in question is (partially) overlapped by another.
When the scan is complete, we start at the end of the file, adding each
node to a real fragtree as before. Where the node is non-overlapped, we
just add it (it doesn't matter that it's not the latest version; there is
no overlap). When the node at the end of the tree _is_ overlapped, we sort
it and all its overlapping nodes into version order and then add them to
the fragtree in that order.
This 'early discard' reduces the peak allocation of tmp_dnode_info
structures from 1.8M to a mere 62872 (3.5%) in the degenerate case
referenced above.
This version of the patch also correctly rememembers the highest node
version# seen for an inode when it's scanned.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-25 03:23:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											jffs2_mark_node_obsolete ( c ,  ref ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-06-18 22:44:21 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										jeb  =  & c - > blocks [ ref - > flash_offset  /  c - > sector_size ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										len  =  ref_totlen ( c ,  jeb ,  ref ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										spin_lock ( & c - > erase_completion_lock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										jeb - > used_size  + =  len ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										jeb - > unchecked_size  - =  len ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										c - > used_size  + =  len ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										c - > unchecked_size  - =  len ; 
							 
						 
					
						
							
								
									
										
										
										
											2007-06-29 13:39:57 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ref - > flash_offset  =  ref_offset ( ref )  |  dirent_node_state ( rd ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-06-18 22:44:21 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										spin_unlock ( & c - > erase_completion_lock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-27 15:46:14 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									fd  =  jffs2_alloc_full_dirent ( rd - > nsize  +  1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( unlikely ( ! fd ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  - ENOMEM ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-27 15:46:14 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									fd - > raw  =  ref ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									fd - > version  =  je32_to_cpu ( rd - > version ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									fd - > ino  =  je32_to_cpu ( rd - > ino ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									fd - > type  =  rd - > type ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] Improve read_inode memory usage, v2.
We originally used to read every node and allocate a jffs2_tmp_dnode_info
structure for each, before processing them in (reverse) version order
and discarding the ones which are obsoleted by later nodes.
With huge logfiles, this behaviour caused memory problems. For example, a
file involved in OLPC trac #1292 has 1822391 nodes, and would cause the XO
machine to run out of memory during the first stage of read_inode().
Instead of just inserting nodes into a tree in version order as we find
them, we now put them into a tree in order of their offset within the
file, which allows us to immediately discard nodes which are completely
obsoleted.
We don't use a full tree with 'fragments' pointing to the real data
structure, as we do in the normal fragtree. We sort only on the start
address, and add an 'overlapped' flag to the tmp_dnode_info to indicate
that the node in question is (partially) overlapped by another.
When the scan is complete, we start at the end of the file, adding each
node to a real fragtree as before. Where the node is non-overlapped, we
just add it (it doesn't matter that it's not the latest version; there is
no overlap). When the node at the end of the tree _is_ overlapped, we sort
it and all its overlapping nodes into version order and then add them to
the fragtree in that order.
This 'early discard' reduces the peak allocation of tmp_dnode_info
structures from 1.8M to a mere 62872 (3.5%) in the degenerate case
referenced above.
This version of the patch also correctly rememembers the highest node
version# seen for an inode when it's scanned.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-25 03:23:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( fd - > version  >  rii - > highest_version ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										rii - > highest_version  =  fd - > version ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-27 15:46:14 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* Pick out the mctime of the latest dirent */ 
							 
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] Improve read_inode memory usage, v2.
We originally used to read every node and allocate a jffs2_tmp_dnode_info
structure for each, before processing them in (reverse) version order
and discarding the ones which are obsoleted by later nodes.
With huge logfiles, this behaviour caused memory problems. For example, a
file involved in OLPC trac #1292 has 1822391 nodes, and would cause the XO
machine to run out of memory during the first stage of read_inode().
Instead of just inserting nodes into a tree in version order as we find
them, we now put them into a tree in order of their offset within the
file, which allows us to immediately discard nodes which are completely
obsoleted.
We don't use a full tree with 'fragments' pointing to the real data
structure, as we do in the normal fragtree. We sort only on the start
address, and add an 'overlapped' flag to the tmp_dnode_info to indicate
that the node in question is (partially) overlapped by another.
When the scan is complete, we start at the end of the file, adding each
node to a real fragtree as before. Where the node is non-overlapped, we
just add it (it doesn't matter that it's not the latest version; there is
no overlap). When the node at the end of the tree _is_ overlapped, we sort
it and all its overlapping nodes into version order and then add them to
the fragtree in that order.
This 'early discard' reduces the peak allocation of tmp_dnode_info
structures from 1.8M to a mere 62872 (3.5%) in the degenerate case
referenced above.
This version of the patch also correctly rememembers the highest node
version# seen for an inode when it's scanned.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-25 03:23:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if ( fd - > version  >  rii - > mctime_ver  & &  je32_to_cpu ( rd - > mctime ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										rii - > mctime_ver  =  fd - > version ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										rii - > latest_mctime  =  je32_to_cpu ( rd - > mctime ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-11-07 11:16:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/*
 
							 
						 
					
						
							
								
									
										
										
										
											2005-07-27 15:46:14 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									 *  Copy  as  much  of  the  name  as  possible  from  the  raw 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  dirent  we ' ve  already  read  from  the  flash . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( read  >  sizeof ( * rd ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										memcpy ( & fd - > name [ 0 ] ,  & rd - > name [ 0 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										       min_t ( uint32_t ,  rd - > nsize ,  ( read  -  sizeof ( * rd ) )  ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-11-07 11:16:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-27 15:46:14 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* Do we need to copy any more of the name directly from the flash? */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( rd - > nsize  +  sizeof ( * rd )  >  read )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* FIXME: point() */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										int  err ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										int  already  =  read  -  sizeof ( * rd ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-11-07 11:16:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										err  =  jffs2_flash_read ( c ,  ( ref_offset ( ref ) )  +  read , 
							 
						 
					
						
							
								
									
										
										
										
											2005-07-27 15:46:14 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												rd - > nsize  -  already ,  & read ,  & fd - > name [ already ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( unlikely ( read  ! =  rd - > nsize  -  already )  & &  likely ( ! err ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  - EIO ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-11-07 11:16:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-27 15:46:14 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( unlikely ( err ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2005-07-28 15:46:43 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											JFFS2_ERROR ( " read remainder of name: error %d \n " ,  err ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-07-27 15:46:14 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											jffs2_free_full_dirent ( fd ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  - EIO ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2005-11-07 11:16:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-27 15:46:14 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									fd - > nhash  =  full_name_hash ( fd - > name ,  rd - > nsize ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									fd - > next  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									fd - > name [ rd - > nsize ]  =  ' \0 ' ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-11-07 11:16:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-27 15:46:14 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/*
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  Wheee .  We  now  have  a  complete  jffs2_full_dirent  structure ,  with 
							 
						 
					
						
							
								
									
										
										
										
											2005-11-07 11:16:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									 *  the  name  in  it  and  everything .  Link  it  into  the  list 
							 
						 
					
						
							
								
									
										
										
										
											2005-07-27 15:46:14 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									 */ 
							 
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] Improve read_inode memory usage, v2.
We originally used to read every node and allocate a jffs2_tmp_dnode_info
structure for each, before processing them in (reverse) version order
and discarding the ones which are obsoleted by later nodes.
With huge logfiles, this behaviour caused memory problems. For example, a
file involved in OLPC trac #1292 has 1822391 nodes, and would cause the XO
machine to run out of memory during the first stage of read_inode().
Instead of just inserting nodes into a tree in version order as we find
them, we now put them into a tree in order of their offset within the
file, which allows us to immediately discard nodes which are completely
obsoleted.
We don't use a full tree with 'fragments' pointing to the real data
structure, as we do in the normal fragtree. We sort only on the start
address, and add an 'overlapped' flag to the tmp_dnode_info to indicate
that the node in question is (partially) overlapped by another.
When the scan is complete, we start at the end of the file, adding each
node to a real fragtree as before. Where the node is non-overlapped, we
just add it (it doesn't matter that it's not the latest version; there is
no overlap). When the node at the end of the tree _is_ overlapped, we sort
it and all its overlapping nodes into version order and then add them to
the fragtree in that order.
This 'early discard' reduces the peak allocation of tmp_dnode_info
structures from 1.8M to a mere 62872 (3.5%) in the degenerate case
referenced above.
This version of the patch also correctly rememembers the highest node
version# seen for an inode when it's scanned.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-25 03:23:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									jffs2_add_fd_to_list ( c ,  fd ,  & rii - > fds ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-07-27 15:46:14 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-27 15:46:14 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Helper  function  for  jffs2_get_inode_nodes ( ) . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  It  is  called  every  time  an  inode  node  is  found . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
									
										
										
										
											2007-07-03 16:51:19 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  Returns :  0  on  success  ( possibly  after  marking  a  bad  node  obsolete ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-07-27 15:46:14 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  	    negative  error  code  on  failure . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
									
										
										
										
											2005-08-01 13:05:22 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  inline  int  read_dnode ( struct  jffs2_sb_info  * c ,  struct  jffs2_raw_node_ref  * ref ,  
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] Improve read_inode memory usage, v2.
We originally used to read every node and allocate a jffs2_tmp_dnode_info
structure for each, before processing them in (reverse) version order
and discarding the ones which are obsoleted by later nodes.
With huge logfiles, this behaviour caused memory problems. For example, a
file involved in OLPC trac #1292 has 1822391 nodes, and would cause the XO
machine to run out of memory during the first stage of read_inode().
Instead of just inserting nodes into a tree in version order as we find
them, we now put them into a tree in order of their offset within the
file, which allows us to immediately discard nodes which are completely
obsoleted.
We don't use a full tree with 'fragments' pointing to the real data
structure, as we do in the normal fragtree. We sort only on the start
address, and add an 'overlapped' flag to the tmp_dnode_info to indicate
that the node in question is (partially) overlapped by another.
When the scan is complete, we start at the end of the file, adding each
node to a real fragtree as before. Where the node is non-overlapped, we
just add it (it doesn't matter that it's not the latest version; there is
no overlap). When the node at the end of the tree _is_ overlapped, we sort
it and all its overlapping nodes into version order and then add them to
the fragtree in that order.
This 'early discard' reduces the peak allocation of tmp_dnode_info
structures from 1.8M to a mere 62872 (3.5%) in the degenerate case
referenced above.
This version of the patch also correctly rememembers the highest node
version# seen for an inode when it's scanned.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-25 03:23:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											     struct  jffs2_raw_inode  * rd ,  int  rdlen , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											     struct  jffs2_readinode_info  * rii ) 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2005-07-27 15:46:14 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  jffs2_tmp_dnode_info  * tn ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-08-01 13:05:22 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									uint32_t  len ,  csize ; 
							 
						 
					
						
							
								
									
										
										
										
											2007-07-03 16:51:19 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									int  ret  =  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-06-18 22:44:21 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									uint32_t  crc ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-11-07 11:16:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-27 15:46:14 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* Obsoleted. This cannot happen, surely? dwmw2 20020308 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									BUG_ON ( ref_obsolete ( ref ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2006-06-18 22:44:21 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									crc  =  crc32 ( 0 ,  rd ,  sizeof ( * rd )  -  8 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( unlikely ( crc  ! =  je32_to_cpu ( rd - > node_crc ) ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										JFFS2_NOTICE ( " node CRC failed on dnode at %#08x: read %#08x, calculated %#08x \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											     ref_offset ( ref ) ,  je32_to_cpu ( rd - > node_crc ) ,  crc ) ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] Improve read_inode memory usage, v2.
We originally used to read every node and allocate a jffs2_tmp_dnode_info
structure for each, before processing them in (reverse) version order
and discarding the ones which are obsoleted by later nodes.
With huge logfiles, this behaviour caused memory problems. For example, a
file involved in OLPC trac #1292 has 1822391 nodes, and would cause the XO
machine to run out of memory during the first stage of read_inode().
Instead of just inserting nodes into a tree in version order as we find
them, we now put them into a tree in order of their offset within the
file, which allows us to immediately discard nodes which are completely
obsoleted.
We don't use a full tree with 'fragments' pointing to the real data
structure, as we do in the normal fragtree. We sort only on the start
address, and add an 'overlapped' flag to the tmp_dnode_info to indicate
that the node in question is (partially) overlapped by another.
When the scan is complete, we start at the end of the file, adding each
node to a real fragtree as before. Where the node is non-overlapped, we
just add it (it doesn't matter that it's not the latest version; there is
no overlap). When the node at the end of the tree _is_ overlapped, we sort
it and all its overlapping nodes into version order and then add them to
the fragtree in that order.
This 'early discard' reduces the peak allocation of tmp_dnode_info
structures from 1.8M to a mere 62872 (3.5%) in the degenerate case
referenced above.
This version of the patch also correctly rememembers the highest node
version# seen for an inode when it's scanned.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-25 03:23:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										jffs2_mark_node_obsolete ( c ,  ref ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-06-18 22:44:21 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-08-01 13:05:22 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									tn  =  jffs2_alloc_tmp_dnode_info ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! tn )  { 
							 
						 
					
						
							
								
									
										
										
										
											2006-04-11 20:12:10 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										JFFS2_ERROR ( " failed to allocate tn (%zu bytes). \n " ,  sizeof ( * tn ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-08-01 13:05:22 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  - ENOMEM ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									tn - > partial_crc  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									csize  =  je32_to_cpu ( rd - > csize ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-11-07 11:16:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-27 15:46:14 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* If we've never checked the CRCs on this node, check them now */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ref_flags ( ref )  = =  REF_UNCHECKED )  { 
							 
						 
					
						
							
								
									
										
										
										
											2005-11-07 11:16:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-27 15:46:14 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										/* Sanity checks */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( unlikely ( je32_to_cpu ( rd - > offset )  >  je32_to_cpu ( rd - > isize ) )  | | 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										    unlikely ( PAD ( je32_to_cpu ( rd - > csize )  +  sizeof ( * rd ) )  ! =  PAD ( je32_to_cpu ( rd - > totlen ) ) ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2007-07-03 16:51:19 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											JFFS2_WARNING ( " inode node header CRC is corrupted at %#08x \n " ,  ref_offset ( ref ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											jffs2_dbg_dump_node ( c ,  ref_offset ( ref ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											jffs2_mark_node_obsolete ( c ,  ref ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-08-01 13:05:22 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											goto  free_out ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-08-01 13:05:22 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( jffs2_is_writebuffered ( c )  & &  csize  ! =  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											/* At this point we are supposed to check the data CRC
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  of  our  unchecked  node .  But  thus  far ,  we  do  not 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  know  whether  the  node  is  valid  or  obsolete .  To 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  figure  this  out ,  we  need  to  walk  all  the  nodes  of 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  the  inode  and  build  the  inode  fragtree .  We  don ' t 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  want  to  spend  time  checking  data  of  nodes  which  may 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  later  be  found  to  be  obsolete .  So  we  put  off  the  full 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  data  CRC  checking  until  we  have  read  all  the  inode 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  nodes  and  have  started  building  the  fragtree . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  The  fragtree  is  being  built  starting  with  nodes 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  having  the  highest  version  number ,  so  we ' ll  be  able 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  to  detect  whether  a  node  is  valid  ( i . e . ,  it  is  not 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  overlapped  by  a  node  with  higher  version )  or  not . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  And  we ' ll  be  able  to  check  only  those  nodes ,  which 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  are  not  obsolete . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  Of  course ,  this  optimization  only  makes  sense  in  case 
							 
						 
					
						
							
								
									
										
										
										
											2008-02-03 15:14:02 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											 *  of  NAND  flashes  ( or  other  flashes  with 
							 
						 
					
						
							
								
									
										
										
										
											2005-08-01 13:05:22 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											 *  ! jffs2_can_mark_obsolete ( ) ) ,  since  on  NOR  flashes 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  nodes  are  marked  obsolete  physically . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  Since  NAND  flashes  ( or  other  flashes  with 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  jffs2_is_writebuffered ( c ) )  are  anyway  read  by 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  fractions  of  c - > wbuf_pagesize ,  and  we  have  just  read 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  the  node  header ,  it  is  likely  that  the  starting  part 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  of  the  node  data  is  also  read  when  we  read  the 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  header .  So  we  don ' t  mind  to  check  the  CRC  of  the 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  starting  part  of  the  data  of  the  node  now ,  and  check 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  the  second  part  later  ( in  jffs2_check_node_data ( ) ) . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  Of  course ,  we  will  not  need  to  re - read  and  re - check 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  the  NAND  page  which  we  have  just  read .  This  is  why  we 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  read  the  whole  NAND  page  at  jffs2_get_inode_nodes ( ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  while  we  needed  only  the  node  header . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											unsigned  char  * buf ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											/* 'buf' will point to the start of data */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											buf  =  ( unsigned  char  * ) rd  +  sizeof ( * rd ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											/* len will be the read data length */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											len  =  min_t ( uint32_t ,  rdlen  -  sizeof ( * rd ) ,  csize ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-08-17 15:57:43 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											tn - > partial_crc  =  crc32 ( 0 ,  buf ,  len ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-09-22 12:25:00 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											dbg_readinode ( " Calculates CRC (%#08x) for %d bytes, csize %d \n " ,  tn - > partial_crc ,  len ,  csize ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-08-01 13:05:22 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											/* If we actually calculated the whole data CRC
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  and  it  is  wrong ,  drop  the  node .  */ 
							 
						 
					
						
							
								
									
										
										
										
											2005-08-04 12:40:02 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											if  ( len  > =  csize  & &  unlikely ( tn - > partial_crc  ! =  je32_to_cpu ( rd - > data_crc ) ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2005-08-03 10:26:50 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												JFFS2_NOTICE ( " wrong data CRC in data node at 0x%08x: read %#08x, calculated %#08x. \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													ref_offset ( ref ) ,  tn - > partial_crc ,  je32_to_cpu ( rd - > data_crc ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2007-07-03 16:51:19 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												jffs2_mark_node_obsolete ( c ,  ref ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-08-01 13:05:22 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												goto  free_out ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-08-03 10:26:50 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-08-01 13:05:22 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										}  else  if  ( csize  = =  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											/*
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  We  checked  the  header  CRC .  If  the  node  has  no  data ,  adjust 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  the  space  accounting  now .  For  other  nodes  this  will  be  done 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  later  either  when  the  node  is  marked  obsolete  or  when  its 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  data  is  checked . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											struct  jffs2_eraseblock  * jeb ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-09-22 12:25:00 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											dbg_readinode ( " the node has no data. \n " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-08-01 13:05:22 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											jeb  =  & c - > blocks [ ref - > flash_offset  /  c - > sector_size ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											len  =  ref_totlen ( c ,  jeb ,  ref ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											spin_lock ( & c - > erase_completion_lock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											jeb - > used_size  + =  len ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											jeb - > unchecked_size  - =  len ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											c - > used_size  + =  len ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											c - > unchecked_size  - =  len ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-07-27 15:46:14 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											ref - > flash_offset  =  ref_offset ( ref )  |  REF_NORMAL ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-08-01 13:05:22 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											spin_unlock ( & c - > erase_completion_lock ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-27 15:46:14 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									tn - > fn  =  jffs2_alloc_full_dnode ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! tn - > fn )  { 
							 
						 
					
						
							
								
									
										
										
										
											2005-07-28 15:46:43 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										JFFS2_ERROR ( " alloc fn failed \n " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-08-01 13:05:22 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										ret  =  - ENOMEM ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										goto  free_out ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-07-27 15:46:14 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2005-11-07 11:16:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-27 15:46:14 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									tn - > version  =  je32_to_cpu ( rd - > version ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									tn - > fn - > ofs  =  je32_to_cpu ( rd - > offset ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-08-01 13:05:22 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									tn - > data_crc  =  je32_to_cpu ( rd - > data_crc ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									tn - > csize  =  csize ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-07-27 15:46:14 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									tn - > fn - > raw  =  ref ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] Improve read_inode memory usage, v2.
We originally used to read every node and allocate a jffs2_tmp_dnode_info
structure for each, before processing them in (reverse) version order
and discarding the ones which are obsoleted by later nodes.
With huge logfiles, this behaviour caused memory problems. For example, a
file involved in OLPC trac #1292 has 1822391 nodes, and would cause the XO
machine to run out of memory during the first stage of read_inode().
Instead of just inserting nodes into a tree in version order as we find
them, we now put them into a tree in order of their offset within the
file, which allows us to immediately discard nodes which are completely
obsoleted.
We don't use a full tree with 'fragments' pointing to the real data
structure, as we do in the normal fragtree. We sort only on the start
address, and add an 'overlapped' flag to the tmp_dnode_info to indicate
that the node in question is (partially) overlapped by another.
When the scan is complete, we start at the end of the file, adding each
node to a real fragtree as before. Where the node is non-overlapped, we
just add it (it doesn't matter that it's not the latest version; there is
no overlap). When the node at the end of the tree _is_ overlapped, we sort
it and all its overlapping nodes into version order and then add them to
the fragtree in that order.
This 'early discard' reduces the peak allocation of tmp_dnode_info
structures from 1.8M to a mere 62872 (3.5%) in the degenerate case
referenced above.
This version of the patch also correctly rememembers the highest node
version# seen for an inode when it's scanned.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-25 03:23:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									tn - > overlapped  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( tn - > version  >  rii - > highest_version ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										rii - > highest_version  =  tn - > version ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-11-07 11:16:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-27 15:46:14 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* There was a bug where we wrote hole nodes out with
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									   csize / dsize  swapped .  Deal  with  it  */ 
							 
						 
					
						
							
								
									
										
										
										
											2005-08-01 13:05:22 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( rd - > compr  = =  JFFS2_COMPR_ZERO  & &  ! je32_to_cpu ( rd - > dsize )  & &  csize ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										tn - > fn - > size  =  csize ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-07-27 15:46:14 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									else  // normal case...
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										tn - > fn - > size  =  je32_to_cpu ( rd - > dsize ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2008-04-23 16:43:15 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									dbg_readinode2 ( " dnode @%08x: ver %u, offset %#04x, dsize %#04x, csize %#04x \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										       ref_offset ( ref ) ,  je32_to_cpu ( rd - > version ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										       je32_to_cpu ( rd - > offset ) ,  je32_to_cpu ( rd - > dsize ) ,  csize ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-11-07 11:16:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] Improve read_inode memory usage, v2.
We originally used to read every node and allocate a jffs2_tmp_dnode_info
structure for each, before processing them in (reverse) version order
and discarding the ones which are obsoleted by later nodes.
With huge logfiles, this behaviour caused memory problems. For example, a
file involved in OLPC trac #1292 has 1822391 nodes, and would cause the XO
machine to run out of memory during the first stage of read_inode().
Instead of just inserting nodes into a tree in version order as we find
them, we now put them into a tree in order of their offset within the
file, which allows us to immediately discard nodes which are completely
obsoleted.
We don't use a full tree with 'fragments' pointing to the real data
structure, as we do in the normal fragtree. We sort only on the start
address, and add an 'overlapped' flag to the tmp_dnode_info to indicate
that the node in question is (partially) overlapped by another.
When the scan is complete, we start at the end of the file, adding each
node to a real fragtree as before. Where the node is non-overlapped, we
just add it (it doesn't matter that it's not the latest version; there is
no overlap). When the node at the end of the tree _is_ overlapped, we sort
it and all its overlapping nodes into version order and then add them to
the fragtree in that order.
This 'early discard' reduces the peak allocation of tmp_dnode_info
structures from 1.8M to a mere 62872 (3.5%) in the degenerate case
referenced above.
This version of the patch also correctly rememembers the highest node
version# seen for an inode when it's scanned.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-25 03:23:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ret  =  jffs2_add_tn_to_tree ( c ,  rii ,  tn ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] Improve read_inode memory usage, v2.
We originally used to read every node and allocate a jffs2_tmp_dnode_info
structure for each, before processing them in (reverse) version order
and discarding the ones which are obsoleted by later nodes.
With huge logfiles, this behaviour caused memory problems. For example, a
file involved in OLPC trac #1292 has 1822391 nodes, and would cause the XO
machine to run out of memory during the first stage of read_inode().
Instead of just inserting nodes into a tree in version order as we find
them, we now put them into a tree in order of their offset within the
file, which allows us to immediately discard nodes which are completely
obsoleted.
We don't use a full tree with 'fragments' pointing to the real data
structure, as we do in the normal fragtree. We sort only on the start
address, and add an 'overlapped' flag to the tmp_dnode_info to indicate
that the node in question is (partially) overlapped by another.
When the scan is complete, we start at the end of the file, adding each
node to a real fragtree as before. Where the node is non-overlapped, we
just add it (it doesn't matter that it's not the latest version; there is
no overlap). When the node at the end of the tree _is_ overlapped, we sort
it and all its overlapping nodes into version order and then add them to
the fragtree in that order.
This 'early discard' reduces the peak allocation of tmp_dnode_info
structures from 1.8M to a mere 62872 (3.5%) in the degenerate case
referenced above.
This version of the patch also correctly rememembers the highest node
version# seen for an inode when it's scanned.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-25 03:23:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ret )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										jffs2_free_full_dnode ( tn - > fn ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									free_out : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										jffs2_free_tmp_dnode_info ( tn ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  ret ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2008-04-23 16:43:15 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# ifdef JFFS2_DBG_READINODE2_MESSAGES 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									dbg_readinode2 ( " After adding ver %d: \n " ,  je32_to_cpu ( rd - > version ) ) ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] Improve read_inode memory usage, v2.
We originally used to read every node and allocate a jffs2_tmp_dnode_info
structure for each, before processing them in (reverse) version order
and discarding the ones which are obsoleted by later nodes.
With huge logfiles, this behaviour caused memory problems. For example, a
file involved in OLPC trac #1292 has 1822391 nodes, and would cause the XO
machine to run out of memory during the first stage of read_inode().
Instead of just inserting nodes into a tree in version order as we find
them, we now put them into a tree in order of their offset within the
file, which allows us to immediately discard nodes which are completely
obsoleted.
We don't use a full tree with 'fragments' pointing to the real data
structure, as we do in the normal fragtree. We sort only on the start
address, and add an 'overlapped' flag to the tmp_dnode_info to indicate
that the node in question is (partially) overlapped by another.
When the scan is complete, we start at the end of the file, adding each
node to a real fragtree as before. Where the node is non-overlapped, we
just add it (it doesn't matter that it's not the latest version; there is
no overlap). When the node at the end of the tree _is_ overlapped, we sort
it and all its overlapping nodes into version order and then add them to
the fragtree in that order.
This 'early discard' reduces the peak allocation of tmp_dnode_info
structures from 1.8M to a mere 62872 (3.5%) in the degenerate case
referenced above.
This version of the patch also correctly rememembers the highest node
version# seen for an inode when it's scanned.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-25 03:23:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									tn  =  tn_first ( & rii - > tn_root ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									while  ( tn )  { 
							 
						 
					
						
							
								
									
										
										
										
											2008-04-23 16:43:15 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										dbg_readinode2 ( " %p: v %d r 0x%x-0x%x ov %d \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											       tn ,  tn - > version ,  tn - > fn - > ofs , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											       tn - > fn - > ofs + tn - > fn - > size ,  tn - > overlapped ) ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] Improve read_inode memory usage, v2.
We originally used to read every node and allocate a jffs2_tmp_dnode_info
structure for each, before processing them in (reverse) version order
and discarding the ones which are obsoleted by later nodes.
With huge logfiles, this behaviour caused memory problems. For example, a
file involved in OLPC trac #1292 has 1822391 nodes, and would cause the XO
machine to run out of memory during the first stage of read_inode().
Instead of just inserting nodes into a tree in version order as we find
them, we now put them into a tree in order of their offset within the
file, which allows us to immediately discard nodes which are completely
obsoleted.
We don't use a full tree with 'fragments' pointing to the real data
structure, as we do in the normal fragtree. We sort only on the start
address, and add an 'overlapped' flag to the tmp_dnode_info to indicate
that the node in question is (partially) overlapped by another.
When the scan is complete, we start at the end of the file, adding each
node to a real fragtree as before. Where the node is non-overlapped, we
just add it (it doesn't matter that it's not the latest version; there is
no overlap). When the node at the end of the tree _is_ overlapped, we sort
it and all its overlapping nodes into version order and then add them to
the fragtree in that order.
This 'early discard' reduces the peak allocation of tmp_dnode_info
structures from 1.8M to a mere 62872 (3.5%) in the degenerate case
referenced above.
This version of the patch also correctly rememembers the highest node
version# seen for an inode when it's scanned.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-25 03:23:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										tn  =  tn_next ( tn ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-27 15:46:14 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Helper  function  for  jffs2_get_inode_nodes ( ) . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  It  is  called  every  time  an  unknown  node  is  found . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
									
										
										
										
											2006-06-18 00:05:26 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  Returns :  0  on  success ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-07-27 15:46:14 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  	    negative  error  code  on  failure . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
									
										
										
										
											2005-08-01 13:05:22 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  inline  int  read_unknown ( struct  jffs2_sb_info  * c ,  struct  jffs2_raw_node_ref  * ref ,  struct  jffs2_unknown_node  * un )  
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2005-07-27 15:46:14 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* We don't mark unknown nodes as REF_UNCHECKED */ 
							 
						 
					
						
							
								
									
										
										
										
											2007-03-09 11:44:00 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ref_flags ( ref )  = =  REF_UNCHECKED )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										JFFS2_ERROR ( " REF_UNCHECKED but unknown node at %#08x \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											    ref_offset ( ref ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										JFFS2_ERROR ( " Node is {%04x,%04x,%08x,%08x}. Please report this error. \n " , 
							 
						 
					
						
							
								
									
										
										
										
											2007-07-10 10:01:22 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											    je16_to_cpu ( un - > magic ) ,  je16_to_cpu ( un - > nodetype ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											    je32_to_cpu ( un - > totlen ) ,  je32_to_cpu ( un - > hdr_crc ) ) ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] Improve read_inode memory usage, v2.
We originally used to read every node and allocate a jffs2_tmp_dnode_info
structure for each, before processing them in (reverse) version order
and discarding the ones which are obsoleted by later nodes.
With huge logfiles, this behaviour caused memory problems. For example, a
file involved in OLPC trac #1292 has 1822391 nodes, and would cause the XO
machine to run out of memory during the first stage of read_inode().
Instead of just inserting nodes into a tree in version order as we find
them, we now put them into a tree in order of their offset within the
file, which allows us to immediately discard nodes which are completely
obsoleted.
We don't use a full tree with 'fragments' pointing to the real data
structure, as we do in the normal fragtree. We sort only on the start
address, and add an 'overlapped' flag to the tmp_dnode_info to indicate
that the node in question is (partially) overlapped by another.
When the scan is complete, we start at the end of the file, adding each
node to a real fragtree as before. Where the node is non-overlapped, we
just add it (it doesn't matter that it's not the latest version; there is
no overlap). When the node at the end of the tree _is_ overlapped, we sort
it and all its overlapping nodes into version order and then add them to
the fragtree in that order.
This 'early discard' reduces the peak allocation of tmp_dnode_info
structures from 1.8M to a mere 62872 (3.5%) in the degenerate case
referenced above.
This version of the patch also correctly rememembers the highest node
version# seen for an inode when it's scanned.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-25 03:23:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										jffs2_mark_node_obsolete ( c ,  ref ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2007-03-09 11:44:00 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2005-11-07 11:16:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-27 15:46:14 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									un - > nodetype  =  cpu_to_je16 ( JFFS2_NODE_ACCURATE  |  je16_to_cpu ( un - > nodetype ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2006-06-18 00:05:26 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									switch ( je16_to_cpu ( un - > nodetype )  &  JFFS2_COMPAT_MASK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  JFFS2_FEATURE_INCOMPAT : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										JFFS2_ERROR ( " unknown INCOMPAT nodetype %#04X at %#08x \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											    je16_to_cpu ( un - > nodetype ) ,  ref_offset ( ref ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* EEP */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										BUG ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  JFFS2_FEATURE_ROCOMPAT : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										JFFS2_ERROR ( " unknown ROCOMPAT nodetype %#04X at %#08x \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											    je16_to_cpu ( un - > nodetype ) ,  ref_offset ( ref ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										BUG_ON ( ! ( c - > flags  &  JFFS2_SB_FLAG_RO ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  JFFS2_FEATURE_RWCOMPAT_COPY : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										JFFS2_NOTICE ( " unknown RWCOMPAT_COPY nodetype %#04X at %#08x \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											     je16_to_cpu ( un - > nodetype ) ,  ref_offset ( ref ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  JFFS2_FEATURE_RWCOMPAT_DELETE : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										JFFS2_NOTICE ( " unknown RWCOMPAT_DELETE nodetype %#04X at %#08x \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											     je16_to_cpu ( un - > nodetype ) ,  ref_offset ( ref ) ) ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] Improve read_inode memory usage, v2.
We originally used to read every node and allocate a jffs2_tmp_dnode_info
structure for each, before processing them in (reverse) version order
and discarding the ones which are obsoleted by later nodes.
With huge logfiles, this behaviour caused memory problems. For example, a
file involved in OLPC trac #1292 has 1822391 nodes, and would cause the XO
machine to run out of memory during the first stage of read_inode().
Instead of just inserting nodes into a tree in version order as we find
them, we now put them into a tree in order of their offset within the
file, which allows us to immediately discard nodes which are completely
obsoleted.
We don't use a full tree with 'fragments' pointing to the real data
structure, as we do in the normal fragtree. We sort only on the start
address, and add an 'overlapped' flag to the tmp_dnode_info to indicate
that the node in question is (partially) overlapped by another.
When the scan is complete, we start at the end of the file, adding each
node to a real fragtree as before. Where the node is non-overlapped, we
just add it (it doesn't matter that it's not the latest version; there is
no overlap). When the node at the end of the tree _is_ overlapped, we sort
it and all its overlapping nodes into version order and then add them to
the fragtree in that order.
This 'early discard' reduces the peak allocation of tmp_dnode_info
structures from 1.8M to a mere 62872 (3.5%) in the degenerate case
referenced above.
This version of the patch also correctly rememembers the highest node
version# seen for an inode when it's scanned.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-25 03:23:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										jffs2_mark_node_obsolete ( c ,  ref ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-27 15:46:14 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-08-01 13:05:22 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/*
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Helper  function  for  jffs2_get_inode_nodes ( ) . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  The  function  detects  whether  more  data  should  be  read  and  reads  it  if  yes . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
									
										
										
											
												tree-wide: fix assorted typos all over the place
That is "success", "unknown", "through", "performance", "[re|un]mapping"
, "access", "default", "reasonable", "[con]currently", "temperature"
, "channel", "[un]used", "application", "example","hierarchy", "therefore"
, "[over|under]flow", "contiguous", "threshold", "enough" and others.
Signed-off-by: André Goddard Rosa <andre.goddard@gmail.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
											 
										 
										
											2009-11-14 13:09:05 -02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  Returns :  0  on  success ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-08-01 13:05:22 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  	    negative  error  code  on  failure . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  int  read_more ( struct  jffs2_sb_info  * c ,  struct  jffs2_raw_node_ref  * ref ,  
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] fix buffer sise calculations in jffs2_get_inode_nodes()
In read inode we have an optimization which prevents one
min. I/O unit (e.g. NAND page) to be read more then once.
Namely, at the beginning we do not know which node type we read,
so we read so we assume we read the directory entry, because it
has the smallest node header. When we read it, we read up to the
next min. I/O unit, just because if later we'll need to read more,
we already have this data.
If it turns out to be that the node is not directory entry, and
we need more data, and we did not read it because it sits in the
next min. I/O unit, we read the whole next (or several next)
min. I/O unit(s). And if it happens to be that we read a data node,
and we've read part of its data, we calculate partial CRC.
So if later we need to check data CRC, we'll only read the rest
of the data from further min. I/O units and continue CRC checking.
This code was a bit messy and buggy. The bug was that it assumed
relatively large min. I/O unit, so that the largest node header
could overlap only one min. I/O unit boundary.
This parch clean-ups the code a bit and fixes this bug.
The patch was not tested on flash with small min. I/O unit, like
NOR-ECC, nut it was tested on NAND with 512 bytes NAND page, so
it at least does not break NAND. It was also tested with mtdram
so it should not break NOR.
Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-04 13:59:11 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										     int  needed_len ,  int  * rdlen ,  unsigned  char  * buf ) 
							 
						 
					
						
							
								
									
										
										
										
											2005-08-01 13:05:22 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] fix buffer sise calculations in jffs2_get_inode_nodes()
In read inode we have an optimization which prevents one
min. I/O unit (e.g. NAND page) to be read more then once.
Namely, at the beginning we do not know which node type we read,
so we read so we assume we read the directory entry, because it
has the smallest node header. When we read it, we read up to the
next min. I/O unit, just because if later we'll need to read more,
we already have this data.
If it turns out to be that the node is not directory entry, and
we need more data, and we did not read it because it sits in the
next min. I/O unit, we read the whole next (or several next)
min. I/O unit(s). And if it happens to be that we read a data node,
and we've read part of its data, we calculate partial CRC.
So if later we need to check data CRC, we'll only read the rest
of the data from further min. I/O units and continue CRC checking.
This code was a bit messy and buggy. The bug was that it assumed
relatively large min. I/O unit, so that the largest node header
could overlap only one min. I/O unit boundary.
This parch clean-ups the code a bit and fixes this bug.
The patch was not tested on flash with small min. I/O unit, like
NOR-ECC, nut it was tested on NAND with 512 bytes NAND page, so
it at least does not break NAND. It was also tested with mtdram
so it should not break NOR.
Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-04 13:59:11 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									int  err ,  to_read  =  needed_len  -  * rdlen ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-08-01 13:05:22 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									size_t  retlen ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									uint32_t  offs ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( jffs2_is_writebuffered ( c ) )  { 
							 
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] fix buffer sise calculations in jffs2_get_inode_nodes()
In read inode we have an optimization which prevents one
min. I/O unit (e.g. NAND page) to be read more then once.
Namely, at the beginning we do not know which node type we read,
so we read so we assume we read the directory entry, because it
has the smallest node header. When we read it, we read up to the
next min. I/O unit, just because if later we'll need to read more,
we already have this data.
If it turns out to be that the node is not directory entry, and
we need more data, and we did not read it because it sits in the
next min. I/O unit, we read the whole next (or several next)
min. I/O unit(s). And if it happens to be that we read a data node,
and we've read part of its data, we calculate partial CRC.
So if later we need to check data CRC, we'll only read the rest
of the data from further min. I/O units and continue CRC checking.
This code was a bit messy and buggy. The bug was that it assumed
relatively large min. I/O unit, so that the largest node header
could overlap only one min. I/O unit boundary.
This parch clean-ups the code a bit and fixes this bug.
The patch was not tested on flash with small min. I/O unit, like
NOR-ECC, nut it was tested on NAND with 512 bytes NAND page, so
it at least does not break NAND. It was also tested with mtdram
so it should not break NOR.
Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-04 13:59:11 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										int  rem  =  to_read  %  c - > wbuf_pagesize ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-08-01 13:05:22 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] fix buffer sise calculations in jffs2_get_inode_nodes()
In read inode we have an optimization which prevents one
min. I/O unit (e.g. NAND page) to be read more then once.
Namely, at the beginning we do not know which node type we read,
so we read so we assume we read the directory entry, because it
has the smallest node header. When we read it, we read up to the
next min. I/O unit, just because if later we'll need to read more,
we already have this data.
If it turns out to be that the node is not directory entry, and
we need more data, and we did not read it because it sits in the
next min. I/O unit, we read the whole next (or several next)
min. I/O unit(s). And if it happens to be that we read a data node,
and we've read part of its data, we calculate partial CRC.
So if later we need to check data CRC, we'll only read the rest
of the data from further min. I/O units and continue CRC checking.
This code was a bit messy and buggy. The bug was that it assumed
relatively large min. I/O unit, so that the largest node header
could overlap only one min. I/O unit boundary.
This parch clean-ups the code a bit and fixes this bug.
The patch was not tested on flash with small min. I/O unit, like
NOR-ECC, nut it was tested on NAND with 512 bytes NAND page, so
it at least does not break NAND. It was also tested with mtdram
so it should not break NOR.
Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-04 13:59:11 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( rem ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											to_read  + =  c - > wbuf_pagesize  -  rem ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2005-08-01 13:05:22 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* We need to read more data */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									offs  =  ref_offset ( ref )  +  * rdlen ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-11-07 11:16:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] fix buffer sise calculations in jffs2_get_inode_nodes()
In read inode we have an optimization which prevents one
min. I/O unit (e.g. NAND page) to be read more then once.
Namely, at the beginning we do not know which node type we read,
so we read so we assume we read the directory entry, because it
has the smallest node header. When we read it, we read up to the
next min. I/O unit, just because if later we'll need to read more,
we already have this data.
If it turns out to be that the node is not directory entry, and
we need more data, and we did not read it because it sits in the
next min. I/O unit, we read the whole next (or several next)
min. I/O unit(s). And if it happens to be that we read a data node,
and we've read part of its data, we calculate partial CRC.
So if later we need to check data CRC, we'll only read the rest
of the data from further min. I/O units and continue CRC checking.
This code was a bit messy and buggy. The bug was that it assumed
relatively large min. I/O unit, so that the largest node header
could overlap only one min. I/O unit boundary.
This parch clean-ups the code a bit and fixes this bug.
The patch was not tested on flash with small min. I/O unit, like
NOR-ECC, nut it was tested on NAND with 512 bytes NAND page, so
it at least does not break NAND. It was also tested with mtdram
so it should not break NOR.
Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-04 13:59:11 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									dbg_readinode ( " read more %d bytes \n " ,  to_read ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-08-01 13:05:22 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] fix buffer sise calculations in jffs2_get_inode_nodes()
In read inode we have an optimization which prevents one
min. I/O unit (e.g. NAND page) to be read more then once.
Namely, at the beginning we do not know which node type we read,
so we read so we assume we read the directory entry, because it
has the smallest node header. When we read it, we read up to the
next min. I/O unit, just because if later we'll need to read more,
we already have this data.
If it turns out to be that the node is not directory entry, and
we need more data, and we did not read it because it sits in the
next min. I/O unit, we read the whole next (or several next)
min. I/O unit(s). And if it happens to be that we read a data node,
and we've read part of its data, we calculate partial CRC.
So if later we need to check data CRC, we'll only read the rest
of the data from further min. I/O units and continue CRC checking.
This code was a bit messy and buggy. The bug was that it assumed
relatively large min. I/O unit, so that the largest node header
could overlap only one min. I/O unit boundary.
This parch clean-ups the code a bit and fixes this bug.
The patch was not tested on flash with small min. I/O unit, like
NOR-ECC, nut it was tested on NAND with 512 bytes NAND page, so
it at least does not break NAND. It was also tested with mtdram
so it should not break NOR.
Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-04 13:59:11 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									err  =  jffs2_flash_read ( c ,  offs ,  to_read ,  & retlen ,  buf  +  * rdlen ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-08-01 13:05:22 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( err )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										JFFS2_ERROR ( " can not read %d bytes from 0x%08x,  " 
							 
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] fix buffer sise calculations in jffs2_get_inode_nodes()
In read inode we have an optimization which prevents one
min. I/O unit (e.g. NAND page) to be read more then once.
Namely, at the beginning we do not know which node type we read,
so we read so we assume we read the directory entry, because it
has the smallest node header. When we read it, we read up to the
next min. I/O unit, just because if later we'll need to read more,
we already have this data.
If it turns out to be that the node is not directory entry, and
we need more data, and we did not read it because it sits in the
next min. I/O unit, we read the whole next (or several next)
min. I/O unit(s). And if it happens to be that we read a data node,
and we've read part of its data, we calculate partial CRC.
So if later we need to check data CRC, we'll only read the rest
of the data from further min. I/O units and continue CRC checking.
This code was a bit messy and buggy. The bug was that it assumed
relatively large min. I/O unit, so that the largest node header
could overlap only one min. I/O unit boundary.
This parch clean-ups the code a bit and fixes this bug.
The patch was not tested on flash with small min. I/O unit, like
NOR-ECC, nut it was tested on NAND with 512 bytes NAND page, so
it at least does not break NAND. It was also tested with mtdram
so it should not break NOR.
Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-04 13:59:11 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											" error code: %d. \n " ,  to_read ,  offs ,  err ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-08-01 13:05:22 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  err ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2005-11-07 11:16:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] fix buffer sise calculations in jffs2_get_inode_nodes()
In read inode we have an optimization which prevents one
min. I/O unit (e.g. NAND page) to be read more then once.
Namely, at the beginning we do not know which node type we read,
so we read so we assume we read the directory entry, because it
has the smallest node header. When we read it, we read up to the
next min. I/O unit, just because if later we'll need to read more,
we already have this data.
If it turns out to be that the node is not directory entry, and
we need more data, and we did not read it because it sits in the
next min. I/O unit, we read the whole next (or several next)
min. I/O unit(s). And if it happens to be that we read a data node,
and we've read part of its data, we calculate partial CRC.
So if later we need to check data CRC, we'll only read the rest
of the data from further min. I/O units and continue CRC checking.
This code was a bit messy and buggy. The bug was that it assumed
relatively large min. I/O unit, so that the largest node header
could overlap only one min. I/O unit boundary.
This parch clean-ups the code a bit and fixes this bug.
The patch was not tested on flash with small min. I/O unit, like
NOR-ECC, nut it was tested on NAND with 512 bytes NAND page, so
it at least does not break NAND. It was also tested with mtdram
so it should not break NOR.
Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-04 13:59:11 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( retlen  <  to_read )  { 
							 
						 
					
						
							
								
									
										
										
										
											2006-04-11 20:12:10 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										JFFS2_ERROR ( " short read at %#08x: %zu instead of %d. \n " , 
							 
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] fix buffer sise calculations in jffs2_get_inode_nodes()
In read inode we have an optimization which prevents one
min. I/O unit (e.g. NAND page) to be read more then once.
Namely, at the beginning we do not know which node type we read,
so we read so we assume we read the directory entry, because it
has the smallest node header. When we read it, we read up to the
next min. I/O unit, just because if later we'll need to read more,
we already have this data.
If it turns out to be that the node is not directory entry, and
we need more data, and we did not read it because it sits in the
next min. I/O unit, we read the whole next (or several next)
min. I/O unit(s). And if it happens to be that we read a data node,
and we've read part of its data, we calculate partial CRC.
So if later we need to check data CRC, we'll only read the rest
of the data from further min. I/O units and continue CRC checking.
This code was a bit messy and buggy. The bug was that it assumed
relatively large min. I/O unit, so that the largest node header
could overlap only one min. I/O unit boundary.
This parch clean-ups the code a bit and fixes this bug.
The patch was not tested on flash with small min. I/O unit, like
NOR-ECC, nut it was tested on NAND with 512 bytes NAND page, so
it at least does not break NAND. It was also tested with mtdram
so it should not break NOR.
Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-04 13:59:11 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												offs ,  retlen ,  to_read ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-08-01 13:05:22 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  - EIO ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] fix buffer sise calculations in jffs2_get_inode_nodes()
In read inode we have an optimization which prevents one
min. I/O unit (e.g. NAND page) to be read more then once.
Namely, at the beginning we do not know which node type we read,
so we read so we assume we read the directory entry, because it
has the smallest node header. When we read it, we read up to the
next min. I/O unit, just because if later we'll need to read more,
we already have this data.
If it turns out to be that the node is not directory entry, and
we need more data, and we did not read it because it sits in the
next min. I/O unit, we read the whole next (or several next)
min. I/O unit(s). And if it happens to be that we read a data node,
and we've read part of its data, we calculate partial CRC.
So if later we need to check data CRC, we'll only read the rest
of the data from further min. I/O units and continue CRC checking.
This code was a bit messy and buggy. The bug was that it assumed
relatively large min. I/O unit, so that the largest node header
could overlap only one min. I/O unit boundary.
This parch clean-ups the code a bit and fixes this bug.
The patch was not tested on flash with small min. I/O unit, like
NOR-ECC, nut it was tested on NAND with 512 bytes NAND page, so
it at least does not break NAND. It was also tested with mtdram
so it should not break NOR.
Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-04 13:59:11 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									* rdlen  + =  to_read ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-08-01 13:05:22 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-27 15:46:14 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/* Get tmp_dnode_info and full_dirent for all non-obsolete nodes associated
  
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] Improve read_inode memory usage, v2.
We originally used to read every node and allocate a jffs2_tmp_dnode_info
structure for each, before processing them in (reverse) version order
and discarding the ones which are obsoleted by later nodes.
With huge logfiles, this behaviour caused memory problems. For example, a
file involved in OLPC trac #1292 has 1822391 nodes, and would cause the XO
machine to run out of memory during the first stage of read_inode().
Instead of just inserting nodes into a tree in version order as we find
them, we now put them into a tree in order of their offset within the
file, which allows us to immediately discard nodes which are completely
obsoleted.
We don't use a full tree with 'fragments' pointing to the real data
structure, as we do in the normal fragtree. We sort only on the start
address, and add an 'overlapped' flag to the tmp_dnode_info to indicate
that the node in question is (partially) overlapped by another.
When the scan is complete, we start at the end of the file, adding each
node to a real fragtree as before. Where the node is non-overlapped, we
just add it (it doesn't matter that it's not the latest version; there is
no overlap). When the node at the end of the tree _is_ overlapped, we sort
it and all its overlapping nodes into version order and then add them to
the fragtree in that order.
This 'early discard' reduces the peak allocation of tmp_dnode_info
structures from 1.8M to a mere 62872 (3.5%) in the degenerate case
referenced above.
This version of the patch also correctly rememembers the highest node
version# seen for an inode when it's scanned.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-25 03:23:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								   with  this  ino .  Perform  a  preliminary  ordering  on  data  nodes ,  throwing  away 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								   those  which  are  completely  obsoleted  by  newer  ones .  The  naïve  approach  we 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								   use  to  take  of  just  returning  them  _all_  in  version  order  will  cause  us  to 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								   run  out  of  memory  in  certain  degenerate  cases .  */ 
							 
						 
					
						
							
								
									
										
										
										
											2005-07-27 15:46:14 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  int  jffs2_get_inode_nodes ( struct  jffs2_sb_info  * c ,  struct  jffs2_inode_info  * f ,  
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] Improve read_inode memory usage, v2.
We originally used to read every node and allocate a jffs2_tmp_dnode_info
structure for each, before processing them in (reverse) version order
and discarding the ones which are obsoleted by later nodes.
With huge logfiles, this behaviour caused memory problems. For example, a
file involved in OLPC trac #1292 has 1822391 nodes, and would cause the XO
machine to run out of memory during the first stage of read_inode().
Instead of just inserting nodes into a tree in version order as we find
them, we now put them into a tree in order of their offset within the
file, which allows us to immediately discard nodes which are completely
obsoleted.
We don't use a full tree with 'fragments' pointing to the real data
structure, as we do in the normal fragtree. We sort only on the start
address, and add an 'overlapped' flag to the tmp_dnode_info to indicate
that the node in question is (partially) overlapped by another.
When the scan is complete, we start at the end of the file, adding each
node to a real fragtree as before. Where the node is non-overlapped, we
just add it (it doesn't matter that it's not the latest version; there is
no overlap). When the node at the end of the tree _is_ overlapped, we sort
it and all its overlapping nodes into version order and then add them to
the fragtree in that order.
This 'early discard' reduces the peak allocation of tmp_dnode_info
structures from 1.8M to a mere 62872 (3.5%) in the degenerate case
referenced above.
This version of the patch also correctly rememembers the highest node
version# seen for an inode when it's scanned.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-25 03:23:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												 struct  jffs2_readinode_info  * rii ) 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2005-07-27 15:46:14 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  jffs2_raw_node_ref  * ref ,  * valid_ref ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-08-01 13:05:22 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									unsigned  char  * buf  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									union  jffs2_node_union  * node ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-07-27 15:46:14 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									size_t  retlen ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-08-01 13:05:22 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									int  len ,  err ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] Improve read_inode memory usage, v2.
We originally used to read every node and allocate a jffs2_tmp_dnode_info
structure for each, before processing them in (reverse) version order
and discarding the ones which are obsoleted by later nodes.
With huge logfiles, this behaviour caused memory problems. For example, a
file involved in OLPC trac #1292 has 1822391 nodes, and would cause the XO
machine to run out of memory during the first stage of read_inode().
Instead of just inserting nodes into a tree in version order as we find
them, we now put them into a tree in order of their offset within the
file, which allows us to immediately discard nodes which are completely
obsoleted.
We don't use a full tree with 'fragments' pointing to the real data
structure, as we do in the normal fragtree. We sort only on the start
address, and add an 'overlapped' flag to the tmp_dnode_info to indicate
that the node in question is (partially) overlapped by another.
When the scan is complete, we start at the end of the file, adding each
node to a real fragtree as before. Where the node is non-overlapped, we
just add it (it doesn't matter that it's not the latest version; there is
no overlap). When the node at the end of the tree _is_ overlapped, we sort
it and all its overlapping nodes into version order and then add them to
the fragtree in that order.
This 'early discard' reduces the peak allocation of tmp_dnode_info
structures from 1.8M to a mere 62872 (3.5%) in the degenerate case
referenced above.
This version of the patch also correctly rememembers the highest node
version# seen for an inode when it's scanned.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-25 03:23:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									rii - > mctime_ver  =  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-11-07 11:16:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-09-22 12:25:00 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									dbg_readinode ( " ino #%u \n " ,  f - > inocache - > ino ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-08-01 13:05:22 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* FIXME: in case of NOR and available ->point() this
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  needs  to  be  fixed .  */ 
							 
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] fix buffer sise calculations in jffs2_get_inode_nodes()
In read inode we have an optimization which prevents one
min. I/O unit (e.g. NAND page) to be read more then once.
Namely, at the beginning we do not know which node type we read,
so we read so we assume we read the directory entry, because it
has the smallest node header. When we read it, we read up to the
next min. I/O unit, just because if later we'll need to read more,
we already have this data.
If it turns out to be that the node is not directory entry, and
we need more data, and we did not read it because it sits in the
next min. I/O unit, we read the whole next (or several next)
min. I/O unit(s). And if it happens to be that we read a data node,
and we've read part of its data, we calculate partial CRC.
So if later we need to check data CRC, we'll only read the rest
of the data from further min. I/O units and continue CRC checking.
This code was a bit messy and buggy. The bug was that it assumed
relatively large min. I/O unit, so that the largest node header
could overlap only one min. I/O unit boundary.
This parch clean-ups the code a bit and fixes this bug.
The patch was not tested on flash with small min. I/O unit, like
NOR-ECC, nut it was tested on NAND with 512 bytes NAND page, so
it at least does not break NAND. It was also tested with mtdram
so it should not break NOR.
Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-04 13:59:11 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									len  =  sizeof ( union  jffs2_node_union )  +  c - > wbuf_pagesize ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-08-01 13:05:22 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									buf  =  kmalloc ( len ,  GFP_KERNEL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! buf ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  - ENOMEM ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-11-07 11:16:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-08-01 13:05:22 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									spin_lock ( & c - > erase_completion_lock ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-07-27 15:46:14 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									valid_ref  =  jffs2_first_valid_node ( f - > inocache - > nodes ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-08-01 13:05:22 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! valid_ref  & &  f - > inocache - > ino  ! =  1 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										JFFS2_WARNING ( " Eep. No valid nodes for ino #%u. \n " ,  f - > inocache - > ino ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-07-27 15:46:14 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									while  ( valid_ref )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* We can hold a pointer to a non-obsolete node without the spinlock,
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										   but  _obsolete_  nodes  may  disappear  at  any  time ,  if  the  block 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										   they ' re  in  gets  erased .  So  if  we  mark  ' ref '  obsolete  while  we ' re 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										   not  holding  the  lock ,  it  can  go  away  immediately .  For  that  reason , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										   we  find  the  next  valid  node  first ,  before  processing  ' ref ' . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										*/ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ref  =  valid_ref ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										valid_ref  =  jffs2_first_valid_node ( ref - > next_in_ino ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										spin_unlock ( & c - > erase_completion_lock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										cond_resched ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-08-01 13:05:22 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										/*
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  At  this  point  we  don ' t  know  the  type  of  the  node  we ' re  going 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  to  read ,  so  we  do  not  know  the  size  of  its  header .  In  order 
							 
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] fix buffer sise calculations in jffs2_get_inode_nodes()
In read inode we have an optimization which prevents one
min. I/O unit (e.g. NAND page) to be read more then once.
Namely, at the beginning we do not know which node type we read,
so we read so we assume we read the directory entry, because it
has the smallest node header. When we read it, we read up to the
next min. I/O unit, just because if later we'll need to read more,
we already have this data.
If it turns out to be that the node is not directory entry, and
we need more data, and we did not read it because it sits in the
next min. I/O unit, we read the whole next (or several next)
min. I/O unit(s). And if it happens to be that we read a data node,
and we've read part of its data, we calculate partial CRC.
So if later we need to check data CRC, we'll only read the rest
of the data from further min. I/O units and continue CRC checking.
This code was a bit messy and buggy. The bug was that it assumed
relatively large min. I/O unit, so that the largest node header
could overlap only one min. I/O unit boundary.
This parch clean-ups the code a bit and fixes this bug.
The patch was not tested on flash with small min. I/O unit, like
NOR-ECC, nut it was tested on NAND with 512 bytes NAND page, so
it at least does not break NAND. It was also tested with mtdram
so it should not break NOR.
Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-04 13:59:11 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										 *  to  minimize  the  amount  of  flash  IO  we  assume  the  header  is 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  of  size  =  JFFS2_MIN_NODE_HEADER . 
							 
						 
					
						
							
								
									
										
										
										
											2005-08-01 13:05:22 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										 */ 
							 
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] fix buffer sise calculations in jffs2_get_inode_nodes()
In read inode we have an optimization which prevents one
min. I/O unit (e.g. NAND page) to be read more then once.
Namely, at the beginning we do not know which node type we read,
so we read so we assume we read the directory entry, because it
has the smallest node header. When we read it, we read up to the
next min. I/O unit, just because if later we'll need to read more,
we already have this data.
If it turns out to be that the node is not directory entry, and
we need more data, and we did not read it because it sits in the
next min. I/O unit, we read the whole next (or several next)
min. I/O unit(s). And if it happens to be that we read a data node,
and we've read part of its data, we calculate partial CRC.
So if later we need to check data CRC, we'll only read the rest
of the data from further min. I/O units and continue CRC checking.
This code was a bit messy and buggy. The bug was that it assumed
relatively large min. I/O unit, so that the largest node header
could overlap only one min. I/O unit boundary.
This parch clean-ups the code a bit and fixes this bug.
The patch was not tested on flash with small min. I/O unit, like
NOR-ECC, nut it was tested on NAND with 512 bytes NAND page, so
it at least does not break NAND. It was also tested with mtdram
so it should not break NOR.
Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-04 13:59:11 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										len  =  JFFS2_MIN_NODE_HEADER ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-08-01 13:05:22 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( jffs2_is_writebuffered ( c ) )  { 
							 
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] fix buffer sise calculations in jffs2_get_inode_nodes()
In read inode we have an optimization which prevents one
min. I/O unit (e.g. NAND page) to be read more then once.
Namely, at the beginning we do not know which node type we read,
so we read so we assume we read the directory entry, because it
has the smallest node header. When we read it, we read up to the
next min. I/O unit, just because if later we'll need to read more,
we already have this data.
If it turns out to be that the node is not directory entry, and
we need more data, and we did not read it because it sits in the
next min. I/O unit, we read the whole next (or several next)
min. I/O unit(s). And if it happens to be that we read a data node,
and we've read part of its data, we calculate partial CRC.
So if later we need to check data CRC, we'll only read the rest
of the data from further min. I/O units and continue CRC checking.
This code was a bit messy and buggy. The bug was that it assumed
relatively large min. I/O unit, so that the largest node header
could overlap only one min. I/O unit boundary.
This parch clean-ups the code a bit and fixes this bug.
The patch was not tested on flash with small min. I/O unit, like
NOR-ECC, nut it was tested on NAND with 512 bytes NAND page, so
it at least does not break NAND. It was also tested with mtdram
so it should not break NOR.
Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-04 13:59:11 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											int  end ,  rem ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-11-07 11:16:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											/*
 
							 
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] fix buffer sise calculations in jffs2_get_inode_nodes()
In read inode we have an optimization which prevents one
min. I/O unit (e.g. NAND page) to be read more then once.
Namely, at the beginning we do not know which node type we read,
so we read so we assume we read the directory entry, because it
has the smallest node header. When we read it, we read up to the
next min. I/O unit, just because if later we'll need to read more,
we already have this data.
If it turns out to be that the node is not directory entry, and
we need more data, and we did not read it because it sits in the
next min. I/O unit, we read the whole next (or several next)
min. I/O unit(s). And if it happens to be that we read a data node,
and we've read part of its data, we calculate partial CRC.
So if later we need to check data CRC, we'll only read the rest
of the data from further min. I/O units and continue CRC checking.
This code was a bit messy and buggy. The bug was that it assumed
relatively large min. I/O unit, so that the largest node header
could overlap only one min. I/O unit boundary.
This parch clean-ups the code a bit and fixes this bug.
The patch was not tested on flash with small min. I/O unit, like
NOR-ECC, nut it was tested on NAND with 512 bytes NAND page, so
it at least does not break NAND. It was also tested with mtdram
so it should not break NOR.
Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-04 13:59:11 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											 *  We  are  about  to  read  JFFS2_MIN_NODE_HEADER  bytes , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  but  this  flash  has  some  minimal  I / O  unit .  It  is 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  possible  that  we ' ll  need  to  read  more  soon ,  so  read 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  up  to  the  next  min .  I / O  unit ,  in  order  not  to 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  re - read  the  same  min .  I / O  unit  twice . 
							 
						 
					
						
							
								
									
										
										
										
											2005-08-01 13:05:22 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											 */ 
							 
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] fix buffer sise calculations in jffs2_get_inode_nodes()
In read inode we have an optimization which prevents one
min. I/O unit (e.g. NAND page) to be read more then once.
Namely, at the beginning we do not know which node type we read,
so we read so we assume we read the directory entry, because it
has the smallest node header. When we read it, we read up to the
next min. I/O unit, just because if later we'll need to read more,
we already have this data.
If it turns out to be that the node is not directory entry, and
we need more data, and we did not read it because it sits in the
next min. I/O unit, we read the whole next (or several next)
min. I/O unit(s). And if it happens to be that we read a data node,
and we've read part of its data, we calculate partial CRC.
So if later we need to check data CRC, we'll only read the rest
of the data from further min. I/O units and continue CRC checking.
This code was a bit messy and buggy. The bug was that it assumed
relatively large min. I/O unit, so that the largest node header
could overlap only one min. I/O unit boundary.
This parch clean-ups the code a bit and fixes this bug.
The patch was not tested on flash with small min. I/O unit, like
NOR-ECC, nut it was tested on NAND with 512 bytes NAND page, so
it at least does not break NAND. It was also tested with mtdram
so it should not break NOR.
Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-04 13:59:11 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											end  =  ref_offset ( ref )  +  len ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											rem  =  end  %  c - > wbuf_pagesize ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( rem ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												end  + =  c - > wbuf_pagesize  -  rem ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											len  =  end  -  ref_offset ( ref ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-08-01 13:05:22 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-09-22 12:25:00 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										dbg_readinode ( " read %d bytes at %#08x(%d). \n " ,  len ,  ref_offset ( ref ) ,  ref_flags ( ref ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-08-01 13:05:22 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-27 15:46:14 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										/* FIXME: point() */ 
							 
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] fix buffer sise calculations in jffs2_get_inode_nodes()
In read inode we have an optimization which prevents one
min. I/O unit (e.g. NAND page) to be read more then once.
Namely, at the beginning we do not know which node type we read,
so we read so we assume we read the directory entry, because it
has the smallest node header. When we read it, we read up to the
next min. I/O unit, just because if later we'll need to read more,
we already have this data.
If it turns out to be that the node is not directory entry, and
we need more data, and we did not read it because it sits in the
next min. I/O unit, we read the whole next (or several next)
min. I/O unit(s). And if it happens to be that we read a data node,
and we've read part of its data, we calculate partial CRC.
So if later we need to check data CRC, we'll only read the rest
of the data from further min. I/O units and continue CRC checking.
This code was a bit messy and buggy. The bug was that it assumed
relatively large min. I/O unit, so that the largest node header
could overlap only one min. I/O unit boundary.
This parch clean-ups the code a bit and fixes this bug.
The patch was not tested on flash with small min. I/O unit, like
NOR-ECC, nut it was tested on NAND with 512 bytes NAND page, so
it at least does not break NAND. It was also tested with mtdram
so it should not break NOR.
Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-04 13:59:11 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										err  =  jffs2_flash_read ( c ,  ref_offset ( ref ) ,  len ,  & retlen ,  buf ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-07-27 15:46:14 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( err )  { 
							 
						 
					
						
							
								
									
										
										
										
											2011-07-16 18:10:35 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											JFFS2_ERROR ( " can not read %d bytes from 0x%08x, error code: %d. \n " ,  len ,  ref_offset ( ref ) ,  err ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-08-01 13:05:22 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											goto  free_out ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2005-11-07 11:16:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-08-01 13:05:22 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( retlen  <  len )  { 
							 
						 
					
						
							
								
									
										
										
										
											2006-04-11 20:12:10 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											JFFS2_ERROR ( " short read at %#08x: %zu instead of %d. \n " ,  ref_offset ( ref ) ,  retlen ,  len ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-08-01 13:05:22 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											err  =  - EIO ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-07-27 15:46:14 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											goto  free_out ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2005-11-07 11:16:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] fix buffer sise calculations in jffs2_get_inode_nodes()
In read inode we have an optimization which prevents one
min. I/O unit (e.g. NAND page) to be read more then once.
Namely, at the beginning we do not know which node type we read,
so we read so we assume we read the directory entry, because it
has the smallest node header. When we read it, we read up to the
next min. I/O unit, just because if later we'll need to read more,
we already have this data.
If it turns out to be that the node is not directory entry, and
we need more data, and we did not read it because it sits in the
next min. I/O unit, we read the whole next (or several next)
min. I/O unit(s). And if it happens to be that we read a data node,
and we've read part of its data, we calculate partial CRC.
So if later we need to check data CRC, we'll only read the rest
of the data from further min. I/O units and continue CRC checking.
This code was a bit messy and buggy. The bug was that it assumed
relatively large min. I/O unit, so that the largest node header
could overlap only one min. I/O unit boundary.
This parch clean-ups the code a bit and fixes this bug.
The patch was not tested on flash with small min. I/O unit, like
NOR-ECC, nut it was tested on NAND with 512 bytes NAND page, so
it at least does not break NAND. It was also tested with mtdram
so it should not break NOR.
Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-04 13:59:11 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										node  =  ( union  jffs2_node_union  * ) buf ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-11-07 11:16:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2006-06-18 00:05:26 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										/* No need to mask in the valid bit; it shouldn't be invalid */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( je32_to_cpu ( node - > u . hdr_crc )  ! =  crc32 ( 0 ,  node ,  sizeof ( node - > u ) - 4 ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											JFFS2_NOTICE ( " Node header CRC failed at %#08x. {%04x,%04x,%08x,%08x} \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												     ref_offset ( ref ) ,  je16_to_cpu ( node - > u . magic ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												     je16_to_cpu ( node - > u . nodetype ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												     je32_to_cpu ( node - > u . totlen ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												     je32_to_cpu ( node - > u . hdr_crc ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											jffs2_dbg_dump_node ( c ,  ref_offset ( ref ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											jffs2_mark_node_obsolete ( c ,  ref ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											goto  cont ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2007-03-10 17:08:44 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( je16_to_cpu ( node - > u . magic )  ! =  JFFS2_MAGIC_BITMASK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											/* Not a JFFS2 node, whinge and move on */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											JFFS2_NOTICE ( " Wrong magic bitmask 0x%04x in node header at %#08x. \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												     je16_to_cpu ( node - > u . magic ) ,  ref_offset ( ref ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2007-03-09 11:44:00 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											jffs2_mark_node_obsolete ( c ,  ref ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											goto  cont ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2006-06-18 00:05:26 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-08-01 13:05:22 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										switch  ( je16_to_cpu ( node - > u . nodetype ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2005-11-07 11:16:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-27 15:46:14 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										case  JFFS2_NODETYPE_DIRENT : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2007-05-30 12:08:14 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											if  ( JFFS2_MIN_NODE_HEADER  <  sizeof ( struct  jffs2_raw_dirent )  & & 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											    len  <  sizeof ( struct  jffs2_raw_dirent ) )  { 
							 
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] fix buffer sise calculations in jffs2_get_inode_nodes()
In read inode we have an optimization which prevents one
min. I/O unit (e.g. NAND page) to be read more then once.
Namely, at the beginning we do not know which node type we read,
so we read so we assume we read the directory entry, because it
has the smallest node header. When we read it, we read up to the
next min. I/O unit, just because if later we'll need to read more,
we already have this data.
If it turns out to be that the node is not directory entry, and
we need more data, and we did not read it because it sits in the
next min. I/O unit, we read the whole next (or several next)
min. I/O unit(s). And if it happens to be that we read a data node,
and we've read part of its data, we calculate partial CRC.
So if later we need to check data CRC, we'll only read the rest
of the data from further min. I/O units and continue CRC checking.
This code was a bit messy and buggy. The bug was that it assumed
relatively large min. I/O unit, so that the largest node header
could overlap only one min. I/O unit boundary.
This parch clean-ups the code a bit and fixes this bug.
The patch was not tested on flash with small min. I/O unit, like
NOR-ECC, nut it was tested on NAND with 512 bytes NAND page, so
it at least does not break NAND. It was also tested with mtdram
so it should not break NOR.
Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-04 13:59:11 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												err  =  read_more ( c ,  ref ,  sizeof ( struct  jffs2_raw_dirent ) ,  & len ,  buf ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-08-01 13:05:22 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												if  ( unlikely ( err ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													goto  free_out ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2005-11-07 11:16:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] Improve read_inode memory usage, v2.
We originally used to read every node and allocate a jffs2_tmp_dnode_info
structure for each, before processing them in (reverse) version order
and discarding the ones which are obsoleted by later nodes.
With huge logfiles, this behaviour caused memory problems. For example, a
file involved in OLPC trac #1292 has 1822391 nodes, and would cause the XO
machine to run out of memory during the first stage of read_inode().
Instead of just inserting nodes into a tree in version order as we find
them, we now put them into a tree in order of their offset within the
file, which allows us to immediately discard nodes which are completely
obsoleted.
We don't use a full tree with 'fragments' pointing to the real data
structure, as we do in the normal fragtree. We sort only on the start
address, and add an 'overlapped' flag to the tmp_dnode_info to indicate
that the node in question is (partially) overlapped by another.
When the scan is complete, we start at the end of the file, adding each
node to a real fragtree as before. Where the node is non-overlapped, we
just add it (it doesn't matter that it's not the latest version; there is
no overlap). When the node at the end of the tree _is_ overlapped, we sort
it and all its overlapping nodes into version order and then add them to
the fragtree in that order.
This 'early discard' reduces the peak allocation of tmp_dnode_info
structures from 1.8M to a mere 62872 (3.5%) in the degenerate case
referenced above.
This version of the patch also correctly rememembers the highest node
version# seen for an inode when it's scanned.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-25 03:23:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											err  =  read_direntry ( c ,  ref ,  & node - > d ,  retlen ,  rii ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( unlikely ( err ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2005-07-27 15:46:14 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												goto  free_out ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-11-07 11:16:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-27 15:46:14 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										case  JFFS2_NODETYPE_INODE : 
							 
						 
					
						
							
								
									
										
										
										
											2005-11-07 11:16:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2007-05-30 12:08:14 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											if  ( JFFS2_MIN_NODE_HEADER  <  sizeof ( struct  jffs2_raw_inode )  & & 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											    len  <  sizeof ( struct  jffs2_raw_inode ) )  { 
							 
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] fix buffer sise calculations in jffs2_get_inode_nodes()
In read inode we have an optimization which prevents one
min. I/O unit (e.g. NAND page) to be read more then once.
Namely, at the beginning we do not know which node type we read,
so we read so we assume we read the directory entry, because it
has the smallest node header. When we read it, we read up to the
next min. I/O unit, just because if later we'll need to read more,
we already have this data.
If it turns out to be that the node is not directory entry, and
we need more data, and we did not read it because it sits in the
next min. I/O unit, we read the whole next (or several next)
min. I/O unit(s). And if it happens to be that we read a data node,
and we've read part of its data, we calculate partial CRC.
So if later we need to check data CRC, we'll only read the rest
of the data from further min. I/O units and continue CRC checking.
This code was a bit messy and buggy. The bug was that it assumed
relatively large min. I/O unit, so that the largest node header
could overlap only one min. I/O unit boundary.
This parch clean-ups the code a bit and fixes this bug.
The patch was not tested on flash with small min. I/O unit, like
NOR-ECC, nut it was tested on NAND with 512 bytes NAND page, so
it at least does not break NAND. It was also tested with mtdram
so it should not break NOR.
Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-04 13:59:11 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												err  =  read_more ( c ,  ref ,  sizeof ( struct  jffs2_raw_inode ) ,  & len ,  buf ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-08-01 13:05:22 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												if  ( unlikely ( err ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													goto  free_out ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-07-27 15:46:14 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] Improve read_inode memory usage, v2.
We originally used to read every node and allocate a jffs2_tmp_dnode_info
structure for each, before processing them in (reverse) version order
and discarding the ones which are obsoleted by later nodes.
With huge logfiles, this behaviour caused memory problems. For example, a
file involved in OLPC trac #1292 has 1822391 nodes, and would cause the XO
machine to run out of memory during the first stage of read_inode().
Instead of just inserting nodes into a tree in version order as we find
them, we now put them into a tree in order of their offset within the
file, which allows us to immediately discard nodes which are completely
obsoleted.
We don't use a full tree with 'fragments' pointing to the real data
structure, as we do in the normal fragtree. We sort only on the start
address, and add an 'overlapped' flag to the tmp_dnode_info to indicate
that the node in question is (partially) overlapped by another.
When the scan is complete, we start at the end of the file, adding each
node to a real fragtree as before. Where the node is non-overlapped, we
just add it (it doesn't matter that it's not the latest version; there is
no overlap). When the node at the end of the tree _is_ overlapped, we sort
it and all its overlapping nodes into version order and then add them to
the fragtree in that order.
This 'early discard' reduces the peak allocation of tmp_dnode_info
structures from 1.8M to a mere 62872 (3.5%) in the degenerate case
referenced above.
This version of the patch also correctly rememembers the highest node
version# seen for an inode when it's scanned.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-25 03:23:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											err  =  read_dnode ( c ,  ref ,  & node - > i ,  len ,  rii ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( unlikely ( err ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2005-07-27 15:46:14 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												goto  free_out ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-27 15:46:14 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											break ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-27 15:46:14 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										default : 
							 
						 
					
						
							
								
									
										
										
										
											2007-05-30 12:08:14 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											if  ( JFFS2_MIN_NODE_HEADER  <  sizeof ( struct  jffs2_unknown_node )  & & 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											    len  <  sizeof ( struct  jffs2_unknown_node ) )  { 
							 
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] fix buffer sise calculations in jffs2_get_inode_nodes()
In read inode we have an optimization which prevents one
min. I/O unit (e.g. NAND page) to be read more then once.
Namely, at the beginning we do not know which node type we read,
so we read so we assume we read the directory entry, because it
has the smallest node header. When we read it, we read up to the
next min. I/O unit, just because if later we'll need to read more,
we already have this data.
If it turns out to be that the node is not directory entry, and
we need more data, and we did not read it because it sits in the
next min. I/O unit, we read the whole next (or several next)
min. I/O unit(s). And if it happens to be that we read a data node,
and we've read part of its data, we calculate partial CRC.
So if later we need to check data CRC, we'll only read the rest
of the data from further min. I/O units and continue CRC checking.
This code was a bit messy and buggy. The bug was that it assumed
relatively large min. I/O unit, so that the largest node header
could overlap only one min. I/O unit boundary.
This parch clean-ups the code a bit and fixes this bug.
The patch was not tested on flash with small min. I/O unit, like
NOR-ECC, nut it was tested on NAND with 512 bytes NAND page, so
it at least does not break NAND. It was also tested with mtdram
so it should not break NOR.
Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-04 13:59:11 +03:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												err  =  read_more ( c ,  ref ,  sizeof ( struct  jffs2_unknown_node ) ,  & len ,  buf ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-08-01 13:05:22 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												if  ( unlikely ( err ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													goto  free_out ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-07-27 15:46:14 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2005-11-07 11:16:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-08-01 13:05:22 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											err  =  read_unknown ( c ,  ref ,  & node - > u ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2007-07-03 16:51:19 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											if  ( unlikely ( err ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2005-07-27 15:46:14 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												goto  free_out ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2006-06-18 00:05:26 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									cont : 
							 
						 
					
						
							
								
									
										
										
										
											2005-07-27 15:46:14 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										spin_lock ( & c - > erase_completion_lock ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2005-08-01 13:05:22 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-27 15:46:14 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									spin_unlock ( & c - > erase_completion_lock ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-08-01 13:05:22 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									kfree ( buf ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-07-27 15:46:14 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] Improve read_inode memory usage, v2.
We originally used to read every node and allocate a jffs2_tmp_dnode_info
structure for each, before processing them in (reverse) version order
and discarding the ones which are obsoleted by later nodes.
With huge logfiles, this behaviour caused memory problems. For example, a
file involved in OLPC trac #1292 has 1822391 nodes, and would cause the XO
machine to run out of memory during the first stage of read_inode().
Instead of just inserting nodes into a tree in version order as we find
them, we now put them into a tree in order of their offset within the
file, which allows us to immediately discard nodes which are completely
obsoleted.
We don't use a full tree with 'fragments' pointing to the real data
structure, as we do in the normal fragtree. We sort only on the start
address, and add an 'overlapped' flag to the tmp_dnode_info to indicate
that the node in question is (partially) overlapped by another.
When the scan is complete, we start at the end of the file, adding each
node to a real fragtree as before. Where the node is non-overlapped, we
just add it (it doesn't matter that it's not the latest version; there is
no overlap). When the node at the end of the tree _is_ overlapped, we sort
it and all its overlapping nodes into version order and then add them to
the fragtree in that order.
This 'early discard' reduces the peak allocation of tmp_dnode_info
structures from 1.8M to a mere 62872 (3.5%) in the degenerate case
referenced above.
This version of the patch also correctly rememembers the highest node
version# seen for an inode when it's scanned.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-25 03:23:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									f - > highest_version  =  rii - > highest_version ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-09-22 12:25:00 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									dbg_readinode ( " nodes of inode #%u were read, the highest version is %u, latest_mctime %u, mctime_ver %u. \n " , 
							 
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] Improve read_inode memory usage, v2.
We originally used to read every node and allocate a jffs2_tmp_dnode_info
structure for each, before processing them in (reverse) version order
and discarding the ones which are obsoleted by later nodes.
With huge logfiles, this behaviour caused memory problems. For example, a
file involved in OLPC trac #1292 has 1822391 nodes, and would cause the XO
machine to run out of memory during the first stage of read_inode().
Instead of just inserting nodes into a tree in version order as we find
them, we now put them into a tree in order of their offset within the
file, which allows us to immediately discard nodes which are completely
obsoleted.
We don't use a full tree with 'fragments' pointing to the real data
structure, as we do in the normal fragtree. We sort only on the start
address, and add an 'overlapped' flag to the tmp_dnode_info to indicate
that the node in question is (partially) overlapped by another.
When the scan is complete, we start at the end of the file, adding each
node to a real fragtree as before. Where the node is non-overlapped, we
just add it (it doesn't matter that it's not the latest version; there is
no overlap). When the node at the end of the tree _is_ overlapped, we sort
it and all its overlapping nodes into version order and then add them to
the fragtree in that order.
This 'early discard' reduces the peak allocation of tmp_dnode_info
structures from 1.8M to a mere 62872 (3.5%) in the degenerate case
referenced above.
This version of the patch also correctly rememembers the highest node
version# seen for an inode when it's scanned.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-25 03:23:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										      f - > inocache - > ino ,  rii - > highest_version ,  rii - > latest_mctime , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										      rii - > mctime_ver ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-07-27 15:46:14 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 free_out : 
							 
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] Improve read_inode memory usage, v2.
We originally used to read every node and allocate a jffs2_tmp_dnode_info
structure for each, before processing them in (reverse) version order
and discarding the ones which are obsoleted by later nodes.
With huge logfiles, this behaviour caused memory problems. For example, a
file involved in OLPC trac #1292 has 1822391 nodes, and would cause the XO
machine to run out of memory during the first stage of read_inode().
Instead of just inserting nodes into a tree in version order as we find
them, we now put them into a tree in order of their offset within the
file, which allows us to immediately discard nodes which are completely
obsoleted.
We don't use a full tree with 'fragments' pointing to the real data
structure, as we do in the normal fragtree. We sort only on the start
address, and add an 'overlapped' flag to the tmp_dnode_info to indicate
that the node in question is (partially) overlapped by another.
When the scan is complete, we start at the end of the file, adding each
node to a real fragtree as before. Where the node is non-overlapped, we
just add it (it doesn't matter that it's not the latest version; there is
no overlap). When the node at the end of the tree _is_ overlapped, we sort
it and all its overlapping nodes into version order and then add them to
the fragtree in that order.
This 'early discard' reduces the peak allocation of tmp_dnode_info
structures from 1.8M to a mere 62872 (3.5%) in the degenerate case
referenced above.
This version of the patch also correctly rememembers the highest node
version# seen for an inode when it's scanned.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-25 03:23:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									jffs2_free_tmp_dnode_info_list ( & rii - > tn_root ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									jffs2_free_full_dirent_list ( rii - > fds ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									rii - > fds  =  NULL ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-08-01 13:05:22 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									kfree ( buf ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-07-27 15:46:14 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  err ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-11-07 11:16:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  int  jffs2_do_read_inode_internal ( struct  jffs2_sb_info  * c ,  
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
													struct  jffs2_inode_info  * f , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													struct  jffs2_raw_inode  * latest_node ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] Improve read_inode memory usage, v2.
We originally used to read every node and allocate a jffs2_tmp_dnode_info
structure for each, before processing them in (reverse) version order
and discarding the ones which are obsoleted by later nodes.
With huge logfiles, this behaviour caused memory problems. For example, a
file involved in OLPC trac #1292 has 1822391 nodes, and would cause the XO
machine to run out of memory during the first stage of read_inode().
Instead of just inserting nodes into a tree in version order as we find
them, we now put them into a tree in order of their offset within the
file, which allows us to immediately discard nodes which are completely
obsoleted.
We don't use a full tree with 'fragments' pointing to the real data
structure, as we do in the normal fragtree. We sort only on the start
address, and add an 'overlapped' flag to the tmp_dnode_info to indicate
that the node in question is (partially) overlapped by another.
When the scan is complete, we start at the end of the file, adding each
node to a real fragtree as before. Where the node is non-overlapped, we
just add it (it doesn't matter that it's not the latest version; there is
no overlap). When the node at the end of the tree _is_ overlapped, we sort
it and all its overlapping nodes into version order and then add them to
the fragtree in that order.
This 'early discard' reduces the peak allocation of tmp_dnode_info
structures from 1.8M to a mere 62872 (3.5%) in the degenerate case
referenced above.
This version of the patch also correctly rememembers the highest node
version# seen for an inode when it's scanned.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-25 03:23:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  jffs2_readinode_info  rii ; 
							 
						 
					
						
							
								
									
										
										
										
											2007-04-25 17:04:23 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									uint32_t  crc ,  new_size ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									size_t  retlen ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  ret ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2008-05-01 18:47:17 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									dbg_readinode ( " ino #%u pino/nlink is %d \n " ,  f - > inocache - > ino , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										      f - > inocache - > pino_nlink ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] Improve read_inode memory usage, v2.
We originally used to read every node and allocate a jffs2_tmp_dnode_info
structure for each, before processing them in (reverse) version order
and discarding the ones which are obsoleted by later nodes.
With huge logfiles, this behaviour caused memory problems. For example, a
file involved in OLPC trac #1292 has 1822391 nodes, and would cause the XO
machine to run out of memory during the first stage of read_inode().
Instead of just inserting nodes into a tree in version order as we find
them, we now put them into a tree in order of their offset within the
file, which allows us to immediately discard nodes which are completely
obsoleted.
We don't use a full tree with 'fragments' pointing to the real data
structure, as we do in the normal fragtree. We sort only on the start
address, and add an 'overlapped' flag to the tmp_dnode_info to indicate
that the node in question is (partially) overlapped by another.
When the scan is complete, we start at the end of the file, adding each
node to a real fragtree as before. Where the node is non-overlapped, we
just add it (it doesn't matter that it's not the latest version; there is
no overlap). When the node at the end of the tree _is_ overlapped, we sort
it and all its overlapping nodes into version order and then add them to
the fragtree in that order.
This 'early discard' reduces the peak allocation of tmp_dnode_info
structures from 1.8M to a mere 62872 (3.5%) in the degenerate case
referenced above.
This version of the patch also correctly rememembers the highest node
version# seen for an inode when it's scanned.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-25 03:23:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									memset ( & rii ,  0 ,  sizeof ( rii ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									/* Grab all nodes relevant to this ino */ 
							 
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] Improve read_inode memory usage, v2.
We originally used to read every node and allocate a jffs2_tmp_dnode_info
structure for each, before processing them in (reverse) version order
and discarding the ones which are obsoleted by later nodes.
With huge logfiles, this behaviour caused memory problems. For example, a
file involved in OLPC trac #1292 has 1822391 nodes, and would cause the XO
machine to run out of memory during the first stage of read_inode().
Instead of just inserting nodes into a tree in version order as we find
them, we now put them into a tree in order of their offset within the
file, which allows us to immediately discard nodes which are completely
obsoleted.
We don't use a full tree with 'fragments' pointing to the real data
structure, as we do in the normal fragtree. We sort only on the start
address, and add an 'overlapped' flag to the tmp_dnode_info to indicate
that the node in question is (partially) overlapped by another.
When the scan is complete, we start at the end of the file, adding each
node to a real fragtree as before. Where the node is non-overlapped, we
just add it (it doesn't matter that it's not the latest version; there is
no overlap). When the node at the end of the tree _is_ overlapped, we sort
it and all its overlapping nodes into version order and then add them to
the fragtree in that order.
This 'early discard' reduces the peak allocation of tmp_dnode_info
structures from 1.8M to a mere 62872 (3.5%) in the degenerate case
referenced above.
This version of the patch also correctly rememembers the highest node
version# seen for an inode when it's scanned.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-25 03:23:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ret  =  jffs2_get_inode_nodes ( c ,  f ,  & rii ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ret )  { 
							 
						 
					
						
							
								
									
										
										
										
											2005-07-28 15:46:43 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										JFFS2_ERROR ( " cannot read nodes for ino %u, returned error is %d \n " ,  f - > inocache - > ino ,  ret ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										if  ( f - > inocache - > state  = =  INO_STATE_READING ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											jffs2_set_inocache_state ( c ,  f - > inocache ,  INO_STATE_CHECKEDABSENT ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  ret ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] Improve read_inode memory usage, v2.
We originally used to read every node and allocate a jffs2_tmp_dnode_info
structure for each, before processing them in (reverse) version order
and discarding the ones which are obsoleted by later nodes.
With huge logfiles, this behaviour caused memory problems. For example, a
file involved in OLPC trac #1292 has 1822391 nodes, and would cause the XO
machine to run out of memory during the first stage of read_inode().
Instead of just inserting nodes into a tree in version order as we find
them, we now put them into a tree in order of their offset within the
file, which allows us to immediately discard nodes which are completely
obsoleted.
We don't use a full tree with 'fragments' pointing to the real data
structure, as we do in the normal fragtree. We sort only on the start
address, and add an 'overlapped' flag to the tmp_dnode_info to indicate
that the node in question is (partially) overlapped by another.
When the scan is complete, we start at the end of the file, adding each
node to a real fragtree as before. Where the node is non-overlapped, we
just add it (it doesn't matter that it's not the latest version; there is
no overlap). When the node at the end of the tree _is_ overlapped, we sort
it and all its overlapping nodes into version order and then add them to
the fragtree in that order.
This 'early discard' reduces the peak allocation of tmp_dnode_info
structures from 1.8M to a mere 62872 (3.5%) in the degenerate case
referenced above.
This version of the patch also correctly rememembers the highest node
version# seen for an inode when it's scanned.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-25 03:23:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ret  =  jffs2_build_inode_fragtree ( c ,  f ,  & rii ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ret )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										JFFS2_ERROR ( " Failed to build final fragtree for inode #%u: error %d \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											    f - > inocache - > ino ,  ret ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( f - > inocache - > state  = =  INO_STATE_READING ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											jffs2_set_inocache_state ( c ,  f - > inocache ,  INO_STATE_CHECKEDABSENT ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										jffs2_free_tmp_dnode_info_list ( & rii . tn_root ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* FIXME: We could at least crc-check them all */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( rii . mdata_tn )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											jffs2_free_full_dnode ( rii . mdata_tn - > fn ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											jffs2_free_tmp_dnode_info ( rii . mdata_tn ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											rii . mdata_tn  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  ret ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2005-07-05 22:03:10 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] Improve read_inode memory usage, v2.
We originally used to read every node and allocate a jffs2_tmp_dnode_info
structure for each, before processing them in (reverse) version order
and discarding the ones which are obsoleted by later nodes.
With huge logfiles, this behaviour caused memory problems. For example, a
file involved in OLPC trac #1292 has 1822391 nodes, and would cause the XO
machine to run out of memory during the first stage of read_inode().
Instead of just inserting nodes into a tree in version order as we find
them, we now put them into a tree in order of their offset within the
file, which allows us to immediately discard nodes which are completely
obsoleted.
We don't use a full tree with 'fragments' pointing to the real data
structure, as we do in the normal fragtree. We sort only on the start
address, and add an 'overlapped' flag to the tmp_dnode_info to indicate
that the node in question is (partially) overlapped by another.
When the scan is complete, we start at the end of the file, adding each
node to a real fragtree as before. Where the node is non-overlapped, we
just add it (it doesn't matter that it's not the latest version; there is
no overlap). When the node at the end of the tree _is_ overlapped, we sort
it and all its overlapping nodes into version order and then add them to
the fragtree in that order.
This 'early discard' reduces the peak allocation of tmp_dnode_info
structures from 1.8M to a mere 62872 (3.5%) in the degenerate case
referenced above.
This version of the patch also correctly rememembers the highest node
version# seen for an inode when it's scanned.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-25 03:23:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( rii . mdata_tn )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( rii . mdata_tn - > fn - > raw  = =  rii . latest_ref )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											f - > metadata  =  rii . mdata_tn - > fn ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											jffs2_free_tmp_dnode_info ( rii . mdata_tn ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											jffs2_kill_tn ( c ,  rii . mdata_tn ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-08-01 13:05:22 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] Improve read_inode memory usage, v2.
We originally used to read every node and allocate a jffs2_tmp_dnode_info
structure for each, before processing them in (reverse) version order
and discarding the ones which are obsoleted by later nodes.
With huge logfiles, this behaviour caused memory problems. For example, a
file involved in OLPC trac #1292 has 1822391 nodes, and would cause the XO
machine to run out of memory during the first stage of read_inode().
Instead of just inserting nodes into a tree in version order as we find
them, we now put them into a tree in order of their offset within the
file, which allows us to immediately discard nodes which are completely
obsoleted.
We don't use a full tree with 'fragments' pointing to the real data
structure, as we do in the normal fragtree. We sort only on the start
address, and add an 'overlapped' flag to the tmp_dnode_info to indicate
that the node in question is (partially) overlapped by another.
When the scan is complete, we start at the end of the file, adding each
node to a real fragtree as before. Where the node is non-overlapped, we
just add it (it doesn't matter that it's not the latest version; there is
no overlap). When the node at the end of the tree _is_ overlapped, we sort
it and all its overlapping nodes into version order and then add them to
the fragtree in that order.
This 'early discard' reduces the peak allocation of tmp_dnode_info
structures from 1.8M to a mere 62872 (3.5%) in the degenerate case
referenced above.
This version of the patch also correctly rememembers the highest node
version# seen for an inode when it's scanned.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-25 03:23:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										rii . mdata_tn  =  NULL ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] Improve read_inode memory usage, v2.
We originally used to read every node and allocate a jffs2_tmp_dnode_info
structure for each, before processing them in (reverse) version order
and discarding the ones which are obsoleted by later nodes.
With huge logfiles, this behaviour caused memory problems. For example, a
file involved in OLPC trac #1292 has 1822391 nodes, and would cause the XO
machine to run out of memory during the first stage of read_inode().
Instead of just inserting nodes into a tree in version order as we find
them, we now put them into a tree in order of their offset within the
file, which allows us to immediately discard nodes which are completely
obsoleted.
We don't use a full tree with 'fragments' pointing to the real data
structure, as we do in the normal fragtree. We sort only on the start
address, and add an 'overlapped' flag to the tmp_dnode_info to indicate
that the node in question is (partially) overlapped by another.
When the scan is complete, we start at the end of the file, adding each
node to a real fragtree as before. Where the node is non-overlapped, we
just add it (it doesn't matter that it's not the latest version; there is
no overlap). When the node at the end of the tree _is_ overlapped, we sort
it and all its overlapping nodes into version order and then add them to
the fragtree in that order.
This 'early discard' reduces the peak allocation of tmp_dnode_info
structures from 1.8M to a mere 62872 (3.5%) in the degenerate case
referenced above.
This version of the patch also correctly rememembers the highest node
version# seen for an inode when it's scanned.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-25 03:23:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									f - > dents  =  rii . fds ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									jffs2_dbg_fragtree_paranoia_check_nolock ( f ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-08-01 13:05:22 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] Improve read_inode memory usage, v2.
We originally used to read every node and allocate a jffs2_tmp_dnode_info
structure for each, before processing them in (reverse) version order
and discarding the ones which are obsoleted by later nodes.
With huge logfiles, this behaviour caused memory problems. For example, a
file involved in OLPC trac #1292 has 1822391 nodes, and would cause the XO
machine to run out of memory during the first stage of read_inode().
Instead of just inserting nodes into a tree in version order as we find
them, we now put them into a tree in order of their offset within the
file, which allows us to immediately discard nodes which are completely
obsoleted.
We don't use a full tree with 'fragments' pointing to the real data
structure, as we do in the normal fragtree. We sort only on the start
address, and add an 'overlapped' flag to the tmp_dnode_info to indicate
that the node in question is (partially) overlapped by another.
When the scan is complete, we start at the end of the file, adding each
node to a real fragtree as before. Where the node is non-overlapped, we
just add it (it doesn't matter that it's not the latest version; there is
no overlap). When the node at the end of the tree _is_ overlapped, we sort
it and all its overlapping nodes into version order and then add them to
the fragtree in that order.
This 'early discard' reduces the peak allocation of tmp_dnode_info
structures from 1.8M to a mere 62872 (3.5%) in the degenerate case
referenced above.
This version of the patch also correctly rememembers the highest node
version# seen for an inode when it's scanned.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-25 03:23:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( unlikely ( ! rii . latest_ref ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										/* No data nodes for this inode. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( f - > inocache - > ino  ! =  1 )  { 
							 
						 
					
						
							
								
									
										
										
										
											2005-07-28 15:46:43 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											JFFS2_WARNING ( " no data nodes found for ino #%u \n " ,  f - > inocache - > ino ) ; 
							 
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] Improve read_inode memory usage, v2.
We originally used to read every node and allocate a jffs2_tmp_dnode_info
structure for each, before processing them in (reverse) version order
and discarding the ones which are obsoleted by later nodes.
With huge logfiles, this behaviour caused memory problems. For example, a
file involved in OLPC trac #1292 has 1822391 nodes, and would cause the XO
machine to run out of memory during the first stage of read_inode().
Instead of just inserting nodes into a tree in version order as we find
them, we now put them into a tree in order of their offset within the
file, which allows us to immediately discard nodes which are completely
obsoleted.
We don't use a full tree with 'fragments' pointing to the real data
structure, as we do in the normal fragtree. We sort only on the start
address, and add an 'overlapped' flag to the tmp_dnode_info to indicate
that the node in question is (partially) overlapped by another.
When the scan is complete, we start at the end of the file, adding each
node to a real fragtree as before. Where the node is non-overlapped, we
just add it (it doesn't matter that it's not the latest version; there is
no overlap). When the node at the end of the tree _is_ overlapped, we sort
it and all its overlapping nodes into version order and then add them to
the fragtree in that order.
This 'early discard' reduces the peak allocation of tmp_dnode_info
structures from 1.8M to a mere 62872 (3.5%) in the degenerate case
referenced above.
This version of the patch also correctly rememembers the highest node
version# seen for an inode when it's scanned.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-25 03:23:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											if  ( ! rii . fds )  { 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
												if  ( f - > inocache - > state  = =  INO_STATE_READING ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													jffs2_set_inocache_state ( c ,  f - > inocache ,  INO_STATE_CHECKEDABSENT ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return  - EIO ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2005-07-28 15:46:43 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											JFFS2_NOTICE ( " but it has children so we fake some modes for it \n " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										latest_node - > mode  =  cpu_to_jemode ( S_IFDIR | S_IRUGO | S_IWUSR | S_IXUGO ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										latest_node - > version  =  cpu_to_je32 ( 0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										latest_node - > atime  =  latest_node - > ctime  =  latest_node - > mtime  =  cpu_to_je32 ( 0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										latest_node - > isize  =  cpu_to_je32 ( 0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										latest_node - > gid  =  cpu_to_je16 ( 0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										latest_node - > uid  =  cpu_to_je16 ( 0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( f - > inocache - > state  = =  INO_STATE_READING ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											jffs2_set_inocache_state ( c ,  f - > inocache ,  INO_STATE_PRESENT ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] Improve read_inode memory usage, v2.
We originally used to read every node and allocate a jffs2_tmp_dnode_info
structure for each, before processing them in (reverse) version order
and discarding the ones which are obsoleted by later nodes.
With huge logfiles, this behaviour caused memory problems. For example, a
file involved in OLPC trac #1292 has 1822391 nodes, and would cause the XO
machine to run out of memory during the first stage of read_inode().
Instead of just inserting nodes into a tree in version order as we find
them, we now put them into a tree in order of their offset within the
file, which allows us to immediately discard nodes which are completely
obsoleted.
We don't use a full tree with 'fragments' pointing to the real data
structure, as we do in the normal fragtree. We sort only on the start
address, and add an 'overlapped' flag to the tmp_dnode_info to indicate
that the node in question is (partially) overlapped by another.
When the scan is complete, we start at the end of the file, adding each
node to a real fragtree as before. Where the node is non-overlapped, we
just add it (it doesn't matter that it's not the latest version; there is
no overlap). When the node at the end of the tree _is_ overlapped, we sort
it and all its overlapping nodes into version order and then add them to
the fragtree in that order.
This 'early discard' reduces the peak allocation of tmp_dnode_info
structures from 1.8M to a mere 62872 (3.5%) in the degenerate case
referenced above.
This version of the patch also correctly rememembers the highest node
version# seen for an inode when it's scanned.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-25 03:23:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ret  =  jffs2_flash_read ( c ,  ref_offset ( rii . latest_ref ) ,  sizeof ( * latest_node ) ,  & retlen ,  ( void  * ) latest_node ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									if  ( ret  | |  retlen  ! =  sizeof ( * latest_node ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2005-07-28 15:46:43 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										JFFS2_ERROR ( " failed to read from flash: error %d, %zd of %zd bytes read \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ret ,  retlen ,  sizeof ( * latest_node ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										/* FIXME: If this fails, there seems to be a memory leak. Find it. */ 
							 
						 
					
						
							
								
									
										
										
										
											2008-04-22 15:13:40 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										mutex_unlock ( & f - > sem ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										jffs2_do_clear_inode ( c ,  f ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  ret ? ret : - EIO ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									crc  =  crc32 ( 0 ,  latest_node ,  sizeof ( * latest_node ) - 8 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( crc  ! =  je32_to_cpu ( latest_node - > node_crc ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2005-07-28 15:46:43 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										JFFS2_ERROR ( " CRC failed for read_inode of inode %u at physical location 0x%x \n " , 
							 
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] Improve read_inode memory usage, v2.
We originally used to read every node and allocate a jffs2_tmp_dnode_info
structure for each, before processing them in (reverse) version order
and discarding the ones which are obsoleted by later nodes.
With huge logfiles, this behaviour caused memory problems. For example, a
file involved in OLPC trac #1292 has 1822391 nodes, and would cause the XO
machine to run out of memory during the first stage of read_inode().
Instead of just inserting nodes into a tree in version order as we find
them, we now put them into a tree in order of their offset within the
file, which allows us to immediately discard nodes which are completely
obsoleted.
We don't use a full tree with 'fragments' pointing to the real data
structure, as we do in the normal fragtree. We sort only on the start
address, and add an 'overlapped' flag to the tmp_dnode_info to indicate
that the node in question is (partially) overlapped by another.
When the scan is complete, we start at the end of the file, adding each
node to a real fragtree as before. Where the node is non-overlapped, we
just add it (it doesn't matter that it's not the latest version; there is
no overlap). When the node at the end of the tree _is_ overlapped, we sort
it and all its overlapping nodes into version order and then add them to
the fragtree in that order.
This 'early discard' reduces the peak allocation of tmp_dnode_info
structures from 1.8M to a mere 62872 (3.5%) in the degenerate case
referenced above.
This version of the patch also correctly rememembers the highest node
version# seen for an inode when it's scanned.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-25 03:23:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											f - > inocache - > ino ,  ref_offset ( rii . latest_ref ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2008-04-22 15:13:40 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										mutex_unlock ( & f - > sem ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										jffs2_do_clear_inode ( c ,  f ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  - EIO ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									switch ( jemode_to_cpu ( latest_node - > mode )  &  S_IFMT )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  S_IFDIR : 
							 
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] Improve read_inode memory usage, v2.
We originally used to read every node and allocate a jffs2_tmp_dnode_info
structure for each, before processing them in (reverse) version order
and discarding the ones which are obsoleted by later nodes.
With huge logfiles, this behaviour caused memory problems. For example, a
file involved in OLPC trac #1292 has 1822391 nodes, and would cause the XO
machine to run out of memory during the first stage of read_inode().
Instead of just inserting nodes into a tree in version order as we find
them, we now put them into a tree in order of their offset within the
file, which allows us to immediately discard nodes which are completely
obsoleted.
We don't use a full tree with 'fragments' pointing to the real data
structure, as we do in the normal fragtree. We sort only on the start
address, and add an 'overlapped' flag to the tmp_dnode_info to indicate
that the node in question is (partially) overlapped by another.
When the scan is complete, we start at the end of the file, adding each
node to a real fragtree as before. Where the node is non-overlapped, we
just add it (it doesn't matter that it's not the latest version; there is
no overlap). When the node at the end of the tree _is_ overlapped, we sort
it and all its overlapping nodes into version order and then add them to
the fragtree in that order.
This 'early discard' reduces the peak allocation of tmp_dnode_info
structures from 1.8M to a mere 62872 (3.5%) in the degenerate case
referenced above.
This version of the patch also correctly rememembers the highest node
version# seen for an inode when it's scanned.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-25 03:23:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( rii . mctime_ver  >  je32_to_cpu ( latest_node - > version ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											/* The times in the latest_node are actually older than
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											   mctime  in  the  latest  dirent .  Cheat .  */ 
							 
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] Improve read_inode memory usage, v2.
We originally used to read every node and allocate a jffs2_tmp_dnode_info
structure for each, before processing them in (reverse) version order
and discarding the ones which are obsoleted by later nodes.
With huge logfiles, this behaviour caused memory problems. For example, a
file involved in OLPC trac #1292 has 1822391 nodes, and would cause the XO
machine to run out of memory during the first stage of read_inode().
Instead of just inserting nodes into a tree in version order as we find
them, we now put them into a tree in order of their offset within the
file, which allows us to immediately discard nodes which are completely
obsoleted.
We don't use a full tree with 'fragments' pointing to the real data
structure, as we do in the normal fragtree. We sort only on the start
address, and add an 'overlapped' flag to the tmp_dnode_info to indicate
that the node in question is (partially) overlapped by another.
When the scan is complete, we start at the end of the file, adding each
node to a real fragtree as before. Where the node is non-overlapped, we
just add it (it doesn't matter that it's not the latest version; there is
no overlap). When the node at the end of the tree _is_ overlapped, we sort
it and all its overlapping nodes into version order and then add them to
the fragtree in that order.
This 'early discard' reduces the peak allocation of tmp_dnode_info
structures from 1.8M to a mere 62872 (3.5%) in the degenerate case
referenced above.
This version of the patch also correctly rememembers the highest node
version# seen for an inode when it's scanned.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-25 03:23:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											latest_node - > ctime  =  latest_node - > mtime  =  cpu_to_je32 ( rii . latest_mctime ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-11-07 11:16:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									case  S_IFREG : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* If it was a regular file, truncate it to the latest node's isize */ 
							 
						 
					
						
							
								
									
										
										
										
											2007-04-25 17:04:23 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										new_size  =  jffs2_truncate_fragtree ( c ,  & f - > fragtree ,  je32_to_cpu ( latest_node - > isize ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( new_size  ! =  je32_to_cpu ( latest_node - > isize ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											JFFS2_WARNING ( " Truncating ino #%u to %d bytes failed because it only had %d bytes to start with! \n " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												      f - > inocache - > ino ,  je32_to_cpu ( latest_node - > isize ) ,  new_size ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											latest_node - > isize  =  cpu_to_je32 ( new_size ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  S_IFLNK : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Hack to work around broken isize in old symlink code.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										   Remove  this  when  dwmw2  comes  to  his  senses  and  stops 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										   symlinks  from  being  an  entirely  gratuitous  special 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										   case .  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! je32_to_cpu ( latest_node - > isize ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											latest_node - > isize  =  latest_node - > dsize ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-03-01 10:50:52 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( f - > inocache - > state  ! =  INO_STATE_CHECKING )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											/* Symlink's inode data is the target path. Read it and
 
							 
						 
					
						
							
								
									
										
										
										
											2005-07-17 12:13:51 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											 *  keep  in  RAM  to  facilitate  quick  follow  symlink 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 *  operation .  */ 
							 
						 
					
						
							
								
									
										
										
										
											2012-04-25 14:45:22 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											uint32_t  csize  =  je32_to_cpu ( latest_node - > csize ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( csize  >  JFFS2_MAX_NAME_LEN )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												mutex_unlock ( & f - > sem ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												jffs2_do_clear_inode ( c ,  f ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return  - ENAMETOOLONG ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2012-04-25 14:45:23 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											f - > target  =  kmalloc ( csize  +  1 ,  GFP_KERNEL ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-07-17 12:13:51 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											if  ( ! f - > target )  { 
							 
						 
					
						
							
								
									
										
										
										
											2012-04-25 14:45:23 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												JFFS2_ERROR ( " can't allocate %u bytes of memory for the symlink target path cache \n " ,  csize ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2008-04-22 15:13:40 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												mutex_unlock ( & f - > sem ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-03-01 10:50:52 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												jffs2_do_clear_inode ( c ,  f ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return  - ENOMEM ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2005-11-07 11:16:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												[JFFS2] Improve read_inode memory usage, v2.
We originally used to read every node and allocate a jffs2_tmp_dnode_info
structure for each, before processing them in (reverse) version order
and discarding the ones which are obsoleted by later nodes.
With huge logfiles, this behaviour caused memory problems. For example, a
file involved in OLPC trac #1292 has 1822391 nodes, and would cause the XO
machine to run out of memory during the first stage of read_inode().
Instead of just inserting nodes into a tree in version order as we find
them, we now put them into a tree in order of their offset within the
file, which allows us to immediately discard nodes which are completely
obsoleted.
We don't use a full tree with 'fragments' pointing to the real data
structure, as we do in the normal fragtree. We sort only on the start
address, and add an 'overlapped' flag to the tmp_dnode_info to indicate
that the node in question is (partially) overlapped by another.
When the scan is complete, we start at the end of the file, adding each
node to a real fragtree as before. Where the node is non-overlapped, we
just add it (it doesn't matter that it's not the latest version; there is
no overlap). When the node at the end of the tree _is_ overlapped, we sort
it and all its overlapping nodes into version order and then add them to
the fragtree in that order.
This 'early discard' reduces the peak allocation of tmp_dnode_info
structures from 1.8M to a mere 62872 (3.5%) in the degenerate case
referenced above.
This version of the patch also correctly rememembers the highest node
version# seen for an inode when it's scanned.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
											 
										 
										
											2007-04-25 03:23:42 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											ret  =  jffs2_flash_read ( c ,  ref_offset ( rii . latest_ref )  +  sizeof ( * latest_node ) , 
							 
						 
					
						
							
								
									
										
										
										
											2012-04-25 14:45:23 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
													       csize ,  & retlen ,  ( char  * ) f - > target ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-11-07 11:16:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2012-04-25 14:45:23 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											if  ( ret  | |  retlen  ! =  csize )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  ( retlen  ! =  csize ) 
							 
						 
					
						
							
								
									
										
										
										
											2005-03-01 10:50:52 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
													ret  =  - EIO ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-07-17 12:13:51 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												kfree ( f - > target ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												f - > target  =  NULL ; 
							 
						 
					
						
							
								
									
										
										
										
											2008-04-22 15:13:40 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												mutex_unlock ( & f - > sem ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-03-01 10:50:52 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												jffs2_do_clear_inode ( c ,  f ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2009-11-12 18:09:48 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												return  ret ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-03-01 10:50:52 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2012-04-25 14:45:23 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											f - > target [ csize ]  =  ' \0 ' ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-09-22 12:25:00 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											dbg_readinode ( " symlink's target '%s' cached \n " ,  f - > target ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-03-01 10:50:52 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2005-11-07 11:16:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										/* fall through... */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  S_IFBLK : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  S_IFCHR : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Certain inode types should have only one data node, and it's
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										   kept  as  the  metadata  node  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( f - > metadata )  { 
							 
						 
					
						
							
								
									
										
										
										
											2005-07-28 15:46:43 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											JFFS2_ERROR ( " Argh. Special inode #%u with mode 0%o had metadata node \n " , 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											       f - > inocache - > ino ,  jemode_to_cpu ( latest_node - > mode ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2008-04-22 15:13:40 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											mutex_unlock ( & f - > sem ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											jffs2_do_clear_inode ( c ,  f ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  - EIO ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! frag_first ( & f - > fragtree ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2005-07-28 15:46:43 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											JFFS2_ERROR ( " Argh. Special inode #%u with mode 0%o has no fragments \n " , 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											       f - > inocache - > ino ,  jemode_to_cpu ( latest_node - > mode ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2008-04-22 15:13:40 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											mutex_unlock ( & f - > sem ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											jffs2_do_clear_inode ( c ,  f ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  - EIO ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* ASSERT: f->fraglist != NULL */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( frag_next ( frag_first ( & f - > fragtree ) ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2005-07-28 15:46:43 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											JFFS2_ERROR ( " Argh. Special inode #%u with mode 0x%x had more than one node \n " , 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											       f - > inocache - > ino ,  jemode_to_cpu ( latest_node - > mode ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											/* FIXME: Deal with it - check crc32, check for duplicate node, check times and discard the older one */ 
							 
						 
					
						
							
								
									
										
										
										
											2008-04-22 15:13:40 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											mutex_unlock ( & f - > sem ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											jffs2_do_clear_inode ( c ,  f ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  - EIO ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* OK. We're happy */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										f - > metadata  =  frag_first ( & f - > fragtree ) - > node ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										jffs2_free_node_frag ( frag_first ( & f - > fragtree ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										f - > fragtree  =  RB_ROOT ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( f - > inocache - > state  = =  INO_STATE_READING ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										jffs2_set_inocache_state ( c ,  f - > inocache ,  INO_STATE_PRESENT ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-27 15:46:14 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/* Scan the list of all nodes present for this ino, build map of versions, etc. */  
						 
					
						
							
								
									
										
										
										
											2005-11-07 11:16:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								int  jffs2_do_read_inode ( struct  jffs2_sb_info  * c ,  struct  jffs2_inode_info  * f ,  
						 
					
						
							
								
									
										
										
										
											2005-07-27 15:46:14 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											uint32_t  ino ,  struct  jffs2_raw_inode  * latest_node ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2005-09-22 12:25:00 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									dbg_readinode ( " read inode #%u \n " ,  ino ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-07-27 15:46:14 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 retry_inocache : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									spin_lock ( & c - > inocache_lock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									f - > inocache  =  jffs2_get_ino_cache ( c ,  ino ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( f - > inocache )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Check its state. We may need to wait before we can use it */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										switch ( f - > inocache - > state )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										case  INO_STATE_UNCHECKED : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										case  INO_STATE_CHECKEDABSENT : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											f - > inocache - > state  =  INO_STATE_READING ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											break ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-11-07 11:16:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-27 15:46:14 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										case  INO_STATE_CHECKING : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										case  INO_STATE_GC : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											/* If it's in either of these states, we need
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											   to  wait  for  whoever ' s  got  it  to  finish  and 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											   put  it  back .  */ 
							 
						 
					
						
							
								
									
										
										
										
											2005-09-22 12:25:00 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											dbg_readinode ( " waiting for ino #%u in state %d \n " ,  ino ,  f - > inocache - > state ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-07-27 15:46:14 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											sleep_on_spinunlock ( & c - > inocache_wq ,  & c - > inocache_lock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											goto  retry_inocache ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										case  INO_STATE_READING : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										case  INO_STATE_PRESENT : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											/* Eep. This should never happen. It can
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											happen  if  Linux  calls  read_inode ( )  again 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											before  clear_inode ( )  has  finished  though .  */ 
							 
						 
					
						
							
								
									
										
										
										
											2005-07-28 15:46:43 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											JFFS2_ERROR ( " Eep. Trying to read_inode #%u when it's already in state %d! \n " ,  ino ,  f - > inocache - > state ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-07-27 15:46:14 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											/* Fail. That's probably better than allowing it to succeed */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											f - > inocache  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											BUG ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									spin_unlock ( & c - > inocache_lock ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! f - > inocache  & &  ino  = =  1 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Special case - no root inode on medium */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										f - > inocache  =  jffs2_alloc_inode_cache ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! f - > inocache )  { 
							 
						 
					
						
							
								
									
										
										
										
											2005-07-28 15:46:43 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											JFFS2_ERROR ( " cannot allocate inocache for root inode \n " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-07-27 15:46:14 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											return  - ENOMEM ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2005-09-22 12:25:00 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										dbg_readinode ( " creating inocache for root inode \n " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-07-27 15:46:14 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										memset ( f - > inocache ,  0 ,  sizeof ( struct  jffs2_inode_cache ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2008-05-01 18:47:17 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										f - > inocache - > ino  =  f - > inocache - > pino_nlink  =  1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-07-27 15:46:14 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										f - > inocache - > nodes  =  ( struct  jffs2_raw_node_ref  * ) f - > inocache ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										f - > inocache - > state  =  INO_STATE_READING ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										jffs2_add_ino_cache ( c ,  f - > inocache ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! f - > inocache )  { 
							 
						 
					
						
							
								
									
										
										
										
											2005-07-28 15:46:43 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										JFFS2_ERROR ( " requestied to read an nonexistent ino %u \n " ,  ino ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-07-27 15:46:14 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  - ENOENT ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  jffs2_do_read_inode_internal ( c ,  f ,  latest_node ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								int  jffs2_do_crccheck_inode ( struct  jffs2_sb_info  * c ,  struct  jffs2_inode_cache  * ic )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  jffs2_raw_inode  n ; 
							 
						 
					
						
							
								
									
										
										
										
											2006-12-04 15:03:01 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  jffs2_inode_info  * f  =  kzalloc ( sizeof ( * f ) ,  GFP_KERNEL ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-07-27 15:46:14 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									int  ret ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! f ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  - ENOMEM ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2008-04-22 15:13:40 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									mutex_init ( & f - > sem ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									mutex_lock ( & f - > sem ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-07-27 15:46:14 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									f - > inocache  =  ic ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ret  =  jffs2_do_read_inode_internal ( c ,  f ,  & n ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! ret )  { 
							 
						 
					
						
							
								
									
										
										
										
											2008-04-22 15:13:40 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										mutex_unlock ( & f - > sem ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-07-27 15:46:14 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										jffs2_do_clear_inode ( c ,  f ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2012-05-10 17:14:03 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									jffs2_xattr_do_crccheck_inode ( c ,  ic ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-07-27 15:46:14 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									kfree  ( f ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  ret ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								void  jffs2_do_clear_inode ( struct  jffs2_sb_info  * c ,  struct  jffs2_inode_info  * f )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  jffs2_full_dirent  * fd ,  * fds ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  deleted ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2006-06-24 09:15:36 +09:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									jffs2_xattr_delete_inode ( c ,  f - > inocache ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2008-04-22 15:13:40 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									mutex_lock ( & f - > sem ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2008-05-01 18:47:17 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									deleted  =  f - > inocache  & &  ! f - > inocache - > pino_nlink ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-02-27 23:01:36 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( f - > inocache  & &  f - > inocache - > state  ! =  INO_STATE_CHECKING ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										jffs2_set_inocache_state ( c ,  f - > inocache ,  INO_STATE_CLEARING ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									if  ( f - > metadata )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( deleted ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											jffs2_mark_node_obsolete ( c ,  f - > metadata - > raw ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										jffs2_free_full_dnode ( f - > metadata ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									jffs2_kill_fragtree ( & f - > fragtree ,  deleted ? c : NULL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-17 12:13:51 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( f - > target )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										kfree ( f - > target ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										f - > target  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2005-11-07 11:16:07 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-17 12:13:51 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									fds  =  f - > dents ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									while ( fds )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										fd  =  fds ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										fds  =  fd - > next ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										jffs2_free_full_dirent ( fd ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-02-27 23:01:36 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( f - > inocache  & &  f - > inocache - > state  ! =  INO_STATE_CHECKING )  { 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										jffs2_set_inocache_state ( c ,  f - > inocache ,  INO_STATE_CHECKEDABSENT ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-02-27 23:01:36 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( f - > inocache - > nodes  = =  ( void  * ) f - > inocache ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											jffs2_del_ino_cache ( c ,  f - > inocache ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2008-04-22 15:13:40 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									mutex_unlock ( & f - > sem ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}