parent.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Copyright (C) 2017-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_trans_resv.h"
  11. #include "xfs_mount.h"
  12. #include "xfs_log_format.h"
  13. #include "xfs_trans.h"
  14. #include "xfs_inode.h"
  15. #include "xfs_icache.h"
  16. #include "xfs_dir2.h"
  17. #include "xfs_dir2_priv.h"
  18. #include "xfs_attr.h"
  19. #include "xfs_parent.h"
  20. #include "scrub/scrub.h"
  21. #include "scrub/common.h"
  22. #include "scrub/readdir.h"
  23. #include "scrub/tempfile.h"
  24. #include "scrub/repair.h"
  25. #include "scrub/listxattr.h"
  26. #include "scrub/xfile.h"
  27. #include "scrub/xfarray.h"
  28. #include "scrub/xfblob.h"
  29. #include "scrub/trace.h"
  30. /* Set us up to scrub parents. */
  31. int
  32. xchk_setup_parent(
  33. struct xfs_scrub *sc)
  34. {
  35. int error;
  36. if (xchk_could_repair(sc)) {
  37. error = xrep_setup_parent(sc);
  38. if (error)
  39. return error;
  40. }
  41. return xchk_setup_inode_contents(sc, 0);
  42. }
  43. /* Parent pointers */
  44. /* Look for an entry in a parent pointing to this inode. */
  45. struct xchk_parent_ctx {
  46. struct xfs_scrub *sc;
  47. xfs_nlink_t nlink;
  48. };
  49. /* Look for a single entry in a directory pointing to an inode. */
  50. STATIC int
  51. xchk_parent_actor(
  52. struct xfs_scrub *sc,
  53. struct xfs_inode *dp,
  54. xfs_dir2_dataptr_t dapos,
  55. const struct xfs_name *name,
  56. xfs_ino_t ino,
  57. void *priv)
  58. {
  59. struct xchk_parent_ctx *spc = priv;
  60. int error = 0;
  61. /* Does this name make sense? */
  62. if (!xfs_dir2_namecheck(name->name, name->len))
  63. error = -EFSCORRUPTED;
  64. if (!xchk_fblock_xref_process_error(sc, XFS_DATA_FORK, 0, &error))
  65. return error;
  66. if (sc->ip->i_ino == ino)
  67. spc->nlink++;
  68. if (xchk_should_terminate(spc->sc, &error))
  69. return error;
  70. return 0;
  71. }
  72. /*
  73. * Try to lock a parent directory for checking dirents. Returns the inode
  74. * flags for the locks we now hold, or zero if we failed.
  75. */
  76. STATIC unsigned int
  77. xchk_parent_ilock_dir(
  78. struct xfs_inode *dp)
  79. {
  80. if (!xfs_ilock_nowait(dp, XFS_ILOCK_SHARED))
  81. return 0;
  82. if (!xfs_need_iread_extents(&dp->i_df))
  83. return XFS_ILOCK_SHARED;
  84. xfs_iunlock(dp, XFS_ILOCK_SHARED);
  85. if (!xfs_ilock_nowait(dp, XFS_ILOCK_EXCL))
  86. return 0;
  87. return XFS_ILOCK_EXCL;
  88. }
  89. /*
  90. * Given the inode number of the alleged parent of the inode being scrubbed,
  91. * try to validate that the parent has exactly one directory entry pointing
  92. * back to the inode being scrubbed. Returns -EAGAIN if we need to revalidate
  93. * the dotdot entry.
  94. */
  95. STATIC int
  96. xchk_parent_validate(
  97. struct xfs_scrub *sc,
  98. xfs_ino_t parent_ino)
  99. {
  100. struct xchk_parent_ctx spc = {
  101. .sc = sc,
  102. .nlink = 0,
  103. };
  104. struct xfs_mount *mp = sc->mp;
  105. struct xfs_inode *dp = NULL;
  106. xfs_nlink_t expected_nlink;
  107. unsigned int lock_mode;
  108. int error = 0;
  109. /* Is this the root dir? Then '..' must point to itself. */
  110. if (sc->ip == mp->m_rootip) {
  111. if (sc->ip->i_ino != mp->m_sb.sb_rootino ||
  112. sc->ip->i_ino != parent_ino)
  113. xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, 0);
  114. return 0;
  115. }
  116. /* Is this the metadata root dir? Then '..' must point to itself. */
  117. if (sc->ip == mp->m_metadirip) {
  118. if (sc->ip->i_ino != mp->m_sb.sb_metadirino ||
  119. sc->ip->i_ino != parent_ino)
  120. xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, 0);
  121. return 0;
  122. }
  123. /* '..' must not point to ourselves. */
  124. if (sc->ip->i_ino == parent_ino) {
  125. xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, 0);
  126. return 0;
  127. }
  128. /*
  129. * If we're an unlinked directory, the parent /won't/ have a link
  130. * to us. Otherwise, it should have one link.
  131. */
  132. expected_nlink = VFS_I(sc->ip)->i_nlink == 0 ? 0 : 1;
  133. /*
  134. * Grab the parent directory inode. This must be released before we
  135. * cancel the scrub transaction.
  136. *
  137. * If _iget returns -EINVAL or -ENOENT then the parent inode number is
  138. * garbage and the directory is corrupt. If the _iget returns
  139. * -EFSCORRUPTED or -EFSBADCRC then the parent is corrupt which is a
  140. * cross referencing error. Any other error is an operational error.
  141. */
  142. error = xchk_iget(sc, parent_ino, &dp);
  143. if (error == -EINVAL || error == -ENOENT) {
  144. error = -EFSCORRUPTED;
  145. xchk_fblock_process_error(sc, XFS_DATA_FORK, 0, &error);
  146. return error;
  147. }
  148. if (!xchk_fblock_xref_process_error(sc, XFS_DATA_FORK, 0, &error))
  149. return error;
  150. if (dp == sc->ip || xrep_is_tempfile(dp) ||
  151. !S_ISDIR(VFS_I(dp)->i_mode)) {
  152. xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, 0);
  153. goto out_rele;
  154. }
  155. lock_mode = xchk_parent_ilock_dir(dp);
  156. if (!lock_mode) {
  157. xchk_iunlock(sc, XFS_ILOCK_EXCL);
  158. xchk_ilock(sc, XFS_ILOCK_EXCL);
  159. error = -EAGAIN;
  160. goto out_rele;
  161. }
  162. /*
  163. * We cannot yet validate this parent pointer if the directory looks as
  164. * though it has been zapped by the inode record repair code.
  165. */
  166. if (xchk_dir_looks_zapped(dp)) {
  167. error = -EBUSY;
  168. xchk_set_incomplete(sc);
  169. goto out_unlock;
  170. }
  171. /* Metadata and regular inodes cannot cross trees. */
  172. if (xfs_is_metadir_inode(dp) != xfs_is_metadir_inode(sc->ip)) {
  173. xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, 0);
  174. goto out_unlock;
  175. }
  176. /* Look for a directory entry in the parent pointing to the child. */
  177. error = xchk_dir_walk(sc, dp, xchk_parent_actor, &spc);
  178. if (!xchk_fblock_xref_process_error(sc, XFS_DATA_FORK, 0, &error))
  179. goto out_unlock;
  180. /*
  181. * Ensure that the parent has as many links to the child as the child
  182. * thinks it has to the parent.
  183. */
  184. if (spc.nlink != expected_nlink)
  185. xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, 0);
  186. out_unlock:
  187. xfs_iunlock(dp, lock_mode);
  188. out_rele:
  189. xchk_irele(sc, dp);
  190. return error;
  191. }
  192. /*
  193. * Checking of Parent Pointers
  194. * ===========================
  195. *
  196. * On filesystems with directory parent pointers, we check the referential
  197. * integrity by visiting each parent pointer of a child file and checking that
  198. * the directory referenced by the pointer actually has a dirent pointing
  199. * forward to the child file.
  200. */
  201. /* Deferred parent pointer entry that we saved for later. */
  202. struct xchk_pptr {
  203. /* Cookie for retrieval of the pptr name. */
  204. xfblob_cookie name_cookie;
  205. /* Parent pointer record. */
  206. struct xfs_parent_rec pptr_rec;
  207. /* Length of the pptr name. */
  208. uint8_t namelen;
  209. };
  210. struct xchk_pptrs {
  211. struct xfs_scrub *sc;
  212. /* How many parent pointers did we find at the end? */
  213. unsigned long long pptrs_found;
  214. /* Parent of this directory. */
  215. xfs_ino_t parent_ino;
  216. /* Fixed-size array of xchk_pptr structures. */
  217. struct xfarray *pptr_entries;
  218. /* Blobs containing parent pointer names. */
  219. struct xfblob *pptr_names;
  220. /* Scratch buffer for scanning pptr xattrs */
  221. struct xfs_da_args pptr_args;
  222. /* If we've cycled the ILOCK, we must revalidate all deferred pptrs. */
  223. bool need_revalidate;
  224. /* Name buffer */
  225. struct xfs_name xname;
  226. char namebuf[MAXNAMELEN];
  227. };
  228. /* Does this parent pointer match the dotdot entry? */
  229. STATIC int
  230. xchk_parent_scan_dotdot(
  231. struct xfs_scrub *sc,
  232. struct xfs_inode *ip,
  233. unsigned int attr_flags,
  234. const unsigned char *name,
  235. unsigned int namelen,
  236. const void *value,
  237. unsigned int valuelen,
  238. void *priv)
  239. {
  240. struct xchk_pptrs *pp = priv;
  241. xfs_ino_t parent_ino;
  242. int error;
  243. if (!(attr_flags & XFS_ATTR_PARENT))
  244. return 0;
  245. error = xfs_parent_from_attr(sc->mp, attr_flags, name, namelen, value,
  246. valuelen, &parent_ino, NULL);
  247. if (error)
  248. return error;
  249. if (pp->parent_ino == parent_ino)
  250. return -ECANCELED;
  251. return 0;
  252. }
  253. /* Look up the dotdot entry so that we can check it as we walk the pptrs. */
  254. STATIC int
  255. xchk_parent_pptr_and_dotdot(
  256. struct xchk_pptrs *pp)
  257. {
  258. struct xfs_scrub *sc = pp->sc;
  259. int error;
  260. /* Look up '..' */
  261. error = xchk_dir_lookup(sc, sc->ip, &xfs_name_dotdot, &pp->parent_ino);
  262. if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, 0, &error))
  263. return error;
  264. if (!xfs_verify_dir_ino(sc->mp, pp->parent_ino)) {
  265. xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, 0);
  266. return 0;
  267. }
  268. /* Is this the root dir? Then '..' must point to itself. */
  269. if (xchk_inode_is_dirtree_root(sc->ip)) {
  270. if (sc->ip->i_ino != pp->parent_ino)
  271. xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, 0);
  272. return 0;
  273. }
  274. /*
  275. * If this is now an unlinked directory, the dotdot value is
  276. * meaningless as long as it points to a valid inode.
  277. */
  278. if (VFS_I(sc->ip)->i_nlink == 0)
  279. return 0;
  280. if (pp->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
  281. return 0;
  282. /* Otherwise, walk the pptrs again, and check. */
  283. error = xchk_xattr_walk(sc, sc->ip, xchk_parent_scan_dotdot, NULL, pp);
  284. if (error == -ECANCELED) {
  285. /* Found a parent pointer that matches dotdot. */
  286. return 0;
  287. }
  288. if (!error || error == -EFSCORRUPTED) {
  289. /* Found a broken parent pointer or no match. */
  290. xchk_fblock_set_corrupt(sc, XFS_ATTR_FORK, 0);
  291. return 0;
  292. }
  293. return error;
  294. }
  295. /*
  296. * Try to lock a parent directory for checking dirents. Returns the inode
  297. * flags for the locks we now hold, or zero if we failed.
  298. */
  299. STATIC unsigned int
  300. xchk_parent_lock_dir(
  301. struct xfs_scrub *sc,
  302. struct xfs_inode *dp)
  303. {
  304. if (!xfs_ilock_nowait(dp, XFS_IOLOCK_SHARED))
  305. return 0;
  306. if (!xfs_ilock_nowait(dp, XFS_ILOCK_SHARED)) {
  307. xfs_iunlock(dp, XFS_IOLOCK_SHARED);
  308. return 0;
  309. }
  310. if (!xfs_need_iread_extents(&dp->i_df))
  311. return XFS_IOLOCK_SHARED | XFS_ILOCK_SHARED;
  312. xfs_iunlock(dp, XFS_ILOCK_SHARED);
  313. if (!xfs_ilock_nowait(dp, XFS_ILOCK_EXCL)) {
  314. xfs_iunlock(dp, XFS_IOLOCK_SHARED);
  315. return 0;
  316. }
  317. return XFS_IOLOCK_SHARED | XFS_ILOCK_EXCL;
  318. }
  319. /* Check the forward link (dirent) associated with this parent pointer. */
  320. STATIC int
  321. xchk_parent_dirent(
  322. struct xchk_pptrs *pp,
  323. const struct xfs_name *xname,
  324. struct xfs_inode *dp)
  325. {
  326. struct xfs_scrub *sc = pp->sc;
  327. xfs_ino_t child_ino;
  328. int error;
  329. /*
  330. * Use the name attached to this parent pointer to look up the
  331. * directory entry in the alleged parent.
  332. */
  333. error = xchk_dir_lookup(sc, dp, xname, &child_ino);
  334. if (error == -ENOENT) {
  335. xchk_fblock_xref_set_corrupt(sc, XFS_ATTR_FORK, 0);
  336. return 0;
  337. }
  338. if (!xchk_fblock_xref_process_error(sc, XFS_ATTR_FORK, 0, &error))
  339. return error;
  340. /* Does the inode number match? */
  341. if (child_ino != sc->ip->i_ino) {
  342. xchk_fblock_xref_set_corrupt(sc, XFS_ATTR_FORK, 0);
  343. return 0;
  344. }
  345. return 0;
  346. }
  347. /* Try to grab a parent directory. */
  348. STATIC int
  349. xchk_parent_iget(
  350. struct xchk_pptrs *pp,
  351. const struct xfs_parent_rec *pptr,
  352. struct xfs_inode **dpp)
  353. {
  354. struct xfs_scrub *sc = pp->sc;
  355. struct xfs_inode *ip;
  356. xfs_ino_t parent_ino = be64_to_cpu(pptr->p_ino);
  357. int error;
  358. /* Validate inode number. */
  359. error = xfs_dir_ino_validate(sc->mp, parent_ino);
  360. if (error) {
  361. xchk_fblock_set_corrupt(sc, XFS_ATTR_FORK, 0);
  362. return -ECANCELED;
  363. }
  364. error = xchk_iget(sc, parent_ino, &ip);
  365. if (error == -EINVAL || error == -ENOENT) {
  366. xchk_fblock_set_corrupt(sc, XFS_ATTR_FORK, 0);
  367. return -ECANCELED;
  368. }
  369. if (!xchk_fblock_xref_process_error(sc, XFS_ATTR_FORK, 0, &error))
  370. return error;
  371. /* The parent must be a directory. */
  372. if (!S_ISDIR(VFS_I(ip)->i_mode)) {
  373. xchk_fblock_xref_set_corrupt(sc, XFS_ATTR_FORK, 0);
  374. goto out_rele;
  375. }
  376. /* Validate generation number. */
  377. if (VFS_I(ip)->i_generation != be32_to_cpu(pptr->p_gen)) {
  378. xchk_fblock_xref_set_corrupt(sc, XFS_ATTR_FORK, 0);
  379. goto out_rele;
  380. }
  381. *dpp = ip;
  382. return 0;
  383. out_rele:
  384. xchk_irele(sc, ip);
  385. return 0;
  386. }
  387. /*
  388. * Walk an xattr of a file. If this xattr is a parent pointer, follow it up
  389. * to a parent directory and check that the parent has a dirent pointing back
  390. * to us.
  391. */
  392. STATIC int
  393. xchk_parent_scan_attr(
  394. struct xfs_scrub *sc,
  395. struct xfs_inode *ip,
  396. unsigned int attr_flags,
  397. const unsigned char *name,
  398. unsigned int namelen,
  399. const void *value,
  400. unsigned int valuelen,
  401. void *priv)
  402. {
  403. struct xfs_name xname = {
  404. .name = name,
  405. .len = namelen,
  406. };
  407. struct xchk_pptrs *pp = priv;
  408. struct xfs_inode *dp = NULL;
  409. const struct xfs_parent_rec *pptr_rec = value;
  410. xfs_ino_t parent_ino;
  411. unsigned int lockmode;
  412. int error;
  413. if (!(attr_flags & XFS_ATTR_PARENT))
  414. return 0;
  415. error = xfs_parent_from_attr(sc->mp, attr_flags, name, namelen, value,
  416. valuelen, &parent_ino, NULL);
  417. if (error) {
  418. xchk_fblock_set_corrupt(sc, XFS_ATTR_FORK, 0);
  419. return error;
  420. }
  421. /* No self-referential parent pointers. */
  422. if (parent_ino == sc->ip->i_ino) {
  423. xchk_fblock_set_corrupt(sc, XFS_ATTR_FORK, 0);
  424. return -ECANCELED;
  425. }
  426. pp->pptrs_found++;
  427. error = xchk_parent_iget(pp, pptr_rec, &dp);
  428. if (error)
  429. return error;
  430. if (!dp)
  431. return 0;
  432. /* Try to lock the inode. */
  433. lockmode = xchk_parent_lock_dir(sc, dp);
  434. if (!lockmode) {
  435. struct xchk_pptr save_pp = {
  436. .pptr_rec = *pptr_rec, /* struct copy */
  437. .namelen = namelen,
  438. };
  439. /* Couldn't lock the inode, so save the pptr for later. */
  440. trace_xchk_parent_defer(sc->ip, &xname, dp->i_ino);
  441. error = xfblob_storename(pp->pptr_names, &save_pp.name_cookie,
  442. &xname);
  443. if (!xchk_fblock_xref_process_error(sc, XFS_ATTR_FORK, 0,
  444. &error))
  445. goto out_rele;
  446. error = xfarray_append(pp->pptr_entries, &save_pp);
  447. if (!xchk_fblock_xref_process_error(sc, XFS_ATTR_FORK, 0,
  448. &error))
  449. goto out_rele;
  450. goto out_rele;
  451. }
  452. error = xchk_parent_dirent(pp, &xname, dp);
  453. if (error)
  454. goto out_unlock;
  455. out_unlock:
  456. xfs_iunlock(dp, lockmode);
  457. out_rele:
  458. xchk_irele(sc, dp);
  459. return error;
  460. }
  461. /*
  462. * Revalidate a parent pointer that we collected in the past but couldn't check
  463. * because of lock contention. Returns 0 if the parent pointer is still valid,
  464. * -ENOENT if it has gone away on us, or a negative errno.
  465. */
  466. STATIC int
  467. xchk_parent_revalidate_pptr(
  468. struct xchk_pptrs *pp,
  469. const struct xfs_name *xname,
  470. struct xfs_parent_rec *pptr)
  471. {
  472. struct xfs_scrub *sc = pp->sc;
  473. int error;
  474. error = xfs_parent_lookup(sc->tp, sc->ip, xname, pptr, &pp->pptr_args);
  475. if (error == -ENOATTR) {
  476. /* Parent pointer went away, nothing to revalidate. */
  477. return -ENOENT;
  478. }
  479. return error;
  480. }
  481. /*
  482. * Check a parent pointer the slow way, which means we cycle locks a bunch
  483. * and put up with revalidation until we get it done.
  484. */
  485. STATIC int
  486. xchk_parent_slow_pptr(
  487. struct xchk_pptrs *pp,
  488. const struct xfs_name *xname,
  489. struct xfs_parent_rec *pptr)
  490. {
  491. struct xfs_scrub *sc = pp->sc;
  492. struct xfs_inode *dp = NULL;
  493. unsigned int lockmode;
  494. int error;
  495. /* Check that the deferred parent pointer still exists. */
  496. if (pp->need_revalidate) {
  497. error = xchk_parent_revalidate_pptr(pp, xname, pptr);
  498. if (error == -ENOENT)
  499. return 0;
  500. if (!xchk_fblock_xref_process_error(sc, XFS_ATTR_FORK, 0,
  501. &error))
  502. return error;
  503. }
  504. error = xchk_parent_iget(pp, pptr, &dp);
  505. if (error)
  506. return error;
  507. if (!dp)
  508. return 0;
  509. /*
  510. * If we can grab both IOLOCK and ILOCK of the alleged parent, we
  511. * can proceed with the validation.
  512. */
  513. lockmode = xchk_parent_lock_dir(sc, dp);
  514. if (lockmode) {
  515. trace_xchk_parent_slowpath(sc->ip, xname, dp->i_ino);
  516. goto check_dirent;
  517. }
  518. /*
  519. * We couldn't lock the parent dir. Drop all the locks and try to
  520. * get them again, one at a time.
  521. */
  522. xchk_iunlock(sc, sc->ilock_flags);
  523. pp->need_revalidate = true;
  524. trace_xchk_parent_ultraslowpath(sc->ip, xname, dp->i_ino);
  525. error = xchk_dir_trylock_for_pptrs(sc, dp, &lockmode);
  526. if (error)
  527. goto out_rele;
  528. /* Revalidate the parent pointer now that we cycled locks. */
  529. error = xchk_parent_revalidate_pptr(pp, xname, pptr);
  530. if (error == -ENOENT) {
  531. error = 0;
  532. goto out_unlock;
  533. }
  534. if (!xchk_fblock_xref_process_error(sc, XFS_ATTR_FORK, 0, &error))
  535. goto out_unlock;
  536. check_dirent:
  537. error = xchk_parent_dirent(pp, xname, dp);
  538. out_unlock:
  539. xfs_iunlock(dp, lockmode);
  540. out_rele:
  541. xchk_irele(sc, dp);
  542. return error;
  543. }
  544. /* Check all the parent pointers that we deferred the first time around. */
  545. STATIC int
  546. xchk_parent_finish_slow_pptrs(
  547. struct xchk_pptrs *pp)
  548. {
  549. xfarray_idx_t array_cur;
  550. int error;
  551. foreach_xfarray_idx(pp->pptr_entries, array_cur) {
  552. struct xchk_pptr pptr;
  553. if (pp->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
  554. return 0;
  555. error = xfarray_load(pp->pptr_entries, array_cur, &pptr);
  556. if (error)
  557. return error;
  558. error = xfblob_loadname(pp->pptr_names, pptr.name_cookie,
  559. &pp->xname, pptr.namelen);
  560. if (error)
  561. return error;
  562. error = xchk_parent_slow_pptr(pp, &pp->xname, &pptr.pptr_rec);
  563. if (error)
  564. return error;
  565. }
  566. /* Empty out both xfiles now that we've checked everything. */
  567. xfarray_truncate(pp->pptr_entries);
  568. xfblob_truncate(pp->pptr_names);
  569. return 0;
  570. }
  571. /* Count the number of parent pointers. */
  572. STATIC int
  573. xchk_parent_count_pptr(
  574. struct xfs_scrub *sc,
  575. struct xfs_inode *ip,
  576. unsigned int attr_flags,
  577. const unsigned char *name,
  578. unsigned int namelen,
  579. const void *value,
  580. unsigned int valuelen,
  581. void *priv)
  582. {
  583. struct xchk_pptrs *pp = priv;
  584. int error;
  585. if (!(attr_flags & XFS_ATTR_PARENT))
  586. return 0;
  587. error = xfs_parent_from_attr(sc->mp, attr_flags, name, namelen, value,
  588. valuelen, NULL, NULL);
  589. if (error)
  590. return error;
  591. pp->pptrs_found++;
  592. return 0;
  593. }
  594. /*
  595. * Compare the number of parent pointers to the link count. For
  596. * non-directories these should be the same. For unlinked directories the
  597. * count should be zero; for linked directories, it should be nonzero.
  598. */
  599. STATIC int
  600. xchk_parent_count_pptrs(
  601. struct xchk_pptrs *pp)
  602. {
  603. struct xfs_scrub *sc = pp->sc;
  604. int error;
  605. /*
  606. * If we cycled the ILOCK while cross-checking parent pointers with
  607. * dirents, then we need to recalculate the number of parent pointers.
  608. */
  609. if (pp->need_revalidate) {
  610. pp->pptrs_found = 0;
  611. error = xchk_xattr_walk(sc, sc->ip, xchk_parent_count_pptr,
  612. NULL, pp);
  613. if (error == -EFSCORRUPTED) {
  614. /* Found a bad parent pointer */
  615. xchk_fblock_set_corrupt(sc, XFS_ATTR_FORK, 0);
  616. return 0;
  617. }
  618. if (error)
  619. return error;
  620. }
  621. if (S_ISDIR(VFS_I(sc->ip)->i_mode)) {
  622. if (xchk_inode_is_dirtree_root(sc->ip))
  623. pp->pptrs_found++;
  624. if (VFS_I(sc->ip)->i_nlink == 0 && pp->pptrs_found > 0)
  625. xchk_ino_set_corrupt(sc, sc->ip->i_ino);
  626. else if (VFS_I(sc->ip)->i_nlink > 0 &&
  627. pp->pptrs_found == 0)
  628. xchk_ino_set_corrupt(sc, sc->ip->i_ino);
  629. } else {
  630. /*
  631. * Starting with metadir, we allow checking of parent pointers
  632. * of non-directory files that are children of the superblock.
  633. * Pretend that we found a parent pointer attr.
  634. */
  635. if (xfs_has_metadir(sc->mp) && xchk_inode_is_sb_rooted(sc->ip))
  636. pp->pptrs_found++;
  637. if (VFS_I(sc->ip)->i_nlink != pp->pptrs_found)
  638. xchk_ino_set_corrupt(sc, sc->ip->i_ino);
  639. }
  640. return 0;
  641. }
  642. /* Check parent pointers of a file. */
  643. STATIC int
  644. xchk_parent_pptr(
  645. struct xfs_scrub *sc)
  646. {
  647. struct xchk_pptrs *pp;
  648. int error;
  649. pp = kvzalloc_obj(struct xchk_pptrs, XCHK_GFP_FLAGS);
  650. if (!pp)
  651. return -ENOMEM;
  652. pp->sc = sc;
  653. pp->xname.name = pp->namebuf;
  654. /*
  655. * Set up some staging memory for parent pointers that we can't check
  656. * due to locking contention.
  657. */
  658. error = xfarray_create("slow parent pointer entries", 0,
  659. sizeof(struct xchk_pptr), &pp->pptr_entries);
  660. if (error)
  661. goto out_pp;
  662. error = xfblob_create("slow parent pointer names", &pp->pptr_names);
  663. if (error)
  664. goto out_entries;
  665. error = xchk_xattr_walk(sc, sc->ip, xchk_parent_scan_attr, NULL, pp);
  666. if (error == -ECANCELED) {
  667. error = 0;
  668. goto out_names;
  669. }
  670. if (error)
  671. goto out_names;
  672. error = xchk_parent_finish_slow_pptrs(pp);
  673. if (error == -ETIMEDOUT) {
  674. /* Couldn't grab a lock, scrub was marked incomplete */
  675. error = 0;
  676. goto out_names;
  677. }
  678. if (error)
  679. goto out_names;
  680. if (pp->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
  681. goto out_names;
  682. /*
  683. * For subdirectories, make sure the dotdot entry references the same
  684. * inode as the parent pointers.
  685. *
  686. * If we're scanning a /consistent/ directory, there should only be
  687. * one parent pointer, and it should point to the same directory as
  688. * the dotdot entry.
  689. *
  690. * However, a corrupt directory tree might feature a subdirectory with
  691. * multiple parents. The directory loop scanner is responsible for
  692. * correcting that kind of problem, so for now we only validate that
  693. * the dotdot entry matches /one/ of the parents.
  694. */
  695. if (S_ISDIR(VFS_I(sc->ip)->i_mode)) {
  696. error = xchk_parent_pptr_and_dotdot(pp);
  697. if (error)
  698. goto out_names;
  699. }
  700. if (pp->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
  701. goto out_names;
  702. /*
  703. * Complain if the number of parent pointers doesn't match the link
  704. * count. This could be a sign of missing parent pointers (or an
  705. * incorrect link count).
  706. */
  707. error = xchk_parent_count_pptrs(pp);
  708. if (error)
  709. goto out_names;
  710. out_names:
  711. xfblob_destroy(pp->pptr_names);
  712. out_entries:
  713. xfarray_destroy(pp->pptr_entries);
  714. out_pp:
  715. kvfree(pp);
  716. return error;
  717. }
  718. /* Scrub a parent pointer. */
  719. int
  720. xchk_parent(
  721. struct xfs_scrub *sc)
  722. {
  723. struct xfs_mount *mp = sc->mp;
  724. xfs_ino_t parent_ino;
  725. int error = 0;
  726. if (xfs_has_parent(mp))
  727. return xchk_parent_pptr(sc);
  728. /*
  729. * If we're a directory, check that the '..' link points up to
  730. * a directory that has one entry pointing to us.
  731. */
  732. if (!S_ISDIR(VFS_I(sc->ip)->i_mode))
  733. return -ENOENT;
  734. /* We're not a special inode, are we? */
  735. if (!xfs_verify_dir_ino(mp, sc->ip->i_ino)) {
  736. xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, 0);
  737. return 0;
  738. }
  739. do {
  740. if (xchk_should_terminate(sc, &error))
  741. break;
  742. /* Look up '..' */
  743. error = xchk_dir_lookup(sc, sc->ip, &xfs_name_dotdot,
  744. &parent_ino);
  745. if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, 0, &error))
  746. return error;
  747. if (!xfs_verify_dir_ino(mp, parent_ino)) {
  748. xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, 0);
  749. return 0;
  750. }
  751. /*
  752. * Check that the dotdot entry points to a parent directory
  753. * containing a dirent pointing to this subdirectory.
  754. */
  755. error = xchk_parent_validate(sc, parent_ino);
  756. } while (error == -EAGAIN);
  757. if (error == -EBUSY) {
  758. /*
  759. * We could not scan a directory, so we marked the check
  760. * incomplete. No further error return is necessary.
  761. */
  762. return 0;
  763. }
  764. return error;
  765. }
  766. /*
  767. * Decide if this file's extended attributes (and therefore its parent
  768. * pointers) have been zapped to satisfy the inode and ifork verifiers.
  769. * Checking and repairing should be postponed until the extended attribute
  770. * structure is fixed.
  771. */
  772. bool
  773. xchk_pptr_looks_zapped(
  774. struct xfs_inode *ip)
  775. {
  776. struct inode *inode = VFS_I(ip);
  777. ASSERT(xfs_has_parent(ip->i_mount));
  778. /*
  779. * Temporary files that cannot be linked into the directory tree do not
  780. * have attr forks because they cannot ever have parents.
  781. */
  782. if (inode->i_nlink == 0 && !(inode_state_read_once(inode) & I_LINKABLE))
  783. return false;
  784. /*
  785. * Directory tree roots do not have parents, so the expected outcome
  786. * of a parent pointer scan is always the empty set. It's safe to scan
  787. * them even if the attr fork was zapped.
  788. */
  789. if (xchk_inode_is_dirtree_root(ip))
  790. return false;
  791. /*
  792. * Metadata inodes that are rooted in the superblock do not have any
  793. * parents. Hence the attr fork will not be initialized, but there are
  794. * no parent pointers that might have been zapped.
  795. */
  796. if (xchk_inode_is_sb_rooted(ip))
  797. return false;
  798. /*
  799. * Linked and linkable non-rootdir files should always have an
  800. * attribute fork because that is where parent pointers are
  801. * stored. If the fork is absent, something is amiss.
  802. */
  803. if (!xfs_inode_has_attr_fork(ip))
  804. return true;
  805. /* Repair zapped this file's attr fork a short time ago */
  806. if (xfs_ifork_zapped(ip, XFS_ATTR_FORK))
  807. return true;
  808. /*
  809. * If the dinode repair found a bad attr fork, it will reset the fork
  810. * to extents format with zero records and wait for the bmapbta
  811. * scrubber to reconstruct the block mappings. The extended attribute
  812. * structure always contain some content when parent pointers are
  813. * enabled, so this is a clear sign of a zapped attr fork.
  814. */
  815. return ip->i_af.if_format == XFS_DINODE_FMT_EXTENTS &&
  816. ip->i_af.if_nextents == 0;
  817. }