Warning: This file is not a C or C++ file. It does not have highlighting.
| 1 | /* SPDX-License-Identifier: GPL-2.0-or-later */ |
|---|---|
| 2 | /* |
| 3 | * Copyright (c) 2021-2024 Oracle. All Rights Reserved. |
| 4 | * Author: Darrick J. Wong <djwong@kernel.org> |
| 5 | */ |
| 6 | #ifndef __XFS_SCRUB_NLINKS_H__ |
| 7 | #define __XFS_SCRUB_NLINKS_H__ |
| 8 | |
| 9 | /* Live link count control structure. */ |
| 10 | struct xchk_nlink_ctrs { |
| 11 | struct xfs_scrub *sc; |
| 12 | |
| 13 | /* Shadow link count data and its mutex. */ |
| 14 | struct xfarray *nlinks; |
| 15 | struct mutex lock; |
| 16 | |
| 17 | /* |
| 18 | * The collection step uses a separate iscan context from the compare |
| 19 | * step because the collection iscan coordinates live updates to the |
| 20 | * observation data while this scanner is running. The compare iscan |
| 21 | * is secondary and can be reinitialized as needed. |
| 22 | */ |
| 23 | struct xchk_iscan collect_iscan; |
| 24 | struct xchk_iscan compare_iscan; |
| 25 | |
| 26 | /* |
| 27 | * Hook into directory updates so that we can receive live updates |
| 28 | * from other writer threads. |
| 29 | */ |
| 30 | struct xfs_dir_hook dhook; |
| 31 | |
| 32 | /* Orphanage reparenting request. */ |
| 33 | struct xrep_adoption adoption; |
| 34 | |
| 35 | /* Directory entry name, plus the trailing null. */ |
| 36 | struct xfs_name xname; |
| 37 | char namebuf[MAXNAMELEN]; |
| 38 | }; |
| 39 | |
| 40 | /* |
| 41 | * In-core link counts for a given inode in the filesystem. |
| 42 | * |
| 43 | * For an empty rootdir, the directory entries and the field to which they are |
| 44 | * accounted are as follows: |
| 45 | * |
| 46 | * Root directory: |
| 47 | * |
| 48 | * . points to self (root.child) |
| 49 | * .. points to self (root.parent) |
| 50 | * f1 points to a child file (f1.parent) |
| 51 | * d1 points to a child dir (d1.parent, root.child) |
| 52 | * |
| 53 | * Subdirectory d1: |
| 54 | * |
| 55 | * . points to self (d1.child) |
| 56 | * .. points to root dir (root.backref) |
| 57 | * f2 points to child file (f2.parent) |
| 58 | * f3 points to root.f1 (f1.parent) |
| 59 | * |
| 60 | * root.nlink == 3 (root.dot, root.dotdot, root.d1) |
| 61 | * d1.nlink == 2 (root.d1, d1.dot) |
| 62 | * f1.nlink == 2 (root.f1, d1.f3) |
| 63 | * f2.nlink == 1 (d1.f2) |
| 64 | */ |
| 65 | struct xchk_nlink { |
| 66 | /* Count of forward links from parent directories to this file. */ |
| 67 | xfs_nlink_t parents; |
| 68 | |
| 69 | /* |
| 70 | * Count of back links to this parent directory from child |
| 71 | * subdirectories. |
| 72 | */ |
| 73 | xfs_nlink_t backrefs; |
| 74 | |
| 75 | /* |
| 76 | * Count of forward links from this directory to all child files and |
| 77 | * the number of dot entries. Should be zero for non-directories. |
| 78 | */ |
| 79 | xfs_nlink_t children; |
| 80 | |
| 81 | /* Record state flags */ |
| 82 | unsigned int flags; |
| 83 | }; |
| 84 | |
| 85 | /* |
| 86 | * This incore link count has been written at least once. We never want to |
| 87 | * store an xchk_nlink that looks uninitialized. |
| 88 | */ |
| 89 | #define XCHK_NLINK_WRITTEN (1U << 0) |
| 90 | |
| 91 | /* Already checked this link count record. */ |
| 92 | #define XCHK_NLINK_COMPARE_SCANNED (1U << 1) |
| 93 | |
| 94 | /* Already made a repair with this link count record. */ |
| 95 | #define XREP_NLINK_DIRTY (1U << 2) |
| 96 | |
| 97 | /* Compute total link count, using large enough variables to detect overflow. */ |
| 98 | static inline uint64_t |
| 99 | xchk_nlink_total(struct xfs_inode *ip, const struct xchk_nlink *live) |
| 100 | { |
| 101 | uint64_t ret = live->parents; |
| 102 | |
| 103 | /* Add one link count for the dot entry of any linked directory. */ |
| 104 | if (ip && S_ISDIR(VFS_I(ip)->i_mode) && VFS_I(ip)->i_nlink) |
| 105 | ret++; |
| 106 | return ret + live->children; |
| 107 | } |
| 108 | |
| 109 | #endif /* __XFS_SCRUB_NLINKS_H__ */ |
| 110 |
Warning: This file is not a C or C++ file. It does not have highlighting.
