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_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 .
2012-04-30 02:23:10 +04:00
* For non - inode extent blocks , ext4_extent_tail
* follows the array .
2006-10-11 12:21:03 +04:00
*/
2012-04-30 02:23:10 +04:00
/*
* This is the extent tail on - disk structure .
* All other extent structures are 12 bytes long . It turns out that
* block_size % 12 > = 4 for at least all powers of 2 greater than 512 , which
* covers all valid ext4 block sizes . Therefore , this tail structure can be
* crammed into the end of the block without having to rebalance the tree .
*/
struct ext4_extent_tail {
__le32 et_checksum ; /* crc32c(uuid+inum+extent_block) */
} ;
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)
2012-04-30 02:37:10 +04:00
# define EXT4_EXTENT_TAIL_OFFSET(hdr) \
( sizeof ( struct ext4_extent_header ) + \
( sizeof ( struct ext4_extent ) * le16_to_cpu ( ( hdr ) - > eh_max ) ) )
static inline struct ext4_extent_tail *
find_ext4_extent_tail ( struct ext4_extent_header * eh )
{
return ( struct ext4_extent_tail * ) ( ( ( void * ) eh ) +
EXT4_EXTENT_TAIL_OFFSET ( eh ) ) ;
}
2006-10-11 12:21:03 +04:00
/*
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
*/
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 ) ;
}
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
}
2009-09-28 23:49:08 +04:00
static inline void ext4_ext_mark_initialized ( struct ext4_extent * ext )
{
ext - > ee_len = cpu_to_le16 ( ext4_ext_get_actual_len ( ext ) ) ;
}
2010-10-28 05:30:14 +04:00
/*
* ext4_ext_pblock :
* combine low and high parts of physical block number into ext4_fsblk_t
*/
static inline ext4_fsblk_t ext4_ext_pblock ( struct ext4_extent * ex )
{
ext4_fsblk_t block ;
block = le32_to_cpu ( ex - > ee_start_lo ) ;
block | = ( ( ext4_fsblk_t ) le16_to_cpu ( ex - > ee_start_hi ) < < 31 ) < < 1 ;
return block ;
}
/*
* ext4_idx_pblock :
* combine low and high parts of a leaf physical block number into ext4_fsblk_t
*/
static inline ext4_fsblk_t ext4_idx_pblock ( struct ext4_extent_idx * ix )
{
ext4_fsblk_t block ;
block = le32_to_cpu ( ix - > ei_leaf_lo ) ;
block | = ( ( ext4_fsblk_t ) le16_to_cpu ( ix - > ei_leaf_hi ) < < 31 ) < < 1 ;
return block ;
}
/*
* ext4_ext_store_pblock :
* stores a large physical block number into an extent struct ,
* breaking it into parts
*/
static inline void ext4_ext_store_pblock ( struct ext4_extent * ex ,
ext4_fsblk_t pb )
{
ex - > ee_start_lo = cpu_to_le32 ( ( unsigned long ) ( pb & 0xffffffff ) ) ;
ex - > ee_start_hi = cpu_to_le16 ( ( unsigned long ) ( ( pb > > 31 ) > > 1 ) &
0xffff ) ;
}
/*
* ext4_idx_store_pblock :
* stores a large physical block number into an index struct ,
* breaking it into parts
*/
static inline void ext4_idx_store_pblock ( struct ext4_extent_idx * ix ,
ext4_fsblk_t pb )
{
ix - > ei_leaf_lo = cpu_to_le32 ( ( unsigned long ) ( pb & 0xffffffff ) ) ;
ix - > ei_leaf_hi = cpu_to_le16 ( ( unsigned long ) ( ( pb > > 31 ) > > 1 ) &
0xffff ) ;
}
2013-04-19 22:04:12 +04:00
# define ext4_ext_dirty(handle, inode, path) \
__ext4_ext_dirty ( __func__ , __LINE__ , ( handle ) , ( inode ) , ( path ) )
int __ext4_ext_dirty ( const char * where , unsigned int line , handle_t * handle ,
struct inode * inode , struct ext4_ext_path * path ) ;
2008-04-30 02:13:32 +04:00
# endif /* _EXT4_EXTENTS */
2006-10-11 12:21:03 +04:00