2005-12-16 01:31:24 +03:00
/* -*- mode: c; c-basic-offset: 8; -*-
* vim : noexpandtab sw = 8 ts = 8 sts = 0 :
*
* journal . h
*
* Defines journalling api and structures .
*
* Copyright ( C ) 2003 , 2005 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_JOURNAL_H
# define OCFS2_JOURNAL_H
# include <linux/fs.h>
2008-11-19 03:53:43 +03:00
# include <linux/jbd2.h>
2005-12-16 01:31:24 +03:00
enum ocfs2_journal_state {
OCFS2_JOURNAL_FREE = 0 ,
OCFS2_JOURNAL_LOADED ,
OCFS2_JOURNAL_IN_SHUTDOWN ,
} ;
struct ocfs2_super ;
struct ocfs2_dinode ;
2008-12-17 02:49:16 +03:00
/*
* The recovery_list is a simple linked list of node numbers to recover .
* It is protected by the recovery_lock .
*/
struct ocfs2_recovery_map {
unsigned int rm_used ;
unsigned int * rm_entries ;
} ;
2005-12-16 01:31:24 +03:00
struct ocfs2_journal {
enum ocfs2_journal_state j_state ; /* Journals current state */
journal_t * j_journal ; /* The kernels journal type */
struct inode * j_inode ; /* Kernel inode pointing to
* this journal */
struct ocfs2_super * j_osb ; /* pointer to the super
* block for the node
* we ' re currently
* running on - - not
* necessarily the super
* block from the node
* which we usually run
* from ( recovery ,
* etc ) */
struct buffer_head * j_bh ; /* Journal disk inode block */
atomic_t j_num_trans ; /* Number of transactions
* currently in the system . */
2010-06-11 02:21:36 +04:00
spinlock_t j_lock ;
2005-12-16 01:31:24 +03:00
unsigned long j_trans_id ;
struct rw_semaphore j_trans_barrier ;
wait_queue_head_t j_checkpointed ;
2010-06-11 02:21:36 +04:00
/* both fields protected by j_lock*/
2005-12-16 01:31:24 +03:00
struct list_head j_la_cleanups ;
struct work_struct j_recovery_work ;
} ;
extern spinlock_t trans_inc_lock ;
/* wrap j_trans_id so we never have it equal to zero. */
static inline unsigned long ocfs2_inc_trans_id ( struct ocfs2_journal * j )
{
unsigned long old_id ;
spin_lock ( & trans_inc_lock ) ;
old_id = j - > j_trans_id + + ;
if ( unlikely ( ! j - > j_trans_id ) )
j - > j_trans_id = 1 ;
spin_unlock ( & trans_inc_lock ) ;
return old_id ;
}
2009-02-13 03:41:25 +03:00
static inline void ocfs2_set_ci_lock_trans ( struct ocfs2_journal * journal ,
struct ocfs2_caching_info * ci )
2005-12-16 01:31:24 +03:00
{
spin_lock ( & trans_inc_lock ) ;
2009-02-13 03:41:25 +03:00
ci - > ci_last_trans = journal - > j_trans_id ;
2005-12-16 01:31:24 +03:00
spin_unlock ( & trans_inc_lock ) ;
}
/* Used to figure out whether it's safe to drop a metadata lock on an
2009-02-13 03:41:25 +03:00
* cached object . Returns true if all the object ' s changes have been
2005-12-16 01:31:24 +03:00
* checkpointed to disk . You should be holding the spinlock on the
* metadata lock while calling this to be sure that nobody can take
* the lock and put it on another transaction . */
2009-02-13 03:41:25 +03:00
static inline int ocfs2_ci_fully_checkpointed ( struct ocfs2_caching_info * ci )
2005-12-16 01:31:24 +03:00
{
int ret ;
2009-02-13 03:41:25 +03:00
struct ocfs2_journal * journal =
OCFS2_SB ( ocfs2_metadata_cache_get_super ( ci ) ) - > journal ;
2005-12-16 01:31:24 +03:00
spin_lock ( & trans_inc_lock ) ;
2009-02-13 03:41:25 +03:00
ret = time_after ( journal - > j_trans_id , ci - > ci_last_trans ) ;
2005-12-16 01:31:24 +03:00
spin_unlock ( & trans_inc_lock ) ;
return ret ;
}
2009-02-13 03:41:25 +03:00
/* convenience function to check if an object backed by struct
* ocfs2_caching_info is still new ( has never hit disk ) Will do you a
* favor and set created_trans = 0 when you ' ve
* been checkpointed . returns ' 1 ' if the ci is still new . */
static inline int ocfs2_ci_is_new ( struct ocfs2_caching_info * ci )
2005-12-16 01:31:24 +03:00
{
int ret ;
2009-02-13 03:41:25 +03:00
struct ocfs2_journal * journal =
OCFS2_SB ( ocfs2_metadata_cache_get_super ( ci ) ) - > journal ;
spin_lock ( & trans_inc_lock ) ;
ret = ! ( time_after ( journal - > j_trans_id , ci - > ci_created_trans ) ) ;
if ( ! ret )
ci - > ci_created_trans = 0 ;
spin_unlock ( & trans_inc_lock ) ;
return ret ;
}
2005-12-16 01:31:24 +03:00
2009-02-13 03:41:25 +03:00
/* Wrapper for inodes so we can check system files */
static inline int ocfs2_inode_is_new ( struct inode * inode )
{
2005-12-16 01:31:24 +03:00
/* System files are never "new" as they're written out by
* mkfs . This helps us early during mount , before we have the
* journal open and j_trans_id could be junk . */
if ( OCFS2_I ( inode ) - > ip_flags & OCFS2_INODE_SYSTEM_FILE )
return 0 ;
2009-02-13 03:41:25 +03:00
return ocfs2_ci_is_new ( INODE_CACHE ( inode ) ) ;
2005-12-16 01:31:24 +03:00
}
2009-02-13 03:41:25 +03:00
static inline void ocfs2_ci_set_new ( struct ocfs2_super * osb ,
struct ocfs2_caching_info * ci )
2005-12-16 01:31:24 +03:00
{
spin_lock ( & trans_inc_lock ) ;
2009-02-13 03:41:25 +03:00
ci - > ci_created_trans = osb - > journal - > j_trans_id ;
2005-12-16 01:31:24 +03:00
spin_unlock ( & trans_inc_lock ) ;
}
/* Exported only for the journal struct init code in super.c. Do not call. */
2009-06-22 22:40:07 +04:00
void ocfs2_orphan_scan_init ( struct ocfs2_super * osb ) ;
2009-07-08 01:22:12 +04:00
void ocfs2_orphan_scan_start ( struct ocfs2_super * osb ) ;
2009-06-04 04:02:55 +04:00
void ocfs2_orphan_scan_stop ( struct ocfs2_super * osb ) ;
void ocfs2_orphan_scan_exit ( struct ocfs2_super * osb ) ;
2006-11-22 17:57:56 +03:00
void ocfs2_complete_recovery ( struct work_struct * work ) ;
2008-02-01 23:03:57 +03:00
void ocfs2_wait_for_recovery ( struct ocfs2_super * osb ) ;
int ocfs2_recovery_init ( struct ocfs2_super * osb ) ;
void ocfs2_recovery_exit ( struct ocfs2_super * osb ) ;
2005-12-16 01:31:24 +03:00
2009-03-07 01:21:46 +03:00
int ocfs2_compute_replay_slots ( struct ocfs2_super * osb ) ;
2005-12-16 01:31:24 +03:00
/*
* Journal Control :
* Initialize , Load , Shutdown , Wipe a journal .
*
* ocfs2_journal_init - Initialize journal structures in the OSB .
* ocfs2_journal_load - Load the given journal off disk . Replay it if
* there ' s transactions still in there .
* ocfs2_journal_shutdown - Shutdown a journal , this will flush all
* uncommitted , uncheckpointed transactions .
* ocfs2_journal_wipe - Wipe transactions from a journal . Optionally
* zero out each block .
* ocfs2_recovery_thread - Perform recovery on a node . osb is our own osb .
* ocfs2_mark_dead_nodes - Start recovery on nodes we won ' t get a heartbeat
* event on .
* ocfs2_start_checkpoint - Kick the commit thread to do a checkpoint .
*/
void ocfs2_set_journal_params ( struct ocfs2_super * osb ) ;
int ocfs2_journal_init ( struct ocfs2_journal * journal ,
int * dirty ) ;
void ocfs2_journal_shutdown ( struct ocfs2_super * osb ) ;
int ocfs2_journal_wipe ( struct ocfs2_journal * journal ,
int full ) ;
2008-07-15 04:31:10 +04:00
int ocfs2_journal_load ( struct ocfs2_journal * journal , int local ,
int replayed ) ;
2005-12-16 01:31:24 +03:00
int ocfs2_check_journals_nolocks ( struct ocfs2_super * osb ) ;
void ocfs2_recovery_thread ( struct ocfs2_super * osb ,
int node_num ) ;
int ocfs2_mark_dead_nodes ( struct ocfs2_super * osb ) ;
void ocfs2_complete_mount_recovery ( struct ocfs2_super * osb ) ;
2008-10-21 01:50:38 +04:00
void ocfs2_complete_quota_recovery ( struct ocfs2_super * osb ) ;
2005-12-16 01:31:24 +03:00
static inline void ocfs2_start_checkpoint ( struct ocfs2_super * osb )
{
wake_up ( & osb - > checkpoint_event ) ;
}
static inline void ocfs2_checkpoint_inode ( struct inode * inode )
{
struct ocfs2_super * osb = OCFS2_SB ( inode - > i_sb ) ;
2006-12-06 04:56:35 +03:00
if ( ocfs2_mount_local ( osb ) )
return ;
2009-02-13 03:41:25 +03:00
if ( ! ocfs2_ci_fully_checkpointed ( INODE_CACHE ( inode ) ) ) {
2005-12-16 01:31:24 +03:00
/* WARNING: This only kicks off a single
* checkpoint . If someone races you and adds more
* metadata to the journal , you won ' t know , and will
2011-03-31 05:57:33 +04:00
* wind up waiting * a lot * longer than necessary . Right
2005-12-16 01:31:24 +03:00
* now we only use this in clear_inode so that ' s
* OK . */
ocfs2_start_checkpoint ( osb ) ;
wait_event ( osb - > journal - > j_checkpointed ,
2009-02-13 03:41:25 +03:00
ocfs2_ci_fully_checkpointed ( INODE_CACHE ( inode ) ) ) ;
2005-12-16 01:31:24 +03:00
}
}
/*
* Transaction Handling :
* Manage the lifetime of a transaction handle .
*
* ocfs2_start_trans - Begin a transaction . Give it an upper estimate of
* the number of blocks that will be changed during
* this handle .
2006-10-10 05:11:45 +04:00
* ocfs2_commit_trans - Complete a handle . It might return - EIO if
* the journal was aborted . The majority of paths don ' t
* check the return value as an error there comes too
* late to do anything ( and will be picked up in a
* later transaction ) .
2005-12-16 01:31:24 +03:00
* ocfs2_extend_trans - Extend a handle by nblocks credits . This may
* commit the handle to disk in the process , but will
* not release any locks taken during the transaction .
2008-09-12 02:53:07 +04:00
* ocfs2_journal_access * - Notify the handle that we want to journal this
2005-12-16 01:31:24 +03:00
* buffer . Will have to call ocfs2_journal_dirty once
* we ' ve actually dirtied it . Type is one of . or .
2008-09-12 02:53:07 +04:00
* Always call the specific flavor of
* ocfs2_journal_access_ * ( ) unless you intend to
* manage the checksum by hand .
2005-12-16 01:31:24 +03:00
* ocfs2_journal_dirty - Mark a journalled buffer as having dirty data .
2008-09-04 07:03:41 +04:00
* ocfs2_jbd2_file_inode - Mark an inode so that its data goes out before
* the current handle commits .
2005-12-16 01:31:24 +03:00
*/
/* You must always start_trans with a number of buffs > 0, but it's
* perfectly legal to go through an entire transaction without having
* dirtied any buffers . */
2006-10-10 05:11:45 +04:00
handle_t * ocfs2_start_trans ( struct ocfs2_super * osb ,
2005-12-16 01:31:24 +03:00
int max_buffs ) ;
2006-10-10 05:11:45 +04:00
int ocfs2_commit_trans ( struct ocfs2_super * osb ,
handle_t * handle ) ;
2006-10-06 01:15:36 +04:00
int ocfs2_extend_trans ( handle_t * handle , int nblocks ) ;
ocfs2: lighten up allocate transaction
The issue scenario is as following:
When fallocating a very large disk space for a small file,
__ocfs2_extend_allocation attempts to get a very large transaction. For
some journal sizes, there may be not enough room for this transaction,
and the fallocate will fail.
The patch below extends & restarts the transaction as necessary while
allocating space, and should work with even the smallest journal. This
patch refers ext4 resize.
Test:
# mkfs.ocfs2 -b 4K -C 32K -T datafiles /dev/sdc
...(jounral size is 32M)
# mount.ocfs2 /dev/sdc /mnt/ocfs2/
# touch /mnt/ocfs2/1.log
# fallocate -o 0 -l 400G /mnt/ocfs2/1.log
fallocate: /mnt/ocfs2/1.log: fallocate failed: Cannot allocate memory
# tail -f /var/log/messages
[ 7372.278591] JBD: fallocate wants too many credits (2051 > 2048)
[ 7372.278597] (fallocate,6438,0):__ocfs2_extend_allocation:709 ERROR: status = -12
[ 7372.278603] (fallocate,6438,0):ocfs2_allocate_unwritten_extents:1504 ERROR: status = -12
[ 7372.278607] (fallocate,6438,0):__ocfs2_change_file_space:1955 ERROR: status = -12
^C
With this patch, the test works well.
Signed-off-by: Younger Liu <younger.liu@huawei.com>
Cc: Jie Liu <jeff.liu@oracle.com>
Cc: Joel Becker <jlbec@evilplan.org>
Cc: Mark Fasheh <mfasheh@suse.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2013-09-12 01:19:44 +04:00
int ocfs2_allocate_extend_trans ( handle_t * handle ,
int thresh ) ;
/*
* Define an arbitrary limit for the amount of data we will anticipate
* writing to any given transaction . For unbounded transactions such as
* fallocate ( 2 ) we can write more than this , but we always
* start off at the maximum transaction size and grow the transaction
* optimistically as we go .
*/
# define OCFS2_MAX_TRANS_DATA 64U
2005-12-16 01:31:24 +03:00
/*
* Create access is for when we get a newly created buffer and we ' re
* not gonna read it off disk , but rather fill it ourselves . Right
* now , we don ' t do anything special with this ( it turns into a write
* request ) , but this is a good placeholder in case we do . . .
*
* Write access is for when we read a block off disk and are going to
* modify it . This way the journalling layer knows it may need to make
* a copy of that block ( if it ' s part of another , uncommitted
* transaction ) before we do so .
*/
# define OCFS2_JOURNAL_ACCESS_CREATE 0
# define OCFS2_JOURNAL_ACCESS_WRITE 1
# define OCFS2_JOURNAL_ACCESS_UNDO 2
2008-10-18 06:25:01 +04:00
2008-09-12 02:53:07 +04:00
/* ocfs2_inode */
2009-02-13 03:41:25 +03:00
int ocfs2_journal_access_di ( handle_t * handle , struct ocfs2_caching_info * ci ,
2008-10-18 06:25:01 +04:00
struct buffer_head * bh , int type ) ;
2008-09-12 02:53:07 +04:00
/* ocfs2_extent_block */
2009-02-13 03:41:25 +03:00
int ocfs2_journal_access_eb ( handle_t * handle , struct ocfs2_caching_info * ci ,
2008-09-12 02:53:07 +04:00
struct buffer_head * bh , int type ) ;
2009-08-18 07:19:20 +04:00
/* ocfs2_refcount_block */
int ocfs2_journal_access_rb ( handle_t * handle , struct ocfs2_caching_info * ci ,
struct buffer_head * bh , int type ) ;
2008-09-12 02:53:07 +04:00
/* ocfs2_group_desc */
2009-02-13 03:41:25 +03:00
int ocfs2_journal_access_gd ( handle_t * handle , struct ocfs2_caching_info * ci ,
2008-09-12 02:53:07 +04:00
struct buffer_head * bh , int type ) ;
/* ocfs2_xattr_block */
2009-02-13 03:41:25 +03:00
int ocfs2_journal_access_xb ( handle_t * handle , struct ocfs2_caching_info * ci ,
2008-09-12 02:53:07 +04:00
struct buffer_head * bh , int type ) ;
/* quota blocks */
2009-02-13 03:41:25 +03:00
int ocfs2_journal_access_dq ( handle_t * handle , struct ocfs2_caching_info * ci ,
2008-09-12 02:53:07 +04:00
struct buffer_head * bh , int type ) ;
/* dirblock */
2009-02-13 03:41:25 +03:00
int ocfs2_journal_access_db ( handle_t * handle , struct ocfs2_caching_info * ci ,
2008-09-12 02:53:07 +04:00
struct buffer_head * bh , int type ) ;
2008-11-13 03:27:44 +03:00
/* ocfs2_dx_root_block */
2009-02-13 03:41:25 +03:00
int ocfs2_journal_access_dr ( handle_t * handle , struct ocfs2_caching_info * ci ,
2008-11-13 03:27:44 +03:00
struct buffer_head * bh , int type ) ;
/* ocfs2_dx_leaf */
2009-02-13 03:41:25 +03:00
int ocfs2_journal_access_dl ( handle_t * handle , struct ocfs2_caching_info * ci ,
2008-11-13 03:27:44 +03:00
struct buffer_head * bh , int type ) ;
2008-09-12 02:53:07 +04:00
/* Anything that has no ecc */
2009-02-13 03:41:25 +03:00
int ocfs2_journal_access ( handle_t * handle , struct ocfs2_caching_info * ci ,
2008-09-12 02:53:07 +04:00
struct buffer_head * bh , int type ) ;
2005-12-16 01:31:24 +03:00
/*
* A word about the journal_access / journal_dirty " dance " . It is
* entirely legal to journal_access a buffer more than once ( as long
* as the access type is the same - - I ' m not sure what will happen if
* access type is different but this should never happen anyway ) It is
* also legal to journal_dirty a buffer more than once . In fact , you
* can even journal_access a buffer after you ' ve done a
* journal_access / journal_dirty pair . The only thing you cannot do
* however , is journal_dirty a buffer which you haven ' t yet passed to
* journal_access at least once .
*
* That said , 99 % of the time this doesn ' t matter and this is what the
* path looks like :
*
* < read a bh >
* ocfs2_journal_access ( handle , bh , OCFS2_JOURNAL_ACCESS_WRITE ) ;
* < modify the bh >
* ocfs2_journal_dirty ( handle , bh ) ;
*/
2010-03-20 00:13:52 +03:00
void ocfs2_journal_dirty ( handle_t * handle , struct buffer_head * bh ) ;
2005-12-16 01:31:24 +03:00
/*
* Credit Macros :
* Convenience macros to calculate number of credits needed .
*
* For convenience sake , I have a set of macros here which calculate
* the * maximum * number of sectors which will be changed for various
* metadata updates .
*/
/* simple file updates like chmod, etc. */
# define OCFS2_INODE_UPDATE_CREDITS 1
2008-08-18 13:11:00 +04:00
/* extended attribute block update */
# define OCFS2_XATTR_BLOCK_UPDATE_CREDITS 1
2009-07-22 15:17:21 +04:00
/* Update of a single quota block */
# define OCFS2_QUOTA_BLOCK_UPDATE_CREDITS 1
2008-10-09 21:38:40 +04:00
/* global quotafile inode update, data block */
2009-07-22 15:17:21 +04:00
# define OCFS2_QINFO_WRITE_CREDITS (OCFS2_INODE_UPDATE_CREDITS + \
OCFS2_QUOTA_BLOCK_UPDATE_CREDITS )
2008-10-09 21:38:40 +04:00
2009-07-22 15:17:21 +04:00
# define OCFS2_LOCAL_QINFO_WRITE_CREDITS OCFS2_QUOTA_BLOCK_UPDATE_CREDITS
2008-10-09 21:38:40 +04:00
/*
* The two writes below can accidentally see global info dirty due
* to set_info ( ) quotactl so make them prepared for the writes .
*/
/* quota data block, global info */
/* Write to local quota file */
2009-07-22 15:17:21 +04:00
# define OCFS2_QWRITE_CREDITS (OCFS2_QINFO_WRITE_CREDITS + \
OCFS2_QUOTA_BLOCK_UPDATE_CREDITS )
2008-10-09 21:38:40 +04:00
/* global quota data block, local quota data block, global quota inode,
* global quota info */
2009-07-22 15:17:21 +04:00
# define OCFS2_QSYNC_CREDITS (OCFS2_QINFO_WRITE_CREDITS + \
2 * OCFS2_QUOTA_BLOCK_UPDATE_CREDITS )
2008-10-09 21:38:40 +04:00
static inline int ocfs2_quota_trans_credits ( struct super_block * sb )
{
int credits = 0 ;
if ( OCFS2_HAS_RO_COMPAT_FEATURE ( sb , OCFS2_FEATURE_RO_COMPAT_USRQUOTA ) )
credits + = OCFS2_QWRITE_CREDITS ;
if ( OCFS2_HAS_RO_COMPAT_FEATURE ( sb , OCFS2_FEATURE_RO_COMPAT_GRPQUOTA ) )
credits + = OCFS2_QWRITE_CREDITS ;
return credits ;
}
2007-12-18 10:47:03 +03:00
/* group extend. inode update and last group update. */
# define OCFS2_GROUP_EXTEND_CREDITS (OCFS2_INODE_UPDATE_CREDITS + 1)
2007-12-18 10:47:25 +03:00
/* group add. inode update and the new group update. */
# define OCFS2_GROUP_ADD_CREDITS (OCFS2_INODE_UPDATE_CREDITS + 1)
2005-12-16 01:31:24 +03:00
/* get one bit out of a suballocator: dinode + group descriptor +
* prev . group desc . if we relink . */
# define OCFS2_SUBALLOC_ALLOC (3)
2008-10-09 21:38:40 +04:00
static inline int ocfs2_inline_to_extents_credits ( struct super_block * sb )
{
return OCFS2_SUBALLOC_ALLOC + OCFS2_INODE_UPDATE_CREDITS +
ocfs2_quota_trans_credits ( sb ) ;
}
2007-09-08 01:46:51 +04:00
2005-12-16 01:31:24 +03:00
/* dinode + group descriptor update. We don't relink on free yet. */
# define OCFS2_SUBALLOC_FREE (2)
# define OCFS2_TRUNCATE_LOG_UPDATE OCFS2_INODE_UPDATE_CREDITS
# define OCFS2_TRUNCATE_LOG_FLUSH_ONE_REC (OCFS2_SUBALLOC_FREE \
+ OCFS2_TRUNCATE_LOG_UPDATE )
2008-10-09 21:38:40 +04:00
static inline int ocfs2_remove_extent_credits ( struct super_block * sb )
{
return OCFS2_TRUNCATE_LOG_UPDATE + OCFS2_INODE_UPDATE_CREDITS +
ocfs2_quota_trans_credits ( sb ) ;
}
2007-07-04 00:34:11 +04:00
2011-02-03 16:16:19 +03:00
/* data block for new dir/symlink, allocation of directory block, dx_root
* update for free list */
# define OCFS2_DIR_LINK_ADDITIONAL_CREDITS (1 + OCFS2_SUBALLOC_ALLOC + 1)
2005-12-16 01:31:24 +03:00
2008-11-13 03:27:44 +03:00
static inline int ocfs2_add_dir_index_credits ( struct super_block * sb )
{
/* 1 block for index, 2 allocs (data, metadata), 1 clusters
* worth of blocks for initial extent . */
return 1 + 2 * OCFS2_SUBALLOC_ALLOC +
ocfs2_clusters_to_blocks ( sb , 1 ) ;
}
/* parent fe, parent block, new file entry, index leaf, inode alloc fe, inode
* alloc group descriptor + mkdir / symlink blocks + dir blocks + xattr
* blocks + quota update */
static inline int ocfs2_mknod_credits ( struct super_block * sb , int is_dir ,
int xattr_credits )
2008-10-09 21:38:40 +04:00
{
2008-11-13 03:27:44 +03:00
int dir_credits = OCFS2_DIR_LINK_ADDITIONAL_CREDITS ;
if ( is_dir )
dir_credits + = ocfs2_add_dir_index_credits ( sb ) ;
return 4 + OCFS2_SUBALLOC_ALLOC + dir_credits + xattr_credits +
2008-10-09 21:38:40 +04:00
ocfs2_quota_trans_credits ( sb ) ;
}
2005-12-16 01:31:24 +03:00
/* local alloc metadata change + main bitmap updates */
# define OCFS2_WINDOW_MOVE_CREDITS (OCFS2_INODE_UPDATE_CREDITS \
+ OCFS2_SUBALLOC_ALLOC + OCFS2_SUBALLOC_FREE )
/* used when we don't need an allocation change for a dir extend. One
* for the dinode , one for the new block . */
# define OCFS2_SIMPLE_DIR_EXTEND_CREDITS (2)
2008-10-09 21:38:40 +04:00
/* file update (nlink, etc) + directory mtime/ctime + dir entry block + quota
2011-10-19 05:34:19 +04:00
* update on dir + index leaf + dx root update for free list +
* previous dirblock update in the free list */
2008-10-09 21:38:40 +04:00
static inline int ocfs2_link_credits ( struct super_block * sb )
{
2011-10-19 05:34:19 +04:00
return 2 * OCFS2_INODE_UPDATE_CREDITS + 4 +
2008-10-09 21:38:40 +04:00
ocfs2_quota_trans_credits ( sb ) ;
}
2005-12-16 01:31:24 +03:00
/* inode + dir inode (if we unlink a dir), + dir entry block + orphan
2009-01-30 05:17:46 +03:00
* dir inode link + dir inode index leaf + dir index root */
2008-10-09 21:38:40 +04:00
static inline int ocfs2_unlink_credits ( struct super_block * sb )
{
/* The quota update from ocfs2_link_credits is unused here... */
2009-01-30 05:17:46 +03:00
return 2 * OCFS2_INODE_UPDATE_CREDITS + 3 + ocfs2_link_credits ( sb ) ;
2008-10-09 21:38:40 +04:00
}
2005-12-16 01:31:24 +03:00
/* dinode + orphan dir dinode + inode alloc dinode + orphan dir entry +
2009-04-30 04:55:08 +04:00
* inode alloc group descriptor + orphan dir index root +
* orphan dir index leaf */
# define OCFS2_DELETE_INODE_CREDITS (3 * OCFS2_INODE_UPDATE_CREDITS + 4)
2005-12-16 01:31:24 +03:00
/* dinode update, old dir dinode update, new dir dinode update, old
* dir dir entry , new dir dir entry , dir entry update for renaming
2008-11-13 03:27:44 +03:00
* directory + target unlink + 3 x dir index leaves */
2008-10-09 21:38:40 +04:00
static inline int ocfs2_rename_credits ( struct super_block * sb )
{
2008-11-13 03:27:44 +03:00
return 3 * OCFS2_INODE_UPDATE_CREDITS + 6 + ocfs2_unlink_credits ( sb ) ;
2008-10-09 21:38:40 +04:00
}
2005-12-16 01:31:24 +03:00
2008-08-18 13:11:00 +04:00
/* global bitmap dinode, group desc., relinked group,
* suballocator dinode , group desc . , relinked group ,
* dinode , xattr block */
# define OCFS2_XATTR_BLOCK_CREATE_CREDITS (OCFS2_SUBALLOC_ALLOC * 2 + \
+ OCFS2_INODE_UPDATE_CREDITS \
+ OCFS2_XATTR_BLOCK_UPDATE_CREDITS )
2008-11-13 03:27:44 +03:00
/* inode update, removal of dx root block from allocator */
# define OCFS2_DX_ROOT_REMOVE_CREDITS (OCFS2_INODE_UPDATE_CREDITS + \
OCFS2_SUBALLOC_FREE )
2008-11-25 04:02:08 +03:00
static inline int ocfs2_calc_dxi_expand_credits ( struct super_block * sb )
{
int credits = 1 + OCFS2_SUBALLOC_ALLOC ;
credits + = ocfs2_clusters_to_blocks ( sb , 1 ) ;
credits + = ocfs2_quota_trans_credits ( sb ) ;
return credits ;
}
2009-08-24 07:12:02 +04:00
/* inode update, new refcount block and its allocation credits. */
# define OCFS2_REFCOUNT_TREE_CREATE_CREDITS (OCFS2_INODE_UPDATE_CREDITS + 1 \
+ OCFS2_SUBALLOC_ALLOC )
/* inode and the refcount block update. */
# define OCFS2_REFCOUNT_TREE_SET_CREDITS (OCFS2_INODE_UPDATE_CREDITS + 1)
/*
* inode and the refcount block update .
* It doesn ' t include the credits for sub alloc change .
* So if we need to free the bit , OCFS2_SUBALLOC_FREE needs to be added .
*/
# define OCFS2_REFCOUNT_TREE_REMOVE_CREDITS (OCFS2_INODE_UPDATE_CREDITS + 1)
2009-08-18 07:29:12 +04:00
/* 2 metadata alloc, 2 new blocks and root refcount block */
# define OCFS2_EXPAND_REFCOUNT_TREE_CREDITS (OCFS2_SUBALLOC_ALLOC * 2 + 3)
2008-08-18 13:38:43 +04:00
/*
* 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 .
*/
2005-12-16 01:31:24 +03:00
static inline int ocfs2_calc_extend_credits ( struct super_block * sb ,
2013-11-13 03:06:52 +04:00
struct ocfs2_extent_list * root_el )
2005-12-16 01:31:24 +03:00
{
2008-08-18 13:38:43 +04:00
int bitmap_blocks , sysfile_bitmap_blocks , extent_blocks ;
2005-12-16 01:31:24 +03:00
/* bitmap dinode, group desc. + relinked group. */
bitmap_blocks = OCFS2_SUBALLOC_ALLOC ;
/* we might need to shift tree depth so lets assume an
* absolute worst case of complete fragmentation . Even with
* that , we only need one update for the dinode , and then
* however many metadata chunks needed * a remaining suballoc
* alloc . */
sysfile_bitmap_blocks = 1 +
2008-08-18 13:38:43 +04:00
( OCFS2_SUBALLOC_ALLOC - 1 ) * ocfs2_extend_meta_needed ( root_el ) ;
2005-12-16 01:31:24 +03:00
/* this does not include *new* metadata blocks, which are
2008-08-18 13:38:43 +04:00
* accounted for in sysfile_bitmap_blocks . root_el +
2005-12-16 01:31:24 +03:00
* prev . last_eb_blk + blocks along edge of tree .
* calc_symlink_credits passes because we just need 1
* credit for the dinode there . */
2008-08-18 13:38:43 +04:00
extent_blocks = 1 + 1 + le16_to_cpu ( root_el - > l_tree_depth ) ;
2005-12-16 01:31:24 +03:00
2008-10-09 21:38:40 +04:00
return bitmap_blocks + sysfile_bitmap_blocks + extent_blocks +
2013-08-14 03:00:57 +04:00
ocfs2_quota_trans_credits ( sb ) ;
2005-12-16 01:31:24 +03:00
}
static inline int ocfs2_calc_symlink_credits ( struct super_block * sb )
{
2008-11-13 03:27:44 +03:00
int blocks = ocfs2_mknod_credits ( sb , 0 , 0 ) ;
2005-12-16 01:31:24 +03:00
/* links can be longer than one block so we may update many
* within our single allocated extent . */
blocks + = ocfs2_clusters_to_blocks ( sb , 1 ) ;
2008-10-09 21:38:40 +04:00
return blocks + ocfs2_quota_trans_credits ( sb ) ;
2005-12-16 01:31:24 +03:00
}
static inline int ocfs2_calc_group_alloc_credits ( struct super_block * sb ,
unsigned int cpg )
{
int blocks ;
int bitmap_blocks = OCFS2_SUBALLOC_ALLOC + 1 ;
/* parent inode update + new block group header + bitmap inode update
+ bitmap blocks affected */
blocks = 1 + 1 + 1 + bitmap_blocks ;
return blocks ;
}
2010-03-26 05:09:29 +03:00
/*
* Allocating a discontiguous block group requires the credits from
* ocfs2_calc_group_alloc_credits ( ) as well as enough credits to fill
* the group descriptor ' s extent list . The caller already has started
* the transaction with ocfs2_calc_group_alloc_credits ( ) . They extend
* it with these credits .
*/
static inline int ocfs2_calc_bg_discontig_credits ( struct super_block * sb )
{
return ocfs2_extent_recs_per_gd ( sb ) ;
}
2005-12-16 01:31:24 +03:00
static inline int ocfs2_calc_tree_trunc_credits ( struct super_block * sb ,
unsigned int clusters_to_del ,
struct ocfs2_dinode * fe ,
struct ocfs2_extent_list * last_el )
{
/* for dinode + all headers in this pass + update to next leaf */
u16 next_free = le16_to_cpu ( last_el - > l_next_free_rec ) ;
u16 tree_depth = le16_to_cpu ( fe - > id2 . i_list . l_tree_depth ) ;
int credits = 1 + tree_depth + 1 ;
int i ;
i = next_free - 1 ;
BUG_ON ( i < 0 ) ;
/* We may be deleting metadata blocks, so metadata alloc dinode +
one desc . block for each possible delete . */
if ( tree_depth & & next_free = = 1 & &
2007-03-08 03:46:57 +03:00
ocfs2_rec_clusters ( last_el , & last_el - > l_recs [ i ] ) = = clusters_to_del )
2005-12-16 01:31:24 +03:00
credits + = 1 + tree_depth ;
/* update to the truncate log. */
credits + = OCFS2_TRUNCATE_LOG_UPDATE ;
2008-10-09 21:38:40 +04:00
credits + = ocfs2_quota_trans_credits ( sb ) ;
2005-12-16 01:31:24 +03:00
return credits ;
}
2008-09-04 07:03:41 +04:00
static inline int ocfs2_jbd2_file_inode ( handle_t * handle , struct inode * inode )
{
return jbd2_journal_file_inode ( handle , & OCFS2_I ( inode ) - > ip_jinode ) ;
}
static inline int ocfs2_begin_ordered_truncate ( struct inode * inode ,
loff_t new_size )
{
2009-02-10 19:15:34 +03:00
return jbd2_journal_begin_ordered_truncate (
OCFS2_SB ( inode - > i_sb ) - > journal - > j_journal ,
& OCFS2_I ( inode ) - > ip_jinode ,
new_size ) ;
2008-09-04 07:03:41 +04:00
}
2014-04-04 01:46:48 +04:00
static inline void ocfs2_update_inode_fsync_trans ( handle_t * handle ,
struct inode * inode ,
int datasync )
{
struct ocfs2_inode_info * oi = OCFS2_I ( inode ) ;
oi - > i_sync_tid = handle - > h_transaction - > t_tid ;
if ( datasync )
oi - > i_datasync_tid = handle - > h_transaction - > t_tid ;
}
2005-12-16 01:31:24 +03:00
# endif /* OCFS2_JOURNAL_H */