/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Copyright ( c ) 2023 - 2024 Oracle . All Rights Reserved .
* Author : Darrick J . Wong < djwong @ kernel . org >
*/
#ifndef __XFS_SCRUB_DIRTREE_H__
#define __XFS_SCRUB_DIRTREE_H__
/*
* Each of these represents one parent pointer path step in a chain going
* up towards the directory tree root . These are stored inside an xfarray .
*/
struct xchk_dirpath_step {
/* Directory entry name associated with this parent link. */
xfblob_cookie name_cookie;
unsigned int name_len;
/* Handle of the parent directory. */
struct xfs_parent_rec pptr_rec;
};
enum xchk_dirpath_outcome {
XCHK_DIRPATH_SCANNING = 0 , /* still being put together */
XCHK_DIRPATH_DELETE, /* delete this path */
XCHK_DIRPATH_CORRUPT, /* corruption detected in path */
XCHK_DIRPATH_LOOP, /* cycle detected further up */
XCHK_DIRPATH_STALE, /* path is stale */
XCHK_DIRPATH_OK, /* path reaches the root */
XREP_DIRPATH_DELETING, /* path is being deleted */
XREP_DIRPATH_DELETED, /* path has been deleted */
XREP_DIRPATH_ADOPTING, /* path is being adopted */
XREP_DIRPATH_ADOPTED, /* path has been adopted */
};
/*
* Each of these represents one parent pointer path out of the directory being
* scanned . These exist in - core , and hopefully there aren ' t more than a
* handful of them .
*/
struct xchk_dirpath {
struct list_head list;
/* Index of the first step in this path. */
xfarray_idx_t first_step;
/* Index of the second step in this path. */
xfarray_idx_t second_step;
/* Inodes seen while walking this path. */
struct xino_bitmap seen_inodes;
/* Number of steps in this path. */
unsigned int nr_steps;
/* Which path is this? */
unsigned int path_nr;
/* What did we conclude from following this path? */
enum xchk_dirpath_outcome outcome;
};
struct xchk_dirtree_outcomes {
/* Number of XCHK_DIRPATH_DELETE */
unsigned int bad;
/* Number of XCHK_DIRPATH_CORRUPT or XCHK_DIRPATH_LOOP */
unsigned int suspect;
/* Number of XCHK_DIRPATH_OK */
unsigned int good;
/* Directory needs to be added to lost+found */
bool needs_adoption;
};
struct xchk_dirtree {
struct xfs_scrub *sc;
/* Root inode that we're looking for. */
xfs_ino_t root_ino;
/*
* This is the inode that we ' re scanning . The live update hook can
* continue to be called after xchk_teardown drops sc - > ip but before
* it calls buf_cleanup , so we keep a copy .
*/
xfs_ino_t scan_ino;
/*
* If we start deleting redundant paths to this subdirectory , this is
* the inode number of the surviving parent and the dotdot entry will
* be set to this value . If the value is NULLFSINO , then use @ root_ino
* as a stand - in until the orphanage can adopt the subdirectory .
*/
xfs_ino_t parent_ino;
/* Scratch buffer for scanning pptr xattrs */
struct xfs_parent_rec pptr_rec;
struct xfs_da_args pptr_args;
/* Name buffer */
struct xfs_name xname;
char namebuf[MAXNAMELEN];
/* Information for reparenting this directory. */
struct xrep_adoption adoption;
/*
* Hook into directory updates so that we can receive live updates
* from other writer threads .
*/
struct xfs_dir_hook dhook;
/* Parent pointer update arguments. */
struct xfs_parent_args ppargs;
/* lock for everything below here */
struct mutex lock;
/* buffer for the live update functions to use for dirent names */
struct xfs_name hook_xname;
unsigned char hook_namebuf[MAXNAMELEN];
/*
* All path steps observed during this scan . Each of the path
* steps for a particular pathwalk are recorded in sequential
* order in the xfarray . A pathwalk ends either with a step
* pointing to the root directory ( success ) or pointing to NULLFSINO
* ( loop detected , empty dir detected , etc ) .
*/
struct xfarray *path_steps;
/* All names observed during this scan. */
struct xfblob *path_names;
/* All paths being tracked by this scanner. */
struct list_head path_list;
/* Number of paths in path_list. */
unsigned int nr_paths;
/* Number of parents found by a pptr scan. */
unsigned int parents_found;
/* Have the path data been invalidated by a concurrent update? */
bool stale:1 ;
/* Has the scan been aborted? */
bool aborted:1 ;
};
#define xchk_dirtree_for_each_path_safe(dl, path, n) \
list_for_each_entry_safe((path), (n), &(dl)->path_list, list)
#define xchk_dirtree_for_each_path(dl, path) \
list_for_each_entry((path), &(dl)->path_list, list)
bool xchk_dirtree_parentless(const struct xchk_dirtree *dl);
int xchk_dirtree_find_paths_to_root(struct xchk_dirtree *dl);
int xchk_dirpath_append(struct xchk_dirtree *dl, struct xfs_inode *ip,
struct xchk_dirpath *path, const struct xfs_name *name,
const struct xfs_parent_rec *pptr);
void xchk_dirtree_evaluate(struct xchk_dirtree *dl,
struct xchk_dirtree_outcomes *oc);
#endif /* __XFS_SCRUB_DIRTREE_H__ */
Messung V0.5 in Prozent C=75 H=100 G=88
¤ Dauer der Verarbeitung: 0.10 Sekunden
(vorverarbeitet am 2026-09-30)
¤
*© Formatika GbR, Deutschland