xfs_inode_item_recover.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (c) 2000-2006 Silicon Graphics, Inc.
  4. * All Rights Reserved.
  5. */
  6. #include "xfs.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_trans.h"
  15. #include "xfs_inode_item.h"
  16. #include "xfs_trace.h"
  17. #include "xfs_trans_priv.h"
  18. #include "xfs_buf_item.h"
  19. #include "xfs_log.h"
  20. #include "xfs_error.h"
  21. #include "xfs_log_priv.h"
  22. #include "xfs_log_recover.h"
  23. #include "xfs_icache.h"
  24. #include "xfs_bmap_btree.h"
  25. STATIC void
  26. xlog_recover_inode_ra_pass2(
  27. struct xlog *log,
  28. struct xlog_recover_item *item)
  29. {
  30. if (item->ri_buf[0].i_len == sizeof(struct xfs_inode_log_format)) {
  31. struct xfs_inode_log_format *ilfp = item->ri_buf[0].i_addr;
  32. xlog_buf_readahead(log, ilfp->ilf_blkno, ilfp->ilf_len,
  33. &xfs_inode_buf_ra_ops);
  34. } else {
  35. struct xfs_inode_log_format_32 *ilfp = item->ri_buf[0].i_addr;
  36. xlog_buf_readahead(log, ilfp->ilf_blkno, ilfp->ilf_len,
  37. &xfs_inode_buf_ra_ops);
  38. }
  39. }
  40. /*
  41. * Inode fork owner changes
  42. *
  43. * If we have been told that we have to reparent the inode fork, it's because an
  44. * extent swap operation on a CRC enabled filesystem has been done and we are
  45. * replaying it. We need to walk the BMBT of the appropriate fork and change the
  46. * owners of it.
  47. *
  48. * The complexity here is that we don't have an inode context to work with, so
  49. * after we've replayed the inode we need to instantiate one. This is where the
  50. * fun begins.
  51. *
  52. * We are in the middle of log recovery, so we can't run transactions. That
  53. * means we cannot use cache coherent inode instantiation via xfs_iget(), as
  54. * that will result in the corresponding iput() running the inode through
  55. * xfs_inactive(). If we've just replayed an inode core that changes the link
  56. * count to zero (i.e. it's been unlinked), then xfs_inactive() will run
  57. * transactions (bad!).
  58. *
  59. * So, to avoid this, we instantiate an inode directly from the inode core we've
  60. * just recovered. We have the buffer still locked, and all we really need to
  61. * instantiate is the inode core and the forks being modified. We can do this
  62. * manually, then run the inode btree owner change, and then tear down the
  63. * xfs_inode without having to run any transactions at all.
  64. *
  65. * Also, because we don't have a transaction context available here but need to
  66. * gather all the buffers we modify for writeback so we pass the buffer_list
  67. * instead for the operation to use.
  68. */
  69. STATIC int
  70. xfs_recover_inode_owner_change(
  71. struct xfs_mount *mp,
  72. struct xfs_dinode *dip,
  73. struct xfs_inode_log_format *in_f,
  74. struct list_head *buffer_list)
  75. {
  76. struct xfs_inode *ip;
  77. int error;
  78. ASSERT(in_f->ilf_fields & (XFS_ILOG_DOWNER|XFS_ILOG_AOWNER));
  79. ip = xfs_inode_alloc(mp, in_f->ilf_ino);
  80. if (!ip)
  81. return -ENOMEM;
  82. /* instantiate the inode */
  83. ASSERT(dip->di_version >= 3);
  84. error = xfs_inode_from_disk(ip, dip);
  85. if (error)
  86. goto out_free_ip;
  87. if (in_f->ilf_fields & XFS_ILOG_DOWNER) {
  88. ASSERT(in_f->ilf_fields & XFS_ILOG_DBROOT);
  89. error = xfs_bmbt_change_owner(NULL, ip, XFS_DATA_FORK,
  90. ip->i_ino, buffer_list);
  91. if (error)
  92. goto out_free_ip;
  93. }
  94. if (in_f->ilf_fields & XFS_ILOG_AOWNER) {
  95. ASSERT(in_f->ilf_fields & XFS_ILOG_ABROOT);
  96. error = xfs_bmbt_change_owner(NULL, ip, XFS_ATTR_FORK,
  97. ip->i_ino, buffer_list);
  98. if (error)
  99. goto out_free_ip;
  100. }
  101. out_free_ip:
  102. xfs_inode_free(ip);
  103. return error;
  104. }
  105. static inline bool xfs_log_dinode_has_bigtime(const struct xfs_log_dinode *ld)
  106. {
  107. return ld->di_version >= 3 &&
  108. (ld->di_flags2 & XFS_DIFLAG2_BIGTIME);
  109. }
  110. /* Convert a log timestamp to an ondisk timestamp. */
  111. static inline xfs_timestamp_t
  112. xfs_log_dinode_to_disk_ts(
  113. struct xfs_log_dinode *from,
  114. const xfs_log_timestamp_t its)
  115. {
  116. struct xfs_legacy_timestamp *lts;
  117. struct xfs_log_legacy_timestamp *lits;
  118. xfs_timestamp_t ts;
  119. if (xfs_log_dinode_has_bigtime(from))
  120. return cpu_to_be64(its);
  121. lts = (struct xfs_legacy_timestamp *)&ts;
  122. lits = (struct xfs_log_legacy_timestamp *)&its;
  123. lts->t_sec = cpu_to_be32(lits->t_sec);
  124. lts->t_nsec = cpu_to_be32(lits->t_nsec);
  125. return ts;
  126. }
  127. static inline bool xfs_log_dinode_has_large_extent_counts(
  128. const struct xfs_log_dinode *ld)
  129. {
  130. return ld->di_version >= 3 &&
  131. (ld->di_flags2 & XFS_DIFLAG2_NREXT64);
  132. }
  133. static inline void
  134. xfs_log_dinode_to_disk_iext_counters(
  135. struct xfs_log_dinode *from,
  136. struct xfs_dinode *to)
  137. {
  138. if (xfs_log_dinode_has_large_extent_counts(from)) {
  139. to->di_big_nextents = cpu_to_be64(from->di_big_nextents);
  140. to->di_big_anextents = cpu_to_be32(from->di_big_anextents);
  141. to->di_nrext64_pad = cpu_to_be16(from->di_nrext64_pad);
  142. } else {
  143. to->di_nextents = cpu_to_be32(from->di_nextents);
  144. to->di_anextents = cpu_to_be16(from->di_anextents);
  145. }
  146. }
  147. STATIC void
  148. xfs_log_dinode_to_disk(
  149. struct xfs_log_dinode *from,
  150. struct xfs_dinode *to,
  151. xfs_lsn_t lsn)
  152. {
  153. to->di_magic = cpu_to_be16(from->di_magic);
  154. to->di_mode = cpu_to_be16(from->di_mode);
  155. to->di_version = from->di_version;
  156. to->di_format = from->di_format;
  157. to->di_onlink = 0;
  158. to->di_uid = cpu_to_be32(from->di_uid);
  159. to->di_gid = cpu_to_be32(from->di_gid);
  160. to->di_nlink = cpu_to_be32(from->di_nlink);
  161. to->di_projid_lo = cpu_to_be16(from->di_projid_lo);
  162. to->di_projid_hi = cpu_to_be16(from->di_projid_hi);
  163. to->di_atime = xfs_log_dinode_to_disk_ts(from, from->di_atime);
  164. to->di_mtime = xfs_log_dinode_to_disk_ts(from, from->di_mtime);
  165. to->di_ctime = xfs_log_dinode_to_disk_ts(from, from->di_ctime);
  166. to->di_size = cpu_to_be64(from->di_size);
  167. to->di_nblocks = cpu_to_be64(from->di_nblocks);
  168. to->di_extsize = cpu_to_be32(from->di_extsize);
  169. to->di_forkoff = from->di_forkoff;
  170. to->di_aformat = from->di_aformat;
  171. to->di_dmevmask = cpu_to_be32(from->di_dmevmask);
  172. to->di_dmstate = cpu_to_be16(from->di_dmstate);
  173. to->di_flags = cpu_to_be16(from->di_flags);
  174. to->di_gen = cpu_to_be32(from->di_gen);
  175. if (from->di_version == 3) {
  176. to->di_changecount = cpu_to_be64(from->di_changecount);
  177. to->di_crtime = xfs_log_dinode_to_disk_ts(from,
  178. from->di_crtime);
  179. to->di_flags2 = cpu_to_be64(from->di_flags2);
  180. to->di_cowextsize = cpu_to_be32(from->di_cowextsize);
  181. to->di_ino = cpu_to_be64(from->di_ino);
  182. to->di_lsn = cpu_to_be64(lsn);
  183. memset(to->di_pad2, 0, sizeof(to->di_pad2));
  184. uuid_copy(&to->di_uuid, &from->di_uuid);
  185. to->di_v3_pad = 0;
  186. } else {
  187. to->di_flushiter = cpu_to_be16(from->di_flushiter);
  188. memset(to->di_v2_pad, 0, sizeof(to->di_v2_pad));
  189. }
  190. xfs_log_dinode_to_disk_iext_counters(from, to);
  191. }
  192. STATIC int
  193. xlog_dinode_verify_extent_counts(
  194. struct xfs_mount *mp,
  195. struct xfs_log_dinode *ldip)
  196. {
  197. xfs_extnum_t nextents;
  198. xfs_aextnum_t anextents;
  199. if (xfs_log_dinode_has_large_extent_counts(ldip)) {
  200. if (!xfs_has_large_extent_counts(mp) ||
  201. (ldip->di_nrext64_pad != 0)) {
  202. XFS_CORRUPTION_ERROR(
  203. "Bad log dinode large extent count format",
  204. XFS_ERRLEVEL_LOW, mp, ldip, sizeof(*ldip));
  205. xfs_alert(mp,
  206. "Bad inode 0x%llx, large extent counts %d, padding 0x%x",
  207. ldip->di_ino, xfs_has_large_extent_counts(mp),
  208. ldip->di_nrext64_pad);
  209. return -EFSCORRUPTED;
  210. }
  211. nextents = ldip->di_big_nextents;
  212. anextents = ldip->di_big_anextents;
  213. } else {
  214. if (ldip->di_version == 3 && ldip->di_v3_pad != 0) {
  215. XFS_CORRUPTION_ERROR(
  216. "Bad log dinode di_v3_pad",
  217. XFS_ERRLEVEL_LOW, mp, ldip, sizeof(*ldip));
  218. xfs_alert(mp,
  219. "Bad inode 0x%llx, di_v3_pad 0x%llx",
  220. ldip->di_ino, ldip->di_v3_pad);
  221. return -EFSCORRUPTED;
  222. }
  223. nextents = ldip->di_nextents;
  224. anextents = ldip->di_anextents;
  225. }
  226. if (unlikely(nextents + anextents > ldip->di_nblocks)) {
  227. XFS_CORRUPTION_ERROR("Bad log dinode extent counts",
  228. XFS_ERRLEVEL_LOW, mp, ldip, sizeof(*ldip));
  229. xfs_alert(mp,
  230. "Bad inode 0x%llx, large extent counts %d, nextents 0x%llx, anextents 0x%x, nblocks 0x%llx",
  231. ldip->di_ino, xfs_has_large_extent_counts(mp), nextents,
  232. anextents, ldip->di_nblocks);
  233. return -EFSCORRUPTED;
  234. }
  235. return 0;
  236. }
  237. STATIC int
  238. xlog_recover_inode_commit_pass2(
  239. struct xlog *log,
  240. struct list_head *buffer_list,
  241. struct xlog_recover_item *item,
  242. xfs_lsn_t current_lsn)
  243. {
  244. struct xfs_inode_log_format *in_f;
  245. struct xfs_mount *mp = log->l_mp;
  246. struct xfs_buf *bp;
  247. struct xfs_dinode *dip;
  248. int len;
  249. char *src;
  250. char *dest;
  251. int error;
  252. int attr_index;
  253. uint fields;
  254. struct xfs_log_dinode *ldip;
  255. uint isize;
  256. int need_free = 0;
  257. xfs_failaddr_t fa;
  258. if (item->ri_buf[0].i_len == sizeof(struct xfs_inode_log_format)) {
  259. in_f = item->ri_buf[0].i_addr;
  260. } else {
  261. in_f = kmalloc(sizeof(struct xfs_inode_log_format),
  262. GFP_KERNEL | __GFP_NOFAIL);
  263. need_free = 1;
  264. error = xfs_inode_item_format_convert(&item->ri_buf[0], in_f);
  265. if (error)
  266. goto error;
  267. }
  268. /*
  269. * Inode buffers can be freed, look out for it,
  270. * and do not replay the inode.
  271. */
  272. if (xlog_is_buffer_cancelled(log, in_f->ilf_blkno, in_f->ilf_len)) {
  273. error = 0;
  274. trace_xfs_log_recover_inode_cancel(log, in_f);
  275. goto error;
  276. }
  277. trace_xfs_log_recover_inode_recover(log, in_f);
  278. error = xfs_buf_read(mp->m_ddev_targp, in_f->ilf_blkno, in_f->ilf_len,
  279. 0, &bp, &xfs_inode_buf_ops);
  280. if (error)
  281. goto error;
  282. ASSERT(in_f->ilf_fields & XFS_ILOG_CORE);
  283. dip = xfs_buf_offset(bp, in_f->ilf_boffset);
  284. /*
  285. * Make sure the place we're flushing out to really looks
  286. * like an inode!
  287. */
  288. if (XFS_IS_CORRUPT(mp, !xfs_verify_magic16(bp, dip->di_magic))) {
  289. xfs_alert(mp,
  290. "%s: Bad inode magic number, dip = "PTR_FMT", dino bp = "PTR_FMT", ino = %lld",
  291. __func__, dip, bp, in_f->ilf_ino);
  292. error = -EFSCORRUPTED;
  293. goto out_release;
  294. }
  295. ldip = item->ri_buf[1].i_addr;
  296. if (XFS_IS_CORRUPT(mp, ldip->di_magic != XFS_DINODE_MAGIC)) {
  297. xfs_alert(mp,
  298. "%s: Bad inode log record, rec ptr "PTR_FMT", ino %lld",
  299. __func__, item, in_f->ilf_ino);
  300. error = -EFSCORRUPTED;
  301. goto out_release;
  302. }
  303. /*
  304. * If the inode has an LSN in it, recover the inode only if the on-disk
  305. * inode's LSN is older than the lsn of the transaction we are
  306. * replaying. We can have multiple checkpoints with the same start LSN,
  307. * so the current LSN being equal to the on-disk LSN doesn't necessarily
  308. * mean that the on-disk inode is more recent than the change being
  309. * replayed.
  310. *
  311. * We must check the current_lsn against the on-disk inode
  312. * here because the we can't trust the log dinode to contain a valid LSN
  313. * (see comment below before replaying the log dinode for details).
  314. *
  315. * Note: we still need to replay an owner change even though the inode
  316. * is more recent than the transaction as there is no guarantee that all
  317. * the btree blocks are more recent than this transaction, too.
  318. */
  319. if (dip->di_version >= 3) {
  320. xfs_lsn_t lsn = be64_to_cpu(dip->di_lsn);
  321. if (lsn && lsn != -1 && XFS_LSN_CMP(lsn, current_lsn) > 0) {
  322. trace_xfs_log_recover_inode_skip(log, in_f);
  323. error = 0;
  324. goto out_owner_change;
  325. }
  326. }
  327. /*
  328. * di_flushiter is only valid for v1/2 inodes. All changes for v3 inodes
  329. * are transactional and if ordering is necessary we can determine that
  330. * more accurately by the LSN field in the V3 inode core. Don't trust
  331. * the inode versions we might be changing them here - use the
  332. * superblock flag to determine whether we need to look at di_flushiter
  333. * to skip replay when the on disk inode is newer than the log one
  334. */
  335. if (!xfs_has_v3inodes(mp)) {
  336. if (ldip->di_flushiter < be16_to_cpu(dip->di_flushiter)) {
  337. /*
  338. * Deal with the wrap case, DI_MAX_FLUSH is less
  339. * than smaller numbers
  340. */
  341. if (be16_to_cpu(dip->di_flushiter) == DI_MAX_FLUSH &&
  342. ldip->di_flushiter < (DI_MAX_FLUSH >> 1)) {
  343. /* do nothing */
  344. } else {
  345. trace_xfs_log_recover_inode_skip(log, in_f);
  346. error = 0;
  347. goto out_release;
  348. }
  349. }
  350. /* Take the opportunity to reset the flush iteration count */
  351. ldip->di_flushiter = 0;
  352. }
  353. if (unlikely(S_ISREG(ldip->di_mode))) {
  354. if ((ldip->di_format != XFS_DINODE_FMT_EXTENTS) &&
  355. (ldip->di_format != XFS_DINODE_FMT_BTREE)) {
  356. XFS_CORRUPTION_ERROR(
  357. "Bad log dinode data fork format for regular file",
  358. XFS_ERRLEVEL_LOW, mp, ldip, sizeof(*ldip));
  359. xfs_alert(mp,
  360. "Bad inode 0x%llx, data fork format 0x%x",
  361. in_f->ilf_ino, ldip->di_format);
  362. error = -EFSCORRUPTED;
  363. goto out_release;
  364. }
  365. } else if (unlikely(S_ISDIR(ldip->di_mode))) {
  366. if ((ldip->di_format != XFS_DINODE_FMT_EXTENTS) &&
  367. (ldip->di_format != XFS_DINODE_FMT_BTREE) &&
  368. (ldip->di_format != XFS_DINODE_FMT_LOCAL)) {
  369. XFS_CORRUPTION_ERROR(
  370. "Bad log dinode data fork format for directory",
  371. XFS_ERRLEVEL_LOW, mp, ldip, sizeof(*ldip));
  372. xfs_alert(mp,
  373. "Bad inode 0x%llx, data fork format 0x%x",
  374. in_f->ilf_ino, ldip->di_format);
  375. error = -EFSCORRUPTED;
  376. goto out_release;
  377. }
  378. }
  379. error = xlog_dinode_verify_extent_counts(mp, ldip);
  380. if (error)
  381. goto out_release;
  382. if (unlikely(ldip->di_forkoff > mp->m_sb.sb_inodesize)) {
  383. XFS_CORRUPTION_ERROR("Bad log dinode fork offset",
  384. XFS_ERRLEVEL_LOW, mp, ldip, sizeof(*ldip));
  385. xfs_alert(mp,
  386. "Bad inode 0x%llx, di_forkoff 0x%x",
  387. in_f->ilf_ino, ldip->di_forkoff);
  388. error = -EFSCORRUPTED;
  389. goto out_release;
  390. }
  391. isize = xfs_log_dinode_size(mp);
  392. if (unlikely(item->ri_buf[1].i_len > isize)) {
  393. XFS_CORRUPTION_ERROR("Bad log dinode size", XFS_ERRLEVEL_LOW,
  394. mp, ldip, sizeof(*ldip));
  395. xfs_alert(mp,
  396. "Bad inode 0x%llx log dinode size 0x%x",
  397. in_f->ilf_ino, item->ri_buf[1].i_len);
  398. error = -EFSCORRUPTED;
  399. goto out_release;
  400. }
  401. /*
  402. * Recover the log dinode inode into the on disk inode.
  403. *
  404. * The LSN in the log dinode is garbage - it can be zero or reflect
  405. * stale in-memory runtime state that isn't coherent with the changes
  406. * logged in this transaction or the changes written to the on-disk
  407. * inode. Hence we write the current lSN into the inode because that
  408. * matches what xfs_iflush() would write inode the inode when flushing
  409. * the changes in this transaction.
  410. */
  411. xfs_log_dinode_to_disk(ldip, dip, current_lsn);
  412. fields = in_f->ilf_fields;
  413. if (fields & XFS_ILOG_DEV)
  414. xfs_dinode_put_rdev(dip, in_f->ilf_u.ilfu_rdev);
  415. if (in_f->ilf_size == 2)
  416. goto out_owner_change;
  417. len = item->ri_buf[2].i_len;
  418. src = item->ri_buf[2].i_addr;
  419. ASSERT(in_f->ilf_size <= 4);
  420. ASSERT((in_f->ilf_size == 3) || (fields & XFS_ILOG_AFORK));
  421. ASSERT(!(fields & XFS_ILOG_DFORK) ||
  422. (len == xlog_calc_iovec_len(in_f->ilf_dsize)));
  423. switch (fields & XFS_ILOG_DFORK) {
  424. case XFS_ILOG_DDATA:
  425. case XFS_ILOG_DEXT:
  426. memcpy(XFS_DFORK_DPTR(dip), src, len);
  427. break;
  428. case XFS_ILOG_DBROOT:
  429. xfs_bmbt_to_bmdr(mp, (struct xfs_btree_block *)src, len,
  430. (struct xfs_bmdr_block *)XFS_DFORK_DPTR(dip),
  431. XFS_DFORK_DSIZE(dip, mp));
  432. break;
  433. default:
  434. /*
  435. * There are no data fork flags set.
  436. */
  437. ASSERT((fields & XFS_ILOG_DFORK) == 0);
  438. break;
  439. }
  440. /*
  441. * If we logged any attribute data, recover it. There may or
  442. * may not have been any other non-core data logged in this
  443. * transaction.
  444. */
  445. if (in_f->ilf_fields & XFS_ILOG_AFORK) {
  446. if (in_f->ilf_fields & XFS_ILOG_DFORK) {
  447. attr_index = 3;
  448. } else {
  449. attr_index = 2;
  450. }
  451. len = item->ri_buf[attr_index].i_len;
  452. src = item->ri_buf[attr_index].i_addr;
  453. ASSERT(len == xlog_calc_iovec_len(in_f->ilf_asize));
  454. switch (in_f->ilf_fields & XFS_ILOG_AFORK) {
  455. case XFS_ILOG_ADATA:
  456. case XFS_ILOG_AEXT:
  457. dest = XFS_DFORK_APTR(dip);
  458. ASSERT(len <= XFS_DFORK_ASIZE(dip, mp));
  459. memcpy(dest, src, len);
  460. break;
  461. case XFS_ILOG_ABROOT:
  462. dest = XFS_DFORK_APTR(dip);
  463. xfs_bmbt_to_bmdr(mp, (struct xfs_btree_block *)src,
  464. len, (struct xfs_bmdr_block *)dest,
  465. XFS_DFORK_ASIZE(dip, mp));
  466. break;
  467. default:
  468. xfs_warn(log->l_mp, "%s: Invalid flag", __func__);
  469. ASSERT(0);
  470. error = -EFSCORRUPTED;
  471. goto out_release;
  472. }
  473. }
  474. out_owner_change:
  475. /* Recover the swapext owner change unless inode has been deleted */
  476. if ((in_f->ilf_fields & (XFS_ILOG_DOWNER|XFS_ILOG_AOWNER)) &&
  477. (dip->di_mode != 0))
  478. error = xfs_recover_inode_owner_change(mp, dip, in_f,
  479. buffer_list);
  480. /* re-generate the checksum and validate the recovered inode. */
  481. xfs_dinode_calc_crc(log->l_mp, dip);
  482. fa = xfs_dinode_verify(log->l_mp, in_f->ilf_ino, dip);
  483. if (fa) {
  484. XFS_CORRUPTION_ERROR(
  485. "Bad dinode after recovery",
  486. XFS_ERRLEVEL_LOW, mp, dip, sizeof(*dip));
  487. xfs_alert(mp,
  488. "Metadata corruption detected at %pS, inode 0x%llx",
  489. fa, in_f->ilf_ino);
  490. error = -EFSCORRUPTED;
  491. goto out_release;
  492. }
  493. ASSERT(bp->b_mount == mp);
  494. bp->b_flags |= _XBF_LOGRECOVERY;
  495. xfs_buf_delwri_queue(bp, buffer_list);
  496. out_release:
  497. xfs_buf_relse(bp);
  498. error:
  499. if (need_free)
  500. kfree(in_f);
  501. return error;
  502. }
  503. const struct xlog_recover_item_ops xlog_inode_item_ops = {
  504. .item_type = XFS_LI_INODE,
  505. .ra_pass2 = xlog_recover_inode_ra_pass2,
  506. .commit_pass2 = xlog_recover_inode_commit_pass2,
  507. };