2006-01-16 19:50:04 +03:00
/*
* Copyright ( C ) Sistina Software , Inc . 1997 - 2003 All rights reserved .
2006-05-18 23:09:15 +04:00
* Copyright ( C ) 2004 - 2006 Red Hat , Inc . All rights reserved .
2006-01-16 19:50:04 +03:00
*
* This copyrighted material is made available to anyone wishing to use ,
* modify , copy , or redistribute it subject to the terms and conditions
2006-09-01 19:05:15 +04:00
* of the GNU General Public License version 2.
2006-01-16 19:50:04 +03:00
*/
2014-03-07 00:10:45 +04:00
# define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
2006-01-16 19:50:04 +03:00
# include <linux/spinlock.h>
# include <linux/completion.h>
# include <linux/buffer_head.h>
# include <linux/crc32.h>
2006-02-28 01:23:27 +03:00
# include <linux/gfs2_ondisk.h>
2016-12-24 22:46:01 +03:00
# include <linux/uaccess.h>
2006-01-16 19:50:04 +03:00
# include "gfs2.h"
2006-02-28 01:23:27 +03:00
# include "incore.h"
2006-01-16 19:50:04 +03:00
# include "glock.h"
2006-02-28 01:23:27 +03:00
# include "util.h"
2006-01-16 19:50:04 +03:00
2006-12-07 07:33:20 +03:00
struct kmem_cache * gfs2_glock_cachep __read_mostly ;
2009-12-08 15:12:13 +03:00
struct kmem_cache * gfs2_glock_aspace_cachep __read_mostly ;
2006-12-07 07:33:20 +03:00
struct kmem_cache * gfs2_inode_cachep __read_mostly ;
struct kmem_cache * gfs2_bufdata_cachep __read_mostly ;
2008-01-29 02:20:26 +03:00
struct kmem_cache * gfs2_rgrpd_cachep __read_mostly ;
2008-11-17 17:25:37 +03:00
struct kmem_cache * gfs2_quotad_cachep __read_mostly ;
2015-10-26 18:40:28 +03:00
struct kmem_cache * gfs2_qadata_cachep __read_mostly ;
2012-04-16 12:28:31 +04:00
mempool_t * gfs2_page_pool __read_mostly ;
2006-01-16 19:50:04 +03:00
void gfs2_assert_i ( struct gfs2_sbd * sdp )
{
2014-03-07 00:10:46 +04:00
fs_emerg ( sdp , " fatal assertion failed \n " ) ;
2006-01-16 19:50:04 +03:00
}
2014-03-07 00:17:21 +04:00
int gfs2_lm_withdraw ( struct gfs2_sbd * sdp , const char * fmt , . . . )
2008-01-30 18:34:04 +03:00
{
2009-01-12 13:43:39 +03:00
struct lm_lockstruct * ls = & sdp - > sd_lockstruct ;
const struct lm_lockops * lm = ls - > ls_ops ;
2008-01-30 18:34:04 +03:00
va_list args ;
2014-03-07 00:17:21 +04:00
struct va_format vaf ;
2008-01-30 18:34:04 +03:00
2009-08-24 13:44:18 +04:00
if ( sdp - > sd_args . ar_errors = = GFS2_ERRORS_WITHDRAW & &
test_and_set_bit ( SDF_SHUTDOWN , & sdp - > sd_flags ) )
2008-01-30 18:34:04 +03:00
return 0 ;
va_start ( args , fmt ) ;
2014-03-07 00:17:21 +04:00
vaf . fmt = fmt ;
vaf . va = & args ;
fs_err ( sdp , " %pV " , & vaf ) ;
2008-01-30 18:34:04 +03:00
va_end ( args ) ;
2009-08-24 13:44:18 +04:00
if ( sdp - > sd_args . ar_errors = = GFS2_ERRORS_WITHDRAW ) {
fs_err ( sdp , " about to withdraw this file system \n " ) ;
BUG_ON ( sdp - > sd_args . ar_debug ) ;
2008-01-30 18:34:04 +03:00
2009-08-24 13:44:18 +04:00
kobject_uevent ( & sdp - > sd_kobj , KOBJ_OFFLINE ) ;
2009-01-12 13:43:39 +03:00
2013-02-13 16:21:40 +04:00
if ( ! strcmp ( sdp - > sd_lockstruct . ls_ops - > lm_proto_name , " lock_dlm " ) )
wait_for_completion ( & sdp - > sd_wdack ) ;
2009-08-24 13:44:18 +04:00
if ( lm - > lm_unmount ) {
fs_err ( sdp , " telling LM to unmount \n " ) ;
lm - > lm_unmount ( sdp ) ;
}
2016-03-23 21:29:59 +03:00
set_bit ( SDF_SKIP_DLM_UNLOCK , & sdp - > sd_flags ) ;
2009-08-24 13:44:18 +04:00
fs_err ( sdp , " withdrawn \n " ) ;
dump_stack ( ) ;
2009-01-12 13:43:39 +03:00
}
2009-08-24 13:44:18 +04:00
if ( sdp - > sd_args . ar_errors = = GFS2_ERRORS_PANIC )
2014-03-07 00:10:45 +04:00
panic ( " GFS2: fsid=%s: panic requested \n " , sdp - > sd_fsname ) ;
2008-01-30 18:34:04 +03:00
return - 1 ;
}
2006-01-16 19:50:04 +03:00
/**
* gfs2_assert_withdraw_i - Cause the machine to withdraw if @ assertion is false
* Returns : - 1 if this call withdrew the machine ,
* - 2 if it was already withdrawn
*/
int gfs2_assert_withdraw_i ( struct gfs2_sbd * sdp , char * assertion ,
const char * function , char * file , unsigned int line )
{
int me ;
me = gfs2_lm_withdraw ( sdp ,
2014-03-07 00:17:21 +04:00
" fatal: assertion \" %s \" failed \n "
" function = %s, file = %s, line = %u \n " ,
assertion , function , file , line ) ;
2006-02-08 14:50:51 +03:00
dump_stack ( ) ;
2006-01-16 19:50:04 +03:00
return ( me ) ? - 1 : - 2 ;
}
/**
* gfs2_assert_warn_i - Print a message to the console if @ assertion is false
* Returns : - 1 if we printed something
* - 2 if we didn ' t
*/
int gfs2_assert_warn_i ( struct gfs2_sbd * sdp , char * assertion ,
const char * function , char * file , unsigned int line )
{
if ( time_before ( jiffies ,
sdp - > sd_last_warning +
gfs2_tune_get ( sdp , gt_complain_secs ) * HZ ) )
return - 2 ;
2009-08-24 13:44:18 +04:00
if ( sdp - > sd_args . ar_errors = = GFS2_ERRORS_WITHDRAW )
2014-03-07 00:10:46 +04:00
fs_warn ( sdp , " warning: assertion \" %s \" failed at function = %s, file = %s, line = %u \n " ,
assertion , function , file , line ) ;
2006-01-16 19:50:04 +03:00
if ( sdp - > sd_args . ar_debug )
BUG ( ) ;
2006-02-08 14:50:51 +03:00
else
dump_stack ( ) ;
2006-01-16 19:50:04 +03:00
2009-08-24 13:44:18 +04:00
if ( sdp - > sd_args . ar_errors = = GFS2_ERRORS_PANIC )
panic ( " GFS2: fsid=%s: warning: assertion \" %s \" failed \n "
" GFS2: fsid=%s: function = %s, file = %s, line = %u \n " ,
sdp - > sd_fsname , assertion ,
sdp - > sd_fsname , function , file , line ) ;
2006-01-16 19:50:04 +03:00
sdp - > sd_last_warning = jiffies ;
return - 1 ;
}
/**
* gfs2_consist_i - Flag a filesystem consistency error and withdraw
* Returns : - 1 if this call withdrew the machine ,
* 0 if it was already withdrawn
*/
int gfs2_consist_i ( struct gfs2_sbd * sdp , int cluster_wide , const char * function ,
char * file , unsigned int line )
{
int rv ;
rv = gfs2_lm_withdraw ( sdp ,
2014-03-07 00:17:21 +04:00
" fatal: filesystem consistency error - function = %s, file = %s, line = %u \n " ,
function , file , line ) ;
2006-01-16 19:50:04 +03:00
return rv ;
}
/**
* gfs2_consist_inode_i - Flag an inode consistency error and withdraw
* Returns : - 1 if this call withdrew the machine ,
* 0 if it was already withdrawn
*/
int gfs2_consist_inode_i ( struct gfs2_inode * ip , int cluster_wide ,
const char * function , char * file , unsigned int line )
{
2006-06-14 23:32:57 +04:00
struct gfs2_sbd * sdp = GFS2_SB ( & ip - > i_inode ) ;
2006-01-16 19:50:04 +03:00
int rv ;
rv = gfs2_lm_withdraw ( sdp ,
2014-03-07 00:17:21 +04:00
" fatal: filesystem consistency error \n "
" inode = %llu %llu \n "
" function = %s, file = %s, line = %u \n " ,
( unsigned long long ) ip - > i_no_formal_ino ,
( unsigned long long ) ip - > i_no_addr ,
function , file , line ) ;
2006-01-16 19:50:04 +03:00
return rv ;
}
/**
* gfs2_consist_rgrpd_i - Flag a RG consistency error and withdraw
* Returns : - 1 if this call withdrew the machine ,
* 0 if it was already withdrawn
*/
int gfs2_consist_rgrpd_i ( struct gfs2_rgrpd * rgd , int cluster_wide ,
const char * function , char * file , unsigned int line )
{
struct gfs2_sbd * sdp = rgd - > rd_sbd ;
int rv ;
rv = gfs2_lm_withdraw ( sdp ,
2014-03-07 00:17:21 +04:00
" fatal: filesystem consistency error \n "
" RG = %llu \n "
" function = %s, file = %s, line = %u \n " ,
( unsigned long long ) rgd - > rd_addr ,
function , file , line ) ;
2006-01-16 19:50:04 +03:00
return rv ;
}
/**
* gfs2_meta_check_ii - Flag a magic number consistency error and withdraw
* Returns : - 1 if this call withdrew the machine ,
* - 2 if it was already withdrawn
*/
int gfs2_meta_check_ii ( struct gfs2_sbd * sdp , struct buffer_head * bh ,
const char * type , const char * function , char * file ,
unsigned int line )
{
int me ;
me = gfs2_lm_withdraw ( sdp ,
2014-03-07 00:17:21 +04:00
" fatal: invalid metadata block \n "
" bh = %llu (%s) \n "
" function = %s, file = %s, line = %u \n " ,
( unsigned long long ) bh - > b_blocknr , type ,
function , file , line ) ;
2006-01-16 19:50:04 +03:00
return ( me ) ? - 1 : - 2 ;
}
/**
* gfs2_metatype_check_ii - Flag a metadata type consistency error and withdraw
* Returns : - 1 if this call withdrew the machine ,
* - 2 if it was already withdrawn
*/
int gfs2_metatype_check_ii ( struct gfs2_sbd * sdp , struct buffer_head * bh ,
2006-09-04 20:49:07 +04:00
u16 type , u16 t , const char * function ,
2006-01-16 19:50:04 +03:00
char * file , unsigned int line )
{
int me ;
me = gfs2_lm_withdraw ( sdp ,
2014-03-07 00:17:21 +04:00
" fatal: invalid metadata block \n "
" bh = %llu (type: exp=%u, found=%u) \n "
" function = %s, file = %s, line = %u \n " ,
( unsigned long long ) bh - > b_blocknr , type , t ,
function , file , line ) ;
2006-01-16 19:50:04 +03:00
return ( me ) ? - 1 : - 2 ;
}
/**
* gfs2_io_error_i - Flag an I / O error and withdraw
* Returns : - 1 if this call withdrew the machine ,
* 0 if it was already withdrawn
*/
int gfs2_io_error_i ( struct gfs2_sbd * sdp , const char * function , char * file ,
unsigned int line )
{
int rv ;
rv = gfs2_lm_withdraw ( sdp ,
2014-03-07 00:17:21 +04:00
" fatal: I/O error \n "
" function = %s, file = %s, line = %u \n " ,
function , file , line ) ;
2006-01-16 19:50:04 +03:00
return rv ;
}
/**
* gfs2_io_error_bh_i - Flag a buffer I / O error and withdraw
* Returns : - 1 if this call withdrew the machine ,
* 0 if it was already withdrawn
*/
int gfs2_io_error_bh_i ( struct gfs2_sbd * sdp , struct buffer_head * bh ,
const char * function , char * file , unsigned int line )
{
int rv ;
rv = gfs2_lm_withdraw ( sdp ,
2014-03-07 00:17:21 +04:00
" fatal: I/O error \n "
" block = %llu \n "
" function = %s, file = %s, line = %u \n " ,
( unsigned long long ) bh - > b_blocknr ,
function , file , line ) ;
2006-01-16 19:50:04 +03:00
return rv ;
}