2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								/*
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *   Copyright  2000  by  Hans  Reiser ,  licensing  governed  by  reiserfs / README 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *   Written  by  Anatoly  P .  Pinchuk  pap @ namesys . botik . ru 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *   Programm  System  Institute 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *   Pereslavl - Zalessky  Russia 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *   This  file  contains  functions  dealing  with  S + tree 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  B_IS_IN_TREE 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  copy_item_head 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  comp_short_keys 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  comp_keys 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  comp_short_le_keys 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  le_key2cpu_key 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  comp_le_keys 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  bin_search 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  get_lkey 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  get_rkey 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  key_in_buffer 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  decrement_bcount 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  decrement_counters_in_path 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  reiserfs_check_path 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  pathrelse_and_restore 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  pathrelse 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  search_by_key_reada 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  search_by_key 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  search_for_position_by_key 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  comp_items 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  prepare_for_direct_item 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  prepare_for_direntry_item 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  prepare_for_delete_or_cut 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  calc_deleted_bytes_number 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  init_tb_struct 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  padd_item 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  reiserfs_delete_item 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  reiserfs_delete_solid_item 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  reiserfs_delete_object 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  maybe_indirect_to_direct 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  indirect_to_direct_roll_back 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  reiserfs_cut_from_item 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  truncate_directory 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  reiserfs_do_truncate 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  reiserfs_paste_into_item 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  reiserfs_insert_item 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <linux/config.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <linux/time.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <linux/string.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <linux/pagemap.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <linux/reiserfs_fs.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <linux/smp_lock.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <linux/buffer_head.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <linux/quotaops.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* Does the buffer contain a disk block which is in the tree. */  
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								inline  int  B_IS_IN_TREE ( const  struct  buffer_head  * p_s_bh )  
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									RFALSE ( B_LEVEL ( p_s_bh )  >  MAX_HEIGHT , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									       " PAP-1010: block (%b) has too big level (%z) " ,  p_s_bh ,  p_s_bh ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  ( B_LEVEL ( p_s_bh )  ! =  FREE_LEVEL ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// to gets item head in le form
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//
  
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								inline  void  copy_item_head ( struct  item_head  * p_v_to ,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											   const  struct  item_head  * p_v_from ) 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									memcpy ( p_v_to ,  p_v_from ,  IH_SIZE ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* k1 is pointer to on-disk structure which is stored in little-endian
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								   form .  k2  is  pointer  to  cpu  variable .  For  key  of  items  of  the  same 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								   object  this  returns  0. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								   Returns :  - 1  if  key1  <  key2  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								   0  if  key1  = =  key2 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								   1  if  key1  >  key2  */ 
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								inline  int  comp_short_keys ( const  struct  reiserfs_key  * le_key ,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											   const  struct  cpu_key  * cpu_key ) 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									__u32  n ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									n  =  le32_to_cpu ( le_key - > k_dir_id ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( n  <  cpu_key - > on_disk_key . k_dir_id ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( n  >  cpu_key - > on_disk_key . k_dir_id ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									n  =  le32_to_cpu ( le_key - > k_objectid ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( n  <  cpu_key - > on_disk_key . k_objectid ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( n  >  cpu_key - > on_disk_key . k_objectid ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* k1 is pointer to on-disk structure which is stored in little-endian
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								   form .  k2  is  pointer  to  cpu  variable . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								   Compare  keys  using  all  4  key  fields . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								   Returns :  - 1  if  key1  <  key2  0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								   if  key1  =  key2  1  if  key1  >  key2  */ 
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  inline  int  comp_keys ( const  struct  reiserfs_key  * le_key ,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											    const  struct  cpu_key  * cpu_key ) 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									int  retval ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									retval  =  comp_short_keys ( le_key ,  cpu_key ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( retval ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  retval ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( le_key_k_offset ( le_key_version ( le_key ) ,  le_key )  < 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									    cpu_key_k_offset ( cpu_key ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( le_key_k_offset ( le_key_version ( le_key ) ,  le_key )  > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									    cpu_key_k_offset ( cpu_key ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( cpu_key - > key_length  = =  3 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* this part is needed only when tail conversion is in progress */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( le_key_k_type ( le_key_version ( le_key ) ,  le_key )  < 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									    cpu_key_k_type ( cpu_key ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( le_key_k_type ( le_key_version ( le_key ) ,  le_key )  > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									    cpu_key_k_type ( cpu_key ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								inline  int  comp_short_le_keys ( const  struct  reiserfs_key  * key1 ,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											      const  struct  reiserfs_key  * key2 ) 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									__u32  * p_s_1_u32 ,  * p_s_2_u32 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  n_key_length  =  REISERFS_SHORT_KEY_LEN ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									p_s_1_u32  =  ( __u32  * )  key1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									p_s_2_u32  =  ( __u32  * )  key2 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  ( ;  n_key_length - - ;  + + p_s_1_u32 ,  + + p_s_2_u32 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( le32_to_cpu ( * p_s_1_u32 )  <  le32_to_cpu ( * p_s_2_u32 ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( le32_to_cpu ( * p_s_1_u32 )  >  le32_to_cpu ( * p_s_2_u32 ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								inline  void  le_key2cpu_key ( struct  cpu_key  * to ,  const  struct  reiserfs_key  * from )  
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									int  version ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									to - > on_disk_key . k_dir_id  =  le32_to_cpu ( from - > k_dir_id ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									to - > on_disk_key . k_objectid  =  le32_to_cpu ( from - > k_objectid ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// find out version of the key
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									version  =  le_key_version ( from ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									to - > version  =  version ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									to - > on_disk_key . k_offset  =  le_key_k_offset ( version ,  from ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									to - > on_disk_key . k_type  =  le_key_k_type ( version ,  from ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// this does not say which one is bigger, it only returns 1 if keys
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// are not equal, 0 otherwise
  
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								inline  int  comp_le_keys ( const  struct  reiserfs_key  * k1 ,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											const  struct  reiserfs_key  * k2 ) 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  memcmp ( k1 ,  k2 ,  sizeof ( struct  reiserfs_key ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/**************************************************************************
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *   Binary  search  toolkit  function                                         * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *   Search  for  an  item  in  the  array  by  the  item  key                        * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *   Returns :     1  if  found ,   0  if  not  found ;                               * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *         * p_n_pos  =  number  of  the  searched  element  if  found ,  else  the     * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *         number  of  the  first  element  that  is  larger  than  p_v_key .         * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* For those not familiar with binary search: n_lbound is the leftmost item that it
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 could  be ,  n_rbound  the  rightmost  item  that  it  could  be .   We  examine  the  item 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 halfway  between  n_lbound  and  n_rbound ,  and  that  tells  us  either  that  we  can  increase 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 n_lbound ,  or  decrease  n_rbound ,  or  that  we  have  found  it ,  or  if  n_lbound  < =  n_rbound  that 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 there  are  no  possible  items ,  and  we  have  not  found  it .  With  each  examination  we 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 cut  the  number  of  possible  items  it  could  be  by  one  more  than  half  rounded  down , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 or  we  find  it .  */ 
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  inline  int  bin_search ( const  void  * p_v_key , 	/* Key to search for.                   */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											     const  void  * p_v_base , 	/* First item in the array.             */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											     int  p_n_num , 	/* Number of items in the array.        */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											     int  p_n_width , 	/* Item size in the array.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														   searched .  Lest  the  reader  be 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														   confused ,  note  that  this  is  crafted 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														   as  a  general  function ,  and  when  it 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														   is  applied  specifically  to  the  array 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														   of  item  headers  in  a  node ,  p_n_width 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														   is  actually  the  item  header  size  not 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														   the  item  size .                       */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											     int  * p_n_pos 	/* Number of the searched for element. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  n_rbound ,  n_lbound ,  n_j ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  ( n_j  =  ( ( n_rbound  =  p_n_num  -  1 )  +  ( n_lbound  =  0 ) )  /  2 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									     n_lbound  < =  n_rbound ;  n_j  =  ( n_rbound  +  n_lbound )  /  2 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										switch  ( comp_keys 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											( ( struct  reiserfs_key  * ) ( ( char  * ) p_v_base  + 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														 n_j  *  p_n_width ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 ( struct  cpu_key  * ) p_v_key ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										case  - 1 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											n_lbound  =  n_j  +  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										case  1 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											n_rbound  =  n_j  -  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										case  0 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											* p_n_pos  =  n_j ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  ITEM_FOUND ; 	/* Key found in the array.  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* bin_search did not find given key, it returns position of key,
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									   that  is  minimal  and  greater  than  the  given  one .  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									* p_n_pos  =  n_lbound ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  ITEM_NOT_FOUND ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# ifdef CONFIG_REISERFS_CHECK 
  
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								extern  struct  tree_balance  * cur_tb ;  
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* Minimal possible key. It is never in the tree. */  
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								const  struct  reiserfs_key  MIN_KEY  =  {  0 ,  0 ,  { { 0 ,  0 } , }  } ;  
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* Maximal possible key. It is never in the tree. */  
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  const  struct  reiserfs_key  MAX_KEY  =  {  
						 
					
						
							
								
									
										
										
										
											2005-05-01 08:59:18 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									__constant_cpu_to_le32 ( 0xffffffff ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									__constant_cpu_to_le32 ( 0xffffffff ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									{ { __constant_cpu_to_le32 ( 0xffffffff ) , 
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									  __constant_cpu_to_le32 ( 0xffffffff ) } , } 
							 
						 
					
						
							
								
									
										
										
										
											2005-05-01 08:59:18 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* Get delimiting key of the buffer by looking for it in the buffers in the path, starting from the bottom
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								   of  the  path ,  and  going  upwards .   We  must  check  the  path ' s  validity  at  each  step .   If  the  key  is  not  in 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								   the  path ,  there  is  no  delimiting  key  in  the  tree  ( buffer  is  first  or  last  buffer  in  tree ) ,  and  in  this 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								   case  we  return  a  special  key ,  either  MIN_KEY  or  MAX_KEY .  */ 
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  inline  const  struct  reiserfs_key  * get_lkey ( const  struct  path  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														  * p_s_chk_path , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														  const  struct  super_block 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														  * p_s_sb ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  n_position ,  n_path_offset  =  p_s_chk_path - > path_length ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  buffer_head  * p_s_parent ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RFALSE ( n_path_offset  <  FIRST_PATH_ELEMENT_OFFSET , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									       " PAP-5010: invalid offset in the path " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* While not higher in path than first element. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									while  ( n_path_offset - -  >  FIRST_PATH_ELEMENT_OFFSET )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										RFALSE ( ! buffer_uptodate 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										       ( PATH_OFFSET_PBUFFER ( p_s_chk_path ,  n_path_offset ) ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										       " PAP-5020: parent is not uptodate " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Parent at the path is not in the tree now. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! B_IS_IN_TREE 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										    ( p_s_parent  = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										     PATH_OFFSET_PBUFFER ( p_s_chk_path ,  n_path_offset ) ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  & MAX_KEY ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Check whether position in the parent is correct. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ( n_position  = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										     PATH_OFFSET_POSITION ( p_s_chk_path , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													  n_path_offset ) )  > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										    B_NR_ITEMS ( p_s_parent ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  & MAX_KEY ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Check whether parent at the path really points to the child. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( B_N_CHILD_NUM ( p_s_parent ,  n_position )  ! = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										    PATH_OFFSET_PBUFFER ( p_s_chk_path , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													n_path_offset  +  1 ) - > b_blocknr ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  & MAX_KEY ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Return delimiting key if position in the parent is not equal to zero. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( n_position ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  B_N_PDELIM_KEY ( p_s_parent ,  n_position  -  1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Return MIN_KEY if we are in the root of the buffer tree. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( PATH_OFFSET_PBUFFER ( p_s_chk_path ,  FIRST_PATH_ELEMENT_OFFSET ) - > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									    b_blocknr  = =  SB_ROOT_BLOCK ( p_s_sb ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  & MIN_KEY ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  & MAX_KEY ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* Get delimiting key of the buffer at the path and its right neighbor. */  
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								inline  const  struct  reiserfs_key  * get_rkey ( const  struct  path  * p_s_chk_path ,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													   const  struct  super_block  * p_s_sb ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  n_position ,  n_path_offset  =  p_s_chk_path - > path_length ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  buffer_head  * p_s_parent ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RFALSE ( n_path_offset  <  FIRST_PATH_ELEMENT_OFFSET , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									       " PAP-5030: invalid offset in the path " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									while  ( n_path_offset - -  >  FIRST_PATH_ELEMENT_OFFSET )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										RFALSE ( ! buffer_uptodate 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										       ( PATH_OFFSET_PBUFFER ( p_s_chk_path ,  n_path_offset ) ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										       " PAP-5040: parent is not uptodate " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Parent at the path is not in the tree now. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! B_IS_IN_TREE 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										    ( p_s_parent  = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										     PATH_OFFSET_PBUFFER ( p_s_chk_path ,  n_path_offset ) ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  & MIN_KEY ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Check whether position in the parent is correct. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ( n_position  = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										     PATH_OFFSET_POSITION ( p_s_chk_path , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													  n_path_offset ) )  > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										    B_NR_ITEMS ( p_s_parent ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  & MIN_KEY ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Check whether parent at the path really points to the child. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( B_N_CHILD_NUM ( p_s_parent ,  n_position )  ! = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										    PATH_OFFSET_PBUFFER ( p_s_chk_path , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													n_path_offset  +  1 ) - > b_blocknr ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  & MIN_KEY ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Return delimiting key if position in the parent is not the last one. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( n_position  ! =  B_NR_ITEMS ( p_s_parent ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  B_N_PDELIM_KEY ( p_s_parent ,  n_position ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Return MAX_KEY if we are in the root of the buffer tree. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( PATH_OFFSET_PBUFFER ( p_s_chk_path ,  FIRST_PATH_ELEMENT_OFFSET ) - > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									    b_blocknr  = =  SB_ROOT_BLOCK ( p_s_sb ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  & MAX_KEY ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  & MIN_KEY ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* Check whether a key is contained in the tree rooted from a buffer at a path. */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* This works by looking at the left and right delimiting keys for the buffer in the last path_element in
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								   the  path .   These  delimiting  keys  are  stored  at  least  one  level  above  that  buffer  in  the  tree .  If  the 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								   buffer  is  the  first  or  last  node  in  the  tree  order  then  one  of  the  delimiting  keys  may  be  absent ,  and  in 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								   this  case  get_lkey  and  get_rkey  return  a  special  key  which  is  MIN_KEY  or  MAX_KEY .  */ 
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  inline  int  key_in_buffer ( struct  path  * p_s_chk_path , 	/* Path which should be checked.  */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												const  struct  cpu_key  * p_s_key , 	/* Key which should be checked.   */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												struct  super_block  * p_s_sb 	/* Super block pointer.           */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									RFALSE ( ! p_s_key  | |  p_s_chk_path - > path_length  <  FIRST_PATH_ELEMENT_OFFSET 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									       | |  p_s_chk_path - > path_length  >  MAX_HEIGHT , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									       " PAP-5050: pointer to the key(%p) is NULL or invalid path length(%d) " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									       p_s_key ,  p_s_chk_path - > path_length ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RFALSE ( ! PATH_PLAST_BUFFER ( p_s_chk_path ) - > b_bdev , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									       " PAP-5060: device must not be NODEV " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( comp_keys ( get_lkey ( p_s_chk_path ,  p_s_sb ) ,  p_s_key )  = =  1 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* left delimiting key is bigger, that the key we look for */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									//  if ( comp_keys(p_s_key, get_rkey(p_s_chk_path, p_s_sb)) != -1 )
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( comp_keys ( get_rkey ( p_s_chk_path ,  p_s_sb ) ,  p_s_key )  ! =  1 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* p_s_key must be less than right delimitiing key */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								inline  void  decrement_bcount ( struct  buffer_head  * p_s_bh )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( p_s_bh )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( atomic_read ( & ( p_s_bh - > b_count ) ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											put_bh ( p_s_bh ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										reiserfs_panic ( NULL , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											       " PAP-5070: decrement_bcount: trying to free free buffer %b " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											       p_s_bh ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* Decrement b_count field of the all buffers in the path. */  
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								void  decrement_counters_in_path ( struct  path  * p_s_search_path )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  n_path_offset  =  p_s_search_path - > path_length ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RFALSE ( n_path_offset  <  ILLEGAL_PATH_ELEMENT_OFFSET  | | 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									       n_path_offset  >  EXTENDED_MAX_HEIGHT  -  1 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									       " PAP-5080: invalid path offset of %d " ,  n_path_offset ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									while  ( n_path_offset  >  ILLEGAL_PATH_ELEMENT_OFFSET )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										struct  buffer_head  * bh ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										bh  =  PATH_OFFSET_PBUFFER ( p_s_search_path ,  n_path_offset - - ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										decrement_bcount ( bh ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									p_s_search_path - > path_length  =  ILLEGAL_PATH_ELEMENT_OFFSET ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								int  reiserfs_check_path ( struct  path  * p )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RFALSE ( p - > path_length  ! =  ILLEGAL_PATH_ELEMENT_OFFSET , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									       " path not properly relsed " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* Release all buffers in the path. Restore dirty bits clean
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								* *  when  preparing  the  buffer  for  the  log  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								* *  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								* *  only  called  from  fix_nodes ( )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								*/  
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								void  pathrelse_and_restore ( struct  super_block  * s ,  struct  path  * p_s_search_path )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  n_path_offset  =  p_s_search_path - > path_length ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RFALSE ( n_path_offset  <  ILLEGAL_PATH_ELEMENT_OFFSET , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									       " clm-4000: invalid path offset " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									while  ( n_path_offset  >  ILLEGAL_PATH_ELEMENT_OFFSET )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										reiserfs_restore_prepared_buffer ( s , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														 PATH_OFFSET_PBUFFER 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														 ( p_s_search_path , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														  n_path_offset ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										brelse ( PATH_OFFSET_PBUFFER ( p_s_search_path ,  n_path_offset - - ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									p_s_search_path - > path_length  =  ILLEGAL_PATH_ELEMENT_OFFSET ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* Release all buffers in the path. */  
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								void  pathrelse ( struct  path  * p_s_search_path )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  n_path_offset  =  p_s_search_path - > path_length ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									RFALSE ( n_path_offset  <  ILLEGAL_PATH_ELEMENT_OFFSET , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									       " PAP-5090: invalid path offset " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									while  ( n_path_offset  >  ILLEGAL_PATH_ELEMENT_OFFSET ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										brelse ( PATH_OFFSET_PBUFFER ( p_s_search_path ,  n_path_offset - - ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									p_s_search_path - > path_length  =  ILLEGAL_PATH_ELEMENT_OFFSET ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  int  is_leaf ( char  * buf ,  int  blocksize ,  struct  buffer_head  * bh )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  block_head  * blkh ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  item_head  * ih ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  used_space ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  prev_location ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  i ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  nr ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									blkh  =  ( struct  block_head  * ) buf ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( blkh_level ( blkh )  ! =  DISK_LEAF_NODE_LEVEL )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										reiserfs_warning ( NULL , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												 " is_leaf: this should be caught earlier " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									nr  =  blkh_nr_item ( blkh ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( nr  <  1  | |  nr  >  ( ( blocksize  -  BLKH_SIZE )  /  ( IH_SIZE  +  MIN_ITEM_LEN ) ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* item number is too big or too small */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										reiserfs_warning ( NULL ,  " is_leaf: nr_item seems wrong: %z " ,  bh ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ih  =  ( struct  item_head  * ) ( buf  +  BLKH_SIZE )  +  nr  -  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									used_space  =  BLKH_SIZE  +  IH_SIZE  *  nr  +  ( blocksize  -  ih_location ( ih ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( used_space  ! =  blocksize  -  blkh_free_space ( blkh ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* free space does not match to calculated amount of use space */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										reiserfs_warning ( NULL ,  " is_leaf: free space seems wrong: %z " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												 bh ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// FIXME: it is_leaf will hit performance too much - we may have
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// return 1 here
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* check tables of item heads */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ih  =  ( struct  item_head  * ) ( buf  +  BLKH_SIZE ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									prev_location  =  blocksize ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  ( i  =  0 ;  i  <  nr ;  i + + ,  ih + + )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( le_ih_k_type ( ih )  = =  TYPE_ANY )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											reiserfs_warning ( NULL , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													 " is_leaf: wrong item type for item %h " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													 ih ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ih_location ( ih )  > =  blocksize 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										    | |  ih_location ( ih )  <  IH_SIZE  *  nr )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											reiserfs_warning ( NULL , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													 " is_leaf: item location seems wrong: %h " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													 ih ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ih_item_len ( ih )  <  1 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										    | |  ih_item_len ( ih )  >  MAX_ITEM_LEN ( blocksize ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											reiserfs_warning ( NULL , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													 " is_leaf: item length seems wrong: %h " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													 ih ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( prev_location  -  ih_location ( ih )  ! =  ih_item_len ( ih ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											reiserfs_warning ( NULL , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													 " is_leaf: item location seems wrong (second one): %h " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													 ih ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										prev_location  =  ih_location ( ih ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// one may imagine much more checks
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* returns 1 if buf looks like an internal node, 0 otherwise */  
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  int  is_internal ( char  * buf ,  int  blocksize ,  struct  buffer_head  * bh )  
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  block_head  * blkh ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  nr ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  used_space ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									blkh  =  ( struct  block_head  * ) buf ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									nr  =  blkh_level ( blkh ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( nr  < =  DISK_LEAF_NODE_LEVEL  | |  nr  >  MAX_HEIGHT )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* this level is not possible for internal nodes */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										reiserfs_warning ( NULL , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												 " is_internal: this should be caught earlier " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									nr  =  blkh_nr_item ( blkh ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( nr  >  ( blocksize  -  BLKH_SIZE  -  DC_SIZE )  /  ( KEY_SIZE  +  DC_SIZE ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* for internal which is not root we might check min number of keys */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										reiserfs_warning ( NULL , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												 " is_internal: number of key seems wrong: %z " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												 bh ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									used_space  =  BLKH_SIZE  +  KEY_SIZE  *  nr  +  DC_SIZE  *  ( nr  +  1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( used_space  ! =  blocksize  -  blkh_free_space ( blkh ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										reiserfs_warning ( NULL , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												 " is_internal: free space seems wrong: %z " ,  bh ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// one may imagine much more checks
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// make sure that bh contains formatted node of reiserfs tree of
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// 'level'-th level
  
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  int  is_tree_node ( struct  buffer_head  * bh ,  int  level )  
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( B_LEVEL ( bh )  ! =  level )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										reiserfs_warning ( NULL , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												 " is_tree_node: node level %d does not match to the expected one %d " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												 B_LEVEL ( bh ) ,  level ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( level  = =  DISK_LEAF_NODE_LEVEL ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  is_leaf ( bh - > b_data ,  bh - > b_size ,  bh ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  is_internal ( bh - > b_data ,  bh - > b_size ,  bh ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define SEARCH_BY_KEY_READA 16 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* The function is NOT SCHEDULE-SAFE! */  
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  void  search_by_key_reada ( struct  super_block  * s ,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												struct  buffer_head  * * bh , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												unsigned  long  * b ,  int  num ) 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									int  i ,  j ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  ( i  =  0 ;  i  <  num ;  i + + )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										bh [ i ]  =  sb_getblk ( s ,  b [ i ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  ( j  =  0 ;  j  <  i ;  j + + )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/*
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  note ,  this  needs  attention  if  we  are  getting  rid  of  the  BKL 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  you  have  to  make  sure  the  prepared  bit  isn ' t  set  on  this  buffer 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! buffer_uptodate ( bh [ j ] ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ll_rw_block ( READA ,  1 ,  bh  +  j ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										brelse ( bh [ j ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/**************************************************************************
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Algorithm    SearchByKey                                                 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *              look  for  item  in  the  Disk  S + Tree  by  its  key                 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Input :   p_s_sb    -   super  block                                         * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *          p_s_key   -  pointer  to  the  key  to  search                         * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Output :  ITEM_FOUND ,  ITEM_NOT_FOUND  or  IO_ERROR                          * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *          p_s_search_path  -  path  from  the  root  to  the  needed  leaf         * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* This function fills up the path from the root to the leaf as it
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								   descends  the  tree  looking  for  the  key .   It  uses  reiserfs_bread  to 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								   try  to  find  buffers  in  the  cache  given  their  block  number .   If  it 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								   does  not  find  them  in  the  cache  it  reads  them  from  disk .   For  each 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								   node  search_by_key  finds  using  reiserfs_bread  it  then  uses 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								   bin_search  to  look  through  that  node .   bin_search  will  find  the 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								   position  of  the  block_number  of  the  next  node  if  it  is  looking 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								   through  an  internal  node .   If  it  is  looking  through  a  leaf  node 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								   bin_search  will  find  the  position  of  the  item  which  has  key  either 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								   equal  to  given  key ,  or  which  is  the  maximal  key  less  than  the  given 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								   key .   search_by_key  returns  a  path  that  must  be  checked  for  the 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								   correctness  of  the  top  of  the  path  but  need  not  be  checked  for  the 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								   correctness  of  the  bottom  of  the  path  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* The function is NOT SCHEDULE-SAFE! */  
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								int  search_by_key ( struct  super_block  * p_s_sb ,  const  struct  cpu_key  * p_s_key , 	/* Key to search. */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										  struct  path  * p_s_search_path , 	/* This structure was
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														   allocated  and  initialized 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														   by  the  calling 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														   function .  It  is  filled  up 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														   by  this  function .   */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										  int  n_stop_level 	/* How far down the tree to search. To
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													   stop  at  leaf  level  -  set  to 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													   DISK_LEAF_NODE_LEVEL  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  n_block_number ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  expected_level ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  buffer_head  * p_s_bh ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  path_element  * p_s_last_element ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  n_node_level ,  n_retval ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  right_neighbor_of_leaf_node ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  fs_gen ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  buffer_head  * reada_bh [ SEARCH_BY_KEY_READA ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									unsigned  long  reada_blocks [ SEARCH_BY_KEY_READA ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  reada_count  =  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# ifdef CONFIG_REISERFS_CHECK 
  
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									int  n_repeat_counter  =  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									PROC_INFO_INC ( p_s_sb ,  search_by_key ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* As we add each node to a path we increase its count.  This means that
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									   we  must  be  careful  to  release  all  nodes  in  a  path  before  we  either 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									   discard  the  path  struct  or  re - use  the  path  struct ,  as  we  do  here .  */ 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									decrement_counters_in_path ( p_s_search_path ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									right_neighbor_of_leaf_node  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* With each iteration of this loop we search through the items in the
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									   current  node ,  and  calculate  the  next  current  node ( next  path  element ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									   for  the  next  iteration  of  this  loop . .  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									n_block_number  =  SB_ROOT_BLOCK ( p_s_sb ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									expected_level  =  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									while  ( 1 )  { 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# ifdef CONFIG_REISERFS_CHECK 
  
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( ! ( + + n_repeat_counter  %  50000 ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											reiserfs_warning ( p_s_sb ,  " PAP-5100: search_by_key: %s: " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													 " there were %d iterations of while loop  " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													 " looking for key %K " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													 current - > comm ,  n_repeat_counter , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													 p_s_key ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										/* prep path to have another element added to it. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										p_s_last_element  = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										    PATH_OFFSET_PELEMENT ( p_s_search_path , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													 + + p_s_search_path - > path_length ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										fs_gen  =  get_generation ( p_s_sb ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Read the next tree node, and set the last element in the path to
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										   have  a  pointer  to  it .  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ( p_s_bh  =  p_s_last_element - > pe_buffer  = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										     sb_getblk ( p_s_sb ,  n_block_number ) ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( ! buffer_uptodate ( p_s_bh )  & &  reada_count  >  1 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												search_by_key_reada ( p_s_sb ,  reada_bh , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														    reada_blocks ,  reada_count ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											ll_rw_block ( READ ,  1 ,  & p_s_bh ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											wait_on_buffer ( p_s_bh ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( ! buffer_uptodate ( p_s_bh ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												goto  io_error ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										      io_error : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											p_s_search_path - > path_length - - ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											pathrelse ( p_s_search_path ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  IO_ERROR ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										reada_count  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( expected_level  = =  - 1 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											expected_level  =  SB_TREE_HEIGHT ( p_s_sb ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										expected_level - - ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* It is possible that schedule occurred. We must check whether the key
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										   to  search  is  still  in  the  tree  rooted  from  the  current  buffer .  If 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										   not  then  repeat  search  from  the  root .  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( fs_changed ( fs_gen ,  p_s_sb )  & & 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										    ( ! B_IS_IN_TREE ( p_s_bh )  | | 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										     B_LEVEL ( p_s_bh )  ! =  expected_level  | | 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										     ! key_in_buffer ( p_s_search_path ,  p_s_key ,  p_s_sb ) ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											PROC_INFO_INC ( p_s_sb ,  search_by_key_fs_changed ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											PROC_INFO_INC ( p_s_sb ,  search_by_key_restarted ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											PROC_INFO_INC ( p_s_sb , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												      sbk_restarted [ expected_level  -  1 ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											decrement_counters_in_path ( p_s_search_path ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											/* Get the root block number so that we can repeat the search
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											   starting  from  the  root .  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											n_block_number  =  SB_ROOT_BLOCK ( p_s_sb ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											expected_level  =  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											right_neighbor_of_leaf_node  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											/* repeat search from the root */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										/* only check that the key is in the buffer if p_s_key is not
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										   equal  to  the  MAX_KEY .  Latter  case  is  only  possible  in 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										   " finish_unfinished() "  processing  during  mount .  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										RFALSE ( comp_keys ( & MAX_KEY ,  p_s_key )  & & 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										       ! key_in_buffer ( p_s_search_path ,  p_s_key ,  p_s_sb ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										       " PAP-5130: key is not in the buffer " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								# ifdef CONFIG_REISERFS_CHECK 
  
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( cur_tb )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											print_cur_tb ( " 5140 " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											reiserfs_panic ( p_s_sb , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												       " PAP-5140: search_by_key: schedule occurred in do_balance! " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// make sure, that the node contents look like a node of
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// certain level
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! is_tree_node ( p_s_bh ,  expected_level ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											reiserfs_warning ( p_s_sb ,  " vs-5150: search_by_key:  " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													 " invalid format found in block %ld. Fsck? " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													 p_s_bh - > b_blocknr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											pathrelse ( p_s_search_path ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  IO_ERROR ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										/* ok, we have acquired next formatted node in the tree */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										n_node_level  =  B_LEVEL ( p_s_bh ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										PROC_INFO_BH_STAT ( p_s_sb ,  p_s_bh ,  n_node_level  -  1 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										RFALSE ( n_node_level  <  n_stop_level , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										       " vs-5152: tree level (%d) is less than stop level (%d) " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										       n_node_level ,  n_stop_level ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										n_retval  =  bin_search ( p_s_key ,  B_N_PITEM_HEAD ( p_s_bh ,  0 ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												      B_NR_ITEMS ( p_s_bh ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												      ( n_node_level  = = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												       DISK_LEAF_NODE_LEVEL )  ?  IH_SIZE  : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												      KEY_SIZE , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												      & ( p_s_last_element - > pe_position ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( n_node_level  = =  n_stop_level )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  n_retval ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										/* we are not in the stop level */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( n_retval  = =  ITEM_FOUND ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											/* item has been found, so we choose the pointer which is to the right of the found one */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											p_s_last_element - > pe_position + + ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* if item was not found we choose the position which is to
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										   the  left  of  the  found  item .  This  requires  no  code , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										   bin_search  did  it  already .  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* So we have chosen a position in the current node which is
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										   an  internal  node .   Now  we  calculate  child  block  number  by 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										   position  in  the  node .  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										n_block_number  = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										    B_N_CHILD_NUM ( p_s_bh ,  p_s_last_element - > pe_position ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* if we are going to read leaf nodes, try for read ahead as well */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ( p_s_search_path - > reada  &  PATH_READA )  & & 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										    n_node_level  = =  DISK_LEAF_NODE_LEVEL  +  1 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											int  pos  =  p_s_last_element - > pe_position ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											int  limit  =  B_NR_ITEMS ( p_s_bh ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											struct  reiserfs_key  * le_key ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( p_s_search_path - > reada  &  PATH_READA_BACK ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												limit  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											while  ( reada_count  <  SEARCH_BY_KEY_READA )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  ( pos  = =  limit ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												reada_blocks [ reada_count + + ]  = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												    B_N_CHILD_NUM ( p_s_bh ,  pos ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  ( p_s_search_path - > reada  &  PATH_READA_BACK ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													pos - - ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												else 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													pos + + ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												/*
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												 *  check  to  make  sure  we ' re  in  the  same  object 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												le_key  =  B_N_PDELIM_KEY ( p_s_bh ,  pos ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  ( le32_to_cpu ( le_key - > k_objectid )  ! = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												    p_s_key - > on_disk_key . k_objectid )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* Form the path to an item and position in this item which contains
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								   file  byte  defined  by  p_s_key .  If  there  is  no  such  item 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								   corresponding  to  the  key ,  we  point  the  path  to  the  item  with 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								   maximal  key  less  than  p_s_key ,  and  * p_n_pos_in_item  is  set  to  one 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								   past  the  last  entry / byte  in  the  item .   If  searching  for  entry  in  a 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								   directory  item ,  and  it  is  not  found ,  * p_n_pos_in_item  is  set  to  one 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								   entry  more  than  the  entry  with  maximal  key  which  is  less  than  the 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								   sought  key . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								   Note  that  if  there  is  no  entry  in  this  same  node  which  is  one  more , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								   then  we  point  to  an  imaginary  entry .   for  direct  items ,  the 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								   position  is  in  units  of  bytes ,  for  indirect  items  the  position  is 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								   in  units  of  blocknr  entries ,  for  directory  items  the  position  is  in 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								   units  of  directory  entries .   */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* The function is NOT SCHEDULE-SAFE! */  
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								int  search_for_position_by_key ( struct  super_block  * p_s_sb , 	/* Pointer to the super block.          */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											       const  struct  cpu_key  * p_cpu_key , 	/* Key to search (cpu variable)         */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											       struct  path  * p_s_search_path 	/* Filled up by this function.          */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  item_head  * p_le_ih ; 	/* pointer to on-disk structure */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  n_blk_size ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									loff_t  item_offset ,  offset ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  reiserfs_dir_entry  de ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  retval ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* If searching for directory entry. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( is_direntry_cpu_key ( p_cpu_key ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  search_by_entry_key ( p_s_sb ,  p_cpu_key ,  p_s_search_path , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													   & de ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* If not searching for directory entry. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* If item is found. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									retval  =  search_item ( p_s_sb ,  p_cpu_key ,  p_s_search_path ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( retval  = =  IO_ERROR ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  retval ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( retval  = =  ITEM_FOUND )  { 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										RFALSE ( ! ih_item_len 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										       ( B_N_PITEM_HEAD 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											( PATH_PLAST_BUFFER ( p_s_search_path ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 PATH_LAST_POSITION ( p_s_search_path ) ) ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										       " PAP-5165: item length equals zero " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										pos_in_item ( p_s_search_path )  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  POSITION_FOUND ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									RFALSE ( ! PATH_LAST_POSITION ( p_s_search_path ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									       " PAP-5170: position equals zero " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* Item is not found. Set path to the previous item. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									p_le_ih  = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									    B_N_PITEM_HEAD ( PATH_PLAST_BUFFER ( p_s_search_path ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											   - - PATH_LAST_POSITION ( p_s_search_path ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									n_blk_size  =  p_s_sb - > s_blocksize ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( comp_short_keys ( & ( p_le_ih - > ih_key ) ,  p_cpu_key ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  FILE_NOT_FOUND ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// FIXME: quite ugly this far
 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									item_offset  =  le_ih_k_offset ( p_le_ih ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									offset  =  cpu_key_k_offset ( p_cpu_key ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* Needed byte is contained in the item pointed to by the path. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( item_offset  < =  offset  & & 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									    item_offset  +  op_bytes_number ( p_le_ih ,  n_blk_size )  >  offset )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										pos_in_item ( p_s_search_path )  =  offset  -  item_offset ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( is_indirect_le_ih ( p_le_ih ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											pos_in_item ( p_s_search_path )  / =  n_blk_size ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  POSITION_FOUND ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* Needed byte is not contained in the item pointed to by the
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									   path .  Set  pos_in_item  out  of  the  item .  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( is_indirect_le_ih ( p_le_ih ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										pos_in_item ( p_s_search_path )  = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										    ih_item_len ( p_le_ih )  /  UNFM_P_SIZE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									else 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										pos_in_item ( p_s_search_path )  =  ih_item_len ( p_le_ih ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  POSITION_NOT_FOUND ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* Compare given item and item pointed to by the path. */  
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								int  comp_items ( const  struct  item_head  * stored_ih ,  const  struct  path  * p_s_path )  
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  buffer_head  * p_s_bh ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  item_head  * ih ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* Last buffer at the path is not in the tree. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! B_IS_IN_TREE ( p_s_bh  =  PATH_PLAST_BUFFER ( p_s_path ) ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* Last path position is invalid. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( PATH_LAST_POSITION ( p_s_path )  > =  B_NR_ITEMS ( p_s_bh ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* we need only to know, whether it is the same item */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ih  =  get_ih ( p_s_path ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  memcmp ( stored_ih ,  ih ,  IH_SIZE ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* unformatted nodes are not logged anymore, ever.  This is safe
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								* *  now  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								*/  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define held_by_others(bh) (atomic_read(&(bh)->b_count) > 1) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// block can not be forgotten as it is in I/O or held by someone
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define block_in_use(bh) (buffer_locked(bh) || (held_by_others(bh))) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// prepare for delete or cut of direct item
  
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  inline  int  prepare_for_direct_item ( struct  path  * path ,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													  struct  item_head  * le_ih , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													  struct  inode  * inode , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													  loff_t  new_file_length ,  int  * cut_size ) 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									loff_t  round_len ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( new_file_length  = =  max_reiserfs_offset ( inode ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* item has to be deleted */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										* cut_size  =  - ( IH_SIZE  +  ih_item_len ( le_ih ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  M_DELETE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// new file gets truncated
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( get_inode_item_key_version ( inode )  = =  KEY_FORMAT_3_6 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										round_len  =  ROUND_UP ( new_file_length ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* this was n_new_file_length < le_ih ... */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( round_len  <  le_ih_k_offset ( le_ih ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											* cut_size  =  - ( IH_SIZE  +  ih_item_len ( le_ih ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  M_DELETE ; 	/* Delete this item. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Calculate first position and size for cutting from item. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										pos_in_item ( path )  =  round_len  -  ( le_ih_k_offset ( le_ih )  -  1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										* cut_size  =  - ( ih_item_len ( le_ih )  -  pos_in_item ( path ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  M_CUT ; 	/* Cut from this item. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// old file: items may have any length
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( new_file_length  <  le_ih_k_offset ( le_ih ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										* cut_size  =  - ( IH_SIZE  +  ih_item_len ( le_ih ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  M_DELETE ; 	/* Delete this item. */ 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Calculate first position and size for cutting from item. */ 
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									* cut_size  =  - ( ih_item_len ( le_ih )  - 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										      ( pos_in_item ( path )  = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										       new_file_length  +  1  -  le_ih_k_offset ( le_ih ) ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  M_CUT ; 		/* Cut from this item. */ 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  inline  int  prepare_for_direntry_item ( struct  path  * path ,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													    struct  item_head  * le_ih , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													    struct  inode  * inode , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													    loff_t  new_file_length , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													    int  * cut_size ) 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( le_ih_k_offset ( le_ih )  = =  DOT_OFFSET  & & 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									    new_file_length  = =  max_reiserfs_offset ( inode ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										RFALSE ( ih_entry_count ( le_ih )  ! =  2 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										       " PAP-5220: incorrect empty directory item (%h) " ,  le_ih ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										* cut_size  =  - ( IH_SIZE  +  ih_item_len ( le_ih ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  M_DELETE ; 	/* Delete the directory item containing "." and ".." entry. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ih_entry_count ( le_ih )  = =  1 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Delete the directory item such as there is one record only
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										   in  this  item  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										* cut_size  =  - ( IH_SIZE  +  ih_item_len ( le_ih ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  M_DELETE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Cut one record from the directory item. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									* cut_size  = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									    - ( DEH_SIZE  + 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									      entry_length ( get_last_bh ( path ) ,  le_ih ,  pos_in_item ( path ) ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  M_CUT ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*  If the path points to a directory or direct item, calculate mode and the size cut, for balance.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    If  the  path  points  to  an  indirect  item ,  remove  some  number  of  its  unformatted  nodes . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    In  case  of  file  truncate  calculate  whether  this  item  must  be  deleted / truncated  or  last 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    unformatted  node  of  this  item  will  be  converted  to  a  direct  item . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    This  function  returns  a  determination  of  what  balance  mode  the  calling  function  should  employ .  */ 
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  char  prepare_for_delete_or_cut ( struct  reiserfs_transaction_handle  * th ,  struct  inode  * inode ,  struct  path  * p_s_path ,  const  struct  cpu_key  * p_s_item_key ,  int  * p_n_removed , 	/* Number of unformatted nodes which were removed
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
																														   from  end  of  the  file .  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												      int  * p_n_cut_size ,  unsigned  long  long  n_new_file_length 	/* MAX_KEY_OFFSET in case of delete. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  super_block  * p_s_sb  =  inode - > i_sb ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  item_head  * p_le_ih  =  PATH_PITEM_HEAD ( p_s_path ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  buffer_head  * p_s_bh  =  PATH_PLAST_BUFFER ( p_s_path ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									BUG_ON ( ! th - > t_trans_id ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* Stat_data item. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( is_statdata_le_ih ( p_le_ih ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										RFALSE ( n_new_file_length  ! =  max_reiserfs_offset ( inode ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										       " PAP-5210: mode must be M_DELETE " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										* p_n_cut_size  =  - ( IH_SIZE  +  ih_item_len ( p_le_ih ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  M_DELETE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* Directory item. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( is_direntry_le_ih ( p_le_ih ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  prepare_for_direntry_item ( p_s_path ,  p_le_ih ,  inode , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														 n_new_file_length , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														 p_n_cut_size ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* Direct item. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( is_direct_le_ih ( p_le_ih ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  prepare_for_direct_item ( p_s_path ,  p_le_ih ,  inode , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													       n_new_file_length ,  p_n_cut_size ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Case of an indirect item. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										int  n_unfm_number , 	/* Number of the item unformatted nodes. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 n_counter ,  n_blk_size ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										__le32  * p_n_unfm_pointer ; 	/* Pointer to the unformatted node number. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										__u32  tmp ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										struct  item_head  s_ih ; 	/* Item header. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										char  c_mode ; 	/* Returned mode of the balance. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										int  need_research ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										n_blk_size  =  p_s_sb - > s_blocksize ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Search for the needed object indirect item until there are no unformatted nodes to be removed. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										do  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											need_research  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											p_s_bh  =  PATH_PLAST_BUFFER ( p_s_path ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											/* Copy indirect item header to a temp variable. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											copy_item_head ( & s_ih ,  PATH_PITEM_HEAD ( p_s_path ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											/* Calculate number of unformatted nodes in this item. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											n_unfm_number  =  I_UNFM_NUM ( & s_ih ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											RFALSE ( ! is_indirect_le_ih ( & s_ih )  | |  ! n_unfm_number  | | 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											       pos_in_item ( p_s_path )  +  1  ! =  n_unfm_number , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											       " PAP-5240: invalid item %h  " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											       " n_unfm_number = %d *p_n_pos_in_item = %d " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											       & s_ih ,  n_unfm_number ,  pos_in_item ( p_s_path ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											/* Calculate balance mode and position in the item to remove unformatted nodes. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( n_new_file_length  = =  max_reiserfs_offset ( inode ) )  { 	/* Case of delete. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												pos_in_item ( p_s_path )  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												* p_n_cut_size  =  - ( IH_SIZE  +  ih_item_len ( & s_ih ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												c_mode  =  M_DELETE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											}  else  { 	/* Case of truncate. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  ( n_new_file_length  <  le_ih_k_offset ( & s_ih ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													pos_in_item ( p_s_path )  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													* p_n_cut_size  = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													    - ( IH_SIZE  +  ih_item_len ( & s_ih ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													c_mode  =  M_DELETE ; 	/* Delete this item. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													/* indirect item must be truncated starting from *p_n_pos_in_item-th position */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													pos_in_item ( p_s_path )  = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													    ( n_new_file_length  +  n_blk_size  - 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													     le_ih_k_offset ( & s_ih ) )  > >  p_s_sb - > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													    s_blocksize_bits ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													RFALSE ( pos_in_item ( p_s_path )  > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													       n_unfm_number , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													       " PAP-5250: invalid position in the item " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													/* Either convert last unformatted node of indirect item to direct item or increase
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													   its  free  space .   */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													if  ( pos_in_item ( p_s_path )  = = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													    n_unfm_number )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														* p_n_cut_size  =  0 ; 	/* Nothing to cut. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														return  M_CONVERT ; 	/* Maybe convert last unformatted node to the direct item. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													/* Calculate size to cut. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													* p_n_cut_size  = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													    - ( ih_item_len ( & s_ih )  - 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													      pos_in_item ( p_s_path )  * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													      UNFM_P_SIZE ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													c_mode  =  M_CUT ; 	/* Cut from this indirect item. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											RFALSE ( n_unfm_number  < =  pos_in_item ( p_s_path ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											       " PAP-5260: invalid position in the indirect item " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											/* pointers to be cut */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											n_unfm_number  - =  pos_in_item ( p_s_path ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											/* Set pointer to the last unformatted node pointer that is to be cut. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											p_n_unfm_pointer  = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											    ( __le32  * )  B_I_PITEM ( p_s_bh , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														 & s_ih )  +  I_UNFM_NUM ( & s_ih )  - 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											    1  -  * p_n_removed ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											/* We go through the unformatted nodes pointers of the indirect
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											   item  and  look  for  the  unformatted  nodes  in  the  cache .  If  we 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											   found  some  of  them  we  free  it ,  zero  corresponding  indirect  item 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											   entry  and  log  buffer  containing  that  indirect  item .  For  this  we 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											   need  to  prepare  last  path  element  for  logging .  If  some 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											   unformatted  node  has  b_count  >  1  we  must  not  free  this 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											   unformatted  node  since  it  is  in  use .  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											reiserfs_prepare_for_journal ( p_s_sb ,  p_s_bh ,  1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// note: path could be changed, first line in for loop takes care
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// of it
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											for  ( n_counter  =  * p_n_removed ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											     n_counter  <  n_unfm_number ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											     n_counter + + ,  p_n_unfm_pointer - - )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												cond_resched ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  ( item_moved ( & s_ih ,  p_s_path ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													need_research  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												RFALSE ( p_n_unfm_pointer  < 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												       ( __le32  * )  B_I_PITEM ( p_s_bh ,  & s_ih ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												       | |  p_n_unfm_pointer  > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												       ( __le32  * )  B_I_PITEM ( p_s_bh , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
															    & s_ih )  + 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												       I_UNFM_NUM ( & s_ih )  -  1 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												       " vs-5265: pointer out of range " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												/* Hole, nothing to remove. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  ( ! get_block_num ( p_n_unfm_pointer ,  0 ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													( * p_n_removed ) + + ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												( * p_n_removed ) + + ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												tmp  =  get_block_num ( p_n_unfm_pointer ,  0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												put_block_num ( p_n_unfm_pointer ,  0 ,  0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												journal_mark_dirty ( th ,  p_s_sb ,  p_s_bh ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												reiserfs_free_block ( th ,  inode ,  tmp ,  1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  ( item_moved ( & s_ih ,  p_s_path ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													need_research  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											/* a trick.  If the buffer has been logged, this
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 * *  will  do  nothing .   If  we ' ve  broken  the  loop  without 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 * *  logging  it ,  it  will  restore  the  buffer 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 * * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											reiserfs_restore_prepared_buffer ( p_s_sb ,  p_s_bh ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											/* This loop can be optimized. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										}  while  ( ( * p_n_removed  <  n_unfm_number  | |  need_research )  & & 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 search_for_position_by_key ( p_s_sb ,  p_s_item_key , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														    p_s_path )  = = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 POSITION_FOUND ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										RFALSE ( * p_n_removed  <  n_unfm_number , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										       " PAP-5310: indirect item is not found " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										RFALSE ( item_moved ( & s_ih ,  p_s_path ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										       " after while, comp failed, retry " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( c_mode  = =  M_CUT ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											pos_in_item ( p_s_path )  * =  UNFM_P_SIZE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  c_mode ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* Calculate number of bytes which will be deleted or cut during balance */  
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  int  calc_deleted_bytes_number ( struct  tree_balance  * p_s_tb ,  char  c_mode )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  n_del_size ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  item_head  * p_le_ih  =  PATH_PITEM_HEAD ( p_s_tb - > tb_path ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( is_statdata_le_ih ( p_le_ih ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									n_del_size  = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									    ( c_mode  = = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									     M_DELETE )  ?  ih_item_len ( p_le_ih )  :  - p_s_tb - > insert_size [ 0 ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( is_direntry_le_ih ( p_le_ih ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// return EMPTY_DIR_SIZE; /* We delete emty directoris only. */
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// we can't use EMPTY_DIR_SIZE, as old format dirs have a different
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// empty size.  ick. FIXME, is this right?
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										//
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  n_del_size ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( is_indirect_le_ih ( p_le_ih ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										n_del_size  =  ( n_del_size  /  UNFM_P_SIZE )  *  ( PATH_PLAST_BUFFER ( p_s_tb - > tb_path ) - > b_size ) ; 	// - get_ih_free_space (p_le_ih);
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  n_del_size ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  void  init_tb_struct ( struct  reiserfs_transaction_handle  * th ,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											   struct  tree_balance  * p_s_tb , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											   struct  super_block  * p_s_sb , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											   struct  path  * p_s_path ,  int  n_size ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									BUG_ON ( ! th - > t_trans_id ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									memset ( p_s_tb ,  ' \0 ' ,  sizeof ( struct  tree_balance ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									p_s_tb - > transaction_handle  =  th ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									p_s_tb - > tb_sb  =  p_s_sb ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									p_s_tb - > tb_path  =  p_s_path ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									PATH_OFFSET_PBUFFER ( p_s_path ,  ILLEGAL_PATH_ELEMENT_OFFSET )  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									PATH_OFFSET_POSITION ( p_s_path ,  ILLEGAL_PATH_ELEMENT_OFFSET )  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									p_s_tb - > insert_size [ 0 ]  =  n_size ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								void  padd_item ( char  * item ,  int  total_length ,  int  length )  
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									int  i ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									for  ( i  =  total_length ;  i  >  length ; ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										item [ - - i ]  =  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# ifdef REISERQUOTA_DEBUG 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								char  key2type ( struct  reiserfs_key  * ih )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( is_direntry_le_key ( 2 ,  ih ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  ' d ' ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( is_direct_le_key ( 2 ,  ih ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  ' D ' ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( is_indirect_le_key ( 2 ,  ih ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  ' i ' ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( is_statdata_le_key ( 2 ,  ih ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  ' s ' ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  ' u ' ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								char  head2type ( struct  item_head  * ih )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( is_direntry_le_ih ( ih ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  ' d ' ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( is_direct_le_ih ( ih ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  ' D ' ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( is_indirect_le_ih ( ih ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  ' i ' ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( is_statdata_le_ih ( ih ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  ' s ' ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  ' u ' ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* Delete object item. */  
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								int  reiserfs_delete_item ( struct  reiserfs_transaction_handle  * th ,  struct  path  * p_s_path , 	/* Path to the deleted item. */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 const  struct  cpu_key  * p_s_item_key , 	/* Key to search for the deleted item.  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 struct  inode  * p_s_inode , 	/* inode is here just to update i_blocks and quotas */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 struct  buffer_head  * p_s_un_bh ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{ 				/* NULL or unformatted node pointer.    */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  super_block  * p_s_sb  =  p_s_inode - > i_sb ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  tree_balance  s_del_balance ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  item_head  s_ih ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  item_head  * q_ih ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  quota_cut_bytes ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  n_ret_value ,  n_del_size ,  n_removed ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# ifdef CONFIG_REISERFS_CHECK 
  
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									char  c_mode ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  n_iter  =  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									BUG_ON ( ! th - > t_trans_id ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									init_tb_struct ( th ,  & s_del_balance ,  p_s_sb ,  p_s_path , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										       0  /*size is unknown */  ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									while  ( 1 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										n_removed  =  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# ifdef CONFIG_REISERFS_CHECK 
  
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										n_iter + + ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										c_mode  = 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										    prepare_for_delete_or_cut ( th ,  p_s_inode ,  p_s_path , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													      p_s_item_key ,  & n_removed , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													      & n_del_size , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													      max_reiserfs_offset ( p_s_inode ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										RFALSE ( c_mode  ! =  M_DELETE ,  " PAP-5320: mode must be M_DELETE " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										copy_item_head ( & s_ih ,  PATH_PITEM_HEAD ( p_s_path ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										s_del_balance . insert_size [ 0 ]  =  n_del_size ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										n_ret_value  =  fix_nodes ( M_DELETE ,  & s_del_balance ,  NULL ,  NULL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( n_ret_value  ! =  REPEAT_SEARCH ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										PROC_INFO_INC ( p_s_sb ,  delete_item_restarted ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// file system changed, repeat search
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										n_ret_value  = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										    search_for_position_by_key ( p_s_sb ,  p_s_item_key ,  p_s_path ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( n_ret_value  = =  IO_ERROR ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( n_ret_value  = =  FILE_NOT_FOUND )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											reiserfs_warning ( p_s_sb , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													 " vs-5340: reiserfs_delete_item:  " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													 " no items of the file %K found " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													 p_s_item_key ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 			/* while (1) */ 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( n_ret_value  ! =  CARRY_ON )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										unfix_nodes ( & s_del_balance ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// reiserfs_delete_item returns item length when success
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									n_ret_value  =  calc_deleted_bytes_number ( & s_del_balance ,  M_DELETE ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									q_ih  =  get_ih ( p_s_path ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									quota_cut_bytes  =  ih_item_len ( q_ih ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* hack so the quota code doesn't have to guess if the file
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 * *  has  a  tail .   On  tail  insert ,  we  allocate  quota  for  1  unformatted  node . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 * *  We  test  the  offset  because  the  tail  might  have  been 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 * *  split  into  multiple  items ,  and  we  only  want  to  decrement  for 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 * *  the  unfm  node  once 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! S_ISLNK ( p_s_inode - > i_mode )  & &  is_direct_le_ih ( q_ih ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ( le_ih_k_offset ( q_ih )  &  ( p_s_sb - > s_blocksize  -  1 ) )  = =  1 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											quota_cut_bytes  =  p_s_sb - > s_blocksize  +  UNFM_P_SIZE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											quota_cut_bytes  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( p_s_un_bh )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										int  off ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										char  * data ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* We are in direct2indirect conversion, so move tail contents
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										   to  the  unformatted  node  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* note, we do the copy before preparing the buffer because we
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 * *  don ' t  care  about  the  contents  of  the  unformatted  node  yet . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 * *  the  only  thing  we  really  care  about  is  the  direct  item ' s  data 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 * *  is  in  the  unformatted  node . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 * * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 * *  Otherwise ,  we  would  have  to  call  reiserfs_prepare_for_journal  on 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 * *  the  unformatted  node ,  which  might  schedule ,  meaning  we ' d  have  to 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 * *  loop  all  the  way  back  up  to  the  start  of  the  while  loop . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 * * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 * *  The  unformatted  node  must  be  dirtied  later  on .   We  can ' t  be 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 * *  sure  here  if  the  entire  tail  has  been  deleted  yet . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 * * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 * *  p_s_un_bh  is  from  the  page  cache  ( all  unformatted  nodes  are 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 * *  from  the  page  cache )  and  might  be  a  highmem  page .   So ,  we 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 * *  can ' t  use  p_s_un_bh - > b_data . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 * *  - clm 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										data  =  kmap_atomic ( p_s_un_bh - > b_page ,  KM_USER0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										off  =  ( ( le_ih_k_offset ( & s_ih )  -  1 )  &  ( PAGE_CACHE_SIZE  -  1 ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										memcpy ( data  +  off , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										       B_I_PITEM ( PATH_PLAST_BUFFER ( p_s_path ) ,  & s_ih ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										       n_ret_value ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										kunmap_atomic ( data ,  KM_USER0 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* Perform balancing after all resources have been collected at once. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									do_balance ( & s_del_balance ,  NULL ,  NULL ,  M_DELETE ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# ifdef REISERQUOTA_DEBUG 
  
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									reiserfs_debug ( p_s_sb ,  REISERFS_DEBUG_CODE , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										       " reiserquota delete_item(): freeing %u, id=%u type=%c " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										       quota_cut_bytes ,  p_s_inode - > i_uid ,  head2type ( & s_ih ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									DQUOT_FREE_SPACE_NODIRTY ( p_s_inode ,  quota_cut_bytes ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* Return deleted body length */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  n_ret_value ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* Summary Of Mechanisms For Handling Collisions Between Processes:
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 deletion  of  the  body  of  the  object  is  performed  by  iput ( ) ,  with  the 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 result  that  if  multiple  processes  are  operating  on  a  file ,  the 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 deletion  of  the  body  of  the  file  is  deferred  until  the  last  process 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 that  has  an  open  inode  performs  its  iput ( ) . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 writes  and  truncates  are  protected  from  collisions  by  use  of 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 semaphores . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 creates ,  linking ,  and  mknod  are  protected  from  collisions  with  other 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 processes  by  making  the  reiserfs_add_entry ( )  the  last  step  in  the 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 creation ,  and  then  rolling  back  all  changes  if  there  was  a  collision . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 -  Hans 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								*/  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* this deletes item which never gets split */  
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								void  reiserfs_delete_solid_item ( struct  reiserfs_transaction_handle  * th ,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												struct  inode  * inode ,  struct  reiserfs_key  * key ) 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  tree_balance  tb ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									INITIALIZE_PATH ( path ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  item_len  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  tb_init  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  cpu_key  cpu_key ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  retval ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  quota_cut_bytes  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									BUG_ON ( ! th - > t_trans_id ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									le_key2cpu_key ( & cpu_key ,  key ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									while  ( 1 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										retval  =  search_item ( th - > t_super ,  & cpu_key ,  & path ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( retval  = =  IO_ERROR )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											reiserfs_warning ( th - > t_super , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													 " vs-5350: reiserfs_delete_solid_item:  " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													 " i/o failure occurred trying to delete %K " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													 & cpu_key ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( retval  ! =  ITEM_FOUND )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											pathrelse ( & path ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// No need for a warning, if there is just no free space to insert '..' item into the newly-created subdir
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( ! 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											    ( ( unsigned  long  long ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											     GET_HASH_VALUE ( le_key_k_offset 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													    ( le_key_version ( key ) ,  key ) )  = =  0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											     & &  ( unsigned  long  long ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											     GET_GENERATION_NUMBER ( le_key_k_offset 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														   ( le_key_version ( key ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														    key ) )  = =  1 ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												reiserfs_warning ( th - > t_super , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														 " vs-5355: reiserfs_delete_solid_item: %k not found " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														 key ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! tb_init )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											tb_init  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											item_len  =  ih_item_len ( PATH_PITEM_HEAD ( & path ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											init_tb_struct ( th ,  & tb ,  th - > t_super ,  & path , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												       - ( IH_SIZE  +  item_len ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										quota_cut_bytes  =  ih_item_len ( PATH_PITEM_HEAD ( & path ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										retval  =  fix_nodes ( M_DELETE ,  & tb ,  NULL ,  NULL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( retval  = =  REPEAT_SEARCH )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											PROC_INFO_INC ( th - > t_super ,  delete_solid_item_restarted ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										if  ( retval  = =  CARRY_ON )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											do_balance ( & tb ,  NULL ,  NULL ,  M_DELETE ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( inode )  { 	/* Should we count quota for item? (we don't count quotas for save-links) */ 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								# ifdef REISERQUOTA_DEBUG 
  
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												reiserfs_debug ( th - > t_super ,  REISERFS_DEBUG_CODE , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													       " reiserquota delete_solid_item(): freeing %u id=%u type=%c " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													       quota_cut_bytes ,  inode - > i_uid , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													       key2type ( key ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
												DQUOT_FREE_SPACE_NODIRTY ( inode , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
															 quota_cut_bytes ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// IO_ERROR, NO_DISK_SPACE, etc
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										reiserfs_warning ( th - > t_super , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												 " vs-5360: reiserfs_delete_solid_item:  " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												 " could not delete %K due to fix_nodes failure " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												 & cpu_key ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										unfix_nodes ( & tb ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										break ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									reiserfs_check_path ( & path ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								int  reiserfs_delete_object ( struct  reiserfs_transaction_handle  * th ,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											   struct  inode  * inode ) 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									int  err ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									inode - > i_size  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									BUG_ON ( ! th - > t_trans_id ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* for directory this deletes item containing "." and ".." */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									err  = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									    reiserfs_do_truncate ( th ,  inode ,  NULL ,  0  /*no timestamp updates */  ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  err ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								# if defined( USE_INODE_GENERATION_COUNTER ) 
  
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( ! old_format_only ( th - > t_super ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										__le32  * inode_generation ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										inode_generation  = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										    & REISERFS_SB ( th - > t_super ) - > s_rs - > s_inode_generation ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										* inode_generation  = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										    cpu_to_le32 ( le32_to_cpu ( * inode_generation )  +  1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								/* USE_INODE_GENERATION_COUNTER */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									reiserfs_delete_solid_item ( th ,  inode ,  INODE_PKEY ( inode ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  err ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  void  unmap_buffers ( struct  page  * page ,  loff_t  pos )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  buffer_head  * bh ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  buffer_head  * head ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  buffer_head  * next ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									unsigned  long  tail_index ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									unsigned  long  cur_index ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( page )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( page_has_buffers ( page ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											tail_index  =  pos  &  ( PAGE_CACHE_SIZE  -  1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											cur_index  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											head  =  page_buffers ( page ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											bh  =  head ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											do  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												next  =  bh - > b_this_page ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												/* we want to unmap the buffers that contain the tail, and
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												 * *  all  the  buffers  after  it  ( since  the  tail  must  be  at  the 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												 * *  end  of  the  file ) .   We  don ' t  want  to  unmap  file  data 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												 * *  before  the  tail ,  since  it  might  be  dirty  and  waiting  to 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												 * *  reach  disk 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												cur_index  + =  bh - > b_size ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  ( cur_index  >  tail_index )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													reiserfs_unmap_buffer ( bh ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												bh  =  next ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											}  while  ( bh  ! =  head ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( PAGE_SIZE  = =  bh - > b_size )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												clear_page_dirty ( page ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  int  maybe_indirect_to_direct ( struct  reiserfs_transaction_handle  * th ,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												    struct  inode  * p_s_inode , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												    struct  page  * page , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												    struct  path  * p_s_path , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												    const  struct  cpu_key  * p_s_item_key , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												    loff_t  n_new_file_size ,  char  * p_c_mode ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  super_block  * p_s_sb  =  p_s_inode - > i_sb ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  n_block_size  =  p_s_sb - > s_blocksize ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  cut_bytes ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									BUG_ON ( ! th - > t_trans_id ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( n_new_file_size  ! =  p_s_inode - > i_size ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										BUG ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* the page being sent in could be NULL if there was an i/o error
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 * *  reading  in  the  last  block .   The  user  will  hit  problems  trying  to 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 * *  read  the  file ,  but  for  now  we  just  skip  the  indirect2direct 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( atomic_read ( & p_s_inode - > i_count )  >  1  | | 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									    ! tail_has_to_be_packed ( p_s_inode )  | | 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									    ! page  | |  ( REISERFS_I ( p_s_inode ) - > i_flags  &  i_nopack_mask ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// leave tail in an unformatted node    
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										* p_c_mode  =  M_SKIP_BALANCING ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										cut_bytes  = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										    n_block_size  -  ( n_new_file_size  &  ( n_block_size  -  1 ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										pathrelse ( p_s_path ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  cut_bytes ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Permorm the conversion to a direct_item. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/*return indirect_to_direct (p_s_inode, p_s_path, p_s_item_key, n_new_file_size, p_c_mode); */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  indirect2direct ( th ,  p_s_inode ,  page ,  p_s_path ,  p_s_item_key , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											       n_new_file_size ,  p_c_mode ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* we did indirect_to_direct conversion. And we have inserted direct
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								   item  successesfully ,  but  there  were  no  disk  space  to  cut  unfm 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								   pointer  being  converted .  Therefore  we  have  to  delete  inserted 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								   direct  item ( s )  */ 
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  void  indirect_to_direct_roll_back ( struct  reiserfs_transaction_handle  * th ,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													 struct  inode  * inode ,  struct  path  * path ) 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  cpu_key  tail_key ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  tail_len ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  removed ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									BUG_ON ( ! th - > t_trans_id ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									make_cpu_key ( & tail_key ,  inode ,  inode - > i_size  +  1 ,  TYPE_DIRECT ,  4 ) ; 	// !!!!
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									tail_key . key_length  =  4 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									tail_len  = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									    ( cpu_key_k_offset ( & tail_key )  &  ( inode - > i_sb - > s_blocksize  -  1 ) )  -  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									while  ( tail_len )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* look for the last byte of the tail */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( search_for_position_by_key ( inode - > i_sb ,  & tail_key ,  path )  = = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										    POSITION_NOT_FOUND ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											reiserfs_panic ( inode - > i_sb , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												       " vs-5615: indirect_to_direct_roll_back: found invalid item " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										RFALSE ( path - > pos_in_item  ! = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										       ih_item_len ( PATH_PITEM_HEAD ( path ) )  -  1 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										       " vs-5616: appended bytes found " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										PATH_LAST_POSITION ( path ) - - ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										removed  = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										    reiserfs_delete_item ( th ,  path ,  & tail_key ,  inode , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													 NULL  /*unbh not needed */  ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										RFALSE ( removed  < =  0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										       | |  removed  >  tail_len , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										       " vs-5617: there was tail %d bytes, removed item length %d bytes " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										       tail_len ,  removed ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										tail_len  - =  removed ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										set_cpu_key_k_offset ( & tail_key , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												     cpu_key_k_offset ( & tail_key )  -  removed ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									reiserfs_warning ( inode - > i_sb , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 " indirect_to_direct_roll_back: indirect_to_direct conversion has been rolled back due to lack of disk space " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									//mark_file_without_tail (inode);
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									mark_inode_dirty ( inode ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* (Truncate or cut entry) or delete object item. Returns < 0 on failure */  
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								int  reiserfs_cut_from_item ( struct  reiserfs_transaction_handle  * th ,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											   struct  path  * p_s_path , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											   struct  cpu_key  * p_s_item_key , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											   struct  inode  * p_s_inode , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											   struct  page  * page ,  loff_t  n_new_file_size ) 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  super_block  * p_s_sb  =  p_s_inode - > i_sb ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Every function which is going to call do_balance must first
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									   create  a  tree_balance  structure .   Then  it  must  fill  up  this 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									   structure  by  using  the  init_tb_struct  and  fix_nodes  functions . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									   After  that  we  can  make  tree  balancing .  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  tree_balance  s_cut_balance ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  item_head  * p_le_ih ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  n_cut_size  =  0 , 	/* Amount to be cut. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									    n_ret_value  =  CARRY_ON ,  n_removed  =  0 , 	/* Number of the removed unformatted nodes. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									    n_is_inode_locked  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									char  c_mode ; 		/* Mode of the balance. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  retval2  =  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  quota_cut_bytes ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									loff_t  tail_pos  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									BUG_ON ( ! th - > t_trans_id ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									init_tb_struct ( th ,  & s_cut_balance ,  p_s_inode - > i_sb ,  p_s_path , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										       n_cut_size ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Repeat this loop until we either cut the item without needing
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									   to  balance ,  or  we  fix_nodes  without  schedule  occurring  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									while  ( 1 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Determine the balance mode, position of the first byte to
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										   be  cut ,  and  size  to  be  cut .   In  case  of  the  indirect  item 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										   free  unformatted  nodes  which  are  pointed  to  by  the  cut 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										   pointers .  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										c_mode  = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										    prepare_for_delete_or_cut ( th ,  p_s_inode ,  p_s_path , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													      p_s_item_key ,  & n_removed , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													      & n_cut_size ,  n_new_file_size ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( c_mode  = =  M_CONVERT )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											/* convert last unformatted node to direct item or leave
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											   tail  in  the  unformatted  node  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											RFALSE ( n_ret_value  ! =  CARRY_ON , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											       " PAP-5570: can not convert twice " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											n_ret_value  = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											    maybe_indirect_to_direct ( th ,  p_s_inode ,  page , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														     p_s_path ,  p_s_item_key , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														     n_new_file_size ,  & c_mode ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( c_mode  = =  M_SKIP_BALANCING ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												/* tail has been left in the unformatted node */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return  n_ret_value ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											n_is_inode_locked  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											/* removing of last unformatted node will change value we
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											   have  to  return  to  truncate .  Save  it  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											retval2  =  n_ret_value ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											/*retval2 = p_s_sb->s_blocksize - (n_new_file_size & (p_s_sb->s_blocksize - 1)); */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											/* So, we have performed the first part of the conversion:
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											   inserting  the  new  direct  item .   Now  we  are  removing  the 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											   last  unformatted  node  pointer .  Set  key  to  search  for 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											   it .  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											set_cpu_key_k_type ( p_s_item_key ,  TYPE_INDIRECT ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											p_s_item_key - > key_length  =  4 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											n_new_file_size  - = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											    ( n_new_file_size  &  ( p_s_sb - > s_blocksize  -  1 ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											tail_pos  =  n_new_file_size ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											set_cpu_key_k_offset ( p_s_item_key ,  n_new_file_size  +  1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( search_for_position_by_key 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											    ( p_s_sb ,  p_s_item_key , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											     p_s_path )  = =  POSITION_NOT_FOUND )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												print_block ( PATH_PLAST_BUFFER ( p_s_path ) ,  3 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													    PATH_LAST_POSITION ( p_s_path )  -  1 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													    PATH_LAST_POSITION ( p_s_path )  +  1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												reiserfs_panic ( p_s_sb , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													       " PAP-5580: reiserfs_cut_from_item: item to convert does not exist (%K) " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													       p_s_item_key ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( n_cut_size  = =  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											pathrelse ( p_s_path ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										s_cut_balance . insert_size [ 0 ]  =  n_cut_size ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										n_ret_value  =  fix_nodes ( c_mode ,  & s_cut_balance ,  NULL ,  NULL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( n_ret_value  ! =  REPEAT_SEARCH ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										PROC_INFO_INC ( p_s_sb ,  cut_from_item_restarted ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										n_ret_value  = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										    search_for_position_by_key ( p_s_sb ,  p_s_item_key ,  p_s_path ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( n_ret_value  = =  POSITION_FOUND ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											continue ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										reiserfs_warning ( p_s_sb , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												 " PAP-5610: reiserfs_cut_from_item: item %K not found " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												 p_s_item_key ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										unfix_nodes ( & s_cut_balance ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  ( n_ret_value  = =  IO_ERROR )  ?  - EIO  :  - ENOENT ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 			/* while */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// check fix_nodes results (IO_ERROR or NO_DISK_SPACE)
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( n_ret_value  ! =  CARRY_ON )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( n_is_inode_locked )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// FIXME: this seems to be not needed: we are always able
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// to cut item
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											indirect_to_direct_roll_back ( th ,  p_s_inode ,  p_s_path ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( n_ret_value  = =  NO_DISK_SPACE ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											reiserfs_warning ( p_s_sb ,  " NO_DISK_SPACE " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										unfix_nodes ( & s_cut_balance ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  - EIO ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* go ahead and perform balancing */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RFALSE ( c_mode  = =  M_PASTE  | |  c_mode  = =  M_INSERT ,  " invalid mode " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Calculate number of bytes that need to be cut from the item. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									quota_cut_bytes  = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									    ( c_mode  = = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									     M_DELETE )  ?  ih_item_len ( get_ih ( p_s_path ) )  :  - s_cut_balance . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									    insert_size [ 0 ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( retval2  = =  - 1 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										n_ret_value  =  calc_deleted_bytes_number ( & s_cut_balance ,  c_mode ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									else 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										n_ret_value  =  retval2 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* For direct items, we only change the quota when deleting the last
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 * *  item . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									p_le_ih  =  PATH_PITEM_HEAD ( s_cut_balance . tb_path ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! S_ISLNK ( p_s_inode - > i_mode )  & &  is_direct_le_ih ( p_le_ih ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( c_mode  = =  M_DELETE  & & 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										    ( le_ih_k_offset ( p_le_ih )  &  ( p_s_sb - > s_blocksize  -  1 ) )  = = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										    1 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											// FIXME: this is to keep 3.5 happy
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											REISERFS_I ( p_s_inode ) - > i_first_direct_byte  =  U32_MAX ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											quota_cut_bytes  =  p_s_sb - > s_blocksize  +  UNFM_P_SIZE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											quota_cut_bytes  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# ifdef CONFIG_REISERFS_CHECK 
  
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( n_is_inode_locked )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										struct  item_head  * le_ih  = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										    PATH_PITEM_HEAD ( s_cut_balance . tb_path ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* we are going to complete indirect2direct conversion. Make
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										   sure ,  that  we  exactly  remove  last  unformatted  node  pointer 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										   of  the  item  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! is_indirect_le_ih ( le_ih ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											reiserfs_panic ( p_s_sb , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												       " vs-5652: reiserfs_cut_from_item:  " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												       " item must be indirect %h " ,  le_ih ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( c_mode  = =  M_DELETE  & &  ih_item_len ( le_ih )  ! =  UNFM_P_SIZE ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											reiserfs_panic ( p_s_sb , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												       " vs-5653: reiserfs_cut_from_item:  " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												       " completing indirect2direct conversion indirect item %h  " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												       " being deleted must be of 4 byte long " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												       le_ih ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( c_mode  = =  M_CUT 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										    & &  s_cut_balance . insert_size [ 0 ]  ! =  - UNFM_P_SIZE )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											reiserfs_panic ( p_s_sb , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												       " vs-5654: reiserfs_cut_from_item:  " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												       " can not complete indirect2direct conversion of %h (CUT, insert_size==%d) " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												       le_ih ,  s_cut_balance . insert_size [ 0 ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* it would be useful to make sure, that right neighboring
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										   item  is  direct  item  of  this  file  */ 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									do_balance ( & s_cut_balance ,  NULL ,  NULL ,  c_mode ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( n_is_inode_locked )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* we've done an indirect->direct conversion.  when the data block
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 * *  was  freed ,  it  was  removed  from  the  list  of  blocks  that  must 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 * *  be  flushed  before  the  transaction  commits ,  make  sure  to 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 * *  unmap  and  invalidate  it 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										unmap_buffers ( page ,  tail_pos ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										REISERFS_I ( p_s_inode ) - > i_flags  & =  ~ i_pack_on_close_mask ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								# ifdef REISERQUOTA_DEBUG 
  
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									reiserfs_debug ( p_s_inode - > i_sb ,  REISERFS_DEBUG_CODE , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										       " reiserquota cut_from_item(): freeing %u id=%u type=%c " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										       quota_cut_bytes ,  p_s_inode - > i_uid ,  ' ? ' ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									DQUOT_FREE_SPACE_NODIRTY ( p_s_inode ,  quota_cut_bytes ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  n_ret_value ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  void  truncate_directory ( struct  reiserfs_transaction_handle  * th ,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											       struct  inode  * inode ) 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									BUG_ON ( ! th - > t_trans_id ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( inode - > i_nlink ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										reiserfs_warning ( inode - > i_sb , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												 " vs-5655: truncate_directory: link count != 0 " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									set_le_key_k_offset ( KEY_FORMAT_3_5 ,  INODE_PKEY ( inode ) ,  DOT_OFFSET ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									set_le_key_k_type ( KEY_FORMAT_3_5 ,  INODE_PKEY ( inode ) ,  TYPE_DIRENTRY ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									reiserfs_delete_solid_item ( th ,  inode ,  INODE_PKEY ( inode ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									reiserfs_update_sd ( th ,  inode ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									set_le_key_k_offset ( KEY_FORMAT_3_5 ,  INODE_PKEY ( inode ) ,  SD_OFFSET ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									set_le_key_k_type ( KEY_FORMAT_3_5 ,  INODE_PKEY ( inode ) ,  TYPE_STAT_DATA ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/* Truncate file to the new size. Note, this must be called with a transaction
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								   already  started  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								int  reiserfs_do_truncate ( struct  reiserfs_transaction_handle  * th ,  struct  inode  * p_s_inode , 	/* ->i_size contains new
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
																				   size  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 struct  page  * page , 	/* up to date for last block */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 int  update_timestamps 	/* when it is called by
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														   file_release  to  convert 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														   the  tail  -  no  timestamps 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														   should  be  updated  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									INITIALIZE_PATH ( s_search_path ) ; 	/* Path to the current object item. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  item_head  * p_le_ih ; 	/* Pointer to an item header. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  cpu_key  s_item_key ; 	/* Key to search for a previous file item. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									loff_t  n_file_size , 	/* Old file size. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 n_new_file_size ; 	/* New file size. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  n_deleted ; 		/* Number of deleted or truncated bytes. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  retval ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  err  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									BUG_ON ( ! th - > t_trans_id ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( ! 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									    ( S_ISREG ( p_s_inode - > i_mode )  | |  S_ISDIR ( p_s_inode - > i_mode ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									     | |  S_ISLNK ( p_s_inode - > i_mode ) ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( S_ISDIR ( p_s_inode - > i_mode ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// deletion of directory - no need to update timestamps
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										truncate_directory ( th ,  p_s_inode ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* Get new file size. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									n_new_file_size  =  p_s_inode - > i_size ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// FIXME: note, that key type is unimportant here
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									make_cpu_key ( & s_item_key ,  p_s_inode ,  max_reiserfs_offset ( p_s_inode ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										     TYPE_DIRECT ,  3 ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									retval  = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									    search_for_position_by_key ( p_s_inode - > i_sb ,  & s_item_key , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												       & s_search_path ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( retval  = =  IO_ERROR )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										reiserfs_warning ( p_s_inode - > i_sb , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												 " vs-5657: reiserfs_do_truncate:  " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												 " i/o failure occurred trying to truncate %K " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												 & s_item_key ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										err  =  - EIO ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										goto  out ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( retval  = =  POSITION_FOUND  | |  retval  = =  FILE_NOT_FOUND )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										reiserfs_warning ( p_s_inode - > i_sb , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												 " PAP-5660: reiserfs_do_truncate:  " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												 " wrong result %d of search for %K " ,  retval , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												 & s_item_key ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										err  =  - EIO ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										goto  out ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									s_search_path . pos_in_item - - ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* Get real file size (total length of all file items) */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									p_le_ih  =  PATH_PITEM_HEAD ( & s_search_path ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( is_statdata_le_ih ( p_le_ih ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										n_file_size  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										loff_t  offset  =  le_ih_k_offset ( p_le_ih ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										int  bytes  = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										    op_bytes_number ( p_le_ih ,  p_s_inode - > i_sb - > s_blocksize ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* this may mismatch with real file size: if last direct item
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										   had  no  padding  zeros  and  last  unformatted  node  had  no  free 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										   space ,  this  file  would  have  this  file  size  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										n_file_size  =  offset  +  bytes  -  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/*
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  are  we  doing  a  full  truncate  or  delete ,  if  so 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 *  kick  in  the  reada  code 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( n_new_file_size  = =  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										s_search_path . reada  =  PATH_READA  |  PATH_READA_BACK ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( n_file_size  = =  0  | |  n_file_size  <  n_new_file_size )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										goto  update_and_out ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* Update key to search for the last file item. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									set_cpu_key_k_offset ( & s_item_key ,  n_file_size ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									do  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* Cut or delete file item. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										n_deleted  = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										    reiserfs_cut_from_item ( th ,  & s_search_path ,  & s_item_key , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													   p_s_inode ,  page ,  n_new_file_size ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( n_deleted  <  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											reiserfs_warning ( p_s_inode - > i_sb , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													 " vs-5665: reiserfs_do_truncate: reiserfs_cut_from_item failed " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											reiserfs_check_path ( & s_search_path ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										RFALSE ( n_deleted  >  n_file_size , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										       " PAP-5670: reiserfs_cut_from_item: too many bytes deleted: deleted %d, file_size %lu, item_key %K " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										       n_deleted ,  n_file_size ,  & s_item_key ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										/* Change key to search the last file item. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										n_file_size  - =  n_deleted ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										set_cpu_key_k_offset ( & s_item_key ,  n_file_size ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										/* While there are bytes to truncate and previous file item is presented in the tree. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/*
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 * *  This  loop  could  take  a  really  long  time ,  and  could  log  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 * *  many  more  blocks  than  a  transaction  can  hold .   So ,  we  do  a  polite 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 * *  journal  end  here ,  and  if  the  transaction  needs  ending ,  we  make 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 * *  sure  the  file  is  consistent  before  ending  the  current  trans 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 * *  and  starting  a  new  one 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( journal_transaction_should_end ( th ,  th - > t_blocks_allocated ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											int  orig_len_alloc  =  th - > t_blocks_allocated ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											decrement_counters_in_path ( & s_search_path ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( update_timestamps )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												p_s_inode - > i_mtime  =  p_s_inode - > i_ctime  = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												    CURRENT_TIME_SEC ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											reiserfs_update_sd ( th ,  p_s_inode ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											err  =  journal_end ( th ,  p_s_inode - > i_sb ,  orig_len_alloc ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												goto  out ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											err  =  journal_begin ( th ,  p_s_inode - > i_sb , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													    JOURNAL_PER_BALANCE_CNT  *  6 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												goto  out ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											reiserfs_update_inode_transaction ( p_s_inode ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									}  while  ( n_file_size  >  ROUND_UP ( n_new_file_size )  & & 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 search_for_position_by_key ( p_s_inode - > i_sb ,  & s_item_key , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													    & s_search_path )  = =  POSITION_FOUND ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RFALSE ( n_file_size  >  ROUND_UP ( n_new_file_size ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									       " PAP-5680: truncate did not finish: new_file_size %Ld, current %Ld, oid %d " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									       n_new_file_size ,  n_file_size ,  s_item_key . on_disk_key . k_objectid ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      update_and_out : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( update_timestamps )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// this is truncate, not file closing
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										p_s_inode - > i_mtime  =  p_s_inode - > i_ctime  =  CURRENT_TIME_SEC ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									reiserfs_update_sd ( th ,  p_s_inode ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								      out : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									pathrelse ( & s_search_path ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  err ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# ifdef CONFIG_REISERFS_CHECK 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// this makes sure, that we __append__, not overwrite or add holes
  
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  void  check_research_for_paste ( struct  path  * path ,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												     const  struct  cpu_key  * p_s_key ) 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									struct  item_head  * found_ih  =  get_ih ( path ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( is_direct_le_ih ( found_ih ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( le_ih_k_offset ( found_ih )  + 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										    op_bytes_number ( found_ih , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												    get_last_bh ( path ) - > b_size )  ! = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										    cpu_key_k_offset ( p_s_key ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										    | |  op_bytes_number ( found_ih , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												       get_last_bh ( path ) - > b_size )  ! = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										    pos_in_item ( path ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											reiserfs_panic ( NULL , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												       " PAP-5720: check_research_for_paste:  " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												       " found direct item %h or position (%d) does not match to key %K " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												       found_ih ,  pos_in_item ( path ) ,  p_s_key ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( is_indirect_le_ih ( found_ih ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( le_ih_k_offset ( found_ih )  + 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										    op_bytes_number ( found_ih , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												    get_last_bh ( path ) - > b_size )  ! = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										    cpu_key_k_offset ( p_s_key ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										    | |  I_UNFM_NUM ( found_ih )  ! =  pos_in_item ( path ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										    | |  get_ih_free_space ( found_ih )  ! =  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											reiserfs_panic ( NULL , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												       " PAP-5730: check_research_for_paste:  " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												       " found indirect item (%h) or position (%d) does not match to key (%K) " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												       found_ih ,  pos_in_item ( path ) ,  p_s_key ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# endif				 /* config reiserfs check */ 
  
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* Paste bytes to the existing item. Returns bytes number pasted into the item. */  
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								int  reiserfs_paste_into_item ( struct  reiserfs_transaction_handle  * th ,  struct  path  * p_s_search_path , 	/* Path to the pasted item.          */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											     const  struct  cpu_key  * p_s_key , 	/* Key to search for the needed item. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											     struct  inode  * inode , 	/* Inode item belongs to */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											     const  char  * p_c_body , 	/* Pointer to the bytes to paste.    */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											     int  n_pasted_size ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{ 				/* Size of pasted bytes.             */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  tree_balance  s_paste_balance ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  retval ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  fs_gen ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									BUG_ON ( ! th - > t_trans_id ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									fs_gen  =  get_generation ( inode - > i_sb ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# ifdef REISERQUOTA_DEBUG 
  
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									reiserfs_debug ( inode - > i_sb ,  REISERFS_DEBUG_CODE , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										       " reiserquota paste_into_item(): allocating %u id=%u type=%c " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										       n_pasted_size ,  inode - > i_uid , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										       key2type ( & ( p_s_key - > on_disk_key ) ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( DQUOT_ALLOC_SPACE_NODIRTY ( inode ,  n_pasted_size ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										pathrelse ( p_s_search_path ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  - EDQUOT ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									init_tb_struct ( th ,  & s_paste_balance ,  th - > t_super ,  p_s_search_path , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										       n_pasted_size ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								# ifdef DISPLACE_NEW_PACKING_LOCALITIES 
  
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									s_paste_balance . key  =  p_s_key - > on_disk_key ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* DQUOT_* can schedule, must check before the fix_nodes */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( fs_changed ( fs_gen ,  inode - > i_sb ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										goto  search_again ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									while  ( ( retval  = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										fix_nodes ( M_PASTE ,  & s_paste_balance ,  NULL , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											  p_c_body ) )  = =  REPEAT_SEARCH )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									      search_again : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* file system changed while we were in the fix_nodes */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										PROC_INFO_INC ( th - > t_super ,  paste_into_item_restarted ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										retval  = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										    search_for_position_by_key ( th - > t_super ,  p_s_key , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													       p_s_search_path ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( retval  = =  IO_ERROR )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											retval  =  - EIO ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											goto  error_out ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( retval  = =  POSITION_FOUND )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											reiserfs_warning ( inode - > i_sb , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													 " PAP-5710: reiserfs_paste_into_item: entry or pasted byte (%K) exists " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													 p_s_key ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											retval  =  - EEXIST ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											goto  error_out ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								# ifdef CONFIG_REISERFS_CHECK 
  
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										check_research_for_paste ( p_s_search_path ,  p_s_key ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* Perform balancing after all resources are collected by fix_nodes, and
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									   accessing  them  will  not  risk  triggering  schedule .  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( retval  = =  CARRY_ON )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										do_balance ( & s_paste_balance ,  NULL  /*ih */  ,  p_c_body ,  M_PASTE ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									retval  =  ( retval  = =  NO_DISK_SPACE )  ?  - ENOSPC  :  - EIO ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      error_out : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* this also releases the path */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									unfix_nodes ( & s_paste_balance ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								# ifdef REISERQUOTA_DEBUG 
  
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									reiserfs_debug ( inode - > i_sb ,  REISERFS_DEBUG_CODE , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										       " reiserquota paste_into_item(): freeing %u id=%u type=%c " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										       n_pasted_size ,  inode - > i_uid , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										       key2type ( & ( p_s_key - > on_disk_key ) ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									DQUOT_FREE_SPACE_NODIRTY ( inode ,  n_pasted_size ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  retval ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/* Insert new item into the buffer at the path. */  
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								int  reiserfs_insert_item ( struct  reiserfs_transaction_handle  * th ,  struct  path  * p_s_path , 	/* Path to the inserteded item.         */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 const  struct  cpu_key  * key ,  struct  item_head  * p_s_ih , 	/* Pointer to the item header to insert. */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											 struct  inode  * inode ,  const  char  * p_c_body ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{ 				/* Pointer to the bytes to insert.      */  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									struct  tree_balance  s_ins_balance ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  retval ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  fs_gen  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									int  quota_bytes  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									BUG_ON ( ! th - > t_trans_id ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( inode )  { 		/* Do we count quotas for item? */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										fs_gen  =  get_generation ( inode - > i_sb ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										quota_bytes  =  ih_item_len ( p_s_ih ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* hack so the quota code doesn't have to guess if the file has
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 * *  a  tail ,  links  are  always  tails ,  so  there ' s  no  guessing  needed 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( ! S_ISLNK ( inode - > i_mode )  & &  is_direct_le_ih ( p_s_ih ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											quota_bytes  =  inode - > i_sb - > s_blocksize  +  UNFM_P_SIZE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								# ifdef REISERQUOTA_DEBUG 
  
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										reiserfs_debug ( inode - > i_sb ,  REISERFS_DEBUG_CODE , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											       " reiserquota insert_item(): allocating %u id=%u type=%c " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											       quota_bytes ,  inode - > i_uid ,  head2type ( p_s_ih ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										/* We can't dirty inode here. It would be immediately written but
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										 *  appropriate  stat  item  isn ' t  inserted  yet . . .  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( DQUOT_ALLOC_SPACE_NODIRTY ( inode ,  quota_bytes ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											pathrelse ( p_s_path ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  - EDQUOT ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									init_tb_struct ( th ,  & s_ins_balance ,  th - > t_super ,  p_s_path , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										       IH_SIZE  +  ih_item_len ( p_s_ih ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								# ifdef DISPLACE_NEW_PACKING_LOCALITIES 
  
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									s_ins_balance . key  =  key - > on_disk_key ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* DQUOT_* can schedule, must check to be sure calling fix_nodes is safe */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( inode  & &  fs_changed ( fs_gen ,  inode - > i_sb ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										goto  search_again ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									while  ( ( retval  = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										fix_nodes ( M_INSERT ,  & s_ins_balance ,  p_s_ih , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											  p_c_body ) )  = =  REPEAT_SEARCH )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									      search_again : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										/* file system changed while we were in the fix_nodes */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										PROC_INFO_INC ( th - > t_super ,  insert_item_restarted ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										retval  =  search_item ( th - > t_super ,  key ,  p_s_path ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( retval  = =  IO_ERROR )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											retval  =  - EIO ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											goto  error_out ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  ( retval  = =  ITEM_FOUND )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											reiserfs_warning ( th - > t_super , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													 " PAP-5760: reiserfs_insert_item:  " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													 " key %K already exists in the tree " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													 key ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											retval  =  - EEXIST ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											goto  error_out ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									/* make balancing after all resources will be collected at a time */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ( retval  = =  CARRY_ON )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										do_balance ( & s_ins_balance ,  p_s_ih ,  p_c_body ,  M_INSERT ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									retval  =  ( retval  = =  NO_DISK_SPACE )  ?  - ENOSPC  :  - EIO ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      error_out : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									/* also releases the path */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									unfix_nodes ( & s_ins_balance ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								# ifdef REISERQUOTA_DEBUG 
  
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									reiserfs_debug ( th - > t_super ,  REISERFS_DEBUG_CODE , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										       " reiserquota insert_item(): freeing %u id=%u type=%c " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										       quota_bytes ,  inode - > i_uid ,  head2type ( p_s_ih ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
									
										
										
										
											2005-07-12 20:21:28 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  ( inode ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										DQUOT_FREE_SPACE_NODIRTY ( inode ,  quota_bytes ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  retval ; 
							 
						 
					
						
							
								
									
										
										
										
											2005-04-16 15:20:36 -07:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}