dirtree.h 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. /* SPDX-License-Identifier: GPL-2.0-or-later */
  2. /*
  3. * Copyright (c) 2023-2024 Oracle. All Rights Reserved.
  4. * Author: Darrick J. Wong <djwong@kernel.org>
  5. */
  6. #ifndef __XFS_SCRUB_DIRTREE_H__
  7. #define __XFS_SCRUB_DIRTREE_H__
  8. /*
  9. * Each of these represents one parent pointer path step in a chain going
  10. * up towards the directory tree root. These are stored inside an xfarray.
  11. */
  12. struct xchk_dirpath_step {
  13. /* Directory entry name associated with this parent link. */
  14. xfblob_cookie name_cookie;
  15. unsigned int name_len;
  16. /* Handle of the parent directory. */
  17. struct xfs_parent_rec pptr_rec;
  18. };
  19. enum xchk_dirpath_outcome {
  20. XCHK_DIRPATH_SCANNING = 0, /* still being put together */
  21. XCHK_DIRPATH_DELETE, /* delete this path */
  22. XCHK_DIRPATH_CORRUPT, /* corruption detected in path */
  23. XCHK_DIRPATH_LOOP, /* cycle detected further up */
  24. XCHK_DIRPATH_STALE, /* path is stale */
  25. XCHK_DIRPATH_OK, /* path reaches the root */
  26. XREP_DIRPATH_DELETING, /* path is being deleted */
  27. XREP_DIRPATH_DELETED, /* path has been deleted */
  28. XREP_DIRPATH_ADOPTING, /* path is being adopted */
  29. XREP_DIRPATH_ADOPTED, /* path has been adopted */
  30. };
  31. /*
  32. * Each of these represents one parent pointer path out of the directory being
  33. * scanned. These exist in-core, and hopefully there aren't more than a
  34. * handful of them.
  35. */
  36. struct xchk_dirpath {
  37. struct list_head list;
  38. /* Index of the first step in this path. */
  39. xfarray_idx_t first_step;
  40. /* Index of the second step in this path. */
  41. xfarray_idx_t second_step;
  42. /* Inodes seen while walking this path. */
  43. struct xino_bitmap seen_inodes;
  44. /* Number of steps in this path. */
  45. unsigned int nr_steps;
  46. /* Which path is this? */
  47. unsigned int path_nr;
  48. /* What did we conclude from following this path? */
  49. enum xchk_dirpath_outcome outcome;
  50. };
  51. struct xchk_dirtree_outcomes {
  52. /* Number of XCHK_DIRPATH_DELETE */
  53. unsigned int bad;
  54. /* Number of XCHK_DIRPATH_CORRUPT or XCHK_DIRPATH_LOOP */
  55. unsigned int suspect;
  56. /* Number of XCHK_DIRPATH_OK */
  57. unsigned int good;
  58. /* Directory needs to be added to lost+found */
  59. bool needs_adoption;
  60. };
  61. struct xchk_dirtree {
  62. struct xfs_scrub *sc;
  63. /* Root inode that we're looking for. */
  64. xfs_ino_t root_ino;
  65. /*
  66. * This is the inode that we're scanning. The live update hook can
  67. * continue to be called after xchk_teardown drops sc->ip but before
  68. * it calls buf_cleanup, so we keep a copy.
  69. */
  70. xfs_ino_t scan_ino;
  71. /*
  72. * If we start deleting redundant paths to this subdirectory, this is
  73. * the inode number of the surviving parent and the dotdot entry will
  74. * be set to this value. If the value is NULLFSINO, then use @root_ino
  75. * as a stand-in until the orphanage can adopt the subdirectory.
  76. */
  77. xfs_ino_t parent_ino;
  78. /* Scratch buffer for scanning pptr xattrs */
  79. struct xfs_parent_rec pptr_rec;
  80. struct xfs_da_args pptr_args;
  81. /* Name buffer */
  82. struct xfs_name xname;
  83. char namebuf[MAXNAMELEN];
  84. /* Information for reparenting this directory. */
  85. struct xrep_adoption adoption;
  86. /*
  87. * Hook into directory updates so that we can receive live updates
  88. * from other writer threads.
  89. */
  90. struct xfs_dir_hook dhook;
  91. /* Parent pointer update arguments. */
  92. struct xfs_parent_args ppargs;
  93. /* lock for everything below here */
  94. struct mutex lock;
  95. /* buffer for the live update functions to use for dirent names */
  96. struct xfs_name hook_xname;
  97. unsigned char hook_namebuf[MAXNAMELEN];
  98. /*
  99. * All path steps observed during this scan. Each of the path
  100. * steps for a particular pathwalk are recorded in sequential
  101. * order in the xfarray. A pathwalk ends either with a step
  102. * pointing to the root directory (success) or pointing to NULLFSINO
  103. * (loop detected, empty dir detected, etc).
  104. */
  105. struct xfarray *path_steps;
  106. /* All names observed during this scan. */
  107. struct xfblob *path_names;
  108. /* All paths being tracked by this scanner. */
  109. struct list_head path_list;
  110. /* Number of paths in path_list. */
  111. unsigned int nr_paths;
  112. /* Number of parents found by a pptr scan. */
  113. unsigned int parents_found;
  114. /* Have the path data been invalidated by a concurrent update? */
  115. bool stale:1;
  116. /* Has the scan been aborted? */
  117. bool aborted:1;
  118. };
  119. #define xchk_dirtree_for_each_path_safe(dl, path, n) \
  120. list_for_each_entry_safe((path), (n), &(dl)->path_list, list)
  121. #define xchk_dirtree_for_each_path(dl, path) \
  122. list_for_each_entry((path), &(dl)->path_list, list)
  123. static inline bool
  124. xchk_dirtree_parentless(const struct xchk_dirtree *dl)
  125. {
  126. struct xfs_scrub *sc = dl->sc;
  127. if (sc->ip == sc->mp->m_rootip)
  128. return true;
  129. if (VFS_I(sc->ip)->i_nlink == 0)
  130. return true;
  131. return false;
  132. }
  133. int xchk_dirtree_find_paths_to_root(struct xchk_dirtree *dl);
  134. int xchk_dirpath_append(struct xchk_dirtree *dl, struct xfs_inode *ip,
  135. struct xchk_dirpath *path, const struct xfs_name *name,
  136. const struct xfs_parent_rec *pptr);
  137. void xchk_dirtree_evaluate(struct xchk_dirtree *dl,
  138. struct xchk_dirtree_outcomes *oc);
  139. #endif /* __XFS_SCRUB_DIRTREE_H__ */