2005-12-16 01:31:24 +03:00
/* -*- mode: c; c-basic-offset: 8; -*-
* vim : noexpandtab sw = 8 ts = 8 sts = 0 :
*
* alloc . h
*
* Function prototypes
*
* Copyright ( C ) 2002 , 2004 Oracle . All rights reserved .
*
* This program is free software ; you can redistribute it and / or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation ; either
* version 2 of the License , or ( at your option ) any later version .
*
* 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
* License along with this program ; if not , write to the
* Free Software Foundation , Inc . , 59 Temple Place - Suite 330 ,
* Boston , MA 021110 - 1307 , USA .
*/
# ifndef OCFS2_ALLOC_H
# define OCFS2_ALLOC_H
2008-08-18 13:38:44 +04:00
2008-08-18 13:38:52 +04:00
/*
* For xattr tree leaf , we limit the leaf byte size to be 64 K .
*/
# define OCFS2_MAX_XATTR_TREE_LEAF_SIZE 65536
2008-08-21 06:36:33 +04:00
/*
* ocfs2_extent_tree and ocfs2_extent_tree_operations are used to abstract
* the b - tree operations in ocfs2 . Now all the b - tree operations are not
* limited to ocfs2_dinode only . Any data which need to allocate clusters
* to store can use b - tree . And it only needs to implement its ocfs2_extent_tree
* and operation .
*
* ocfs2_extent_tree becomes the first - class object for extent tree
* manipulation . Callers of the alloc . c code need to fill it via one of
2008-08-22 23:46:09 +04:00
* the ocfs2_init_ * _extent_tree ( ) operations below .
2008-08-21 06:36:33 +04:00
*
* ocfs2_extent_tree contains info for the root of the b - tree , it must have a
* root ocfs2_extent_list and a root_bh so that they can be used in the b - tree
2008-10-18 06:25:01 +04:00
* functions . With metadata ecc , we now call different journal_access
* functions for each type of metadata , so it must have the
* root_journal_access function .
2008-08-21 06:36:33 +04:00
* ocfs2_extent_tree_operations abstract the normal operations we do for
* the root of extent b - tree .
*/
struct ocfs2_extent_tree_operations ;
struct ocfs2_extent_tree {
struct ocfs2_extent_tree_operations * et_ops ;
struct buffer_head * et_root_bh ;
struct ocfs2_extent_list * et_root_el ;
2008-10-18 06:25:01 +04:00
ocfs2_journal_access_func et_root_journal_access ;
2008-08-21 06:36:33 +04:00
void * et_object ;
unsigned int et_max_leaf_clusters ;
} ;
/*
2008-08-22 23:46:09 +04:00
* ocfs2_init_ * _extent_tree ( ) will fill an ocfs2_extent_tree from the
* specified object buffer .
2008-08-21 06:36:33 +04:00
*/
2008-08-22 23:46:09 +04:00
void ocfs2_init_dinode_extent_tree ( struct ocfs2_extent_tree * et ,
struct inode * inode ,
struct buffer_head * bh ) ;
void ocfs2_init_xattr_tree_extent_tree ( struct ocfs2_extent_tree * et ,
2008-08-21 06:36:33 +04:00
struct inode * inode ,
2008-08-22 23:46:09 +04:00
struct buffer_head * bh ) ;
2008-12-10 01:24:33 +03:00
struct ocfs2_xattr_value_buf ;
2008-08-22 23:46:09 +04:00
void ocfs2_init_xattr_value_extent_tree ( struct ocfs2_extent_tree * et ,
struct inode * inode ,
2008-12-10 01:24:33 +03:00
struct ocfs2_xattr_value_buf * vb ) ;
2008-11-13 03:27:44 +03:00
void ocfs2_init_dx_root_extent_tree ( struct ocfs2_extent_tree * et ,
struct inode * inode ,
struct buffer_head * bh ) ;
2008-08-21 06:36:33 +04:00
2008-11-14 01:49:16 +03:00
/*
* Read an extent block into * bh . If * bh is NULL , a bh will be
* allocated . This is a cached read . The extent block will be validated
* with ocfs2_validate_extent_block ( ) .
*/
int ocfs2_read_extent_block ( struct inode * inode , u64 eb_blkno ,
struct buffer_head * * bh ) ;
2005-12-16 01:31:24 +03:00
struct ocfs2_alloc_context ;
2008-08-21 06:36:33 +04:00
int ocfs2_insert_extent ( struct ocfs2_super * osb ,
handle_t * handle ,
struct inode * inode ,
struct ocfs2_extent_tree * et ,
u32 cpos ,
u64 start_blk ,
u32 new_clusters ,
u8 flags ,
struct ocfs2_alloc_context * meta_ac ) ;
2008-08-18 13:38:45 +04:00
enum ocfs2_alloc_restarted {
RESTART_NONE = 0 ,
RESTART_TRANS ,
RESTART_META
} ;
int ocfs2_add_clusters_in_btree ( struct ocfs2_super * osb ,
struct inode * inode ,
u32 * logical_offset ,
u32 clusters_to_add ,
int mark_unwritten ,
2008-08-21 06:36:33 +04:00
struct ocfs2_extent_tree * et ,
2008-08-18 13:38:45 +04:00
handle_t * handle ,
struct ocfs2_alloc_context * data_ac ,
struct ocfs2_alloc_context * meta_ac ,
2008-08-21 06:36:33 +04:00
enum ocfs2_alloc_restarted * reason_ret ) ;
2007-06-18 21:48:04 +04:00
struct ocfs2_cached_dealloc_ctxt ;
2008-08-21 06:36:33 +04:00
int ocfs2_mark_extent_written ( struct inode * inode ,
struct ocfs2_extent_tree * et ,
2007-06-18 21:48:04 +04:00
handle_t * handle , u32 cpos , u32 len , u32 phys ,
struct ocfs2_alloc_context * meta_ac ,
2008-08-21 06:36:33 +04:00
struct ocfs2_cached_dealloc_ctxt * dealloc ) ;
int ocfs2_remove_extent ( struct inode * inode ,
struct ocfs2_extent_tree * et ,
2007-07-04 00:34:11 +04:00
u32 cpos , u32 len , handle_t * handle ,
struct ocfs2_alloc_context * meta_ac ,
2008-08-21 06:36:33 +04:00
struct ocfs2_cached_dealloc_ctxt * dealloc ) ;
2008-11-13 02:16:38 +03:00
int ocfs2_remove_btree_range ( struct inode * inode ,
struct ocfs2_extent_tree * et ,
u32 cpos , u32 phys_cpos , u32 len ,
struct ocfs2_cached_dealloc_ctxt * dealloc ) ;
2005-12-16 01:31:24 +03:00
int ocfs2_num_free_extents ( struct ocfs2_super * osb ,
struct inode * inode ,
2008-08-21 06:36:33 +04:00
struct ocfs2_extent_tree * et ) ;
2008-08-18 13:38:44 +04:00
2008-08-18 13:38:43 +04:00
/*
* how many new metadata chunks would an allocation need at maximum ?
*
* Please note that the caller must make sure that root_el is the root
* of extent tree . So for an inode , it should be & fe - > id2 . i_list . Otherwise
* the result may be wrong .
*/
static inline int ocfs2_extend_meta_needed ( struct ocfs2_extent_list * root_el )
2005-12-16 01:31:24 +03:00
{
/*
* Rather than do all the work of determining how much we need
* ( involves a ton of reads and locks ) , just ask for the
* maximal limit . That ' s a tree depth shift . So , one block for
* level of the tree ( current l_tree_depth ) , one block for the
* new tree_depth = = 0 extent_block , and one block at the new
* top - of - the tree .
*/
2008-08-18 13:38:43 +04:00
return le16_to_cpu ( root_el - > l_tree_depth ) + 2 ;
2005-12-16 01:31:24 +03:00
}
2007-09-14 03:33:54 +04:00
void ocfs2_dinode_new_extent_list ( struct inode * inode , struct ocfs2_dinode * di ) ;
2007-09-08 01:46:51 +04:00
void ocfs2_set_inode_data_inline ( struct inode * inode , struct ocfs2_dinode * di ) ;
int ocfs2_convert_inline_data_to_extents ( struct inode * inode ,
struct buffer_head * di_bh ) ;
2005-12-16 01:31:24 +03:00
int ocfs2_truncate_log_init ( struct ocfs2_super * osb ) ;
void ocfs2_truncate_log_shutdown ( struct ocfs2_super * osb ) ;
void ocfs2_schedule_truncate_log_flush ( struct ocfs2_super * osb ,
int cancel ) ;
int ocfs2_flush_truncate_log ( struct ocfs2_super * osb ) ;
int ocfs2_begin_truncate_log_recovery ( struct ocfs2_super * osb ,
int slot_num ,
struct ocfs2_dinode * * tl_copy ) ;
int ocfs2_complete_truncate_log_recovery ( struct ocfs2_super * osb ,
struct ocfs2_dinode * tl_copy ) ;
2007-07-04 00:34:11 +04:00
int ocfs2_truncate_log_needs_flush ( struct ocfs2_super * osb ) ;
int ocfs2_truncate_log_append ( struct ocfs2_super * osb ,
handle_t * handle ,
u64 start_blk ,
unsigned int num_clusters ) ;
int __ocfs2_flush_truncate_log ( struct ocfs2_super * osb ) ;
2005-12-16 01:31:24 +03:00
2007-06-23 02:45:27 +04:00
/*
* Process local structure which describes the block unlinks done
* during an operation . This is populated via
* ocfs2_cache_block_dealloc ( ) .
*
* ocfs2_run_deallocs ( ) should be called after the potentially
* de - allocating routines . No journal handles should be open , and most
* locks should have been dropped .
*/
struct ocfs2_cached_dealloc_ctxt {
struct ocfs2_per_slot_free_list * c_first_suballocator ;
2008-11-12 03:26:58 +03:00
struct ocfs2_cached_block_free * c_global_allocator ;
2007-06-23 02:45:27 +04:00
} ;
static inline void ocfs2_init_dealloc_ctxt ( struct ocfs2_cached_dealloc_ctxt * c )
{
c - > c_first_suballocator = NULL ;
2008-11-12 03:26:58 +03:00
c - > c_global_allocator = NULL ;
2007-06-23 02:45:27 +04:00
}
2008-11-12 03:26:58 +03:00
int ocfs2_cache_cluster_dealloc ( struct ocfs2_cached_dealloc_ctxt * ctxt ,
u64 blkno , unsigned int bit ) ;
2008-11-12 03:27:00 +03:00
static inline int ocfs2_dealloc_has_cluster ( struct ocfs2_cached_dealloc_ctxt * c )
{
return c - > c_global_allocator ! = NULL ;
}
2007-06-23 02:45:27 +04:00
int ocfs2_run_deallocs ( struct ocfs2_super * osb ,
struct ocfs2_cached_dealloc_ctxt * ctxt ) ;
2005-12-16 01:31:24 +03:00
struct ocfs2_truncate_context {
2007-06-23 02:52:36 +04:00
struct ocfs2_cached_dealloc_ctxt tc_dealloc ;
2005-12-16 01:31:24 +03:00
int tc_ext_alloc_locked ; /* is it cluster locked? */
/* these get destroyed once it's passed to ocfs2_commit_truncate. */
struct buffer_head * tc_last_eb_bh ;
} ;
2007-07-07 01:41:18 +04:00
int ocfs2_zero_range_for_truncate ( struct inode * inode , handle_t * handle ,
u64 range_start , u64 range_end ) ;
2005-12-16 01:31:24 +03:00
int ocfs2_prepare_truncate ( struct ocfs2_super * osb ,
struct inode * inode ,
struct buffer_head * fe_bh ,
struct ocfs2_truncate_context * * tc ) ;
int ocfs2_commit_truncate ( struct ocfs2_super * osb ,
struct inode * inode ,
struct buffer_head * fe_bh ,
struct ocfs2_truncate_context * tc ) ;
2007-09-08 01:46:51 +04:00
int ocfs2_truncate_inline ( struct inode * inode , struct buffer_head * di_bh ,
unsigned int start , unsigned int end , int trunc ) ;
2005-12-16 01:31:24 +03:00
2007-01-17 23:31:35 +03:00
int ocfs2_find_leaf ( struct inode * inode , struct ocfs2_extent_list * root_el ,
u32 cpos , struct buffer_head * * leaf_bh ) ;
2007-06-18 21:48:04 +04:00
int ocfs2_search_extent_list ( struct ocfs2_extent_list * el , u32 v_cluster ) ;
2007-01-17 23:31:35 +03:00
2007-03-08 03:46:57 +03:00
/*
* Helper function to look at the # of clusters in an extent record .
*/
static inline unsigned int ocfs2_rec_clusters ( struct ocfs2_extent_list * el ,
struct ocfs2_extent_rec * rec )
{
/*
* Cluster count in extent records is slightly different
* between interior nodes and leaf nodes . This is to support
* unwritten extents which need a flags field in leaf node
* records , thus shrinking the available space for a clusters
* field .
*/
if ( el - > l_tree_depth )
return le32_to_cpu ( rec - > e_int_clusters ) ;
else
return le16_to_cpu ( rec - > e_leaf_clusters ) ;
}
2008-10-04 01:32:11 +04:00
/*
* This is only valid for leaf nodes , which are the only ones that can
* have empty extents anyway .
*/
static inline int ocfs2_is_empty_extent ( struct ocfs2_extent_rec * rec )
{
return ! rec - > e_leaf_clusters ;
}
2005-12-16 01:31:24 +03:00
# endif /* OCFS2_ALLOC_H */