readdir.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Copyright (C) 2022-2023 Oracle. All Rights Reserved.
  4. * Author: Darrick J. Wong <djwong@kernel.org>
  5. */
  6. #include "xfs_platform.h"
  7. #include "xfs_fs.h"
  8. #include "xfs_shared.h"
  9. #include "xfs_format.h"
  10. #include "xfs_log_format.h"
  11. #include "xfs_trans_resv.h"
  12. #include "xfs_mount.h"
  13. #include "xfs_inode.h"
  14. #include "xfs_dir2.h"
  15. #include "xfs_dir2_priv.h"
  16. #include "xfs_trace.h"
  17. #include "xfs_bmap.h"
  18. #include "xfs_trans.h"
  19. #include "xfs_error.h"
  20. #include "scrub/scrub.h"
  21. #include "scrub/common.h"
  22. #include "scrub/readdir.h"
  23. /* Call a function for every entry in a shortform directory. */
  24. STATIC int
  25. xchk_dir_walk_sf(
  26. struct xfs_scrub *sc,
  27. struct xfs_inode *dp,
  28. xchk_dirent_fn dirent_fn,
  29. void *priv)
  30. {
  31. struct xfs_name name = {
  32. .name = ".",
  33. .len = 1,
  34. .type = XFS_DIR3_FT_DIR,
  35. };
  36. struct xfs_mount *mp = dp->i_mount;
  37. struct xfs_da_geometry *geo = mp->m_dir_geo;
  38. struct xfs_dir2_sf_entry *sfep;
  39. struct xfs_dir2_sf_hdr *sfp = dp->i_df.if_data;
  40. xfs_ino_t ino;
  41. xfs_dir2_dataptr_t dapos;
  42. unsigned int i;
  43. int error;
  44. ASSERT(dp->i_df.if_bytes == dp->i_disk_size);
  45. ASSERT(sfp != NULL);
  46. /* dot entry */
  47. dapos = xfs_dir2_db_off_to_dataptr(geo, geo->datablk,
  48. geo->data_entry_offset);
  49. error = dirent_fn(sc, dp, dapos, &name, dp->i_ino, priv);
  50. if (error)
  51. return error;
  52. /* dotdot entry */
  53. dapos = xfs_dir2_db_off_to_dataptr(geo, geo->datablk,
  54. geo->data_entry_offset +
  55. xfs_dir2_data_entsize(mp, sizeof(".") - 1));
  56. ino = xfs_dir2_sf_get_parent_ino(sfp);
  57. name.name = "..";
  58. name.len = 2;
  59. error = dirent_fn(sc, dp, dapos, &name, ino, priv);
  60. if (error)
  61. return error;
  62. /* iterate everything else */
  63. sfep = xfs_dir2_sf_firstentry(sfp);
  64. for (i = 0; i < sfp->count; i++) {
  65. dapos = xfs_dir2_db_off_to_dataptr(geo, geo->datablk,
  66. xfs_dir2_sf_get_offset(sfep));
  67. ino = xfs_dir2_sf_get_ino(mp, sfp, sfep);
  68. name.name = sfep->name;
  69. name.len = sfep->namelen;
  70. name.type = xfs_dir2_sf_get_ftype(mp, sfep);
  71. error = dirent_fn(sc, dp, dapos, &name, ino, priv);
  72. if (error)
  73. return error;
  74. sfep = xfs_dir2_sf_nextentry(mp, sfp, sfep);
  75. }
  76. return 0;
  77. }
  78. /* Call a function for every entry in a block directory. */
  79. STATIC int
  80. xchk_dir_walk_block(
  81. struct xfs_scrub *sc,
  82. struct xfs_inode *dp,
  83. xchk_dirent_fn dirent_fn,
  84. void *priv)
  85. {
  86. struct xfs_mount *mp = dp->i_mount;
  87. struct xfs_da_geometry *geo = mp->m_dir_geo;
  88. struct xfs_buf *bp;
  89. unsigned int off, next_off, end;
  90. int error;
  91. error = xfs_dir3_block_read(sc->tp, dp, dp->i_ino, &bp);
  92. if (error)
  93. return error;
  94. /* Walk each directory entry. */
  95. end = xfs_dir3_data_end_offset(geo, bp->b_addr);
  96. for (off = geo->data_entry_offset; off < end; off = next_off) {
  97. struct xfs_name name = { };
  98. struct xfs_dir2_data_unused *dup = bp->b_addr + off;
  99. struct xfs_dir2_data_entry *dep = bp->b_addr + off;
  100. xfs_ino_t ino;
  101. xfs_dir2_dataptr_t dapos;
  102. /* Skip an empty entry. */
  103. if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) {
  104. next_off = off + be16_to_cpu(dup->length);
  105. continue;
  106. }
  107. /* Otherwise, find the next entry and report it. */
  108. next_off = off + xfs_dir2_data_entsize(mp, dep->namelen);
  109. if (next_off > end)
  110. break;
  111. dapos = xfs_dir2_db_off_to_dataptr(geo, geo->datablk, off);
  112. ino = be64_to_cpu(dep->inumber);
  113. name.name = dep->name;
  114. name.len = dep->namelen;
  115. name.type = xfs_dir2_data_get_ftype(mp, dep);
  116. error = dirent_fn(sc, dp, dapos, &name, ino, priv);
  117. if (error)
  118. break;
  119. }
  120. xfs_trans_brelse(sc->tp, bp);
  121. return error;
  122. }
  123. /* Read a leaf-format directory buffer. */
  124. STATIC int
  125. xchk_read_leaf_dir_buf(
  126. struct xfs_trans *tp,
  127. struct xfs_inode *dp,
  128. struct xfs_da_geometry *geo,
  129. xfs_dir2_off_t *curoff,
  130. struct xfs_buf **bpp)
  131. {
  132. struct xfs_iext_cursor icur;
  133. struct xfs_bmbt_irec map;
  134. struct xfs_ifork *ifp = xfs_ifork_ptr(dp, XFS_DATA_FORK);
  135. xfs_dablk_t last_da;
  136. xfs_dablk_t map_off;
  137. xfs_dir2_off_t new_off;
  138. *bpp = NULL;
  139. /*
  140. * Look for mapped directory blocks at or above the current offset.
  141. * Truncate down to the nearest directory block to start the scanning
  142. * operation.
  143. */
  144. last_da = xfs_dir2_byte_to_da(geo, XFS_DIR2_LEAF_OFFSET);
  145. map_off = xfs_dir2_db_to_da(geo, xfs_dir2_byte_to_db(geo, *curoff));
  146. if (!xfs_iext_lookup_extent(dp, ifp, map_off, &icur, &map))
  147. return 0;
  148. if (map.br_startoff >= last_da)
  149. return 0;
  150. xfs_trim_extent(&map, map_off, last_da - map_off);
  151. /* Read the directory block of that first mapping. */
  152. new_off = xfs_dir2_da_to_byte(geo, map.br_startoff);
  153. if (new_off > *curoff)
  154. *curoff = new_off;
  155. return xfs_dir3_data_read(tp, dp, dp->i_ino, map.br_startoff, 0, bpp);
  156. }
  157. /* Call a function for every entry in a leaf directory. */
  158. STATIC int
  159. xchk_dir_walk_leaf(
  160. struct xfs_scrub *sc,
  161. struct xfs_inode *dp,
  162. xchk_dirent_fn dirent_fn,
  163. void *priv)
  164. {
  165. struct xfs_mount *mp = dp->i_mount;
  166. struct xfs_da_geometry *geo = mp->m_dir_geo;
  167. struct xfs_buf *bp = NULL;
  168. xfs_dir2_off_t curoff = 0;
  169. unsigned int offset = 0;
  170. int error;
  171. /* Iterate every directory offset in this directory. */
  172. while (curoff < XFS_DIR2_LEAF_OFFSET) {
  173. struct xfs_name name = { };
  174. struct xfs_dir2_data_unused *dup;
  175. struct xfs_dir2_data_entry *dep;
  176. xfs_ino_t ino;
  177. unsigned int length;
  178. xfs_dir2_dataptr_t dapos;
  179. /*
  180. * If we have no buffer, or we're off the end of the
  181. * current buffer, need to get another one.
  182. */
  183. if (!bp || offset >= geo->blksize) {
  184. if (bp) {
  185. xfs_trans_brelse(sc->tp, bp);
  186. bp = NULL;
  187. }
  188. error = xchk_read_leaf_dir_buf(sc->tp, dp, geo, &curoff,
  189. &bp);
  190. if (error || !bp)
  191. break;
  192. /*
  193. * Find our position in the block.
  194. */
  195. offset = geo->data_entry_offset;
  196. curoff += geo->data_entry_offset;
  197. }
  198. /* Skip an empty entry. */
  199. dup = bp->b_addr + offset;
  200. if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) {
  201. length = be16_to_cpu(dup->length);
  202. offset += length;
  203. curoff += length;
  204. continue;
  205. }
  206. /* Otherwise, find the next entry and report it. */
  207. dep = bp->b_addr + offset;
  208. length = xfs_dir2_data_entsize(mp, dep->namelen);
  209. dapos = xfs_dir2_byte_to_dataptr(curoff) & 0x7fffffff;
  210. ino = be64_to_cpu(dep->inumber);
  211. name.name = dep->name;
  212. name.len = dep->namelen;
  213. name.type = xfs_dir2_data_get_ftype(mp, dep);
  214. error = dirent_fn(sc, dp, dapos, &name, ino, priv);
  215. if (error)
  216. break;
  217. /* Advance to the next entry. */
  218. offset += length;
  219. curoff += length;
  220. }
  221. if (bp)
  222. xfs_trans_brelse(sc->tp, bp);
  223. return error;
  224. }
  225. /*
  226. * Call a function for every entry in a directory.
  227. *
  228. * Callers must hold the ILOCK. File types are XFS_DIR3_FT_*.
  229. */
  230. int
  231. xchk_dir_walk(
  232. struct xfs_scrub *sc,
  233. struct xfs_inode *dp,
  234. xchk_dirent_fn dirent_fn,
  235. void *priv)
  236. {
  237. struct xfs_da_args args = {
  238. .dp = dp,
  239. .geo = dp->i_mount->m_dir_geo,
  240. .trans = sc->tp,
  241. .owner = dp->i_ino,
  242. };
  243. int error;
  244. if (xfs_is_shutdown(dp->i_mount))
  245. return -EIO;
  246. ASSERT(S_ISDIR(VFS_I(dp)->i_mode));
  247. xfs_assert_ilocked(dp, XFS_ILOCK_SHARED | XFS_ILOCK_EXCL);
  248. switch (xfs_dir2_format(&args, &error)) {
  249. case XFS_DIR2_FMT_SF:
  250. return xchk_dir_walk_sf(sc, dp, dirent_fn, priv);
  251. case XFS_DIR2_FMT_BLOCK:
  252. return xchk_dir_walk_block(sc, dp, dirent_fn, priv);
  253. case XFS_DIR2_FMT_LEAF:
  254. case XFS_DIR2_FMT_NODE:
  255. return xchk_dir_walk_leaf(sc, dp, dirent_fn, priv);
  256. default:
  257. return error;
  258. }
  259. }
  260. /*
  261. * Look up the inode number for an exact name in a directory.
  262. *
  263. * Callers must hold the ILOCK. File types are XFS_DIR3_FT_*. Names are not
  264. * checked for correctness.
  265. */
  266. int
  267. xchk_dir_lookup(
  268. struct xfs_scrub *sc,
  269. struct xfs_inode *dp,
  270. const struct xfs_name *name,
  271. xfs_ino_t *ino)
  272. {
  273. struct xfs_da_args args = {
  274. .dp = dp,
  275. .geo = dp->i_mount->m_dir_geo,
  276. .trans = sc->tp,
  277. .name = name->name,
  278. .namelen = name->len,
  279. .filetype = name->type,
  280. .hashval = xfs_dir2_hashname(dp->i_mount, name),
  281. .whichfork = XFS_DATA_FORK,
  282. .op_flags = XFS_DA_OP_OKNOENT,
  283. .owner = dp->i_ino,
  284. };
  285. int error;
  286. if (xfs_is_shutdown(dp->i_mount))
  287. return -EIO;
  288. /*
  289. * A temporary directory's block headers are written with the owner
  290. * set to sc->ip, so we must switch the owner here for the lookup.
  291. */
  292. if (dp == sc->tempip)
  293. args.owner = sc->ip->i_ino;
  294. ASSERT(S_ISDIR(VFS_I(dp)->i_mode));
  295. xfs_assert_ilocked(dp, XFS_ILOCK_SHARED | XFS_ILOCK_EXCL);
  296. error = xfs_dir_lookup_args(&args);
  297. if (!error)
  298. *ino = args.inumber;
  299. return error;
  300. }
  301. /*
  302. * Try to grab the IOLOCK and ILOCK of sc->ip and ip, returning @ip's lock
  303. * state. The caller may have a transaction, so we must use trylock for both
  304. * IOLOCKs.
  305. */
  306. static inline unsigned int
  307. xchk_dir_trylock_both(
  308. struct xfs_scrub *sc,
  309. struct xfs_inode *ip)
  310. {
  311. if (!xchk_ilock_nowait(sc, XFS_IOLOCK_EXCL))
  312. return 0;
  313. if (!xfs_ilock_nowait(ip, XFS_IOLOCK_SHARED))
  314. goto parent_iolock;
  315. xchk_ilock(sc, XFS_ILOCK_EXCL);
  316. if (!xfs_ilock_nowait(ip, XFS_ILOCK_EXCL))
  317. goto parent_ilock;
  318. return XFS_IOLOCK_SHARED | XFS_ILOCK_EXCL;
  319. parent_ilock:
  320. xchk_iunlock(sc, XFS_ILOCK_EXCL);
  321. xfs_iunlock(ip, XFS_IOLOCK_SHARED);
  322. parent_iolock:
  323. xchk_iunlock(sc, XFS_IOLOCK_EXCL);
  324. return 0;
  325. }
  326. /*
  327. * Try for a limited time to grab the IOLOCK and ILOCK of both the scrub target
  328. * (@sc->ip) and the inode at the other end (@ip) of a directory or parent
  329. * pointer link so that we can check that link.
  330. *
  331. * We do not know ahead of time that the directory tree is /not/ corrupt, so we
  332. * cannot use the "lock two inode" functions because we do not know that there
  333. * is not a racing thread trying to take the locks in opposite order. First
  334. * take IOLOCK_EXCL of the scrub target, and then try to take IOLOCK_SHARED
  335. * of @ip to synchronize with the VFS. Next, take ILOCK_EXCL of the scrub
  336. * target and @ip to synchronize with XFS.
  337. *
  338. * If the trylocks succeed, *lockmode will be set to the locks held for @ip;
  339. * @sc->ilock_flags will be set for the locks held for @sc->ip; and zero will
  340. * be returned. If not, returns -EDEADLOCK to try again; or -ETIMEDOUT if
  341. * XCHK_TRY_HARDER was set. Returns -EINTR if the process has been killed.
  342. */
  343. int
  344. xchk_dir_trylock_for_pptrs(
  345. struct xfs_scrub *sc,
  346. struct xfs_inode *ip,
  347. unsigned int *lockmode)
  348. {
  349. unsigned int nr;
  350. int error = 0;
  351. ASSERT(sc->ilock_flags == 0);
  352. for (nr = 0; nr < HZ; nr++) {
  353. *lockmode = xchk_dir_trylock_both(sc, ip);
  354. if (*lockmode)
  355. return 0;
  356. if (xchk_should_terminate(sc, &error))
  357. return error;
  358. delay(1);
  359. }
  360. if (sc->flags & XCHK_TRY_HARDER) {
  361. xchk_set_incomplete(sc);
  362. return -ETIMEDOUT;
  363. }
  364. return -EDEADLOCK;
  365. }