inode.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633
  1. /*
  2. * Copyright (C) 2017 Oracle. All Rights Reserved.
  3. *
  4. * Author: Darrick J. Wong <darrick.wong@oracle.com>
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public License
  8. * as published by the Free Software Foundation; either version 2
  9. * of the License, or (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it would be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, write the Free Software Foundation,
  18. * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
  19. */
  20. #include "xfs.h"
  21. #include "xfs_fs.h"
  22. #include "xfs_shared.h"
  23. #include "xfs_format.h"
  24. #include "xfs_trans_resv.h"
  25. #include "xfs_mount.h"
  26. #include "xfs_defer.h"
  27. #include "xfs_btree.h"
  28. #include "xfs_bit.h"
  29. #include "xfs_log_format.h"
  30. #include "xfs_trans.h"
  31. #include "xfs_sb.h"
  32. #include "xfs_inode.h"
  33. #include "xfs_icache.h"
  34. #include "xfs_inode_buf.h"
  35. #include "xfs_inode_fork.h"
  36. #include "xfs_ialloc.h"
  37. #include "xfs_da_format.h"
  38. #include "xfs_reflink.h"
  39. #include "scrub/xfs_scrub.h"
  40. #include "scrub/scrub.h"
  41. #include "scrub/common.h"
  42. #include "scrub/trace.h"
  43. /*
  44. * Grab total control of the inode metadata. It doesn't matter here if
  45. * the file data is still changing; exclusive access to the metadata is
  46. * the goal.
  47. */
  48. int
  49. xfs_scrub_setup_inode(
  50. struct xfs_scrub_context *sc,
  51. struct xfs_inode *ip)
  52. {
  53. struct xfs_mount *mp = sc->mp;
  54. int error;
  55. /*
  56. * Try to get the inode. If the verifiers fail, we try again
  57. * in raw mode.
  58. */
  59. error = xfs_scrub_get_inode(sc, ip);
  60. switch (error) {
  61. case 0:
  62. break;
  63. case -EFSCORRUPTED:
  64. case -EFSBADCRC:
  65. return xfs_scrub_trans_alloc(sc->sm, mp, &sc->tp);
  66. default:
  67. return error;
  68. }
  69. /* Got the inode, lock it and we're ready to go. */
  70. sc->ilock_flags = XFS_IOLOCK_EXCL | XFS_MMAPLOCK_EXCL;
  71. xfs_ilock(sc->ip, sc->ilock_flags);
  72. error = xfs_scrub_trans_alloc(sc->sm, mp, &sc->tp);
  73. if (error)
  74. goto out;
  75. sc->ilock_flags |= XFS_ILOCK_EXCL;
  76. xfs_ilock(sc->ip, XFS_ILOCK_EXCL);
  77. out:
  78. /* scrub teardown will unlock and release the inode for us */
  79. return error;
  80. }
  81. /* Inode core */
  82. /*
  83. * Validate di_extsize hint.
  84. *
  85. * The rules are documented at xfs_ioctl_setattr_check_extsize().
  86. * These functions must be kept in sync with each other.
  87. */
  88. STATIC void
  89. xfs_scrub_inode_extsize(
  90. struct xfs_scrub_context *sc,
  91. struct xfs_buf *bp,
  92. struct xfs_dinode *dip,
  93. xfs_ino_t ino,
  94. uint16_t mode,
  95. uint16_t flags)
  96. {
  97. struct xfs_mount *mp = sc->mp;
  98. bool rt_flag;
  99. bool hint_flag;
  100. bool inherit_flag;
  101. uint32_t extsize;
  102. uint32_t extsize_bytes;
  103. uint32_t blocksize_bytes;
  104. rt_flag = (flags & XFS_DIFLAG_REALTIME);
  105. hint_flag = (flags & XFS_DIFLAG_EXTSIZE);
  106. inherit_flag = (flags & XFS_DIFLAG_EXTSZINHERIT);
  107. extsize = be32_to_cpu(dip->di_extsize);
  108. extsize_bytes = XFS_FSB_TO_B(sc->mp, extsize);
  109. if (rt_flag)
  110. blocksize_bytes = mp->m_sb.sb_rextsize << mp->m_sb.sb_blocklog;
  111. else
  112. blocksize_bytes = mp->m_sb.sb_blocksize;
  113. if ((hint_flag || inherit_flag) && !(S_ISDIR(mode) || S_ISREG(mode)))
  114. goto bad;
  115. if (hint_flag && !S_ISREG(mode))
  116. goto bad;
  117. if (inherit_flag && !S_ISDIR(mode))
  118. goto bad;
  119. if ((hint_flag || inherit_flag) && extsize == 0)
  120. goto bad;
  121. if (!(hint_flag || inherit_flag) && extsize != 0)
  122. goto bad;
  123. if (extsize_bytes % blocksize_bytes)
  124. goto bad;
  125. if (extsize > MAXEXTLEN)
  126. goto bad;
  127. if (!rt_flag && extsize > mp->m_sb.sb_agblocks / 2)
  128. goto bad;
  129. return;
  130. bad:
  131. xfs_scrub_ino_set_corrupt(sc, ino, bp);
  132. }
  133. /*
  134. * Validate di_cowextsize hint.
  135. *
  136. * The rules are documented at xfs_ioctl_setattr_check_cowextsize().
  137. * These functions must be kept in sync with each other.
  138. */
  139. STATIC void
  140. xfs_scrub_inode_cowextsize(
  141. struct xfs_scrub_context *sc,
  142. struct xfs_buf *bp,
  143. struct xfs_dinode *dip,
  144. xfs_ino_t ino,
  145. uint16_t mode,
  146. uint16_t flags,
  147. uint64_t flags2)
  148. {
  149. struct xfs_mount *mp = sc->mp;
  150. bool rt_flag;
  151. bool hint_flag;
  152. uint32_t extsize;
  153. uint32_t extsize_bytes;
  154. rt_flag = (flags & XFS_DIFLAG_REALTIME);
  155. hint_flag = (flags2 & XFS_DIFLAG2_COWEXTSIZE);
  156. extsize = be32_to_cpu(dip->di_cowextsize);
  157. extsize_bytes = XFS_FSB_TO_B(sc->mp, extsize);
  158. if (hint_flag && !xfs_sb_version_hasreflink(&mp->m_sb))
  159. goto bad;
  160. if (hint_flag && !(S_ISDIR(mode) || S_ISREG(mode)))
  161. goto bad;
  162. if (hint_flag && extsize == 0)
  163. goto bad;
  164. if (!hint_flag && extsize != 0)
  165. goto bad;
  166. if (hint_flag && rt_flag)
  167. goto bad;
  168. if (extsize_bytes % mp->m_sb.sb_blocksize)
  169. goto bad;
  170. if (extsize > MAXEXTLEN)
  171. goto bad;
  172. if (extsize > mp->m_sb.sb_agblocks / 2)
  173. goto bad;
  174. return;
  175. bad:
  176. xfs_scrub_ino_set_corrupt(sc, ino, bp);
  177. }
  178. /* Make sure the di_flags make sense for the inode. */
  179. STATIC void
  180. xfs_scrub_inode_flags(
  181. struct xfs_scrub_context *sc,
  182. struct xfs_buf *bp,
  183. struct xfs_dinode *dip,
  184. xfs_ino_t ino,
  185. uint16_t mode,
  186. uint16_t flags)
  187. {
  188. struct xfs_mount *mp = sc->mp;
  189. if (flags & ~XFS_DIFLAG_ANY)
  190. goto bad;
  191. /* rt flags require rt device */
  192. if ((flags & (XFS_DIFLAG_REALTIME | XFS_DIFLAG_RTINHERIT)) &&
  193. !mp->m_rtdev_targp)
  194. goto bad;
  195. /* new rt bitmap flag only valid for rbmino */
  196. if ((flags & XFS_DIFLAG_NEWRTBM) && ino != mp->m_sb.sb_rbmino)
  197. goto bad;
  198. /* directory-only flags */
  199. if ((flags & (XFS_DIFLAG_RTINHERIT |
  200. XFS_DIFLAG_EXTSZINHERIT |
  201. XFS_DIFLAG_PROJINHERIT |
  202. XFS_DIFLAG_NOSYMLINKS)) &&
  203. !S_ISDIR(mode))
  204. goto bad;
  205. /* file-only flags */
  206. if ((flags & (XFS_DIFLAG_REALTIME | FS_XFLAG_EXTSIZE)) &&
  207. !S_ISREG(mode))
  208. goto bad;
  209. /* filestreams and rt make no sense */
  210. if ((flags & XFS_DIFLAG_FILESTREAM) && (flags & XFS_DIFLAG_REALTIME))
  211. goto bad;
  212. return;
  213. bad:
  214. xfs_scrub_ino_set_corrupt(sc, ino, bp);
  215. }
  216. /* Make sure the di_flags2 make sense for the inode. */
  217. STATIC void
  218. xfs_scrub_inode_flags2(
  219. struct xfs_scrub_context *sc,
  220. struct xfs_buf *bp,
  221. struct xfs_dinode *dip,
  222. xfs_ino_t ino,
  223. uint16_t mode,
  224. uint16_t flags,
  225. uint64_t flags2)
  226. {
  227. struct xfs_mount *mp = sc->mp;
  228. if (flags2 & ~XFS_DIFLAG2_ANY)
  229. goto bad;
  230. /* reflink flag requires reflink feature */
  231. if ((flags2 & XFS_DIFLAG2_REFLINK) &&
  232. !xfs_sb_version_hasreflink(&mp->m_sb))
  233. goto bad;
  234. /* cowextsize flag is checked w.r.t. mode separately */
  235. /* file/dir-only flags */
  236. if ((flags2 & XFS_DIFLAG2_DAX) && !(S_ISREG(mode) || S_ISDIR(mode)))
  237. goto bad;
  238. /* file-only flags */
  239. if ((flags2 & XFS_DIFLAG2_REFLINK) && !S_ISREG(mode))
  240. goto bad;
  241. /* realtime and reflink make no sense, currently */
  242. if ((flags & XFS_DIFLAG_REALTIME) && (flags2 & XFS_DIFLAG2_REFLINK))
  243. goto bad;
  244. /* dax and reflink make no sense, currently */
  245. if ((flags2 & XFS_DIFLAG2_DAX) && (flags2 & XFS_DIFLAG2_REFLINK))
  246. goto bad;
  247. return;
  248. bad:
  249. xfs_scrub_ino_set_corrupt(sc, ino, bp);
  250. }
  251. /* Scrub all the ondisk inode fields. */
  252. STATIC void
  253. xfs_scrub_dinode(
  254. struct xfs_scrub_context *sc,
  255. struct xfs_buf *bp,
  256. struct xfs_dinode *dip,
  257. xfs_ino_t ino)
  258. {
  259. struct xfs_mount *mp = sc->mp;
  260. size_t fork_recs;
  261. unsigned long long isize;
  262. uint64_t flags2;
  263. uint32_t nextents;
  264. uint16_t flags;
  265. uint16_t mode;
  266. flags = be16_to_cpu(dip->di_flags);
  267. if (dip->di_version >= 3)
  268. flags2 = be64_to_cpu(dip->di_flags2);
  269. else
  270. flags2 = 0;
  271. /* di_mode */
  272. mode = be16_to_cpu(dip->di_mode);
  273. switch (mode & S_IFMT) {
  274. case S_IFLNK:
  275. case S_IFREG:
  276. case S_IFDIR:
  277. case S_IFCHR:
  278. case S_IFBLK:
  279. case S_IFIFO:
  280. case S_IFSOCK:
  281. /* mode is recognized */
  282. break;
  283. default:
  284. xfs_scrub_ino_set_corrupt(sc, ino, bp);
  285. break;
  286. }
  287. /* v1/v2 fields */
  288. switch (dip->di_version) {
  289. case 1:
  290. /*
  291. * We autoconvert v1 inodes into v2 inodes on writeout,
  292. * so just mark this inode for preening.
  293. */
  294. xfs_scrub_ino_set_preen(sc, ino, bp);
  295. break;
  296. case 2:
  297. case 3:
  298. if (dip->di_onlink != 0)
  299. xfs_scrub_ino_set_corrupt(sc, ino, bp);
  300. if (dip->di_mode == 0 && sc->ip)
  301. xfs_scrub_ino_set_corrupt(sc, ino, bp);
  302. if (dip->di_projid_hi != 0 &&
  303. !xfs_sb_version_hasprojid32bit(&mp->m_sb))
  304. xfs_scrub_ino_set_corrupt(sc, ino, bp);
  305. break;
  306. default:
  307. xfs_scrub_ino_set_corrupt(sc, ino, bp);
  308. return;
  309. }
  310. /*
  311. * di_uid/di_gid -- -1 isn't invalid, but there's no way that
  312. * userspace could have created that.
  313. */
  314. if (dip->di_uid == cpu_to_be32(-1U) ||
  315. dip->di_gid == cpu_to_be32(-1U))
  316. xfs_scrub_ino_set_warning(sc, ino, bp);
  317. /* di_format */
  318. switch (dip->di_format) {
  319. case XFS_DINODE_FMT_DEV:
  320. if (!S_ISCHR(mode) && !S_ISBLK(mode) &&
  321. !S_ISFIFO(mode) && !S_ISSOCK(mode))
  322. xfs_scrub_ino_set_corrupt(sc, ino, bp);
  323. break;
  324. case XFS_DINODE_FMT_LOCAL:
  325. if (!S_ISDIR(mode) && !S_ISLNK(mode))
  326. xfs_scrub_ino_set_corrupt(sc, ino, bp);
  327. break;
  328. case XFS_DINODE_FMT_EXTENTS:
  329. if (!S_ISREG(mode) && !S_ISDIR(mode) && !S_ISLNK(mode))
  330. xfs_scrub_ino_set_corrupt(sc, ino, bp);
  331. break;
  332. case XFS_DINODE_FMT_BTREE:
  333. if (!S_ISREG(mode) && !S_ISDIR(mode))
  334. xfs_scrub_ino_set_corrupt(sc, ino, bp);
  335. break;
  336. case XFS_DINODE_FMT_UUID:
  337. default:
  338. xfs_scrub_ino_set_corrupt(sc, ino, bp);
  339. break;
  340. }
  341. /* di_[amc]time.nsec */
  342. if (be32_to_cpu(dip->di_atime.t_nsec) >= NSEC_PER_SEC)
  343. xfs_scrub_ino_set_corrupt(sc, ino, bp);
  344. if (be32_to_cpu(dip->di_mtime.t_nsec) >= NSEC_PER_SEC)
  345. xfs_scrub_ino_set_corrupt(sc, ino, bp);
  346. if (be32_to_cpu(dip->di_ctime.t_nsec) >= NSEC_PER_SEC)
  347. xfs_scrub_ino_set_corrupt(sc, ino, bp);
  348. /*
  349. * di_size. xfs_dinode_verify checks for things that screw up
  350. * the VFS such as the upper bit being set and zero-length
  351. * symlinks/directories, but we can do more here.
  352. */
  353. isize = be64_to_cpu(dip->di_size);
  354. if (isize & (1ULL << 63))
  355. xfs_scrub_ino_set_corrupt(sc, ino, bp);
  356. /* Devices, fifos, and sockets must have zero size */
  357. if (!S_ISDIR(mode) && !S_ISREG(mode) && !S_ISLNK(mode) && isize != 0)
  358. xfs_scrub_ino_set_corrupt(sc, ino, bp);
  359. /* Directories can't be larger than the data section size (32G) */
  360. if (S_ISDIR(mode) && (isize == 0 || isize >= XFS_DIR2_SPACE_SIZE))
  361. xfs_scrub_ino_set_corrupt(sc, ino, bp);
  362. /* Symlinks can't be larger than SYMLINK_MAXLEN */
  363. if (S_ISLNK(mode) && (isize == 0 || isize >= XFS_SYMLINK_MAXLEN))
  364. xfs_scrub_ino_set_corrupt(sc, ino, bp);
  365. /*
  366. * Warn if the running kernel can't handle the kinds of offsets
  367. * needed to deal with the file size. In other words, if the
  368. * pagecache can't cache all the blocks in this file due to
  369. * overly large offsets, flag the inode for admin review.
  370. */
  371. if (isize >= mp->m_super->s_maxbytes)
  372. xfs_scrub_ino_set_warning(sc, ino, bp);
  373. /* di_nblocks */
  374. if (flags2 & XFS_DIFLAG2_REFLINK) {
  375. ; /* nblocks can exceed dblocks */
  376. } else if (flags & XFS_DIFLAG_REALTIME) {
  377. /*
  378. * nblocks is the sum of data extents (in the rtdev),
  379. * attr extents (in the datadev), and both forks' bmbt
  380. * blocks (in the datadev). This clumsy check is the
  381. * best we can do without cross-referencing with the
  382. * inode forks.
  383. */
  384. if (be64_to_cpu(dip->di_nblocks) >=
  385. mp->m_sb.sb_dblocks + mp->m_sb.sb_rblocks)
  386. xfs_scrub_ino_set_corrupt(sc, ino, bp);
  387. } else {
  388. if (be64_to_cpu(dip->di_nblocks) >= mp->m_sb.sb_dblocks)
  389. xfs_scrub_ino_set_corrupt(sc, ino, bp);
  390. }
  391. xfs_scrub_inode_flags(sc, bp, dip, ino, mode, flags);
  392. xfs_scrub_inode_extsize(sc, bp, dip, ino, mode, flags);
  393. /* di_nextents */
  394. nextents = be32_to_cpu(dip->di_nextents);
  395. fork_recs = XFS_DFORK_DSIZE(dip, mp) / sizeof(struct xfs_bmbt_rec);
  396. switch (dip->di_format) {
  397. case XFS_DINODE_FMT_EXTENTS:
  398. if (nextents > fork_recs)
  399. xfs_scrub_ino_set_corrupt(sc, ino, bp);
  400. break;
  401. case XFS_DINODE_FMT_BTREE:
  402. if (nextents <= fork_recs)
  403. xfs_scrub_ino_set_corrupt(sc, ino, bp);
  404. break;
  405. default:
  406. if (nextents != 0)
  407. xfs_scrub_ino_set_corrupt(sc, ino, bp);
  408. break;
  409. }
  410. /* di_forkoff */
  411. if (XFS_DFORK_APTR(dip) >= (char *)dip + mp->m_sb.sb_inodesize)
  412. xfs_scrub_ino_set_corrupt(sc, ino, bp);
  413. if (dip->di_anextents != 0 && dip->di_forkoff == 0)
  414. xfs_scrub_ino_set_corrupt(sc, ino, bp);
  415. if (dip->di_forkoff == 0 && dip->di_aformat != XFS_DINODE_FMT_EXTENTS)
  416. xfs_scrub_ino_set_corrupt(sc, ino, bp);
  417. /* di_aformat */
  418. if (dip->di_aformat != XFS_DINODE_FMT_LOCAL &&
  419. dip->di_aformat != XFS_DINODE_FMT_EXTENTS &&
  420. dip->di_aformat != XFS_DINODE_FMT_BTREE)
  421. xfs_scrub_ino_set_corrupt(sc, ino, bp);
  422. /* di_anextents */
  423. nextents = be16_to_cpu(dip->di_anextents);
  424. fork_recs = XFS_DFORK_ASIZE(dip, mp) / sizeof(struct xfs_bmbt_rec);
  425. switch (dip->di_aformat) {
  426. case XFS_DINODE_FMT_EXTENTS:
  427. if (nextents > fork_recs)
  428. xfs_scrub_ino_set_corrupt(sc, ino, bp);
  429. break;
  430. case XFS_DINODE_FMT_BTREE:
  431. if (nextents <= fork_recs)
  432. xfs_scrub_ino_set_corrupt(sc, ino, bp);
  433. break;
  434. default:
  435. if (nextents != 0)
  436. xfs_scrub_ino_set_corrupt(sc, ino, bp);
  437. }
  438. if (dip->di_version >= 3) {
  439. if (be32_to_cpu(dip->di_crtime.t_nsec) >= NSEC_PER_SEC)
  440. xfs_scrub_ino_set_corrupt(sc, ino, bp);
  441. xfs_scrub_inode_flags2(sc, bp, dip, ino, mode, flags, flags2);
  442. xfs_scrub_inode_cowextsize(sc, bp, dip, ino, mode, flags,
  443. flags2);
  444. }
  445. }
  446. /* Map and read a raw inode. */
  447. STATIC int
  448. xfs_scrub_inode_map_raw(
  449. struct xfs_scrub_context *sc,
  450. xfs_ino_t ino,
  451. struct xfs_buf **bpp,
  452. struct xfs_dinode **dipp)
  453. {
  454. struct xfs_imap imap;
  455. struct xfs_mount *mp = sc->mp;
  456. struct xfs_buf *bp = NULL;
  457. struct xfs_dinode *dip;
  458. int error;
  459. error = xfs_imap(mp, sc->tp, ino, &imap, XFS_IGET_UNTRUSTED);
  460. if (error == -EINVAL) {
  461. /*
  462. * Inode could have gotten deleted out from under us;
  463. * just forget about it.
  464. */
  465. error = -ENOENT;
  466. goto out;
  467. }
  468. if (!xfs_scrub_process_error(sc, XFS_INO_TO_AGNO(mp, ino),
  469. XFS_INO_TO_AGBNO(mp, ino), &error))
  470. goto out;
  471. error = xfs_trans_read_buf(mp, sc->tp, mp->m_ddev_targp,
  472. imap.im_blkno, imap.im_len, XBF_UNMAPPED, &bp,
  473. NULL);
  474. if (!xfs_scrub_process_error(sc, XFS_INO_TO_AGNO(mp, ino),
  475. XFS_INO_TO_AGBNO(mp, ino), &error))
  476. goto out;
  477. /*
  478. * Is this really an inode? We disabled verifiers in the above
  479. * xfs_trans_read_buf call because the inode buffer verifier
  480. * fails on /any/ inode record in the inode cluster with a bad
  481. * magic or version number, not just the one that we're
  482. * checking. Therefore, grab the buffer unconditionally, attach
  483. * the inode verifiers by hand, and run the inode verifier only
  484. * on the one inode we want.
  485. */
  486. bp->b_ops = &xfs_inode_buf_ops;
  487. dip = xfs_buf_offset(bp, imap.im_boffset);
  488. if (xfs_dinode_verify(mp, ino, dip) != NULL ||
  489. !xfs_dinode_good_version(mp, dip->di_version)) {
  490. xfs_scrub_ino_set_corrupt(sc, ino, bp);
  491. goto out_buf;
  492. }
  493. /* ...and is it the one we asked for? */
  494. if (be32_to_cpu(dip->di_gen) != sc->sm->sm_gen) {
  495. error = -ENOENT;
  496. goto out_buf;
  497. }
  498. *dipp = dip;
  499. *bpp = bp;
  500. out:
  501. return error;
  502. out_buf:
  503. xfs_trans_brelse(sc->tp, bp);
  504. return error;
  505. }
  506. /* Scrub an inode. */
  507. int
  508. xfs_scrub_inode(
  509. struct xfs_scrub_context *sc)
  510. {
  511. struct xfs_dinode di;
  512. struct xfs_mount *mp = sc->mp;
  513. struct xfs_buf *bp = NULL;
  514. struct xfs_dinode *dip;
  515. xfs_ino_t ino;
  516. bool has_shared;
  517. int error = 0;
  518. /* Did we get the in-core inode, or are we doing this manually? */
  519. if (sc->ip) {
  520. ino = sc->ip->i_ino;
  521. xfs_inode_to_disk(sc->ip, &di, 0);
  522. dip = &di;
  523. } else {
  524. /* Map & read inode. */
  525. ino = sc->sm->sm_ino;
  526. error = xfs_scrub_inode_map_raw(sc, ino, &bp, &dip);
  527. if (error || !bp)
  528. goto out;
  529. }
  530. xfs_scrub_dinode(sc, bp, dip, ino);
  531. if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
  532. goto out;
  533. /* Now let's do the things that require a live inode. */
  534. if (!sc->ip)
  535. goto out;
  536. /*
  537. * Does this inode have the reflink flag set but no shared extents?
  538. * Set the preening flag if this is the case.
  539. */
  540. if (xfs_is_reflink_inode(sc->ip)) {
  541. error = xfs_reflink_inode_has_shared_extents(sc->tp, sc->ip,
  542. &has_shared);
  543. if (!xfs_scrub_process_error(sc, XFS_INO_TO_AGNO(mp, ino),
  544. XFS_INO_TO_AGBNO(mp, ino), &error))
  545. goto out;
  546. if (!has_shared)
  547. xfs_scrub_ino_set_preen(sc, ino, bp);
  548. }
  549. out:
  550. if (bp)
  551. xfs_trans_brelse(sc->tp, bp);
  552. return error;
  553. }