2006-12-07 07:37:15 +03:00
/*
* Interface between ext4 and JBD
*/
2008-04-30 02:13:32 +04:00
# include "ext4_jbd2.h"
2006-12-07 07:37:15 +03:00
2009-11-23 04:52:12 +03:00
# include <trace/events/ext4.h>
2006-12-07 07:37:15 +03:00
int __ext4_journal_get_undo_access ( const char * where , handle_t * handle ,
struct buffer_head * bh )
{
2009-01-07 08:06:22 +03:00
int err = 0 ;
if ( ext4_handle_valid ( handle ) ) {
err = jbd2_journal_get_undo_access ( handle , bh ) ;
if ( err )
ext4_journal_abort_handle ( where , __func__ , bh ,
handle , err ) ;
}
2006-12-07 07:37:15 +03:00
return err ;
}
int __ext4_journal_get_write_access ( const char * where , handle_t * handle ,
struct buffer_head * bh )
{
2009-01-07 08:06:22 +03:00
int err = 0 ;
if ( ext4_handle_valid ( handle ) ) {
err = jbd2_journal_get_write_access ( handle , bh ) ;
if ( err )
ext4_journal_abort_handle ( where , __func__ , bh ,
handle , err ) ;
}
2006-12-07 07:37:15 +03:00
return err ;
}
int __ext4_journal_forget ( const char * where , handle_t * handle ,
struct buffer_head * bh )
{
2009-01-07 08:06:22 +03:00
int err = 0 ;
if ( ext4_handle_valid ( handle ) ) {
err = jbd2_journal_forget ( handle , bh ) ;
if ( err )
ext4_journal_abort_handle ( where , __func__ , bh ,
handle , err ) ;
}
2009-07-13 17:07:20 +04:00
else
2009-09-10 05:32:41 +04:00
bforget ( bh ) ;
2006-12-07 07:37:15 +03:00
return err ;
}
2009-11-23 04:52:12 +03:00
/*
* The ext4 forget function must perform a revoke if we are freeing data
* which has been journaled . Metadata ( eg . indirect blocks ) must be
* revoked in all cases .
*
* " bh " may be NULL : a metadata block may have been freed from memory
* but there may still be a record of it in the journal , and that record
* still needs to be revoked .
*
* If the handle isn ' t valid we ' re not journaling , but we still need to
* call into ext4_journal_revoke ( ) to put the buffer head .
*/
int __ext4_forget ( const char * where , handle_t * handle , int is_metadata ,
struct inode * inode , struct buffer_head * bh ,
ext4_fsblk_t blocknr )
{
int err ;
might_sleep ( ) ;
trace_ext4_forget ( inode , is_metadata , blocknr ) ;
BUFFER_TRACE ( bh , " enter " ) ;
jbd_debug ( 4 , " forgetting bh %p: is_metadata = %d, mode %o, "
" data mode %x \n " ,
bh , is_metadata , inode - > i_mode ,
test_opt ( inode - > i_sb , DATA_FLAGS ) ) ;
2009-11-24 19:05:59 +03:00
/* In the no journal case, we can just do a bforget and return */
if ( ! ext4_handle_valid ( handle ) ) {
bforget ( bh ) ;
return 0 ;
}
2009-11-23 04:52:12 +03:00
/* Never use the revoke function if we are doing full data
* journaling : there is no need to , and a V1 superblock won ' t
* support it . Otherwise , only skip the revoke on un - journaled
* data blocks . */
if ( test_opt ( inode - > i_sb , DATA_FLAGS ) = = EXT4_MOUNT_JOURNAL_DATA | |
( ! is_metadata & & ! ext4_should_journal_data ( inode ) ) ) {
if ( bh ) {
BUFFER_TRACE ( bh , " call jbd2_journal_forget " ) ;
return __ext4_journal_forget ( where , handle , bh ) ;
}
return 0 ;
}
/*
* data ! = journal & & ( is_metadata | | should_journal_data ( inode ) )
*/
2009-11-24 19:05:59 +03:00
BUFFER_TRACE ( bh , " call jbd2_journal_revoke " ) ;
err = jbd2_journal_revoke ( handle , blocknr , bh ) ;
if ( err ) {
ext4_journal_abort_handle ( where , __func__ , bh , handle , err ) ;
2009-11-23 04:52:12 +03:00
ext4_abort ( inode - > i_sb , __func__ ,
" error %d when attempting revoke " , err ) ;
2009-11-24 19:05:59 +03:00
}
2009-11-23 04:52:12 +03:00
BUFFER_TRACE ( bh , " exit " ) ;
return err ;
}
2006-12-07 07:37:15 +03:00
int __ext4_journal_get_create_access ( const char * where ,
handle_t * handle , struct buffer_head * bh )
{
2009-01-07 08:06:22 +03:00
int err = 0 ;
if ( ext4_handle_valid ( handle ) ) {
err = jbd2_journal_get_create_access ( handle , bh ) ;
if ( err )
ext4_journal_abort_handle ( where , __func__ , bh ,
handle , err ) ;
}
2006-12-07 07:37:15 +03:00
return err ;
}
2009-01-07 08:06:22 +03:00
int __ext4_handle_dirty_metadata ( const char * where , handle_t * handle ,
struct inode * inode , struct buffer_head * bh )
2006-12-07 07:37:15 +03:00
{
2009-01-07 08:06:22 +03:00
int err = 0 ;
if ( ext4_handle_valid ( handle ) ) {
err = jbd2_journal_dirty_metadata ( handle , bh ) ;
if ( err )
ext4_journal_abort_handle ( where , __func__ , bh ,
handle , err ) ;
} else {
2009-09-12 21:41:55 +04:00
if ( inode & & bh )
mark_buffer_dirty_inode ( bh , inode ) ;
else
mark_buffer_dirty ( bh ) ;
2009-01-07 08:06:22 +03:00
if ( inode & & inode_needs_sync ( inode ) ) {
sync_dirty_buffer ( bh ) ;
if ( buffer_req ( bh ) & & ! buffer_uptodate ( bh ) ) {
ext4_error ( inode - > i_sb , __func__ ,
" IO error syncing inode, "
" inode=%lu, block=%llu " ,
inode - > i_ino ,
( unsigned long long ) bh - > b_blocknr ) ;
err = - EIO ;
}
}
}
2006-12-07 07:37:15 +03:00
return err ;
}