2018-06-05 19:42:14 -07:00
// SPDX-License-Identifier: GPL-2.0+
2017-10-17 21:37:46 -07:00
/*
* Copyright ( C ) 2017 Oracle . All Rights Reserved .
* Author : Darrick J . Wong < darrick . wong @ oracle . com >
*/
# include "xfs.h"
# include "xfs_fs.h"
# include "xfs_shared.h"
# include "xfs_format.h"
# include "xfs_trans_resv.h"
# include "xfs_mount.h"
# include "xfs_log_format.h"
# include "xfs_trans.h"
# include "xfs_rtalloc.h"
# include "xfs_inode.h"
# include "scrub/scrub.h"
# include "scrub/common.h"
/* Set us up with the realtime metadata locked. */
int
2018-07-19 12:29:11 -07:00
xchk_setup_rt (
2018-07-19 12:29:12 -07:00
struct xfs_scrub * sc ,
2018-07-19 12:29:12 -07:00
struct xfs_inode * ip )
2017-10-17 21:37:46 -07:00
{
2018-07-19 12:29:12 -07:00
int error ;
2017-10-17 21:37:46 -07:00
2018-07-19 12:29:11 -07:00
error = xchk_setup_fs ( sc , ip ) ;
2017-10-17 21:37:46 -07:00
if ( error )
return error ;
sc - > ilock_flags = XFS_ILOCK_EXCL | XFS_ILOCK_RTBITMAP ;
2018-01-08 10:41:34 -08:00
sc - > ip = sc - > mp - > m_rbmip ;
2017-10-17 21:37:46 -07:00
xfs_ilock ( sc - > ip , sc - > ilock_flags ) ;
return 0 ;
}
/* Realtime bitmap. */
/* Scrub a free extent record from the realtime bitmap. */
STATIC int
2018-07-19 12:29:11 -07:00
xchk_rtbitmap_rec (
2018-07-19 12:29:12 -07:00
struct xfs_trans * tp ,
struct xfs_rtalloc_rec * rec ,
void * priv )
2017-10-17 21:37:46 -07:00
{
2018-07-19 12:29:12 -07:00
struct xfs_scrub * sc = priv ;
2018-07-19 12:29:12 -07:00
xfs_rtblock_t startblock ;
xfs_rtblock_t blockcount ;
2017-10-17 21:37:46 -07:00
2018-05-31 09:12:10 -07:00
startblock = rec - > ar_startext * tp - > t_mountp - > m_sb . sb_rextsize ;
blockcount = rec - > ar_extcount * tp - > t_mountp - > m_sb . sb_rextsize ;
if ( startblock + blockcount < = startblock | |
! xfs_verify_rtbno ( sc - > mp , startblock ) | |
! xfs_verify_rtbno ( sc - > mp , startblock + blockcount - 1 ) )
2018-07-19 12:29:11 -07:00
xchk_fblock_set_corrupt ( sc , XFS_DATA_FORK , 0 ) ;
2017-10-17 21:37:46 -07:00
return 0 ;
}
/* Scrub the realtime bitmap. */
int
2018-07-19 12:29:11 -07:00
xchk_rtbitmap (
2018-07-19 12:29:12 -07:00
struct xfs_scrub * sc )
2017-10-17 21:37:46 -07:00
{
2018-07-19 12:29:12 -07:00
int error ;
2017-10-17 21:37:46 -07:00
2018-05-14 06:34:33 -07:00
/* Invoke the fork scrubber. */
2018-07-19 12:29:11 -07:00
error = xchk_metadata_inode_forks ( sc ) ;
2018-05-14 06:34:33 -07:00
if ( error | | ( sc - > sm - > sm_flags & XFS_SCRUB_OFLAG_CORRUPT ) )
return error ;
2018-07-19 12:29:11 -07:00
error = xfs_rtalloc_query_all ( sc - > tp , xchk_rtbitmap_rec , sc ) ;
if ( ! xchk_fblock_process_error ( sc , XFS_DATA_FORK , 0 , & error ) )
2017-10-17 21:37:46 -07:00
goto out ;
out :
return error ;
}
/* Scrub the realtime summary. */
int
2018-07-19 12:29:11 -07:00
xchk_rtsummary (
2018-07-19 12:29:12 -07:00
struct xfs_scrub * sc )
2017-10-17 21:37:46 -07:00
{
2018-07-19 12:29:12 -07:00
struct xfs_inode * rsumip = sc - > mp - > m_rsumip ;
struct xfs_inode * old_ip = sc - > ip ;
uint old_ilock_flags = sc - > ilock_flags ;
int error = 0 ;
2018-05-14 06:34:33 -07:00
/*
* We ILOCK ' d the rt bitmap ip in the setup routine , now lock the
* rt summary ip in compliance with the rt inode locking rules .
*
* Since we switch sc - > ip to rsumip we have to save the old ilock
* flags so that we don ' t mix up the inode state that @ sc tracks .
*/
sc - > ip = rsumip ;
sc - > ilock_flags = XFS_ILOCK_EXCL | XFS_ILOCK_RTSUM ;
xfs_ilock ( sc - > ip , sc - > ilock_flags ) ;
/* Invoke the fork scrubber. */
2018-07-19 12:29:11 -07:00
error = xchk_metadata_inode_forks ( sc ) ;
2018-05-14 06:34:33 -07:00
if ( error | | ( sc - > sm - > sm_flags & XFS_SCRUB_OFLAG_CORRUPT ) )
goto out ;
2017-10-17 21:37:46 -07:00
/* XXX: implement this some day */
2018-07-19 12:29:11 -07:00
xchk_set_incomplete ( sc ) ;
2018-05-14 06:34:33 -07:00
out :
/* Switch back to the rtbitmap inode and lock flags. */
xfs_iunlock ( sc - > ip , sc - > ilock_flags ) ;
sc - > ilock_flags = old_ilock_flags ;
sc - > ip = old_ip ;
return error ;
2017-10-17 21:37:46 -07:00
}
2018-01-16 18:53:10 -08:00
/* xref check that the extent is not free in the rtbitmap */
void
2018-07-19 12:29:11 -07:00
xchk_xref_is_used_rt_space (
2018-07-19 12:29:12 -07:00
struct xfs_scrub * sc ,
2018-07-19 12:29:12 -07:00
xfs_rtblock_t fsbno ,
xfs_extlen_t len )
2018-01-16 18:53:10 -08:00
{
2018-07-19 12:29:12 -07:00
xfs_rtblock_t startext ;
xfs_rtblock_t endext ;
xfs_rtblock_t extcount ;
bool is_free ;
int error ;
2018-01-16 18:53:10 -08:00
2018-07-19 12:29:11 -07:00
if ( xchk_skip_xref ( sc - > sm ) )
2018-05-14 06:34:31 -07:00
return ;
2018-05-31 09:12:10 -07:00
startext = fsbno ;
endext = fsbno + len - 1 ;
do_div ( startext , sc - > mp - > m_sb . sb_rextsize ) ;
2019-02-01 09:08:53 -08:00
do_div ( endext , sc - > mp - > m_sb . sb_rextsize ) ;
extcount = endext - startext + 1 ;
2018-01-16 18:53:10 -08:00
xfs_ilock ( sc - > mp - > m_rbmip , XFS_ILOCK_SHARED | XFS_ILOCK_RTBITMAP ) ;
2018-05-31 09:12:10 -07:00
error = xfs_rtalloc_extent_is_free ( sc - > mp , sc - > tp , startext , extcount ,
2018-01-16 18:53:10 -08:00
& is_free ) ;
2018-07-19 12:29:11 -07:00
if ( ! xchk_should_check_xref ( sc , & error , NULL ) )
2018-01-16 18:53:10 -08:00
goto out_unlock ;
if ( is_free )
2018-07-19 12:29:11 -07:00
xchk_ino_xref_set_corrupt ( sc , sc - > mp - > m_rbmip - > i_ino ) ;
2018-01-16 18:53:10 -08:00
out_unlock :
xfs_iunlock ( sc - > mp - > m_rbmip , XFS_ILOCK_SHARED | XFS_ILOCK_RTBITMAP ) ;
}