1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (c) 2021-2024 Oracle. All Rights Reserved.
4 * Author: Darrick J. Wong <djwong@kernel.org>
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"
18 #include "xfs_bmap_btree.h"
19 #include "xfs_trans_space.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"
34 * Create a temporary file for reconstructing metadata, with the intention of
35 * atomically exchanging the temporary file's contents with the file that's
43 struct xfs_icreate_args args
= {
44 .pip
= sc
->mp
->m_rootip
,
46 .flags
= XFS_ICREATE_TMPFILE
| XFS_ICREATE_UNLINKABLE
,
48 struct xfs_mount
*mp
= sc
->mp
;
49 struct xfs_trans
*tp
= NULL
;
50 struct xfs_dquot
*udqp
;
51 struct xfs_dquot
*gdqp
;
52 struct xfs_dquot
*pdqp
;
53 struct xfs_trans_res
*tres
;
54 struct xfs_inode
*dp
= mp
->m_rootip
;
57 bool is_dir
= S_ISDIR(mode
);
60 if (xfs_is_shutdown(mp
))
62 if (xfs_is_readonly(mp
))
65 ASSERT(sc
->tp
== NULL
);
66 ASSERT(sc
->tempip
== NULL
);
69 * Make sure that we have allocated dquot(s) on disk. The temporary
70 * inode should be completely root owned so that we don't fail due to
73 error
= xfs_icreate_dqalloc(&args
, &udqp
, &gdqp
, &pdqp
);
78 resblks
= xfs_mkdir_space_res(mp
, 0);
79 tres
= &M_RES(mp
)->tr_mkdir
;
81 resblks
= XFS_IALLOC_SPACE_RES(mp
);
82 tres
= &M_RES(mp
)->tr_create_tmpfile
;
85 error
= xfs_trans_alloc_icreate(mp
, tres
, udqp
, gdqp
, pdqp
, resblks
,
88 goto out_release_dquots
;
90 /* Allocate inode, set up directory. */
91 error
= xfs_dialloc(&tp
, &args
, &ino
);
93 goto out_trans_cancel
;
94 error
= xfs_icreate(tp
, ino
, &args
, &sc
->tempip
);
96 goto out_trans_cancel
;
98 /* We don't touch file data, so drop the realtime flags. */
99 sc
->tempip
->i_diflags
&= ~(XFS_DIFLAG_REALTIME
| XFS_DIFLAG_RTINHERIT
);
100 xfs_trans_log_inode(tp
, sc
->tempip
, XFS_ILOG_CORE
);
103 * Mark our temporary file as private so that LSMs and the ACL code
104 * don't try to add their own metadata or reason about these files.
105 * The file should never be exposed to userspace.
107 VFS_I(sc
->tempip
)->i_flags
|= S_PRIVATE
;
108 VFS_I(sc
->tempip
)->i_opflags
&= ~IOP_XATTR
;
111 error
= xfs_dir_init(tp
, sc
->tempip
, dp
);
113 goto out_trans_cancel
;
114 } else if (S_ISLNK(VFS_I(sc
->tempip
)->i_mode
)) {
116 * Initialize the temporary symlink with a meaningless target
117 * that won't trip the verifiers. Repair must rewrite the
118 * target with meaningful content before swapping with the file
119 * being repaired. A single-byte target will not write a
120 * remote target block, so the owner is irrelevant.
122 error
= xfs_symlink_write_target(tp
, sc
->tempip
,
123 sc
->tempip
->i_ino
, ".", 1, 0, 0);
125 goto out_trans_cancel
;
129 * Attach the dquot(s) to the inodes and modify them incore.
130 * These ids of the inode couldn't have changed since the new
131 * inode has been locked ever since it was created.
133 xfs_qm_vop_create_dqattach(tp
, sc
->tempip
, udqp
, gdqp
, pdqp
);
136 * Put our temp file on the unlinked list so it's purged automatically.
137 * All file-based metadata being reconstructed using this file must be
138 * atomically exchanged with the original file because the contents
139 * here will be purged when the inode is dropped or log recovery cleans
140 * out the unlinked list.
142 error
= xfs_iunlink(tp
, sc
->tempip
);
144 goto out_trans_cancel
;
146 error
= xfs_trans_commit(tp
);
148 goto out_release_inode
;
150 trace_xrep_tempfile_create(sc
);
156 /* Finish setting up the incore / vfs context. */
157 xfs_iunlock(sc
->tempip
, XFS_ILOCK_EXCL
);
158 xfs_setup_iops(sc
->tempip
);
159 xfs_finish_inode_setup(sc
->tempip
);
161 sc
->temp_ilock_flags
= 0;
165 xfs_trans_cancel(tp
);
168 * Wait until after the current transaction is aborted to finish the
169 * setup of the inode and release the inode. This prevents recursive
170 * transactions and deadlocks from xfs_inactive.
173 xfs_iunlock(sc
->tempip
, XFS_ILOCK_EXCL
);
174 xfs_finish_inode_setup(sc
->tempip
);
175 xchk_irele(sc
, sc
->tempip
);
185 /* Take IOLOCK_EXCL on the temporary file, maybe. */
187 xrep_tempfile_iolock_nowait(
188 struct xfs_scrub
*sc
)
190 if (xfs_ilock_nowait(sc
->tempip
, XFS_IOLOCK_EXCL
)) {
191 sc
->temp_ilock_flags
|= XFS_IOLOCK_EXCL
;
199 * Take the temporary file's IOLOCK while holding a different inode's IOLOCK.
200 * In theory nobody else should hold the tempfile's IOLOCK, but we use trylock
201 * to avoid deadlocks and lockdep complaints.
204 xrep_tempfile_iolock_polled(
205 struct xfs_scrub
*sc
)
209 while (!xrep_tempfile_iolock_nowait(sc
)) {
210 if (xchk_should_terminate(sc
, &error
))
218 /* Release IOLOCK_EXCL on the temporary file. */
220 xrep_tempfile_iounlock(
221 struct xfs_scrub
*sc
)
223 xfs_iunlock(sc
->tempip
, XFS_IOLOCK_EXCL
);
224 sc
->temp_ilock_flags
&= ~XFS_IOLOCK_EXCL
;
227 /* Prepare the temporary file for metadata updates by grabbing ILOCK_EXCL. */
230 struct xfs_scrub
*sc
)
232 sc
->temp_ilock_flags
|= XFS_ILOCK_EXCL
;
233 xfs_ilock(sc
->tempip
, XFS_ILOCK_EXCL
);
236 /* Try to grab ILOCK_EXCL on the temporary file. */
238 xrep_tempfile_ilock_nowait(
239 struct xfs_scrub
*sc
)
241 if (xfs_ilock_nowait(sc
->tempip
, XFS_ILOCK_EXCL
)) {
242 sc
->temp_ilock_flags
|= XFS_ILOCK_EXCL
;
249 /* Unlock ILOCK_EXCL on the temporary file after an update. */
251 xrep_tempfile_iunlock(
252 struct xfs_scrub
*sc
)
254 xfs_iunlock(sc
->tempip
, XFS_ILOCK_EXCL
);
255 sc
->temp_ilock_flags
&= ~XFS_ILOCK_EXCL
;
259 * Begin the process of making changes to both the file being scrubbed and
260 * the temporary file by taking ILOCK_EXCL on both.
263 xrep_tempfile_ilock_both(
264 struct xfs_scrub
*sc
)
266 xfs_lock_two_inodes(sc
->ip
, XFS_ILOCK_EXCL
, sc
->tempip
, XFS_ILOCK_EXCL
);
267 sc
->ilock_flags
|= XFS_ILOCK_EXCL
;
268 sc
->temp_ilock_flags
|= XFS_ILOCK_EXCL
;
271 /* Unlock ILOCK_EXCL on both files. */
273 xrep_tempfile_iunlock_both(
274 struct xfs_scrub
*sc
)
276 xrep_tempfile_iunlock(sc
);
277 xchk_iunlock(sc
, XFS_ILOCK_EXCL
);
280 /* Release the temporary file. */
283 struct xfs_scrub
*sc
)
288 if (sc
->temp_ilock_flags
) {
289 xfs_iunlock(sc
->tempip
, sc
->temp_ilock_flags
);
290 sc
->temp_ilock_flags
= 0;
293 xchk_irele(sc
, sc
->tempip
);
298 * Make sure that the given range of the data fork of the temporary file is
299 * mapped to written blocks. The caller must ensure that both inodes are
300 * joined to the transaction.
303 xrep_tempfile_prealloc(
304 struct xfs_scrub
*sc
,
308 struct xfs_bmbt_irec map
;
309 xfs_fileoff_t end
= off
+ len
;
312 ASSERT(sc
->tempip
!= NULL
);
313 ASSERT(!XFS_NOT_DQATTACHED(sc
->mp
, sc
->tempip
));
315 for (; off
< end
; off
= map
.br_startoff
+ map
.br_blockcount
) {
319 * If we have a real extent mapping this block then we're
322 error
= xfs_bmapi_read(sc
->tempip
, off
, end
- off
, &map
, &nmaps
,
328 return -EFSCORRUPTED
;
331 if (xfs_bmap_is_written_extent(&map
))
335 * If we find a delalloc reservation then something is very
336 * very wrong. Bail out.
338 if (map
.br_startblock
== DELAYSTARTBLOCK
)
339 return -EFSCORRUPTED
;
342 * Make sure this block has a real zeroed extent allocated to
346 error
= xfs_bmapi_write(sc
->tp
, sc
->tempip
, off
, end
- off
,
347 XFS_BMAPI_CONVERT
| XFS_BMAPI_ZERO
, 0, &map
,
352 return -EFSCORRUPTED
;
354 trace_xrep_tempfile_prealloc(sc
, XFS_DATA_FORK
, &map
);
356 /* Commit new extent and all deferred work. */
357 error
= xfs_defer_finish(&sc
->tp
);
366 * Write data to each block of a file. The given range of the tempfile's data
367 * fork must already be populated with written extents.
370 xrep_tempfile_copyin(
371 struct xfs_scrub
*sc
,
374 xrep_tempfile_copyin_fn prep_fn
,
377 LIST_HEAD(buffers_list
);
378 struct xfs_mount
*mp
= sc
->mp
;
380 xfs_fileoff_t flush_mask
;
381 xfs_fileoff_t end
= off
+ len
;
382 loff_t pos
= XFS_FSB_TO_B(mp
, off
);
385 ASSERT(S_ISREG(VFS_I(sc
->tempip
)->i_mode
));
387 /* Flush buffers to disk every 512K */
388 flush_mask
= XFS_B_TO_FSBT(mp
, (1U << 19)) - 1;
390 for (; off
< end
; off
++, pos
+= mp
->m_sb
.sb_blocksize
) {
391 struct xfs_bmbt_irec map
;
394 /* Read block mapping for this file block. */
395 error
= xfs_bmapi_read(sc
->tempip
, off
, 1, &map
, &nmaps
, 0);
398 if (nmaps
== 0 || !xfs_bmap_is_written_extent(&map
)) {
399 error
= -EFSCORRUPTED
;
403 /* Get the metadata buffer for this offset in the file. */
404 error
= xfs_trans_get_buf(sc
->tp
, mp
->m_ddev_targp
,
405 XFS_FSB_TO_DADDR(mp
, map
.br_startblock
),
406 mp
->m_bsize
, 0, &bp
);
410 trace_xrep_tempfile_copyin(sc
, XFS_DATA_FORK
, &map
);
412 /* Read in a block's worth of data from the xfile. */
413 error
= prep_fn(sc
, bp
, data
);
415 xfs_trans_brelse(sc
->tp
, bp
);
419 /* Queue buffer, and flush if we have too much dirty data. */
420 xfs_buf_delwri_queue_here(bp
, &buffers_list
);
421 xfs_trans_brelse(sc
->tp
, bp
);
423 if (!(off
& flush_mask
)) {
424 error
= xfs_buf_delwri_submit(&buffers_list
);
431 * Write the new blocks to disk. If the ordered list isn't empty after
432 * that, then something went wrong and we have to fail. This should
433 * never happen, but we'll check anyway.
435 error
= xfs_buf_delwri_submit(&buffers_list
);
439 if (!list_empty(&buffers_list
)) {
440 ASSERT(list_empty(&buffers_list
));
448 xfs_buf_delwri_cancel(&buffers_list
);
453 * Set the temporary file's size. Caller must join the tempfile to the scrub
454 * transaction and is responsible for adjusting block mappings as needed.
457 xrep_tempfile_set_isize(
458 struct xfs_scrub
*sc
,
459 unsigned long long isize
)
461 if (sc
->tempip
->i_disk_size
== isize
)
464 sc
->tempip
->i_disk_size
= isize
;
465 i_size_write(VFS_I(sc
->tempip
), isize
);
466 return xrep_tempfile_roll_trans(sc
);
470 * Roll a repair transaction involving the temporary file. Caller must join
471 * both the temporary file and the file being scrubbed to the transaction.
472 * This function return with both inodes joined to a new scrub transaction,
473 * or the usual negative errno.
476 xrep_tempfile_roll_trans(
477 struct xfs_scrub
*sc
)
481 xfs_trans_log_inode(sc
->tp
, sc
->tempip
, XFS_ILOG_CORE
);
482 error
= xrep_roll_trans(sc
);
486 xfs_trans_ijoin(sc
->tp
, sc
->tempip
, 0);
491 * Fill out the mapping exchange request in preparation for atomically
492 * committing the contents of a metadata file that we've rebuilt in the temp
496 xrep_tempexch_prep_request(
497 struct xfs_scrub
*sc
,
499 struct xrep_tempexch
*tx
)
501 struct xfs_exchmaps_req
*req
= &tx
->req
;
503 memset(tx
, 0, sizeof(struct xrep_tempexch
));
505 /* COW forks don't exist on disk. */
506 if (whichfork
== XFS_COW_FORK
) {
511 /* Both files should have the relevant forks. */
512 if (!xfs_ifork_ptr(sc
->ip
, whichfork
) ||
513 !xfs_ifork_ptr(sc
->tempip
, whichfork
)) {
514 ASSERT(xfs_ifork_ptr(sc
->ip
, whichfork
) != NULL
);
515 ASSERT(xfs_ifork_ptr(sc
->tempip
, whichfork
) != NULL
);
519 /* Exchange all mappings in both forks. */
520 req
->ip1
= sc
->tempip
;
526 req
->flags
|= XFS_EXCHMAPS_ATTR_FORK
;
529 /* Always exchange sizes when exchanging data fork mappings. */
530 req
->flags
|= XFS_EXCHMAPS_SET_SIZES
;
533 req
->blockcount
= XFS_MAX_FILEOFF
;
539 * Fill out the mapping exchange resource estimation structures in preparation
540 * for exchanging the contents of a metadata file that we've rebuilt in the
541 * temp file. Caller must hold IOLOCK_EXCL but not ILOCK_EXCL on both files.
544 xrep_tempexch_estimate(
545 struct xfs_scrub
*sc
,
546 struct xrep_tempexch
*tx
)
548 struct xfs_exchmaps_req
*req
= &tx
->req
;
549 struct xfs_ifork
*ifp
;
550 struct xfs_ifork
*tifp
;
551 int whichfork
= xfs_exchmaps_reqfork(req
);
555 * The exchmaps code only knows how to exchange file fork space
556 * mappings. Any fork data in local format must be promoted to a
557 * single block before the exchange can take place.
559 ifp
= xfs_ifork_ptr(sc
->ip
, whichfork
);
560 if (ifp
->if_format
== XFS_DINODE_FMT_LOCAL
)
563 tifp
= xfs_ifork_ptr(sc
->tempip
, whichfork
);
564 if (tifp
->if_format
== XFS_DINODE_FMT_LOCAL
)
569 /* Both files have mapped extents; use the regular estimate. */
570 return xfs_exchrange_estimate(req
);
573 * The file being repaired is in local format, but the temp
574 * file has mapped extents. To perform the exchange, the file
575 * being repaired must have its shorform data converted to an
576 * ondisk block so that the forks will be in extents format.
577 * We need one resblk for the conversion; the number of
578 * exchanges is (worst case) the temporary file's extent count
579 * plus the block we converted.
581 req
->ip1_bcount
= sc
->tempip
->i_nblocks
;
583 req
->nr_exchanges
= 1 + tifp
->if_nextents
;
588 * The temporary file is in local format, but the file being
589 * repaired has mapped extents. To perform the exchange, the
590 * temp file must have its shortform data converted to an
591 * ondisk block, and the fork changed to extents format. We
592 * need one resblk for the conversion; the number of exchanges
593 * is (worst case) the extent count of the file being repaired
594 * plus the block we converted.
597 req
->ip2_bcount
= sc
->ip
->i_nblocks
;
598 req
->nr_exchanges
= 1 + ifp
->if_nextents
;
603 * Both forks are in local format. To perform the exchange,
604 * both files must have their shortform data converted to
605 * fsblocks, and both forks must be converted to extents
606 * format. We need two resblks for the two conversions, and
607 * the number of exchanges is 1 since there's only one block at
608 * fileoff 0. Presumably, the caller could not exchange the
609 * two inode fork areas directly.
613 req
->nr_exchanges
= 1;
618 return xfs_exchmaps_estimate_overhead(req
);
622 * Obtain a quota reservation to make sure we don't hit EDQUOT. We can skip
623 * this if quota enforcement is disabled or if both inodes' dquots are the
624 * same. The qretry structure must be initialized to zeroes before the first
625 * call to this function.
628 xrep_tempexch_reserve_quota(
629 struct xfs_scrub
*sc
,
630 const struct xrep_tempexch
*tx
)
632 struct xfs_trans
*tp
= sc
->tp
;
633 const struct xfs_exchmaps_req
*req
= &tx
->req
;
634 int64_t ddelta
, rdelta
;
638 * Don't bother with a quota reservation if we're not enforcing them
639 * or the two inodes have the same dquots.
641 if (!XFS_IS_QUOTA_ON(tp
->t_mountp
) || req
->ip1
== req
->ip2
||
642 (req
->ip1
->i_udquot
== req
->ip2
->i_udquot
&&
643 req
->ip1
->i_gdquot
== req
->ip2
->i_gdquot
&&
644 req
->ip1
->i_pdquot
== req
->ip2
->i_pdquot
))
648 * Quota reservation for each file comes from two sources. First, we
649 * need to account for any net gain in mapped blocks during the
650 * exchange. Second, we need reservation for the gross gain in mapped
651 * blocks so that we don't trip over any quota block reservation
652 * assertions. We must reserve the gross gain because the quota code
653 * subtracts from bcount the number of blocks that we unmap; it does
654 * not add that quantity back to the quota block reservation.
656 ddelta
= max_t(int64_t, 0, req
->ip2_bcount
- req
->ip1_bcount
);
657 rdelta
= max_t(int64_t, 0, req
->ip2_rtbcount
- req
->ip1_rtbcount
);
658 error
= xfs_trans_reserve_quota_nblks(tp
, req
->ip1
,
659 ddelta
+ req
->ip1_bcount
, rdelta
+ req
->ip1_rtbcount
,
664 ddelta
= max_t(int64_t, 0, req
->ip1_bcount
- req
->ip2_bcount
);
665 rdelta
= max_t(int64_t, 0, req
->ip1_rtbcount
- req
->ip2_rtbcount
);
666 return xfs_trans_reserve_quota_nblks(tp
, req
->ip2
,
667 ddelta
+ req
->ip2_bcount
, rdelta
+ req
->ip2_rtbcount
,
672 * Prepare an existing transaction for an atomic file contents exchange.
674 * This function fills out the mapping exchange request and resource estimation
675 * structures in preparation for exchanging the contents of a metadata file
676 * that has been rebuilt in the temp file. Next, it reserves space and quota
677 * for the transaction.
679 * The caller must hold ILOCK_EXCL of the scrub target file and the temporary
680 * file. The caller must join both inodes to the transaction with no unlock
681 * flags, and is responsible for dropping both ILOCKs when appropriate. Only
682 * use this when those ILOCKs cannot be dropped.
685 xrep_tempexch_trans_reserve(
686 struct xfs_scrub
*sc
,
688 struct xrep_tempexch
*tx
)
692 ASSERT(sc
->tp
!= NULL
);
693 xfs_assert_ilocked(sc
->ip
, XFS_ILOCK_EXCL
);
694 xfs_assert_ilocked(sc
->tempip
, XFS_ILOCK_EXCL
);
696 error
= xrep_tempexch_prep_request(sc
, whichfork
, tx
);
700 error
= xfs_exchmaps_estimate(&tx
->req
);
704 error
= xfs_trans_reserve_more(sc
->tp
, tx
->req
.resblks
, 0);
708 return xrep_tempexch_reserve_quota(sc
, tx
);
712 * Create a new transaction for a file contents exchange.
714 * This function fills out the mapping excahange request and resource
715 * estimation structures in preparation for exchanging the contents of a
716 * metadata file that has been rebuilt in the temp file. Next, it reserves
717 * space, takes ILOCK_EXCL of both inodes, joins them to the transaction and
718 * reserves quota for the transaction.
720 * The caller is responsible for dropping both ILOCKs when appropriate.
723 xrep_tempexch_trans_alloc(
724 struct xfs_scrub
*sc
,
726 struct xrep_tempexch
*tx
)
728 unsigned int flags
= 0;
731 ASSERT(sc
->tp
== NULL
);
732 ASSERT(xfs_has_exchange_range(sc
->mp
));
734 error
= xrep_tempexch_prep_request(sc
, whichfork
, tx
);
738 error
= xrep_tempexch_estimate(sc
, tx
);
742 if (xfs_has_lazysbcount(sc
->mp
))
743 flags
|= XFS_TRANS_RES_FDBLKS
;
745 error
= xfs_trans_alloc(sc
->mp
, &M_RES(sc
->mp
)->tr_itruncate
,
746 tx
->req
.resblks
, 0, flags
, &sc
->tp
);
750 sc
->temp_ilock_flags
|= XFS_ILOCK_EXCL
;
751 sc
->ilock_flags
|= XFS_ILOCK_EXCL
;
752 xfs_exchrange_ilock(sc
->tp
, sc
->ip
, sc
->tempip
);
754 return xrep_tempexch_reserve_quota(sc
, tx
);
758 * Exchange file mappings (and hence file contents) between the file being
759 * repaired and the temporary file. Returns with both inodes locked and joined
760 * to a clean scrub transaction.
763 xrep_tempexch_contents(
764 struct xfs_scrub
*sc
,
765 struct xrep_tempexch
*tx
)
769 ASSERT(xfs_has_exchange_range(sc
->mp
));
771 xfs_exchange_mappings(sc
->tp
, &tx
->req
);
772 error
= xfs_defer_finish(&sc
->tp
);
777 * If we exchanged the ondisk sizes of two metadata files, we must
778 * exchanged the incore sizes as well.
780 if (tx
->req
.flags
& XFS_EXCHMAPS_SET_SIZES
) {
783 temp
= i_size_read(VFS_I(sc
->ip
));
784 i_size_write(VFS_I(sc
->ip
), i_size_read(VFS_I(sc
->tempip
)));
785 i_size_write(VFS_I(sc
->tempip
), temp
);
792 * Write local format data from one of the temporary file's forks into the same
793 * fork of file being repaired, and exchange the file sizes, if appropriate.
794 * Caller must ensure that the file being repaired has enough fork space to
795 * hold all the bytes.
798 xrep_tempfile_copyout_local(
799 struct xfs_scrub
*sc
,
802 struct xfs_ifork
*temp_ifp
;
803 struct xfs_ifork
*ifp
;
804 unsigned int ilog_flags
= XFS_ILOG_CORE
;
806 temp_ifp
= xfs_ifork_ptr(sc
->tempip
, whichfork
);
807 ifp
= xfs_ifork_ptr(sc
->ip
, whichfork
);
809 ASSERT(temp_ifp
!= NULL
);
811 ASSERT(temp_ifp
->if_format
== XFS_DINODE_FMT_LOCAL
);
812 ASSERT(ifp
->if_format
== XFS_DINODE_FMT_LOCAL
);
816 ASSERT(sc
->tempip
->i_disk_size
<=
817 xfs_inode_data_fork_size(sc
->ip
));
820 ASSERT(sc
->tempip
->i_forkoff
>= sc
->ip
->i_forkoff
);
827 /* Recreate @sc->ip's incore fork (ifp) with data from temp_ifp. */
828 xfs_idestroy_fork(ifp
);
829 xfs_init_local_fork(sc
->ip
, whichfork
, temp_ifp
->if_data
,
832 if (whichfork
== XFS_DATA_FORK
) {
833 i_size_write(VFS_I(sc
->ip
), i_size_read(VFS_I(sc
->tempip
)));
834 sc
->ip
->i_disk_size
= sc
->tempip
->i_disk_size
;
837 ilog_flags
|= xfs_ilog_fdata(whichfork
);
838 xfs_trans_log_inode(sc
->tp
, sc
->ip
, ilog_flags
);
841 /* Decide if a given XFS inode is a temporary file for a repair. */
844 const struct xfs_inode
*ip
)
846 const struct inode
*inode
= &ip
->i_vnode
;
848 if (IS_PRIVATE(inode
) && !(inode
->i_opflags
& IOP_XATTR
))