tempfile.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Copyright (c) 2021-2024 Oracle. All Rights Reserved.
  4. * Author: Darrick J. Wong <djwong@kernel.org>
  5. */
  6. #include "xfs.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_ialloc.h"
  16. #include "xfs_quota.h"
  17. #include "xfs_bmap.h"
  18. #include "xfs_bmap_btree.h"
  19. #include "xfs_trans_space.h"
  20. #include "xfs_dir2.h"
  21. #include "xfs_exchrange.h"
  22. #include "xfs_exchmaps.h"
  23. #include "xfs_defer.h"
  24. #include "xfs_symlink_remote.h"
  25. #include "scrub/scrub.h"
  26. #include "scrub/common.h"
  27. #include "scrub/repair.h"
  28. #include "scrub/trace.h"
  29. #include "scrub/tempfile.h"
  30. #include "scrub/tempexch.h"
  31. #include "scrub/xfile.h"
  32. /*
  33. * Create a temporary file for reconstructing metadata, with the intention of
  34. * atomically exchanging the temporary file's contents with the file that's
  35. * being repaired.
  36. */
  37. int
  38. xrep_tempfile_create(
  39. struct xfs_scrub *sc,
  40. uint16_t mode)
  41. {
  42. struct xfs_icreate_args args = {
  43. .pip = sc->mp->m_rootip,
  44. .mode = mode,
  45. .flags = XFS_ICREATE_TMPFILE | XFS_ICREATE_UNLINKABLE,
  46. };
  47. struct xfs_mount *mp = sc->mp;
  48. struct xfs_trans *tp = NULL;
  49. struct xfs_dquot *udqp;
  50. struct xfs_dquot *gdqp;
  51. struct xfs_dquot *pdqp;
  52. struct xfs_trans_res *tres;
  53. struct xfs_inode *dp = mp->m_rootip;
  54. xfs_ino_t ino;
  55. unsigned int resblks;
  56. bool is_dir = S_ISDIR(mode);
  57. int error;
  58. if (xfs_is_shutdown(mp))
  59. return -EIO;
  60. if (xfs_is_readonly(mp))
  61. return -EROFS;
  62. ASSERT(sc->tp == NULL);
  63. ASSERT(sc->tempip == NULL);
  64. /*
  65. * Make sure that we have allocated dquot(s) on disk. The temporary
  66. * inode should be completely root owned so that we don't fail due to
  67. * quota limits.
  68. */
  69. error = xfs_icreate_dqalloc(&args, &udqp, &gdqp, &pdqp);
  70. if (error)
  71. return error;
  72. if (is_dir) {
  73. resblks = xfs_mkdir_space_res(mp, 0);
  74. tres = &M_RES(mp)->tr_mkdir;
  75. } else {
  76. resblks = XFS_IALLOC_SPACE_RES(mp);
  77. tres = &M_RES(mp)->tr_create_tmpfile;
  78. }
  79. error = xfs_trans_alloc_icreate(mp, tres, udqp, gdqp, pdqp, resblks,
  80. &tp);
  81. if (error)
  82. goto out_release_dquots;
  83. /* Allocate inode, set up directory. */
  84. error = xfs_dialloc(&tp, &args, &ino);
  85. if (error)
  86. goto out_trans_cancel;
  87. error = xfs_icreate(tp, ino, &args, &sc->tempip);
  88. if (error)
  89. goto out_trans_cancel;
  90. /* We don't touch file data, so drop the realtime flags. */
  91. sc->tempip->i_diflags &= ~(XFS_DIFLAG_REALTIME | XFS_DIFLAG_RTINHERIT);
  92. xfs_trans_log_inode(tp, sc->tempip, XFS_ILOG_CORE);
  93. /*
  94. * Mark our temporary file as private so that LSMs and the ACL code
  95. * don't try to add their own metadata or reason about these files.
  96. * The file should never be exposed to userspace.
  97. */
  98. VFS_I(sc->tempip)->i_flags |= S_PRIVATE;
  99. VFS_I(sc->tempip)->i_opflags &= ~IOP_XATTR;
  100. if (is_dir) {
  101. error = xfs_dir_init(tp, sc->tempip, dp);
  102. if (error)
  103. goto out_trans_cancel;
  104. } else if (S_ISLNK(VFS_I(sc->tempip)->i_mode)) {
  105. /*
  106. * Initialize the temporary symlink with a meaningless target
  107. * that won't trip the verifiers. Repair must rewrite the
  108. * target with meaningful content before swapping with the file
  109. * being repaired. A single-byte target will not write a
  110. * remote target block, so the owner is irrelevant.
  111. */
  112. error = xfs_symlink_write_target(tp, sc->tempip,
  113. sc->tempip->i_ino, ".", 1, 0, 0);
  114. if (error)
  115. goto out_trans_cancel;
  116. }
  117. /*
  118. * Attach the dquot(s) to the inodes and modify them incore.
  119. * These ids of the inode couldn't have changed since the new
  120. * inode has been locked ever since it was created.
  121. */
  122. xfs_qm_vop_create_dqattach(tp, sc->tempip, udqp, gdqp, pdqp);
  123. /*
  124. * Put our temp file on the unlinked list so it's purged automatically.
  125. * All file-based metadata being reconstructed using this file must be
  126. * atomically exchanged with the original file because the contents
  127. * here will be purged when the inode is dropped or log recovery cleans
  128. * out the unlinked list.
  129. */
  130. error = xfs_iunlink(tp, sc->tempip);
  131. if (error)
  132. goto out_trans_cancel;
  133. error = xfs_trans_commit(tp);
  134. if (error)
  135. goto out_release_inode;
  136. trace_xrep_tempfile_create(sc);
  137. xfs_qm_dqrele(udqp);
  138. xfs_qm_dqrele(gdqp);
  139. xfs_qm_dqrele(pdqp);
  140. /* Finish setting up the incore / vfs context. */
  141. xfs_iunlock(sc->tempip, XFS_ILOCK_EXCL);
  142. xfs_setup_iops(sc->tempip);
  143. xfs_finish_inode_setup(sc->tempip);
  144. sc->temp_ilock_flags = 0;
  145. return error;
  146. out_trans_cancel:
  147. xfs_trans_cancel(tp);
  148. out_release_inode:
  149. /*
  150. * Wait until after the current transaction is aborted to finish the
  151. * setup of the inode and release the inode. This prevents recursive
  152. * transactions and deadlocks from xfs_inactive.
  153. */
  154. if (sc->tempip) {
  155. xfs_iunlock(sc->tempip, XFS_ILOCK_EXCL);
  156. xfs_finish_inode_setup(sc->tempip);
  157. xchk_irele(sc, sc->tempip);
  158. }
  159. out_release_dquots:
  160. xfs_qm_dqrele(udqp);
  161. xfs_qm_dqrele(gdqp);
  162. xfs_qm_dqrele(pdqp);
  163. return error;
  164. }
  165. /* Take IOLOCK_EXCL on the temporary file, maybe. */
  166. bool
  167. xrep_tempfile_iolock_nowait(
  168. struct xfs_scrub *sc)
  169. {
  170. if (xfs_ilock_nowait(sc->tempip, XFS_IOLOCK_EXCL)) {
  171. sc->temp_ilock_flags |= XFS_IOLOCK_EXCL;
  172. return true;
  173. }
  174. return false;
  175. }
  176. /*
  177. * Take the temporary file's IOLOCK while holding a different inode's IOLOCK.
  178. * In theory nobody else should hold the tempfile's IOLOCK, but we use trylock
  179. * to avoid deadlocks and lockdep complaints.
  180. */
  181. int
  182. xrep_tempfile_iolock_polled(
  183. struct xfs_scrub *sc)
  184. {
  185. int error = 0;
  186. while (!xrep_tempfile_iolock_nowait(sc)) {
  187. if (xchk_should_terminate(sc, &error))
  188. return error;
  189. delay(1);
  190. }
  191. return 0;
  192. }
  193. /* Release IOLOCK_EXCL on the temporary file. */
  194. void
  195. xrep_tempfile_iounlock(
  196. struct xfs_scrub *sc)
  197. {
  198. xfs_iunlock(sc->tempip, XFS_IOLOCK_EXCL);
  199. sc->temp_ilock_flags &= ~XFS_IOLOCK_EXCL;
  200. }
  201. /* Prepare the temporary file for metadata updates by grabbing ILOCK_EXCL. */
  202. void
  203. xrep_tempfile_ilock(
  204. struct xfs_scrub *sc)
  205. {
  206. sc->temp_ilock_flags |= XFS_ILOCK_EXCL;
  207. xfs_ilock(sc->tempip, XFS_ILOCK_EXCL);
  208. }
  209. /* Try to grab ILOCK_EXCL on the temporary file. */
  210. bool
  211. xrep_tempfile_ilock_nowait(
  212. struct xfs_scrub *sc)
  213. {
  214. if (xfs_ilock_nowait(sc->tempip, XFS_ILOCK_EXCL)) {
  215. sc->temp_ilock_flags |= XFS_ILOCK_EXCL;
  216. return true;
  217. }
  218. return false;
  219. }
  220. /* Unlock ILOCK_EXCL on the temporary file after an update. */
  221. void
  222. xrep_tempfile_iunlock(
  223. struct xfs_scrub *sc)
  224. {
  225. xfs_iunlock(sc->tempip, XFS_ILOCK_EXCL);
  226. sc->temp_ilock_flags &= ~XFS_ILOCK_EXCL;
  227. }
  228. /*
  229. * Begin the process of making changes to both the file being scrubbed and
  230. * the temporary file by taking ILOCK_EXCL on both.
  231. */
  232. void
  233. xrep_tempfile_ilock_both(
  234. struct xfs_scrub *sc)
  235. {
  236. xfs_lock_two_inodes(sc->ip, XFS_ILOCK_EXCL, sc->tempip, XFS_ILOCK_EXCL);
  237. sc->ilock_flags |= XFS_ILOCK_EXCL;
  238. sc->temp_ilock_flags |= XFS_ILOCK_EXCL;
  239. }
  240. /* Unlock ILOCK_EXCL on both files. */
  241. void
  242. xrep_tempfile_iunlock_both(
  243. struct xfs_scrub *sc)
  244. {
  245. xrep_tempfile_iunlock(sc);
  246. xchk_iunlock(sc, XFS_ILOCK_EXCL);
  247. }
  248. /* Release the temporary file. */
  249. void
  250. xrep_tempfile_rele(
  251. struct xfs_scrub *sc)
  252. {
  253. if (!sc->tempip)
  254. return;
  255. if (sc->temp_ilock_flags) {
  256. xfs_iunlock(sc->tempip, sc->temp_ilock_flags);
  257. sc->temp_ilock_flags = 0;
  258. }
  259. xchk_irele(sc, sc->tempip);
  260. sc->tempip = NULL;
  261. }
  262. /*
  263. * Make sure that the given range of the data fork of the temporary file is
  264. * mapped to written blocks. The caller must ensure that both inodes are
  265. * joined to the transaction.
  266. */
  267. int
  268. xrep_tempfile_prealloc(
  269. struct xfs_scrub *sc,
  270. xfs_fileoff_t off,
  271. xfs_filblks_t len)
  272. {
  273. struct xfs_bmbt_irec map;
  274. xfs_fileoff_t end = off + len;
  275. int error;
  276. ASSERT(sc->tempip != NULL);
  277. ASSERT(!XFS_NOT_DQATTACHED(sc->mp, sc->tempip));
  278. for (; off < end; off = map.br_startoff + map.br_blockcount) {
  279. int nmaps = 1;
  280. /*
  281. * If we have a real extent mapping this block then we're
  282. * in ok shape.
  283. */
  284. error = xfs_bmapi_read(sc->tempip, off, end - off, &map, &nmaps,
  285. XFS_DATA_FORK);
  286. if (error)
  287. return error;
  288. if (nmaps == 0) {
  289. ASSERT(nmaps != 0);
  290. return -EFSCORRUPTED;
  291. }
  292. if (xfs_bmap_is_written_extent(&map))
  293. continue;
  294. /*
  295. * If we find a delalloc reservation then something is very
  296. * very wrong. Bail out.
  297. */
  298. if (map.br_startblock == DELAYSTARTBLOCK)
  299. return -EFSCORRUPTED;
  300. /*
  301. * Make sure this block has a real zeroed extent allocated to
  302. * it.
  303. */
  304. nmaps = 1;
  305. error = xfs_bmapi_write(sc->tp, sc->tempip, off, end - off,
  306. XFS_BMAPI_CONVERT | XFS_BMAPI_ZERO, 0, &map,
  307. &nmaps);
  308. if (error)
  309. return error;
  310. if (nmaps != 1)
  311. return -EFSCORRUPTED;
  312. trace_xrep_tempfile_prealloc(sc, XFS_DATA_FORK, &map);
  313. /* Commit new extent and all deferred work. */
  314. error = xfs_defer_finish(&sc->tp);
  315. if (error)
  316. return error;
  317. }
  318. return 0;
  319. }
  320. /*
  321. * Write data to each block of a file. The given range of the tempfile's data
  322. * fork must already be populated with written extents.
  323. */
  324. int
  325. xrep_tempfile_copyin(
  326. struct xfs_scrub *sc,
  327. xfs_fileoff_t off,
  328. xfs_filblks_t len,
  329. xrep_tempfile_copyin_fn prep_fn,
  330. void *data)
  331. {
  332. LIST_HEAD(buffers_list);
  333. struct xfs_mount *mp = sc->mp;
  334. struct xfs_buf *bp;
  335. xfs_fileoff_t flush_mask;
  336. xfs_fileoff_t end = off + len;
  337. loff_t pos = XFS_FSB_TO_B(mp, off);
  338. int error = 0;
  339. ASSERT(S_ISREG(VFS_I(sc->tempip)->i_mode));
  340. /* Flush buffers to disk every 512K */
  341. flush_mask = XFS_B_TO_FSBT(mp, (1U << 19)) - 1;
  342. for (; off < end; off++, pos += mp->m_sb.sb_blocksize) {
  343. struct xfs_bmbt_irec map;
  344. int nmaps = 1;
  345. /* Read block mapping for this file block. */
  346. error = xfs_bmapi_read(sc->tempip, off, 1, &map, &nmaps, 0);
  347. if (error)
  348. goto out_err;
  349. if (nmaps == 0 || !xfs_bmap_is_written_extent(&map)) {
  350. error = -EFSCORRUPTED;
  351. goto out_err;
  352. }
  353. /* Get the metadata buffer for this offset in the file. */
  354. error = xfs_trans_get_buf(sc->tp, mp->m_ddev_targp,
  355. XFS_FSB_TO_DADDR(mp, map.br_startblock),
  356. mp->m_bsize, 0, &bp);
  357. if (error)
  358. goto out_err;
  359. trace_xrep_tempfile_copyin(sc, XFS_DATA_FORK, &map);
  360. /* Read in a block's worth of data from the xfile. */
  361. error = prep_fn(sc, bp, data);
  362. if (error) {
  363. xfs_trans_brelse(sc->tp, bp);
  364. goto out_err;
  365. }
  366. /* Queue buffer, and flush if we have too much dirty data. */
  367. xfs_buf_delwri_queue_here(bp, &buffers_list);
  368. xfs_trans_brelse(sc->tp, bp);
  369. if (!(off & flush_mask)) {
  370. error = xfs_buf_delwri_submit(&buffers_list);
  371. if (error)
  372. goto out_err;
  373. }
  374. }
  375. /*
  376. * Write the new blocks to disk. If the ordered list isn't empty after
  377. * that, then something went wrong and we have to fail. This should
  378. * never happen, but we'll check anyway.
  379. */
  380. error = xfs_buf_delwri_submit(&buffers_list);
  381. if (error)
  382. goto out_err;
  383. if (!list_empty(&buffers_list)) {
  384. ASSERT(list_empty(&buffers_list));
  385. error = -EIO;
  386. goto out_err;
  387. }
  388. return 0;
  389. out_err:
  390. xfs_buf_delwri_cancel(&buffers_list);
  391. return error;
  392. }
  393. /*
  394. * Set the temporary file's size. Caller must join the tempfile to the scrub
  395. * transaction and is responsible for adjusting block mappings as needed.
  396. */
  397. int
  398. xrep_tempfile_set_isize(
  399. struct xfs_scrub *sc,
  400. unsigned long long isize)
  401. {
  402. if (sc->tempip->i_disk_size == isize)
  403. return 0;
  404. sc->tempip->i_disk_size = isize;
  405. i_size_write(VFS_I(sc->tempip), isize);
  406. return xrep_tempfile_roll_trans(sc);
  407. }
  408. /*
  409. * Roll a repair transaction involving the temporary file. Caller must join
  410. * both the temporary file and the file being scrubbed to the transaction.
  411. * This function return with both inodes joined to a new scrub transaction,
  412. * or the usual negative errno.
  413. */
  414. int
  415. xrep_tempfile_roll_trans(
  416. struct xfs_scrub *sc)
  417. {
  418. int error;
  419. xfs_trans_log_inode(sc->tp, sc->tempip, XFS_ILOG_CORE);
  420. error = xrep_roll_trans(sc);
  421. if (error)
  422. return error;
  423. xfs_trans_ijoin(sc->tp, sc->tempip, 0);
  424. return 0;
  425. }
  426. /*
  427. * Fill out the mapping exchange request in preparation for atomically
  428. * committing the contents of a metadata file that we've rebuilt in the temp
  429. * file.
  430. */
  431. STATIC int
  432. xrep_tempexch_prep_request(
  433. struct xfs_scrub *sc,
  434. int whichfork,
  435. struct xrep_tempexch *tx)
  436. {
  437. struct xfs_exchmaps_req *req = &tx->req;
  438. memset(tx, 0, sizeof(struct xrep_tempexch));
  439. /* COW forks don't exist on disk. */
  440. if (whichfork == XFS_COW_FORK) {
  441. ASSERT(0);
  442. return -EINVAL;
  443. }
  444. /* Both files should have the relevant forks. */
  445. if (!xfs_ifork_ptr(sc->ip, whichfork) ||
  446. !xfs_ifork_ptr(sc->tempip, whichfork)) {
  447. ASSERT(xfs_ifork_ptr(sc->ip, whichfork) != NULL);
  448. ASSERT(xfs_ifork_ptr(sc->tempip, whichfork) != NULL);
  449. return -EINVAL;
  450. }
  451. /* Exchange all mappings in both forks. */
  452. req->ip1 = sc->tempip;
  453. req->ip2 = sc->ip;
  454. req->startoff1 = 0;
  455. req->startoff2 = 0;
  456. switch (whichfork) {
  457. case XFS_ATTR_FORK:
  458. req->flags |= XFS_EXCHMAPS_ATTR_FORK;
  459. break;
  460. case XFS_DATA_FORK:
  461. /* Always exchange sizes when exchanging data fork mappings. */
  462. req->flags |= XFS_EXCHMAPS_SET_SIZES;
  463. break;
  464. }
  465. req->blockcount = XFS_MAX_FILEOFF;
  466. return 0;
  467. }
  468. /*
  469. * Fill out the mapping exchange resource estimation structures in preparation
  470. * for exchanging the contents of a metadata file that we've rebuilt in the
  471. * temp file. Caller must hold IOLOCK_EXCL but not ILOCK_EXCL on both files.
  472. */
  473. STATIC int
  474. xrep_tempexch_estimate(
  475. struct xfs_scrub *sc,
  476. struct xrep_tempexch *tx)
  477. {
  478. struct xfs_exchmaps_req *req = &tx->req;
  479. struct xfs_ifork *ifp;
  480. struct xfs_ifork *tifp;
  481. int whichfork = xfs_exchmaps_reqfork(req);
  482. int state = 0;
  483. /*
  484. * The exchmaps code only knows how to exchange file fork space
  485. * mappings. Any fork data in local format must be promoted to a
  486. * single block before the exchange can take place.
  487. */
  488. ifp = xfs_ifork_ptr(sc->ip, whichfork);
  489. if (ifp->if_format == XFS_DINODE_FMT_LOCAL)
  490. state |= 1;
  491. tifp = xfs_ifork_ptr(sc->tempip, whichfork);
  492. if (tifp->if_format == XFS_DINODE_FMT_LOCAL)
  493. state |= 2;
  494. switch (state) {
  495. case 0:
  496. /* Both files have mapped extents; use the regular estimate. */
  497. return xfs_exchrange_estimate(req);
  498. case 1:
  499. /*
  500. * The file being repaired is in local format, but the temp
  501. * file has mapped extents. To perform the exchange, the file
  502. * being repaired must have its shorform data converted to an
  503. * ondisk block so that the forks will be in extents format.
  504. * We need one resblk for the conversion; the number of
  505. * exchanges is (worst case) the temporary file's extent count
  506. * plus the block we converted.
  507. */
  508. req->ip1_bcount = sc->tempip->i_nblocks;
  509. req->ip2_bcount = 1;
  510. req->nr_exchanges = 1 + tifp->if_nextents;
  511. req->resblks = 1;
  512. break;
  513. case 2:
  514. /*
  515. * The temporary file is in local format, but the file being
  516. * repaired has mapped extents. To perform the exchange, the
  517. * temp file must have its shortform data converted to an
  518. * ondisk block, and the fork changed to extents format. We
  519. * need one resblk for the conversion; the number of exchanges
  520. * is (worst case) the extent count of the file being repaired
  521. * plus the block we converted.
  522. */
  523. req->ip1_bcount = 1;
  524. req->ip2_bcount = sc->ip->i_nblocks;
  525. req->nr_exchanges = 1 + ifp->if_nextents;
  526. req->resblks = 1;
  527. break;
  528. case 3:
  529. /*
  530. * Both forks are in local format. To perform the exchange,
  531. * both files must have their shortform data converted to
  532. * fsblocks, and both forks must be converted to extents
  533. * format. We need two resblks for the two conversions, and
  534. * the number of exchanges is 1 since there's only one block at
  535. * fileoff 0. Presumably, the caller could not exchange the
  536. * two inode fork areas directly.
  537. */
  538. req->ip1_bcount = 1;
  539. req->ip2_bcount = 1;
  540. req->nr_exchanges = 1;
  541. req->resblks = 2;
  542. break;
  543. }
  544. return xfs_exchmaps_estimate_overhead(req);
  545. }
  546. /*
  547. * Obtain a quota reservation to make sure we don't hit EDQUOT. We can skip
  548. * this if quota enforcement is disabled or if both inodes' dquots are the
  549. * same. The qretry structure must be initialized to zeroes before the first
  550. * call to this function.
  551. */
  552. STATIC int
  553. xrep_tempexch_reserve_quota(
  554. struct xfs_scrub *sc,
  555. const struct xrep_tempexch *tx)
  556. {
  557. struct xfs_trans *tp = sc->tp;
  558. const struct xfs_exchmaps_req *req = &tx->req;
  559. int64_t ddelta, rdelta;
  560. int error;
  561. /*
  562. * Don't bother with a quota reservation if we're not enforcing them
  563. * or the two inodes have the same dquots.
  564. */
  565. if (!XFS_IS_QUOTA_ON(tp->t_mountp) || req->ip1 == req->ip2 ||
  566. (req->ip1->i_udquot == req->ip2->i_udquot &&
  567. req->ip1->i_gdquot == req->ip2->i_gdquot &&
  568. req->ip1->i_pdquot == req->ip2->i_pdquot))
  569. return 0;
  570. /*
  571. * Quota reservation for each file comes from two sources. First, we
  572. * need to account for any net gain in mapped blocks during the
  573. * exchange. Second, we need reservation for the gross gain in mapped
  574. * blocks so that we don't trip over any quota block reservation
  575. * assertions. We must reserve the gross gain because the quota code
  576. * subtracts from bcount the number of blocks that we unmap; it does
  577. * not add that quantity back to the quota block reservation.
  578. */
  579. ddelta = max_t(int64_t, 0, req->ip2_bcount - req->ip1_bcount);
  580. rdelta = max_t(int64_t, 0, req->ip2_rtbcount - req->ip1_rtbcount);
  581. error = xfs_trans_reserve_quota_nblks(tp, req->ip1,
  582. ddelta + req->ip1_bcount, rdelta + req->ip1_rtbcount,
  583. true);
  584. if (error)
  585. return error;
  586. ddelta = max_t(int64_t, 0, req->ip1_bcount - req->ip2_bcount);
  587. rdelta = max_t(int64_t, 0, req->ip1_rtbcount - req->ip2_rtbcount);
  588. return xfs_trans_reserve_quota_nblks(tp, req->ip2,
  589. ddelta + req->ip2_bcount, rdelta + req->ip2_rtbcount,
  590. true);
  591. }
  592. /*
  593. * Prepare an existing transaction for an atomic file contents exchange.
  594. *
  595. * This function fills out the mapping exchange request and resource estimation
  596. * structures in preparation for exchanging the contents of a metadata file
  597. * that has been rebuilt in the temp file. Next, it reserves space and quota
  598. * for the transaction.
  599. *
  600. * The caller must hold ILOCK_EXCL of the scrub target file and the temporary
  601. * file. The caller must join both inodes to the transaction with no unlock
  602. * flags, and is responsible for dropping both ILOCKs when appropriate. Only
  603. * use this when those ILOCKs cannot be dropped.
  604. */
  605. int
  606. xrep_tempexch_trans_reserve(
  607. struct xfs_scrub *sc,
  608. int whichfork,
  609. struct xrep_tempexch *tx)
  610. {
  611. int error;
  612. ASSERT(sc->tp != NULL);
  613. xfs_assert_ilocked(sc->ip, XFS_ILOCK_EXCL);
  614. xfs_assert_ilocked(sc->tempip, XFS_ILOCK_EXCL);
  615. error = xrep_tempexch_prep_request(sc, whichfork, tx);
  616. if (error)
  617. return error;
  618. error = xfs_exchmaps_estimate(&tx->req);
  619. if (error)
  620. return error;
  621. error = xfs_trans_reserve_more(sc->tp, tx->req.resblks, 0);
  622. if (error)
  623. return error;
  624. return xrep_tempexch_reserve_quota(sc, tx);
  625. }
  626. /*
  627. * Create a new transaction for a file contents exchange.
  628. *
  629. * This function fills out the mapping excahange request and resource
  630. * estimation structures in preparation for exchanging the contents of a
  631. * metadata file that has been rebuilt in the temp file. Next, it reserves
  632. * space, takes ILOCK_EXCL of both inodes, joins them to the transaction and
  633. * reserves quota for the transaction.
  634. *
  635. * The caller is responsible for dropping both ILOCKs when appropriate.
  636. */
  637. int
  638. xrep_tempexch_trans_alloc(
  639. struct xfs_scrub *sc,
  640. int whichfork,
  641. struct xrep_tempexch *tx)
  642. {
  643. unsigned int flags = 0;
  644. int error;
  645. ASSERT(sc->tp == NULL);
  646. ASSERT(xfs_has_exchange_range(sc->mp));
  647. error = xrep_tempexch_prep_request(sc, whichfork, tx);
  648. if (error)
  649. return error;
  650. error = xrep_tempexch_estimate(sc, tx);
  651. if (error)
  652. return error;
  653. if (xfs_has_lazysbcount(sc->mp))
  654. flags |= XFS_TRANS_RES_FDBLKS;
  655. error = xfs_trans_alloc(sc->mp, &M_RES(sc->mp)->tr_itruncate,
  656. tx->req.resblks, 0, flags, &sc->tp);
  657. if (error)
  658. return error;
  659. sc->temp_ilock_flags |= XFS_ILOCK_EXCL;
  660. sc->ilock_flags |= XFS_ILOCK_EXCL;
  661. xfs_exchrange_ilock(sc->tp, sc->ip, sc->tempip);
  662. return xrep_tempexch_reserve_quota(sc, tx);
  663. }
  664. /*
  665. * Exchange file mappings (and hence file contents) between the file being
  666. * repaired and the temporary file. Returns with both inodes locked and joined
  667. * to a clean scrub transaction.
  668. */
  669. int
  670. xrep_tempexch_contents(
  671. struct xfs_scrub *sc,
  672. struct xrep_tempexch *tx)
  673. {
  674. int error;
  675. ASSERT(xfs_has_exchange_range(sc->mp));
  676. xfs_exchange_mappings(sc->tp, &tx->req);
  677. error = xfs_defer_finish(&sc->tp);
  678. if (error)
  679. return error;
  680. /*
  681. * If we exchanged the ondisk sizes of two metadata files, we must
  682. * exchanged the incore sizes as well.
  683. */
  684. if (tx->req.flags & XFS_EXCHMAPS_SET_SIZES) {
  685. loff_t temp;
  686. temp = i_size_read(VFS_I(sc->ip));
  687. i_size_write(VFS_I(sc->ip), i_size_read(VFS_I(sc->tempip)));
  688. i_size_write(VFS_I(sc->tempip), temp);
  689. }
  690. return 0;
  691. }
  692. /*
  693. * Write local format data from one of the temporary file's forks into the same
  694. * fork of file being repaired, and exchange the file sizes, if appropriate.
  695. * Caller must ensure that the file being repaired has enough fork space to
  696. * hold all the bytes.
  697. */
  698. void
  699. xrep_tempfile_copyout_local(
  700. struct xfs_scrub *sc,
  701. int whichfork)
  702. {
  703. struct xfs_ifork *temp_ifp;
  704. struct xfs_ifork *ifp;
  705. unsigned int ilog_flags = XFS_ILOG_CORE;
  706. temp_ifp = xfs_ifork_ptr(sc->tempip, whichfork);
  707. ifp = xfs_ifork_ptr(sc->ip, whichfork);
  708. ASSERT(temp_ifp != NULL);
  709. ASSERT(ifp != NULL);
  710. ASSERT(temp_ifp->if_format == XFS_DINODE_FMT_LOCAL);
  711. ASSERT(ifp->if_format == XFS_DINODE_FMT_LOCAL);
  712. switch (whichfork) {
  713. case XFS_DATA_FORK:
  714. ASSERT(sc->tempip->i_disk_size <=
  715. xfs_inode_data_fork_size(sc->ip));
  716. break;
  717. case XFS_ATTR_FORK:
  718. ASSERT(sc->tempip->i_forkoff >= sc->ip->i_forkoff);
  719. break;
  720. default:
  721. ASSERT(0);
  722. return;
  723. }
  724. /* Recreate @sc->ip's incore fork (ifp) with data from temp_ifp. */
  725. xfs_idestroy_fork(ifp);
  726. xfs_init_local_fork(sc->ip, whichfork, temp_ifp->if_data,
  727. temp_ifp->if_bytes);
  728. if (whichfork == XFS_DATA_FORK) {
  729. i_size_write(VFS_I(sc->ip), i_size_read(VFS_I(sc->tempip)));
  730. sc->ip->i_disk_size = sc->tempip->i_disk_size;
  731. }
  732. ilog_flags |= xfs_ilog_fdata(whichfork);
  733. xfs_trans_log_inode(sc->tp, sc->ip, ilog_flags);
  734. }
  735. /* Decide if a given XFS inode is a temporary file for a repair. */
  736. bool
  737. xrep_is_tempfile(
  738. const struct xfs_inode *ip)
  739. {
  740. const struct inode *inode = &ip->i_vnode;
  741. if (IS_PRIVATE(inode) && !(inode->i_opflags & IOP_XATTR))
  742. return true;
  743. return false;
  744. }