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_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_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 "xfs_metafile.h"
26 #include "scrub/scrub.h"
27 #include "scrub/common.h"
28 #include "scrub/repair.h"
29 #include "scrub/trace.h"
30 #include "scrub/tempfile.h"
31 #include "scrub/tempexch.h"
32 #include "scrub/xfile.h"
33
34 /*
35 * Create a temporary file for reconstructing metadata, with the intention of
36 * atomically exchanging the temporary file's contents with the file that's
37 * being repaired.
38 */
39 int
xrep_tempfile_create(struct xfs_scrub * sc,uint16_t mode)40 xrep_tempfile_create(
41 struct xfs_scrub *sc,
42 uint16_t mode)
43 {
44 struct xfs_icreate_args args = {
45 .pip = sc->mp->m_rootip,
46 .mode = mode,
47 .flags = XFS_ICREATE_TMPFILE | XFS_ICREATE_UNLINKABLE,
48 };
49 struct xfs_mount *mp = sc->mp;
50 struct xfs_trans *tp = NULL;
51 struct xfs_dquot *udqp;
52 struct xfs_dquot *gdqp;
53 struct xfs_dquot *pdqp;
54 struct xfs_trans_res *tres;
55 struct xfs_inode *dp = mp->m_rootip;
56 xfs_ino_t ino;
57 unsigned int resblks;
58 bool is_dir = S_ISDIR(mode);
59 int error;
60
61 if (xfs_is_shutdown(mp))
62 return -EIO;
63 if (xfs_is_readonly(mp))
64 return -EROFS;
65
66 ASSERT(sc->tp == NULL);
67 ASSERT(sc->tempip == NULL);
68
69 /*
70 * Make sure that we have allocated dquot(s) on disk. The temporary
71 * inode should be completely root owned so that we don't fail due to
72 * quota limits.
73 */
74 error = xfs_icreate_dqalloc(&args, &udqp, &gdqp, &pdqp);
75 if (error)
76 return error;
77
78 if (is_dir) {
79 resblks = xfs_mkdir_space_res(mp, 0);
80 tres = &M_RES(mp)->tr_mkdir;
81 } else {
82 resblks = XFS_IALLOC_SPACE_RES(mp);
83 tres = &M_RES(mp)->tr_create_tmpfile;
84 }
85
86 error = xfs_trans_alloc_icreate(mp, tres, udqp, gdqp, pdqp, resblks,
87 &tp);
88 if (error)
89 goto out_release_dquots;
90
91 /* Allocate inode, set up directory. */
92 error = xfs_dialloc(&tp, &args, &ino);
93 if (error)
94 goto out_trans_cancel;
95 error = xfs_icreate(tp, ino, &args, &sc->tempip);
96 if (error)
97 goto out_trans_cancel;
98
99 /* We don't touch file data, so drop the realtime flags. */
100 sc->tempip->i_diflags &= ~(XFS_DIFLAG_REALTIME | XFS_DIFLAG_RTINHERIT);
101 xfs_trans_log_inode(tp, sc->tempip, XFS_ILOG_CORE);
102
103 /*
104 * Mark our temporary file as private so that LSMs and the ACL code
105 * don't try to add their own metadata or reason about these files.
106 * The file should never be exposed to userspace.
107 */
108 VFS_I(sc->tempip)->i_flags |= S_PRIVATE;
109 VFS_I(sc->tempip)->i_opflags &= ~IOP_XATTR;
110
111 if (is_dir) {
112 error = xfs_dir_init(tp, sc->tempip, dp);
113 if (error)
114 goto out_trans_cancel;
115 } else if (S_ISLNK(VFS_I(sc->tempip)->i_mode)) {
116 /*
117 * Initialize the temporary symlink with a meaningless target
118 * that won't trip the verifiers. Repair must rewrite the
119 * target with meaningful content before swapping with the file
120 * being repaired. A single-byte target will not write a
121 * remote target block, so the owner is irrelevant.
122 */
123 error = xfs_symlink_write_target(tp, sc->tempip,
124 I_INO(sc->tempip), ".", 1, 0, 0);
125 if (error)
126 goto out_trans_cancel;
127 }
128
129 /*
130 * Attach the dquot(s) to the inodes and modify them incore.
131 * These ids of the inode couldn't have changed since the new
132 * inode has been locked ever since it was created.
133 */
134 xfs_qm_vop_create_dqattach(tp, sc->tempip, udqp, gdqp, pdqp);
135
136 /*
137 * Put our temp file on the unlinked list so it's purged automatically.
138 * All file-based metadata being reconstructed using this file must be
139 * atomically exchanged with the original file because the contents
140 * here will be purged when the inode is dropped or log recovery cleans
141 * out the unlinked list.
142 */
143 error = xfs_iunlink(tp, sc->tempip);
144 if (error)
145 goto out_trans_cancel;
146
147 error = xfs_trans_commit(tp);
148 if (error)
149 goto out_release_inode;
150
151 trace_xrep_tempfile_create(sc);
152
153 xfs_qm_dqrele(udqp);
154 xfs_qm_dqrele(gdqp);
155 xfs_qm_dqrele(pdqp);
156
157 /* Finish setting up the incore / vfs context. */
158 xfs_iunlock(sc->tempip, XFS_ILOCK_EXCL);
159 xfs_setup_iops(sc->tempip);
160 xfs_finish_inode_setup(sc->tempip);
161
162 sc->temp_ilock_flags = 0;
163 return error;
164
165 out_trans_cancel:
166 xfs_trans_cancel(tp);
167 out_release_inode:
168 /*
169 * Wait until after the current transaction is aborted to finish the
170 * setup of the inode and release the inode. This prevents recursive
171 * transactions and deadlocks from xfs_inactive.
172 */
173 if (sc->tempip) {
174 xfs_iunlock(sc->tempip, XFS_ILOCK_EXCL);
175 xfs_finish_inode_setup(sc->tempip);
176 xchk_irele(sc, sc->tempip);
177 sc->tempip = NULL;
178 }
179 out_release_dquots:
180 xfs_qm_dqrele(udqp);
181 xfs_qm_dqrele(gdqp);
182 xfs_qm_dqrele(pdqp);
183
184 return error;
185 }
186
187 /*
188 * Move sc->tempip from the regular directory tree to the metadata directory
189 * tree if sc->ip is part of the metadata directory tree and tempip has an
190 * eligible file mode.
191 *
192 * Temporary files have to be created before we even know which inode we're
193 * going to scrub, so we assume that they will be part of the regular directory
194 * tree. If it turns out that we're actually scrubbing a file from the
195 * metadata directory tree, we have to subtract the temp file from the root
196 * dquots and detach the dquots prior to setting the METADATA iflag. However,
197 * the scrub setup functions grab sc->ip and create sc->tempip before we
198 * actually get around to checking if the file mode is the right type for the
199 * scrubber.
200 */
201 int
xrep_tempfile_adjust_directory_tree(struct xfs_scrub * sc)202 xrep_tempfile_adjust_directory_tree(
203 struct xfs_scrub *sc)
204 {
205 int error;
206
207 if (!sc->tempip)
208 return 0;
209
210 ASSERT(sc->tp == NULL);
211 ASSERT(!xfs_is_metadir_inode(sc->tempip));
212
213 if (!sc->ip || !xfs_is_metadir_inode(sc->ip))
214 return 0;
215 if (!S_ISDIR(VFS_I(sc->tempip)->i_mode) &&
216 !S_ISREG(VFS_I(sc->tempip)->i_mode))
217 return 0;
218
219 xfs_ilock(sc->tempip, XFS_IOLOCK_EXCL);
220 sc->temp_ilock_flags |= XFS_IOLOCK_EXCL;
221
222 error = xchk_trans_alloc(sc, 0);
223 if (error)
224 goto out_iolock;
225
226 xrep_tempfile_ilock(sc);
227 xfs_trans_ijoin(sc->tp, sc->tempip, 0);
228
229 /* Metadir files are not accounted in quota, so drop icount */
230 xfs_trans_mod_dquot_byino(sc->tp, sc->tempip, XFS_TRANS_DQ_ICOUNT, -1L);
231 xfs_metafile_set_iflag(sc->tp, sc->tempip, XFS_METAFILE_UNKNOWN);
232
233 error = xrep_trans_commit(sc);
234 if (error)
235 goto out_ilock;
236
237 xfs_iflags_set(sc->tempip, XFS_IRECOVERY);
238 xfs_qm_dqdetach(sc->tempip);
239 out_ilock:
240 xrep_tempfile_iunlock(sc);
241 out_iolock:
242 xrep_tempfile_iounlock(sc);
243 return error;
244 }
245
246 /*
247 * Remove this temporary file from the metadata directory tree so that it can
248 * be inactivated the normal way.
249 */
250 STATIC int
xrep_tempfile_remove_metadir(struct xfs_scrub * sc)251 xrep_tempfile_remove_metadir(
252 struct xfs_scrub *sc)
253 {
254 int error;
255
256 if (!sc->tempip || !xfs_is_metadir_inode(sc->tempip))
257 return 0;
258
259 ASSERT(sc->tp == NULL);
260
261 xfs_iflags_clear(sc->tempip, XFS_IRECOVERY);
262
263 xfs_ilock(sc->tempip, XFS_IOLOCK_EXCL);
264 sc->temp_ilock_flags |= XFS_IOLOCK_EXCL;
265
266 error = xchk_trans_alloc(sc, 0);
267 if (error)
268 goto out_iolock;
269
270 xrep_tempfile_ilock(sc);
271 xfs_trans_ijoin(sc->tp, sc->tempip, 0);
272
273 xfs_metafile_clear_iflag(sc->tp, sc->tempip);
274
275 /* Non-metadir files are accounted in quota, so bump bcount/icount */
276 error = xfs_qm_dqattach_locked(sc->tempip, false);
277 if (error)
278 goto out_cancel;
279
280 xfs_trans_mod_dquot_byino(sc->tp, sc->tempip, XFS_TRANS_DQ_ICOUNT, 1L);
281 xfs_trans_mod_dquot_byino(sc->tp, sc->tempip, XFS_TRANS_DQ_BCOUNT,
282 sc->tempip->i_nblocks);
283 error = xrep_trans_commit(sc);
284 goto out_ilock;
285
286 out_cancel:
287 xchk_trans_cancel(sc);
288 out_ilock:
289 xrep_tempfile_iunlock(sc);
290 out_iolock:
291 xrep_tempfile_iounlock(sc);
292 return error;
293 }
294
295 /* Take IOLOCK_EXCL on the temporary file, maybe. */
296 bool
xrep_tempfile_iolock_nowait(struct xfs_scrub * sc)297 xrep_tempfile_iolock_nowait(
298 struct xfs_scrub *sc)
299 {
300 if (xfs_ilock_nowait(sc->tempip, XFS_IOLOCK_EXCL)) {
301 sc->temp_ilock_flags |= XFS_IOLOCK_EXCL;
302 return true;
303 }
304
305 return false;
306 }
307
308 /*
309 * Take the temporary file's IOLOCK while holding a different inode's IOLOCK.
310 * In theory nobody else should hold the tempfile's IOLOCK, but we use trylock
311 * to avoid deadlocks and lockdep complaints.
312 */
313 int
xrep_tempfile_iolock_polled(struct xfs_scrub * sc)314 xrep_tempfile_iolock_polled(
315 struct xfs_scrub *sc)
316 {
317 int error = 0;
318
319 while (!xrep_tempfile_iolock_nowait(sc)) {
320 if (xchk_should_terminate(sc, &error))
321 return error;
322 delay(1);
323 }
324
325 return 0;
326 }
327
328 /* Release IOLOCK_EXCL on the temporary file. */
329 void
xrep_tempfile_iounlock(struct xfs_scrub * sc)330 xrep_tempfile_iounlock(
331 struct xfs_scrub *sc)
332 {
333 xfs_iunlock(sc->tempip, XFS_IOLOCK_EXCL);
334 sc->temp_ilock_flags &= ~XFS_IOLOCK_EXCL;
335 }
336
337 /* Prepare the temporary file for metadata updates by grabbing ILOCK_EXCL. */
338 void
xrep_tempfile_ilock(struct xfs_scrub * sc)339 xrep_tempfile_ilock(
340 struct xfs_scrub *sc)
341 {
342 sc->temp_ilock_flags |= XFS_ILOCK_EXCL;
343 xfs_ilock(sc->tempip, XFS_ILOCK_EXCL);
344 }
345
346 /* Try to grab ILOCK_EXCL on the temporary file. */
347 bool
xrep_tempfile_ilock_nowait(struct xfs_scrub * sc)348 xrep_tempfile_ilock_nowait(
349 struct xfs_scrub *sc)
350 {
351 if (xfs_ilock_nowait(sc->tempip, XFS_ILOCK_EXCL)) {
352 sc->temp_ilock_flags |= XFS_ILOCK_EXCL;
353 return true;
354 }
355
356 return false;
357 }
358
359 /* Unlock ILOCK_EXCL on the temporary file after an update. */
360 void
xrep_tempfile_iunlock(struct xfs_scrub * sc)361 xrep_tempfile_iunlock(
362 struct xfs_scrub *sc)
363 {
364 xfs_iunlock(sc->tempip, XFS_ILOCK_EXCL);
365 sc->temp_ilock_flags &= ~XFS_ILOCK_EXCL;
366 }
367
368 /*
369 * Begin the process of making changes to both the file being scrubbed and
370 * the temporary file by taking ILOCK_EXCL on both.
371 */
372 void
xrep_tempfile_ilock_both(struct xfs_scrub * sc)373 xrep_tempfile_ilock_both(
374 struct xfs_scrub *sc)
375 {
376 xfs_lock_two_inodes(sc->ip, XFS_ILOCK_EXCL, sc->tempip, XFS_ILOCK_EXCL);
377 sc->ilock_flags |= XFS_ILOCK_EXCL;
378 sc->temp_ilock_flags |= XFS_ILOCK_EXCL;
379 }
380
381 /* Unlock ILOCK_EXCL on both files. */
382 void
xrep_tempfile_iunlock_both(struct xfs_scrub * sc)383 xrep_tempfile_iunlock_both(
384 struct xfs_scrub *sc)
385 {
386 xrep_tempfile_iunlock(sc);
387 xchk_iunlock(sc, XFS_ILOCK_EXCL);
388 }
389
390 /* Release the temporary file. */
391 void
xrep_tempfile_rele(struct xfs_scrub * sc)392 xrep_tempfile_rele(
393 struct xfs_scrub *sc)
394 {
395 if (!sc->tempip)
396 return;
397
398 if (sc->temp_ilock_flags) {
399 xfs_iunlock(sc->tempip, sc->temp_ilock_flags);
400 sc->temp_ilock_flags = 0;
401 }
402
403 xrep_tempfile_remove_metadir(sc);
404 xchk_irele(sc, sc->tempip);
405 sc->tempip = NULL;
406 }
407
408 /*
409 * Make sure that the given range of the data fork of the temporary file is
410 * mapped to written blocks. The caller must ensure that both inodes are
411 * joined to the transaction.
412 */
413 int
xrep_tempfile_prealloc(struct xfs_scrub * sc,xfs_fileoff_t off,xfs_filblks_t len)414 xrep_tempfile_prealloc(
415 struct xfs_scrub *sc,
416 xfs_fileoff_t off,
417 xfs_filblks_t len)
418 {
419 struct xfs_bmbt_irec map;
420 xfs_fileoff_t end = off + len;
421 int error;
422
423 ASSERT(sc->tempip != NULL);
424 ASSERT(!XFS_NOT_DQATTACHED(sc->mp, sc->tempip));
425
426 for (; off < end; off = map.br_startoff + map.br_blockcount) {
427 int nmaps = 1;
428
429 /*
430 * If we have a real extent mapping this block then we're
431 * in ok shape.
432 */
433 error = xfs_bmapi_read(sc->tempip, off, end - off, &map, &nmaps,
434 XFS_DATA_FORK);
435 if (error)
436 return error;
437 if (nmaps == 0) {
438 ASSERT(nmaps != 0);
439 return -EFSCORRUPTED;
440 }
441
442 if (xfs_bmap_is_written_extent(&map))
443 continue;
444
445 /*
446 * If we find a delalloc reservation then something is very
447 * very wrong. Bail out.
448 */
449 if (map.br_startblock == DELAYSTARTBLOCK)
450 return -EFSCORRUPTED;
451
452 /*
453 * Make sure this block has a real zeroed extent allocated to
454 * it.
455 */
456 nmaps = 1;
457 error = xfs_bmapi_write(sc->tp, sc->tempip, off, end - off,
458 XFS_BMAPI_CONVERT | XFS_BMAPI_ZERO, 0, &map,
459 &nmaps);
460 if (error)
461 return error;
462 if (nmaps != 1)
463 return -EFSCORRUPTED;
464
465 trace_xrep_tempfile_prealloc(sc, XFS_DATA_FORK, &map);
466
467 /* Commit new extent and all deferred work. */
468 error = xfs_defer_finish(&sc->tp);
469 if (error)
470 return error;
471 }
472
473 return 0;
474 }
475
476 /*
477 * Write data to each block of a file. The given range of the tempfile's data
478 * fork must already be populated with written extents.
479 */
480 int
xrep_tempfile_copyin(struct xfs_scrub * sc,xfs_fileoff_t off,xfs_filblks_t len,xrep_tempfile_copyin_fn prep_fn,void * data)481 xrep_tempfile_copyin(
482 struct xfs_scrub *sc,
483 xfs_fileoff_t off,
484 xfs_filblks_t len,
485 xrep_tempfile_copyin_fn prep_fn,
486 void *data)
487 {
488 LIST_HEAD(buffers_list);
489 struct xfs_mount *mp = sc->mp;
490 struct xfs_buf *bp;
491 xfs_fileoff_t flush_mask;
492 xfs_fileoff_t end = off + len;
493 loff_t pos = XFS_FSB_TO_B(mp, off);
494 int error = 0;
495
496 ASSERT(S_ISREG(VFS_I(sc->tempip)->i_mode));
497
498 /* Flush buffers to disk every 512K */
499 flush_mask = XFS_B_TO_FSBT(mp, (1U << 19)) - 1;
500
501 for (; off < end; off++, pos += mp->m_sb.sb_blocksize) {
502 struct xfs_bmbt_irec map;
503 int nmaps = 1;
504
505 /* Read block mapping for this file block. */
506 error = xfs_bmapi_read(sc->tempip, off, 1, &map, &nmaps, 0);
507 if (error)
508 goto out_err;
509 if (nmaps == 0 || !xfs_bmap_is_written_extent(&map)) {
510 error = -EFSCORRUPTED;
511 goto out_err;
512 }
513
514 /* Get the metadata buffer for this offset in the file. */
515 error = xfs_trans_get_buf(sc->tp, mp->m_ddev_targp,
516 XFS_FSB_TO_DADDR(mp, map.br_startblock),
517 mp->m_bsize, 0, &bp);
518 if (error)
519 goto out_err;
520
521 trace_xrep_tempfile_copyin(sc, XFS_DATA_FORK, &map);
522
523 /* Read in a block's worth of data from the xfile. */
524 error = prep_fn(sc, bp, data);
525 if (error) {
526 xfs_trans_brelse(sc->tp, bp);
527 goto out_err;
528 }
529
530 /* Queue buffer, and flush if we have too much dirty data. */
531 xfs_buf_delwri_queue_here(bp, &buffers_list);
532 xfs_trans_brelse(sc->tp, bp);
533
534 if (!(off & flush_mask)) {
535 error = xfs_buf_delwri_submit(&buffers_list);
536 if (error)
537 goto out_err;
538 }
539 }
540
541 /*
542 * Write the new blocks to disk. If the ordered list isn't empty after
543 * that, then something went wrong and we have to fail. This should
544 * never happen, but we'll check anyway.
545 */
546 error = xfs_buf_delwri_submit(&buffers_list);
547 if (error)
548 goto out_err;
549
550 if (!list_empty(&buffers_list)) {
551 ASSERT(list_empty(&buffers_list));
552 error = -EIO;
553 goto out_err;
554 }
555
556 return 0;
557
558 out_err:
559 xfs_buf_delwri_cancel(&buffers_list);
560 return error;
561 }
562
563 /*
564 * Set the temporary file's size. Caller must join the tempfile to the scrub
565 * transaction and is responsible for adjusting block mappings as needed.
566 */
567 int
xrep_tempfile_set_isize(struct xfs_scrub * sc,unsigned long long isize)568 xrep_tempfile_set_isize(
569 struct xfs_scrub *sc,
570 unsigned long long isize)
571 {
572 if (sc->tempip->i_disk_size == isize)
573 return 0;
574
575 sc->tempip->i_disk_size = isize;
576 i_size_write(VFS_I(sc->tempip), isize);
577 return xrep_tempfile_roll_trans(sc);
578 }
579
580 /*
581 * Roll a repair transaction involving the temporary file. Caller must join
582 * both the temporary file and the file being scrubbed to the transaction.
583 * This function return with both inodes joined to a new scrub transaction,
584 * or the usual negative errno.
585 */
586 int
xrep_tempfile_roll_trans(struct xfs_scrub * sc)587 xrep_tempfile_roll_trans(
588 struct xfs_scrub *sc)
589 {
590 int error;
591
592 xfs_trans_log_inode(sc->tp, sc->tempip, XFS_ILOG_CORE);
593 error = xrep_roll_trans(sc);
594 if (error)
595 return error;
596
597 xfs_trans_ijoin(sc->tp, sc->tempip, 0);
598 return 0;
599 }
600
601 /*
602 * Fill out the mapping exchange request in preparation for atomically
603 * committing the contents of a metadata file that we've rebuilt in the temp
604 * file.
605 */
606 STATIC int
xrep_tempexch_prep_request(struct xfs_scrub * sc,int whichfork,xfs_fileoff_t off,xfs_filblks_t len,struct xrep_tempexch * tx)607 xrep_tempexch_prep_request(
608 struct xfs_scrub *sc,
609 int whichfork,
610 xfs_fileoff_t off,
611 xfs_filblks_t len,
612 struct xrep_tempexch *tx)
613 {
614 struct xfs_exchmaps_req *req = &tx->req;
615
616 memset(tx, 0, sizeof(struct xrep_tempexch));
617
618 /* COW forks don't exist on disk. */
619 if (whichfork == XFS_COW_FORK) {
620 ASSERT(0);
621 return -EINVAL;
622 }
623
624 /* Both files should have the relevant forks. */
625 if (!xfs_ifork_ptr(sc->ip, whichfork) ||
626 !xfs_ifork_ptr(sc->tempip, whichfork)) {
627 ASSERT(xfs_ifork_ptr(sc->ip, whichfork) != NULL);
628 ASSERT(xfs_ifork_ptr(sc->tempip, whichfork) != NULL);
629 return -EINVAL;
630 }
631
632 /* Exchange all mappings in both forks. */
633 req->ip1 = sc->tempip;
634 req->ip2 = sc->ip;
635 req->startoff1 = off;
636 req->startoff2 = off;
637 switch (whichfork) {
638 case XFS_ATTR_FORK:
639 req->flags |= XFS_EXCHMAPS_ATTR_FORK;
640 break;
641 case XFS_DATA_FORK:
642 /* Exchange sizes when exchanging all data fork mappings. */
643 if (off == 0 && len == XFS_MAX_FILEOFF)
644 req->flags |= XFS_EXCHMAPS_SET_SIZES;
645 break;
646 }
647 req->blockcount = len;
648
649 return 0;
650 }
651
652 static inline unsigned int
xrep_tempexch_estimate_sf_resblks(struct xfs_scrub * sc,int whichfork)653 xrep_tempexch_estimate_sf_resblks(
654 struct xfs_scrub *sc,
655 int whichfork)
656 {
657 /* repairing a symlink target */
658 if (S_ISLNK(VFS_I(sc->ip)->i_mode) && whichfork == XFS_DATA_FORK)
659 return 1;
660
661 /* everything else is a directory or an xattr structure */
662 return xfs_dabuf_nfsb(sc->mp, whichfork);
663 }
664
665 /*
666 * Fill out the mapping exchange resource estimation structures in preparation
667 * for exchanging the contents of a metadata file that we've rebuilt in the
668 * temp file. Caller must hold IOLOCK_EXCL but not ILOCK_EXCL on both files.
669 */
670 STATIC int
xrep_tempexch_estimate(struct xfs_scrub * sc,struct xrep_tempexch * tx)671 xrep_tempexch_estimate(
672 struct xfs_scrub *sc,
673 struct xrep_tempexch *tx)
674 {
675 struct xfs_exchmaps_req *req = &tx->req;
676 struct xfs_ifork *ifp;
677 struct xfs_ifork *tifp;
678 int whichfork = xfs_exchmaps_reqfork(req);
679 unsigned int sf_resblks =
680 xrep_tempexch_estimate_sf_resblks(sc, whichfork);
681 int state = 0;
682
683 /*
684 * The exchmaps code only knows how to exchange file fork space
685 * mappings. Any fork data in local format must be promoted to a
686 * single block before the exchange can take place.
687 */
688 ifp = xfs_ifork_ptr(sc->ip, whichfork);
689 if (ifp->if_format == XFS_DINODE_FMT_LOCAL)
690 state |= 1;
691
692 tifp = xfs_ifork_ptr(sc->tempip, whichfork);
693 if (tifp->if_format == XFS_DINODE_FMT_LOCAL)
694 state |= 2;
695
696 switch (state) {
697 case 0:
698 /* Both files have mapped extents; use the regular estimate. */
699 return xfs_exchrange_estimate(req);
700 case 1:
701 /*
702 * The file being repaired is in local format, but the temp
703 * file has mapped extents. To perform the exchange, the file
704 * being repaired must have its shorform data converted to an
705 * ondisk block so that the forks will be in extents format.
706 * We need one resblk for the conversion; the number of
707 * exchanges is (worst case) the temporary file's extent count
708 * plus the block we converted.
709 */
710 req->ip1_bcount = sc->tempip->i_nblocks;
711 req->ip2_bcount = sf_resblks;
712 req->nr_exchanges = 1 + tifp->if_nextents;
713 req->resblks = sf_resblks;
714 break;
715 case 2:
716 /*
717 * The temporary file is in local format, but the file being
718 * repaired has mapped extents. To perform the exchange, the
719 * temp file must have its shortform data converted to an
720 * ondisk block, and the fork changed to extents format. We
721 * need one resblk for the conversion; the number of exchanges
722 * is (worst case) the extent count of the file being repaired
723 * plus the block we converted.
724 */
725 req->ip1_bcount = sf_resblks;
726 req->ip2_bcount = sc->ip->i_nblocks;
727 req->nr_exchanges = 1 + ifp->if_nextents;
728 req->resblks = sf_resblks;
729 break;
730 case 3:
731 /*
732 * Both forks are in local format. To perform the exchange,
733 * both files must have their shortform data converted to
734 * fsblocks, and both forks must be converted to extents
735 * format. We need two resblks for the two conversions, and
736 * the number of exchanges is 1 since there's only one block at
737 * fileoff 0. Presumably, the caller could not exchange the
738 * two inode fork areas directly.
739 */
740 req->ip1_bcount = sf_resblks;
741 req->ip2_bcount = sf_resblks;
742 req->nr_exchanges = 1;
743 req->resblks = 2 * sf_resblks;
744 break;
745 }
746
747 return xfs_exchmaps_estimate_overhead(req);
748 }
749
750 /*
751 * Obtain a quota reservation to make sure we don't hit EDQUOT. We can skip
752 * this if quota enforcement is disabled or if both inodes' dquots are the
753 * same. The qretry structure must be initialized to zeroes before the first
754 * call to this function.
755 */
756 STATIC int
xrep_tempexch_reserve_quota(struct xfs_scrub * sc,const struct xrep_tempexch * tx)757 xrep_tempexch_reserve_quota(
758 struct xfs_scrub *sc,
759 const struct xrep_tempexch *tx)
760 {
761 struct xfs_trans *tp = sc->tp;
762 const struct xfs_exchmaps_req *req = &tx->req;
763 int64_t ddelta, rdelta;
764 int error;
765
766 /*
767 * Don't bother with a quota reservation if we're not enforcing them
768 * or the two inodes have the same dquots.
769 */
770 if (!XFS_IS_QUOTA_ON(tp->t_mountp) || req->ip1 == req->ip2 ||
771 xfs_is_metadir_inode(req->ip1) ||
772 (req->ip1->i_udquot == req->ip2->i_udquot &&
773 req->ip1->i_gdquot == req->ip2->i_gdquot &&
774 req->ip1->i_pdquot == req->ip2->i_pdquot))
775 return 0;
776
777 /*
778 * Quota reservation for each file comes from two sources. First, we
779 * need to account for any net gain in mapped blocks during the
780 * exchange. Second, we need reservation for the gross gain in mapped
781 * blocks so that we don't trip over any quota block reservation
782 * assertions. We must reserve the gross gain because the quota code
783 * subtracts from bcount the number of blocks that we unmap; it does
784 * not add that quantity back to the quota block reservation.
785 */
786 ddelta = max_t(int64_t, 0, req->ip2_bcount - req->ip1_bcount);
787 rdelta = max_t(int64_t, 0, req->ip2_rtbcount - req->ip1_rtbcount);
788 error = xfs_trans_reserve_quota_nblks(tp, req->ip1,
789 ddelta + req->ip1_bcount, rdelta + req->ip1_rtbcount,
790 true);
791 if (error)
792 return error;
793
794 ddelta = max_t(int64_t, 0, req->ip1_bcount - req->ip2_bcount);
795 rdelta = max_t(int64_t, 0, req->ip1_rtbcount - req->ip2_rtbcount);
796 return xfs_trans_reserve_quota_nblks(tp, req->ip2,
797 ddelta + req->ip2_bcount, rdelta + req->ip2_rtbcount,
798 true);
799 }
800
801 /*
802 * Prepare an existing transaction for an atomic file contents exchange.
803 *
804 * This function fills out the mapping exchange request and resource estimation
805 * structures in preparation for exchanging the contents of a metadata file
806 * that has been rebuilt in the temp file. Next, it reserves space and quota
807 * for the transaction.
808 *
809 * The caller must hold ILOCK_EXCL of the scrub target file and the temporary
810 * file. The caller must join both inodes to the transaction with no unlock
811 * flags, and is responsible for dropping both ILOCKs when appropriate. Only
812 * use this when those ILOCKs cannot be dropped.
813 */
814 int
xrep_tempexch_trans_reserve(struct xfs_scrub * sc,int whichfork,xfs_fileoff_t off,xfs_filblks_t len,struct xrep_tempexch * tx)815 xrep_tempexch_trans_reserve(
816 struct xfs_scrub *sc,
817 int whichfork,
818 xfs_fileoff_t off,
819 xfs_filblks_t len,
820 struct xrep_tempexch *tx)
821 {
822 int error;
823
824 ASSERT(sc->tp != NULL);
825 xfs_assert_ilocked(sc->ip, XFS_ILOCK_EXCL);
826 xfs_assert_ilocked(sc->tempip, XFS_ILOCK_EXCL);
827
828 error = xrep_tempexch_prep_request(sc, whichfork, off, len, tx);
829 if (error)
830 return error;
831
832 error = xfs_exchmaps_estimate(&tx->req);
833 if (error)
834 return error;
835
836 error = xfs_trans_reserve_more(sc->tp, tx->req.resblks, 0);
837 if (error)
838 return error;
839
840 return xrep_tempexch_reserve_quota(sc, tx);
841 }
842
843 /*
844 * Create a new transaction for a file contents exchange.
845 *
846 * This function fills out the mapping excahange request and resource
847 * estimation structures in preparation for exchanging the contents of a
848 * metadata file that has been rebuilt in the temp file. Next, it reserves
849 * space, takes ILOCK_EXCL of both inodes, joins them to the transaction and
850 * reserves quota for the transaction.
851 *
852 * The caller is responsible for dropping both ILOCKs when appropriate.
853 */
854 int
xrep_tempexch_trans_alloc(struct xfs_scrub * sc,int whichfork,struct xrep_tempexch * tx)855 xrep_tempexch_trans_alloc(
856 struct xfs_scrub *sc,
857 int whichfork,
858 struct xrep_tempexch *tx)
859 {
860 unsigned int flags = 0;
861 int error;
862
863 ASSERT(sc->tp == NULL);
864 ASSERT(xfs_has_exchange_range(sc->mp));
865
866 error = xrep_tempexch_prep_request(sc, whichfork, 0, XFS_MAX_FILEOFF,
867 tx);
868 if (error)
869 return error;
870
871 error = xrep_tempexch_estimate(sc, tx);
872 if (error)
873 return error;
874
875 if (xfs_has_lazysbcount(sc->mp))
876 flags |= XFS_TRANS_RES_FDBLKS;
877
878 error = xfs_trans_alloc(sc->mp, &M_RES(sc->mp)->tr_itruncate,
879 tx->req.resblks, 0, flags, &sc->tp);
880 if (error)
881 return error;
882
883 sc->temp_ilock_flags |= XFS_ILOCK_EXCL;
884 sc->ilock_flags |= XFS_ILOCK_EXCL;
885 xfs_exchrange_ilock(sc->tp, sc->ip, sc->tempip);
886
887 return xrep_tempexch_reserve_quota(sc, tx);
888 }
889
890 /*
891 * Exchange file mappings (and hence file contents) between the file being
892 * repaired and the temporary file. Returns with both inodes locked and joined
893 * to a clean scrub transaction.
894 */
895 int
xrep_tempexch_contents(struct xfs_scrub * sc,struct xrep_tempexch * tx)896 xrep_tempexch_contents(
897 struct xfs_scrub *sc,
898 struct xrep_tempexch *tx)
899 {
900 int error;
901
902 ASSERT(xfs_has_exchange_range(sc->mp));
903
904 xfs_exchange_mappings(sc->tp, &tx->req);
905 error = xfs_defer_finish(&sc->tp);
906 if (error)
907 return error;
908
909 /*
910 * If we exchanged the ondisk sizes of two metadata files, we must
911 * exchanged the incore sizes as well.
912 */
913 if (tx->req.flags & XFS_EXCHMAPS_SET_SIZES) {
914 loff_t temp;
915
916 temp = i_size_read(VFS_I(sc->ip));
917 i_size_write(VFS_I(sc->ip), i_size_read(VFS_I(sc->tempip)));
918 i_size_write(VFS_I(sc->tempip), temp);
919 }
920
921 return 0;
922 }
923
924 /*
925 * Write local format data from one of the temporary file's forks into the same
926 * fork of file being repaired, and exchange the file sizes, if appropriate.
927 * Caller must ensure that the file being repaired has enough fork space to
928 * hold all the bytes.
929 */
930 void
xrep_tempfile_copyout_local(struct xfs_scrub * sc,int whichfork)931 xrep_tempfile_copyout_local(
932 struct xfs_scrub *sc,
933 int whichfork)
934 {
935 struct xfs_ifork *temp_ifp;
936 struct xfs_ifork *ifp;
937 unsigned int ilog_flags = XFS_ILOG_CORE;
938
939 temp_ifp = xfs_ifork_ptr(sc->tempip, whichfork);
940 ifp = xfs_ifork_ptr(sc->ip, whichfork);
941
942 ASSERT(temp_ifp != NULL);
943 ASSERT(ifp != NULL);
944 ASSERT(temp_ifp->if_format == XFS_DINODE_FMT_LOCAL);
945 ASSERT(ifp->if_format == XFS_DINODE_FMT_LOCAL);
946
947 switch (whichfork) {
948 case XFS_DATA_FORK:
949 ASSERT(sc->tempip->i_disk_size <=
950 xfs_inode_data_fork_size(sc->ip));
951 break;
952 case XFS_ATTR_FORK:
953 ASSERT(sc->tempip->i_forkoff >= sc->ip->i_forkoff);
954 break;
955 default:
956 ASSERT(0);
957 return;
958 }
959
960 /* Recreate @sc->ip's incore fork (ifp) with data from temp_ifp. */
961 xfs_idestroy_fork(ifp);
962 xfs_init_local_fork(sc->ip, whichfork, temp_ifp->if_data,
963 temp_ifp->if_bytes);
964
965 if (whichfork == XFS_DATA_FORK) {
966 i_size_write(VFS_I(sc->ip), i_size_read(VFS_I(sc->tempip)));
967 sc->ip->i_disk_size = sc->tempip->i_disk_size;
968 }
969
970 ilog_flags |= xfs_ilog_fdata(whichfork);
971 xfs_trans_log_inode(sc->tp, sc->ip, ilog_flags);
972 }
973
974 /* Decide if a given XFS inode is a temporary file for a repair. */
975 bool
xrep_is_tempfile(const struct xfs_inode * ip)976 xrep_is_tempfile(
977 const struct xfs_inode *ip)
978 {
979 const struct inode *inode = &ip->i_vnode;
980 struct xfs_mount *mp = ip->i_mount;
981
982 /*
983 * Files in the metadata directory tree also have S_PRIVATE set and
984 * IOP_XATTR unset, so we must distinguish them separately. We (ab)use
985 * the IRECOVERY flag to mark temporary metadir inodes knowing that the
986 * end of log recovery clears IRECOVERY, so the only ones that can
987 * exist during online repair are the ones we create.
988 */
989 if (xfs_has_metadir(mp) && (ip->i_diflags2 & XFS_DIFLAG2_METADATA))
990 return __xfs_iflags_test(ip, XFS_IRECOVERY);
991
992 if (IS_PRIVATE(inode) && !(inode->i_opflags & IOP_XATTR))
993 return true;
994
995 return false;
996 }
997