nlinks.h 2.9 KB

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