2006-10-11 12:21:03 +04:00
/*
* Copyright ( c ) 2003 - 2006 , Cluster File Systems , Inc , info @ clusterfs . com
* Written by Alex Tomas < alex @ clusterfs . com >
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public Licens
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 -
*/
2008-04-30 02:13:32 +04:00
# ifndef _EXT4_EXTENTS
# define _EXT4_EXTENTS
2006-10-11 12:21:03 +04:00
2008-04-30 02:13:32 +04:00
# include "ext4.h"
2006-10-11 12:21:03 +04:00
/*
2007-02-17 21:20:16 +03:00
* With AGGRESSIVE_TEST defined , the capacity of index / leaf blocks
2006-10-11 12:21:07 +04:00
* becomes very small , so index split , in - depth growing and
* other hard changes happen much more often .
* This is for debug purposes only .
2006-10-11 12:21:03 +04:00
*/
2007-02-17 21:20:16 +03:00
# define AGGRESSIVE_TEST_
2006-10-11 12:21:03 +04:00
/*
2006-10-11 12:21:07 +04:00
* With EXTENTS_STATS defined , the number of blocks and extents
* are collected in the truncate path . They ' ll be shown at
* umount time .
2006-10-11 12:21:03 +04:00
*/
# define EXTENTS_STATS__
/*
2006-10-11 12:21:07 +04:00
* If CHECK_BINSEARCH is defined , then the results of the binary search
* will also be checked by linear search .
2006-10-11 12:21:03 +04:00
*/
# define CHECK_BINSEARCH__
/*
2006-10-11 12:21:07 +04:00
* If EXT_DEBUG is defined you can use the ' extdebug ' mount option
* to get lots of info about what ' s going on .
2006-10-11 12:21:03 +04:00
*/
# define EXT_DEBUG__
# ifdef EXT_DEBUG
# define ext_debug(a...) printk(a)
# else
# define ext_debug(a...)
# endif
/*
2006-10-11 12:21:07 +04:00
* If EXT_STATS is defined then stats numbers are collected .
* These number will be displayed at umount time .
2006-10-11 12:21:03 +04:00
*/
# define EXT_STATS_
/*
2006-10-11 12:21:07 +04:00
* ext4_inode has i_block array ( 60 bytes total ) .
* The first 12 bytes store ext4_extent_header ;
* the remainder stores an array of ext4_extent .
2006-10-11 12:21:03 +04:00
*/
/*
2006-10-11 12:21:07 +04:00
* This is the extent on - disk structure .
* It ' s used at the bottom of the tree .
2006-10-11 12:21:03 +04:00
*/
struct ext4_extent {
__le32 ee_block ; /* first logical block extent covers */
__le16 ee_len ; /* number of blocks covered by extent */
__le16 ee_start_hi ; /* high 16 bits of physical block */
2007-10-17 02:38:25 +04:00
__le32 ee_start_lo ; /* low 32 bits of physical block */
2006-10-11 12:21:03 +04:00
} ;
/*
2006-10-11 12:21:07 +04:00
* This is index on - disk structure .
* It ' s used at all the levels except the bottom .
2006-10-11 12:21:03 +04:00
*/
struct ext4_extent_idx {
__le32 ei_block ; /* index covers logical blocks from 'block' */
2007-10-17 02:38:25 +04:00
__le32 ei_leaf_lo ; /* pointer to the physical block of the next *
2006-10-11 12:21:07 +04:00
* level . leaf or next index could be there */
2006-10-11 12:21:03 +04:00
__le16 ei_leaf_hi ; /* high 16 bits of physical block */
__u16 ei_unused ;
} ;
/*
2006-10-11 12:21:07 +04:00
* Each block ( leaves and indexes ) , even inode - stored has header .
2006-10-11 12:21:03 +04:00
*/
struct ext4_extent_header {
__le16 eh_magic ; /* probably will support different formats */
__le16 eh_entries ; /* number of valid entries */
__le16 eh_max ; /* capacity of store in entries */
2006-10-11 12:21:07 +04:00
__le16 eh_depth ; /* has tree real underlying blocks? */
2006-10-11 12:21:03 +04:00
__le32 eh_generation ; /* generation of the tree */
} ;
# define EXT4_EXT_MAGIC cpu_to_le16(0xf30a)
/*
2006-10-11 12:21:07 +04:00
* Array of ext4_ext_path contains path to some extent .
* Creation / lookup routines use it for traversal / splitting / etc .
* Truncate uses it to simulate recursive walking .
2006-10-11 12:21:03 +04:00
*/
struct ext4_ext_path {
2006-10-11 12:21:05 +04:00
ext4_fsblk_t p_block ;
2006-10-11 12:21:03 +04:00
__u16 p_depth ;
struct ext4_extent * p_ext ;
struct ext4_extent_idx * p_idx ;
struct ext4_extent_header * p_hdr ;
struct buffer_head * p_bh ;
} ;
/*
* structure for external API
*/
# define EXT4_EXT_CACHE_NO 0
# define EXT4_EXT_CACHE_GAP 1
# define EXT4_EXT_CACHE_EXTENT 2
2008-10-07 08:46:36 +04:00
/*
* to be called by ext4_ext_walk_space ( )
* negative retcode - error
* positive retcode - signal for ext4_ext_walk_space ( ) , see below
* callback must return valid extent ( passed or newly created )
*/
typedef int ( * ext_prepare_callback ) ( struct inode * , struct ext4_ext_path * ,
struct ext4_ext_cache * ,
struct ext4_extent * , void * ) ;
# define EXT_CONTINUE 0
# define EXT_BREAK 1
# define EXT_REPEAT 2
2006-10-11 12:21:03 +04:00
# define EXT_MAX_BLOCK 0xffffffff
2007-07-18 17:02:56 +04:00
/*
* EXT_INIT_MAX_LEN is the maximum number of blocks we can have in an
* initialized extent . This is 2 ^ 15 and not ( 2 ^ 16 - 1 ) , since we use the
* MSB of ee_len field in the extent datastructure to signify if this
* particular extent is an initialized extent or an uninitialized ( i . e .
* preallocated ) .
* EXT_UNINIT_MAX_LEN is the maximum number of blocks we can have in an
* uninitialized extent .
* If ee_len is < = 0x8000 , it is an initialized extent . Otherwise , it is an
* uninitialized one . In other words , if MSB of ee_len is set , it is an
* uninitialized extent with only one special scenario when ee_len = 0x8000 .
* In this case we can not have an uninitialized extent of zero length and
* thus we make it as a special case of initialized extent with 0x8000 length .
* This way we get better extent - to - group alignment for initialized extents .
* Hence , the maximum number of blocks we can have in an * initialized *
* extent is 2 ^ 15 ( 32768 ) and in an * uninitialized * extent is 2 ^ 15 - 1 ( 32767 ) .
*/
# define EXT_INIT_MAX_LEN (1UL << 15)
# define EXT_UNINIT_MAX_LEN (EXT_INIT_MAX_LEN - 1)
2006-10-11 12:21:06 +04:00
2006-10-11 12:21:03 +04:00
# define EXT_FIRST_EXTENT(__hdr__) \
( ( struct ext4_extent * ) ( ( ( char * ) ( __hdr__ ) ) + \
sizeof ( struct ext4_extent_header ) ) )
# define EXT_FIRST_INDEX(__hdr__) \
( ( struct ext4_extent_idx * ) ( ( ( char * ) ( __hdr__ ) ) + \
sizeof ( struct ext4_extent_header ) ) )
# define EXT_HAS_FREE_INDEX(__path__) \
2007-05-24 21:04:54 +04:00
( le16_to_cpu ( ( __path__ ) - > p_hdr - > eh_entries ) \
< le16_to_cpu ( ( __path__ ) - > p_hdr - > eh_max ) )
2006-10-11 12:21:03 +04:00
# define EXT_LAST_EXTENT(__hdr__) \
( EXT_FIRST_EXTENT ( ( __hdr__ ) ) + le16_to_cpu ( ( __hdr__ ) - > eh_entries ) - 1 )
# define EXT_LAST_INDEX(__hdr__) \
( EXT_FIRST_INDEX ( ( __hdr__ ) ) + le16_to_cpu ( ( __hdr__ ) - > eh_entries ) - 1 )
# define EXT_MAX_EXTENT(__hdr__) \
( EXT_FIRST_EXTENT ( ( __hdr__ ) ) + le16_to_cpu ( ( __hdr__ ) - > eh_max ) - 1 )
# define EXT_MAX_INDEX(__hdr__) \
( EXT_FIRST_INDEX ( ( __hdr__ ) ) + le16_to_cpu ( ( __hdr__ ) - > eh_max ) - 1 )
static inline struct ext4_extent_header * ext_inode_hdr ( struct inode * inode )
{
return ( struct ext4_extent_header * ) EXT4_I ( inode ) - > i_data ;
}
static inline struct ext4_extent_header * ext_block_hdr ( struct buffer_head * bh )
{
return ( struct ext4_extent_header * ) bh - > b_data ;
}
static inline unsigned short ext_depth ( struct inode * inode )
{
return le16_to_cpu ( ext_inode_hdr ( inode ) - > eh_depth ) ;
}
static inline void
ext4_ext_invalidate_cache ( struct inode * inode )
{
EXT4_I ( inode ) - > i_cached_extent . ec_type = EXT4_EXT_CACHE_NO ;
}
2007-07-18 05:42:41 +04:00
static inline void ext4_ext_mark_uninitialized ( struct ext4_extent * ext )
{
2007-07-18 17:02:56 +04:00
/* We can not have an uninitialized extent of zero length! */
BUG_ON ( ( le16_to_cpu ( ext - > ee_len ) & ~ EXT_INIT_MAX_LEN ) = = 0 ) ;
ext - > ee_len | = cpu_to_le16 ( EXT_INIT_MAX_LEN ) ;
2007-07-18 05:42:41 +04:00
}
static inline int ext4_ext_is_uninitialized ( struct ext4_extent * ext )
{
2007-07-18 17:02:56 +04:00
/* Extent with ee_len of 0x8000 is treated as an initialized extent */
return ( le16_to_cpu ( ext - > ee_len ) > EXT_INIT_MAX_LEN ) ;
2007-07-18 05:42:41 +04:00
}
static inline int ext4_ext_get_actual_len ( struct ext4_extent * ext )
{
2007-07-18 17:02:56 +04:00
return ( le16_to_cpu ( ext - > ee_len ) < = EXT_INIT_MAX_LEN ?
le16_to_cpu ( ext - > ee_len ) :
( le16_to_cpu ( ext - > ee_len ) - EXT_INIT_MAX_LEN ) ) ;
2007-07-18 05:42:41 +04:00
}
2008-07-15 01:52:37 +04:00
extern int ext4_ext_calc_metadata_amount ( struct inode * inode , int blocks ) ;
2008-01-29 07:58:26 +03:00
extern ext4_fsblk_t idx_pblock ( struct ext4_extent_idx * ) ;
extern void ext4_ext_store_pblock ( struct ext4_extent * , ext4_fsblk_t ) ;
2006-10-11 12:21:03 +04:00
extern int ext4_extent_tree_init ( handle_t * , struct inode * ) ;
2008-08-20 06:16:05 +04:00
extern int ext4_ext_calc_credits_for_single_extent ( struct inode * inode ,
int num ,
struct ext4_ext_path * path ) ;
2007-07-18 05:42:38 +04:00
extern int ext4_ext_try_to_merge ( struct inode * inode ,
struct ext4_ext_path * path ,
struct ext4_extent * ) ;
2007-05-24 21:04:13 +04:00
extern unsigned int ext4_ext_check_overlap ( struct inode * , struct ext4_extent * , struct ext4_ext_path * ) ;
2006-10-11 12:21:03 +04:00
extern int ext4_ext_insert_extent ( handle_t * , struct inode * , struct ext4_ext_path * , struct ext4_extent * ) ;
2008-10-07 08:46:36 +04:00
extern int ext4_ext_walk_space ( struct inode * , ext4_lblk_t , ext4_lblk_t ,
ext_prepare_callback , void * ) ;
2008-01-29 07:58:27 +03:00
extern struct ext4_ext_path * ext4_ext_find_extent ( struct inode * , ext4_lblk_t ,
struct ext4_ext_path * ) ;
2008-01-29 07:58:27 +03:00
extern int ext4_ext_search_left ( struct inode * , struct ext4_ext_path * ,
ext4_lblk_t * , ext4_fsblk_t * ) ;
extern int ext4_ext_search_right ( struct inode * , struct ext4_ext_path * ,
ext4_lblk_t * , ext4_fsblk_t * ) ;
2008-02-26 00:54:37 +03:00
extern void ext4_ext_drop_refs ( struct ext4_ext_path * ) ;
2009-03-27 23:39:58 +03:00
extern int ext4_ext_check_inode ( struct inode * inode ) ;
2008-04-30 02:13:32 +04:00
# endif /* _EXT4_EXTENTS */
2006-10-11 12:21:03 +04:00