2005-04-17 02:20:36 +04:00
/*
2005-11-02 06:58:39 +03:00
* Copyright ( c ) 2000 - 2001 , 2005 Silicon Graphics , Inc .
* All Rights Reserved .
2005-04-17 02:20:36 +04:00
*
2005-11-02 06:58:39 +03:00
* This program is free software ; you can redistribute it and / or
* modify it under the terms of the GNU General Public License as
2005-04-17 02:20:36 +04:00
* published by the Free Software Foundation .
*
2005-11-02 06:58:39 +03:00
* This program is distributed in the hope that it would 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 .
2005-04-17 02:20:36 +04:00
*
2005-11-02 06:58:39 +03:00
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write the Free Software Foundation ,
* Inc . , 51 Franklin St , Fifth Floor , Boston , MA 02110 - 1301 USA
2005-04-17 02:20:36 +04:00
*/
# include "xfs.h"
2013-10-23 03:51:50 +04:00
# include "xfs_format.h"
2005-11-02 06:38:42 +03:00
# include "xfs_fs.h"
2013-10-23 03:50:10 +04:00
# include "xfs_log_format.h"
# include "xfs_trans_resv.h"
2005-11-02 06:38:42 +03:00
# include "xfs_sb.h"
2007-08-28 08:00:13 +04:00
# include "xfs_ag.h"
2005-04-17 02:20:36 +04:00
# include "xfs_mount.h"
# include "xfs_error.h"
# ifdef DEBUG
int xfs_etrap [ XFS_ERROR_NTRAP ] = {
0 ,
} ;
int
xfs_error_trap ( int e )
{
int i ;
if ( ! e )
return 0 ;
for ( i = 0 ; i < XFS_ERROR_NTRAP ; i + + ) {
if ( xfs_etrap [ i ] = = 0 )
break ;
if ( e ! = xfs_etrap [ i ] )
continue ;
2011-03-07 02:08:35 +03:00
xfs_notice ( NULL , " %s: error %d " , __func__ , e ) ;
2005-04-17 02:20:36 +04:00
BUG ( ) ;
break ;
}
return e ;
}
int xfs_etest [ XFS_NUM_INJECT_ERROR ] ;
int64_t xfs_etest_fsid [ XFS_NUM_INJECT_ERROR ] ;
char * xfs_etest_fsname [ XFS_NUM_INJECT_ERROR ] ;
2010-11-30 07:15:31 +03:00
int xfs_error_test_active ;
2005-04-17 02:20:36 +04:00
int
xfs_error_test ( int error_tag , int * fsidp , char * expression ,
int line , char * file , unsigned long randfactor )
{
int i ;
int64_t fsid ;
2013-03-04 16:58:20 +04:00
if ( prandom_u32 ( ) % randfactor )
2005-04-17 02:20:36 +04:00
return 0 ;
memcpy ( & fsid , fsidp , sizeof ( xfs_fsid_t ) ) ;
for ( i = 0 ; i < XFS_NUM_INJECT_ERROR ; i + + ) {
if ( xfs_etest [ i ] = = error_tag & & xfs_etest_fsid [ i ] = = fsid ) {
2011-03-07 02:08:35 +03:00
xfs_warn ( NULL ,
2005-04-17 02:20:36 +04:00
" Injecting error (%s) at file %s, line %d, on filesystem \" %s \" " ,
expression , file , line , xfs_etest_fsname [ i ] ) ;
return 1 ;
}
}
return 0 ;
}
int
xfs_errortag_add ( int error_tag , xfs_mount_t * mp )
{
int i ;
int len ;
int64_t fsid ;
memcpy ( & fsid , mp - > m_fixedfsid , sizeof ( xfs_fsid_t ) ) ;
for ( i = 0 ; i < XFS_NUM_INJECT_ERROR ; i + + ) {
if ( xfs_etest_fsid [ i ] = = fsid & & xfs_etest [ i ] = = error_tag ) {
2011-03-07 02:08:35 +03:00
xfs_warn ( mp , " error tag #%d on " , error_tag ) ;
2005-04-17 02:20:36 +04:00
return 0 ;
}
}
for ( i = 0 ; i < XFS_NUM_INJECT_ERROR ; i + + ) {
if ( xfs_etest [ i ] = = 0 ) {
2011-03-07 02:08:35 +03:00
xfs_warn ( mp , " Turned on XFS error tag #%d " ,
2005-04-17 02:20:36 +04:00
error_tag ) ;
xfs_etest [ i ] = error_tag ;
xfs_etest_fsid [ i ] = fsid ;
len = strlen ( mp - > m_fsname ) ;
xfs_etest_fsname [ i ] = kmem_alloc ( len + 1 , KM_SLEEP ) ;
strcpy ( xfs_etest_fsname [ i ] , mp - > m_fsname ) ;
2010-11-30 07:15:31 +03:00
xfs_error_test_active + + ;
2005-04-17 02:20:36 +04:00
return 0 ;
}
}
2011-03-07 02:08:35 +03:00
xfs_warn ( mp , " error tag overflow, too many turned on " ) ;
2005-04-17 02:20:36 +04:00
return 1 ;
}
int
2007-08-30 11:20:53 +04:00
xfs_errortag_clearall ( xfs_mount_t * mp , int loud )
2005-04-17 02:20:36 +04:00
{
2007-08-30 11:20:53 +04:00
int64_t fsid ;
2005-04-17 02:20:36 +04:00
int cleared = 0 ;
2007-08-30 11:20:53 +04:00
int i ;
memcpy ( & fsid , mp - > m_fixedfsid , sizeof ( xfs_fsid_t ) ) ;
2005-04-17 02:20:36 +04:00
for ( i = 0 ; i < XFS_NUM_INJECT_ERROR ; i + + ) {
if ( ( fsid = = 0LL | | xfs_etest_fsid [ i ] = = fsid ) & &
xfs_etest [ i ] ! = 0 ) {
cleared = 1 ;
2011-03-07 02:08:35 +03:00
xfs_warn ( mp , " Clearing XFS error tag #%d " ,
2005-04-17 02:20:36 +04:00
xfs_etest [ i ] ) ;
xfs_etest [ i ] = 0 ;
xfs_etest_fsid [ i ] = 0LL ;
2008-05-19 10:31:57 +04:00
kmem_free ( xfs_etest_fsname [ i ] ) ;
2005-04-17 02:20:36 +04:00
xfs_etest_fsname [ i ] = NULL ;
2010-11-30 07:15:31 +03:00
xfs_error_test_active - - ;
2005-04-17 02:20:36 +04:00
}
}
if ( loud | | cleared )
2011-03-07 02:08:35 +03:00
xfs_warn ( mp , " Cleared all XFS error tags for filesystem " ) ;
2005-04-17 02:20:36 +04:00
return 0 ;
}
2008-08-13 10:17:37 +04:00
# endif /* DEBUG */
2005-04-17 02:20:36 +04:00
void
xfs_error_report (
2010-04-13 09:22:08 +04:00
const char * tag ,
int level ,
struct xfs_mount * mp ,
const char * filename ,
int linenum ,
inst_t * ra )
2005-04-17 02:20:36 +04:00
{
if ( level < = xfs_error_level ) {
2011-03-07 02:02:35 +03:00
xfs_alert_tag ( mp , XFS_PTAG_ERROR_REPORT ,
2014-02-27 08:21:37 +04:00
" Internal error %s at line %d of file %s. Caller %pF " ,
2010-04-13 09:22:08 +04:00
tag , linenum , filename , ra ) ;
2005-04-17 02:20:36 +04:00
xfs_stack_trace ( ) ;
}
}
void
xfs_corruption_error (
2010-04-13 09:22:08 +04:00
const char * tag ,
int level ,
struct xfs_mount * mp ,
void * p ,
const char * filename ,
int linenum ,
inst_t * ra )
2005-04-17 02:20:36 +04:00
{
if ( level < = xfs_error_level )
2013-04-03 09:11:11 +04:00
xfs_hex_dump ( p , 64 ) ;
2010-04-13 09:22:08 +04:00
xfs_error_report ( tag , level , mp , filename , linenum , ra ) ;
2011-03-07 02:03:35 +03:00
xfs_alert ( mp , " Corruption detected. Unmount and run xfs_repair " ) ;
2005-04-17 02:20:36 +04:00
}
2014-02-27 08:21:07 +04:00
/*
* Warnings specifically for verifier errors . Differentiate CRC vs . invalid
* values , and omit the stack trace unless the error level is tuned high .
*/
void
xfs_verifier_error (
struct xfs_buf * bp )
{
struct xfs_mount * mp = bp - > b_target - > bt_mount ;
xfs_alert ( mp , " Metadata %s detected at %pF, block 0x%llx " ,
bp - > b_error = = EFSBADCRC ? " CRC error " : " corruption " ,
__return_address , bp - > b_bn ) ;
xfs_alert ( mp , " Unmount and run xfs_repair " ) ;
if ( xfs_error_level > = XFS_ERRLEVEL_LOW ) {
xfs_alert ( mp , " First 64 bytes of corrupted metadata buffer: " ) ;
xfs_hex_dump ( xfs_buf_offset ( bp , 0 ) , 64 ) ;
}
if ( xfs_error_level > = XFS_ERRLEVEL_HIGH )
xfs_stack_trace ( ) ;
}