2023-04-11 18:59:56 -07:00
// SPDX-License-Identifier: GPL-2.0-or-later
2017-10-17 21:37:45 -07:00
/*
2023-04-11 18:59:57 -07:00
* Copyright ( C ) 2017 - 2023 Oracle . All Rights Reserved .
2023-04-11 18:59:56 -07:00
* Author : Darrick J . Wong < djwong @ kernel . org >
2017-10-17 21:37:45 -07:00
*/
# 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"
2024-04-15 14:54:59 -07:00
# include "xfs_trans.h"
2017-10-17 21:37:45 -07:00
# include "xfs_inode.h"
# include "xfs_symlink.h"
2023-12-15 10:03:35 -08:00
# include "xfs_health.h"
2024-02-22 12:45:01 -08:00
# include "xfs_symlink_remote.h"
2017-10-17 21:37:45 -07:00
# include "scrub/scrub.h"
# include "scrub/common.h"
2023-12-15 10:03:35 -08:00
# include "scrub/health.h"
2024-04-15 14:54:59 -07:00
# include "scrub/repair.h"
2017-10-17 21:37:45 -07:00
/* Set us up to scrub a symbolic link. */
int
2018-07-19 12:29:11 -07:00
xchk_setup_symlink (
2021-04-07 17:59:39 -07:00
struct xfs_scrub * sc )
2017-10-17 21:37:45 -07:00
{
2024-04-15 14:54:59 -07:00
unsigned int resblks = 0 ;
int error ;
2017-10-17 21:37:45 -07:00
/* Allocate the buffer without the inode lock held. */
2022-11-06 17:03:15 -08:00
sc - > buf = kvzalloc ( XFS_SYMLINK_MAXLEN + 1 , XCHK_GFP_FLAGS ) ;
2017-10-17 21:37:45 -07:00
if ( ! sc - > buf )
return - ENOMEM ;
2024-04-15 14:54:59 -07:00
if ( xchk_could_repair ( sc ) ) {
error = xrep_setup_symlink ( sc , & resblks ) ;
if ( error )
return error ;
}
return xchk_setup_inode_contents ( sc , resblks ) ;
2017-10-17 21:37:45 -07:00
}
/* Symbolic links. */
int
2018-07-19 12:29:11 -07:00
xchk_symlink (
2018-07-19 12:29:12 -07:00
struct xfs_scrub * sc )
2017-10-17 21:37:45 -07:00
{
2018-07-19 12:29:12 -07:00
struct xfs_inode * ip = sc - > ip ;
struct xfs_ifork * ifp ;
loff_t len ;
int error = 0 ;
2017-10-17 21:37:45 -07:00
if ( ! S_ISLNK ( VFS_I ( ip ) - > i_mode ) )
return - ENOENT ;
2023-12-15 10:03:35 -08:00
if ( xchk_file_looks_zapped ( sc , XFS_SICK_INO_SYMLINK_ZAPPED ) ) {
xchk_fblock_set_corrupt ( sc , XFS_DATA_FORK , 0 ) ;
return 0 ;
}
2022-07-09 10:56:05 -07:00
ifp = xfs_ifork_ptr ( ip , XFS_DATA_FORK ) ;
2021-03-29 11:11:40 -07:00
len = ip - > i_disk_size ;
2017-10-17 21:37:45 -07:00
/* Plausible size? */
if ( len > XFS_SYMLINK_MAXLEN | | len < = 0 ) {
2018-07-19 12:29:11 -07:00
xchk_fblock_set_corrupt ( sc , XFS_DATA_FORK , 0 ) ;
2023-12-15 10:03:35 -08:00
return 0 ;
2017-10-17 21:37:45 -07:00
}
/* Inline symlink? */
2021-04-13 11:15:11 -07:00
if ( ifp - > if_format = = XFS_DINODE_FMT_LOCAL ) {
2022-07-09 10:56:07 -07:00
if ( len > xfs_inode_data_fork_size ( ip ) | |
2023-12-20 07:34:55 +01:00
len > strnlen ( ifp - > if_data , xfs_inode_data_fork_size ( ip ) ) )
2018-07-19 12:29:11 -07:00
xchk_fblock_set_corrupt ( sc , XFS_DATA_FORK , 0 ) ;
2023-12-15 10:03:35 -08:00
return 0 ;
2017-10-17 21:37:45 -07:00
}
/* Remote symlink; must read the contents. */
2024-02-22 12:45:17 -08:00
error = xfs_symlink_remote_read ( sc - > ip , sc - > buf ) ;
2018-07-19 12:29:11 -07:00
if ( ! xchk_fblock_process_error ( sc , XFS_DATA_FORK , 0 , & error ) )
2023-12-15 10:03:35 -08:00
return error ;
2017-10-17 21:37:45 -07:00
if ( strnlen ( sc - > buf , XFS_SYMLINK_MAXLEN ) < len )
2018-07-19 12:29:11 -07:00
xchk_fblock_set_corrupt ( sc , XFS_DATA_FORK , 0 ) ;
2023-12-15 10:03:35 -08:00
/* If a remote symlink is clean, it is clearly not zapped. */
xchk_mark_healthy_if_clean ( sc , XFS_SICK_INO_SYMLINK_ZAPPED ) ;
return 0 ;
2017-10-17 21:37:45 -07:00
}