2018-06-06 05:42:14 +03:00
// SPDX-License-Identifier: GPL-2.0+
2017-10-18 07:37:46 +03: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"
2020-07-02 18:42:12 +03:00
# include "xfs_bmap.h"
2017-10-18 07:37:46 +03:00
# include "scrub/scrub.h"
# include "scrub/common.h"
/* Set us up with the realtime metadata locked. */
int
2018-07-19 22:29:11 +03:00
xchk_setup_rt (
2021-04-08 03:59:39 +03:00
struct xfs_scrub * sc )
2017-10-18 07:37:46 +03:00
{
2018-07-19 22:29:12 +03:00
int error ;
2017-10-18 07:37:46 +03:00
2021-04-08 03:59:39 +03:00
error = xchk_setup_fs ( sc ) ;
2017-10-18 07:37:46 +03:00
if ( error )
return error ;
sc - > ilock_flags = XFS_ILOCK_EXCL | XFS_ILOCK_RTBITMAP ;
2018-01-08 21:41:34 +03:00
sc - > ip = sc - > mp - > m_rbmip ;
2017-10-18 07:37:46 +03: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 22:29:11 +03:00
xchk_rtbitmap_rec (
2022-04-11 23:49:41 +03:00
struct xfs_mount * mp ,
2018-07-19 22:29:12 +03:00
struct xfs_trans * tp ,
2021-08-11 03:02:16 +03:00
const struct xfs_rtalloc_rec * rec ,
2018-07-19 22:29:12 +03:00
void * priv )
2017-10-18 07:37:46 +03:00
{
2018-07-19 22:29:12 +03:00
struct xfs_scrub * sc = priv ;
2018-07-19 22:29:12 +03:00
xfs_rtblock_t startblock ;
xfs_rtblock_t blockcount ;
2017-10-18 07:37:46 +03:00
2022-04-11 23:49:41 +03:00
startblock = rec - > ar_startext * mp - > m_sb . sb_rextsize ;
blockcount = rec - > ar_extcount * mp - > m_sb . sb_rextsize ;
2018-05-31 19:12:10 +03:00
2022-04-11 23:49:41 +03:00
if ( ! xfs_verify_rtext ( mp , startblock , blockcount ) )
2018-07-19 22:29:11 +03:00
xchk_fblock_set_corrupt ( sc , XFS_DATA_FORK , 0 ) ;
2017-10-18 07:37:46 +03:00
return 0 ;
}
2020-07-02 18:42:12 +03:00
/* Make sure the entire rtbitmap file is mapped with written extents. */
STATIC int
xchk_rtbitmap_check_extents (
struct xfs_scrub * sc )
{
struct xfs_mount * mp = sc - > mp ;
struct xfs_bmbt_irec map ;
xfs_rtblock_t off ;
int nmap ;
int error = 0 ;
for ( off = 0 ; off < mp - > m_sb . sb_rbmblocks ; ) {
if ( xchk_should_terminate ( sc , & error ) | |
( sc - > sm - > sm_flags & XFS_SCRUB_OFLAG_CORRUPT ) )
break ;
/* Make sure we have a written extent. */
nmap = 1 ;
error = xfs_bmapi_read ( mp - > m_rbmip , off ,
mp - > m_sb . sb_rbmblocks - off , & map , & nmap ,
XFS_DATA_FORK ) ;
if ( ! xchk_fblock_process_error ( sc , XFS_DATA_FORK , off , & error ) )
break ;
if ( nmap ! = 1 | | ! xfs_bmap_is_written_extent ( & map ) ) {
xchk_fblock_set_corrupt ( sc , XFS_DATA_FORK , off ) ;
break ;
}
off + = map . br_blockcount ;
}
return error ;
}
2017-10-18 07:37:46 +03:00
/* Scrub the realtime bitmap. */
int
2018-07-19 22:29:11 +03:00
xchk_rtbitmap (
2018-07-19 22:29:12 +03:00
struct xfs_scrub * sc )
2017-10-18 07:37:46 +03:00
{
2018-07-19 22:29:12 +03:00
int error ;
2017-10-18 07:37:46 +03:00
2020-07-02 18:42:13 +03:00
/* Is the size of the rtbitmap correct? */
2021-03-29 21:11:40 +03:00
if ( sc - > mp - > m_rbmip - > i_disk_size ! =
2020-07-02 18:42:13 +03:00
XFS_FSB_TO_B ( sc - > mp , sc - > mp - > m_sb . sb_rbmblocks ) ) {
xchk_ino_set_corrupt ( sc , sc - > mp - > m_rbmip - > i_ino ) ;
return 0 ;
}
2018-05-14 16:34:33 +03:00
/* Invoke the fork scrubber. */
2018-07-19 22:29:11 +03:00
error = xchk_metadata_inode_forks ( sc ) ;
2018-05-14 16:34:33 +03:00
if ( error | | ( sc - > sm - > sm_flags & XFS_SCRUB_OFLAG_CORRUPT ) )
2020-07-02 18:42:12 +03:00
return error ;
error = xchk_rtbitmap_check_extents ( sc ) ;
if ( error | | ( sc - > sm - > sm_flags & XFS_SCRUB_OFLAG_CORRUPT ) )
2018-05-14 16:34:33 +03:00
return error ;
2022-04-11 23:49:41 +03:00
error = xfs_rtalloc_query_all ( sc - > mp , sc - > tp , xchk_rtbitmap_rec , sc ) ;
2018-07-19 22:29:11 +03:00
if ( ! xchk_fblock_process_error ( sc , XFS_DATA_FORK , 0 , & error ) )
2017-10-18 07:37:46 +03:00
goto out ;
out :
return error ;
}
/* Scrub the realtime summary. */
int
2018-07-19 22:29:11 +03:00
xchk_rtsummary (
2018-07-19 22:29:12 +03:00
struct xfs_scrub * sc )
2017-10-18 07:37:46 +03:00
{
2018-07-19 22:29:12 +03: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 16:34:33 +03: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 22:29:11 +03:00
error = xchk_metadata_inode_forks ( sc ) ;
2018-05-14 16:34:33 +03:00
if ( error | | ( sc - > sm - > sm_flags & XFS_SCRUB_OFLAG_CORRUPT ) )
goto out ;
2017-10-18 07:37:46 +03:00
/* XXX: implement this some day */
2018-07-19 22:29:11 +03:00
xchk_set_incomplete ( sc ) ;
2018-05-14 16:34:33 +03: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-18 07:37:46 +03:00
}
2018-01-17 05:53:10 +03:00
/* xref check that the extent is not free in the rtbitmap */
void
2018-07-19 22:29:11 +03:00
xchk_xref_is_used_rt_space (
2018-07-19 22:29:12 +03:00
struct xfs_scrub * sc ,
2018-07-19 22:29:12 +03:00
xfs_rtblock_t fsbno ,
xfs_extlen_t len )
2018-01-17 05:53:10 +03:00
{
2018-07-19 22:29:12 +03:00
xfs_rtblock_t startext ;
xfs_rtblock_t endext ;
xfs_rtblock_t extcount ;
bool is_free ;
int error ;
2018-01-17 05:53:10 +03:00
2018-07-19 22:29:11 +03:00
if ( xchk_skip_xref ( sc - > sm ) )
2018-05-14 16:34:31 +03:00
return ;
2018-05-31 19:12:10 +03:00
startext = fsbno ;
endext = fsbno + len - 1 ;
do_div ( startext , sc - > mp - > m_sb . sb_rextsize ) ;
2019-02-01 20:08:53 +03:00
do_div ( endext , sc - > mp - > m_sb . sb_rextsize ) ;
extcount = endext - startext + 1 ;
2018-01-17 05:53:10 +03:00
xfs_ilock ( sc - > mp - > m_rbmip , XFS_ILOCK_SHARED | XFS_ILOCK_RTBITMAP ) ;
2018-05-31 19:12:10 +03:00
error = xfs_rtalloc_extent_is_free ( sc - > mp , sc - > tp , startext , extcount ,
2018-01-17 05:53:10 +03:00
& is_free ) ;
2018-07-19 22:29:11 +03:00
if ( ! xchk_should_check_xref ( sc , & error , NULL ) )
2018-01-17 05:53:10 +03:00
goto out_unlock ;
if ( is_free )
2018-07-19 22:29:11 +03:00
xchk_ino_xref_set_corrupt ( sc , sc - > mp - > m_rbmip - > i_ino ) ;
2018-01-17 05:53:10 +03:00
out_unlock :
xfs_iunlock ( sc - > mp - > m_rbmip , XFS_ILOCK_SHARED | XFS_ILOCK_RTBITMAP ) ;
}