Lines Matching +full:ip +full:- +full:block

1 // SPDX-License-Identifier: GPL-2.0+
40 * through the use of a copy-on-write mechanism. At a high level, that
41 * means that when we want to write to a shared block, we allocate a new
42 * block, write the data to the new block, and if that succeeds we map the
43 * new block into the file.
46 * of disk blocks to dirty-but-not-yet-mapped file blocks as long as
50 * The delalloc mechanism begins when the kernel wants to make a block
52 * create a delalloc mapping, which is a regular in-core extent, but without
54 * a flag that this is a delalloc mapping, and a worst-case estimate of how
64 * D: --RRRRRRSSSRRRRRRRR--- (data fork)
65 * C: ------DDDDDDD--------- (CoW fork)
73 * D: --RRRRRRSSSRRRRRRRR---
74 * C: ------UUUUUUU---------
76 * We want to adapt the delalloc mechanism for copy-on-write, since the
86 * Block-aligned directio writes will use the same mechanism as buffered
94 * D: --RRRRRRSSSRRRRRRRR---
95 * C: ------UUrrUUU---------
97 * CoW remapping must be done after the data block write completes,
99 * the new block has been written. Since the new mappings are kept in a
105 * only to remap the blocks that we've actually written out -- we must
110 * D: --RRRRRRrrSRRRRRRRR---
111 * C: ------UU--UUU---------
123 * Given an AG extent, find the lowest-numbered run of shared blocks
147 cur = xfs_refcountbt_init_cursor(pag->pag_mount, tp, agbp, pag); in xfs_reflink_find_shared()
159 * Trim the mapping to the next block where there's a change in the
161 * find the lowest-numbered extent of shared blocks that coincides with
162 * the given block mapping. If the shared extent overlaps the start of
170 struct xfs_inode *ip, in xfs_reflink_trim_around_shared() argument
174 struct xfs_mount *mp = ip->i_mount; in xfs_reflink_trim_around_shared()
183 if (!xfs_is_cow_inode(ip) || !xfs_bmap_is_written_extent(irec)) { in xfs_reflink_trim_around_shared()
188 trace_xfs_reflink_trim_around_shared(ip, irec); in xfs_reflink_trim_around_shared()
190 pag = xfs_perag_get(mp, XFS_FSB_TO_AGNO(mp, irec->br_startblock)); in xfs_reflink_trim_around_shared()
191 agbno = XFS_FSB_TO_AGBNO(mp, irec->br_startblock); in xfs_reflink_trim_around_shared()
192 aglen = irec->br_blockcount; in xfs_reflink_trim_around_shared()
213 irec->br_blockcount = flen; in xfs_reflink_trim_around_shared()
224 irec->br_blockcount = fbno - agbno; in xfs_reflink_trim_around_shared()
230 struct xfs_inode *ip, in xfs_bmap_trim_cow() argument
235 if (xfs_is_always_cow_inode(ip) && in xfs_bmap_trim_cow()
236 !isnullstartblock(imap->br_startblock)) { in xfs_bmap_trim_cow()
242 return xfs_reflink_trim_around_shared(ip, imap, shared); in xfs_bmap_trim_cow()
247 struct xfs_inode *ip, in xfs_reflink_convert_cow_locked() argument
257 if (!xfs_iext_lookup_extent(ip, ip->i_cowfp, offset_fsb, &icur, &got)) in xfs_reflink_convert_cow_locked()
266 return -EIO; in xfs_reflink_convert_cow_locked()
273 error = xfs_bmap_add_extent_unwritten_real(NULL, ip, in xfs_reflink_convert_cow_locked()
278 } while (xfs_iext_next_extent(ip->i_cowfp, &icur, &got)); in xfs_reflink_convert_cow_locked()
286 struct xfs_inode *ip, in xfs_reflink_convert_cow() argument
290 struct xfs_mount *mp = ip->i_mount; in xfs_reflink_convert_cow()
293 xfs_filblks_t count_fsb = end_fsb - offset_fsb; in xfs_reflink_convert_cow()
298 xfs_ilock(ip, XFS_ILOCK_EXCL); in xfs_reflink_convert_cow()
299 error = xfs_reflink_convert_cow_locked(ip, offset_fsb, count_fsb); in xfs_reflink_convert_cow()
300 xfs_iunlock(ip, XFS_ILOCK_EXCL); in xfs_reflink_convert_cow()
311 struct xfs_inode *ip, in xfs_find_trim_cow_extent() argument
317 xfs_fileoff_t offset_fsb = imap->br_startoff; in xfs_find_trim_cow_extent()
318 xfs_filblks_t count_fsb = imap->br_blockcount; in xfs_find_trim_cow_extent()
327 if (!xfs_iext_lookup_extent(ip, ip->i_cowfp, offset_fsb, &icur, cmap)) in xfs_find_trim_cow_extent()
328 cmap->br_startoff = offset_fsb + count_fsb; in xfs_find_trim_cow_extent()
329 if (cmap->br_startoff > offset_fsb) { in xfs_find_trim_cow_extent()
330 xfs_trim_extent(imap, imap->br_startoff, in xfs_find_trim_cow_extent()
331 cmap->br_startoff - imap->br_startoff); in xfs_find_trim_cow_extent()
332 return xfs_bmap_trim_cow(ip, imap, shared); in xfs_find_trim_cow_extent()
336 if (isnullstartblock(cmap->br_startblock)) { in xfs_find_trim_cow_extent()
337 xfs_trim_extent(imap, cmap->br_startoff, cmap->br_blockcount); in xfs_find_trim_cow_extent()
341 /* real extent found - no need to allocate */ in xfs_find_trim_cow_extent()
349 struct xfs_inode *ip, in xfs_reflink_convert_unwritten() argument
354 xfs_fileoff_t offset_fsb = imap->br_startoff; in xfs_reflink_convert_unwritten()
355 xfs_filblks_t count_fsb = imap->br_blockcount; in xfs_reflink_convert_unwritten()
368 if (!convert_now || cmap->br_state == XFS_EXT_NORM) in xfs_reflink_convert_unwritten()
371 trace_xfs_reflink_convert_cow(ip, cmap); in xfs_reflink_convert_unwritten()
373 error = xfs_reflink_convert_cow_locked(ip, offset_fsb, count_fsb); in xfs_reflink_convert_unwritten()
375 cmap->br_state = XFS_EXT_NORM; in xfs_reflink_convert_unwritten()
382 struct xfs_inode *ip, in xfs_reflink_fill_cow_hole() argument
389 struct xfs_mount *mp = ip->i_mount; in xfs_reflink_fill_cow_hole()
397 resaligned = xfs_aligned_fsb_count(imap->br_startoff, in xfs_reflink_fill_cow_hole()
398 imap->br_blockcount, xfs_get_cowextsz_hint(ip)); in xfs_reflink_fill_cow_hole()
401 xfs_iunlock(ip, *lockmode); in xfs_reflink_fill_cow_hole()
404 error = xfs_trans_alloc_inode(ip, &M_RES(mp)->tr_write, resblks, 0, in xfs_reflink_fill_cow_hole()
411 error = xfs_find_trim_cow_extent(ip, imap, cmap, shared, &found); in xfs_reflink_fill_cow_hole()
422 error = xfs_bmapi_write(tp, ip, imap->br_startoff, imap->br_blockcount, in xfs_reflink_fill_cow_hole()
428 xfs_inode_set_cowblocks_tag(ip); in xfs_reflink_fill_cow_hole()
434 return xfs_reflink_convert_unwritten(ip, imap, cmap, convert_now); in xfs_reflink_fill_cow_hole()
443 struct xfs_inode *ip, in xfs_reflink_fill_delalloc() argument
450 struct xfs_mount *mp = ip->i_mount; in xfs_reflink_fill_delalloc()
457 xfs_iunlock(ip, *lockmode); in xfs_reflink_fill_delalloc()
460 error = xfs_trans_alloc_inode(ip, &M_RES(mp)->tr_write, 0, 0, in xfs_reflink_fill_delalloc()
467 error = xfs_find_trim_cow_extent(ip, imap, cmap, shared, in xfs_reflink_fill_delalloc()
477 ASSERT(isnullstartblock(cmap->br_startblock) || in xfs_reflink_fill_delalloc()
478 cmap->br_startblock == DELAYSTARTBLOCK); in xfs_reflink_fill_delalloc()
484 error = xfs_bmapi_write(tp, ip, cmap->br_startoff, in xfs_reflink_fill_delalloc()
485 cmap->br_blockcount, in xfs_reflink_fill_delalloc()
491 xfs_inode_set_cowblocks_tag(ip); in xfs_reflink_fill_delalloc()
495 } while (cmap->br_startoff + cmap->br_blockcount <= imap->br_startoff); in xfs_reflink_fill_delalloc()
497 return xfs_reflink_convert_unwritten(ip, imap, cmap, convert_now); in xfs_reflink_fill_delalloc()
507 struct xfs_inode *ip, in xfs_reflink_allocate_cow() argument
517 xfs_assert_ilocked(ip, XFS_ILOCK_EXCL); in xfs_reflink_allocate_cow()
518 if (!ip->i_cowfp) { in xfs_reflink_allocate_cow()
519 ASSERT(!xfs_is_reflink_inode(ip)); in xfs_reflink_allocate_cow()
520 xfs_ifork_init_cow(ip); in xfs_reflink_allocate_cow()
523 error = xfs_find_trim_cow_extent(ip, imap, cmap, shared, &found); in xfs_reflink_allocate_cow()
529 return xfs_reflink_convert_unwritten(ip, imap, cmap, in xfs_reflink_allocate_cow()
536 if (cmap->br_startoff > imap->br_startoff) in xfs_reflink_allocate_cow()
537 return xfs_reflink_fill_cow_hole(ip, imap, cmap, shared, in xfs_reflink_allocate_cow()
544 if (isnullstartblock(cmap->br_startblock) || in xfs_reflink_allocate_cow()
545 cmap->br_startblock == DELAYSTARTBLOCK) in xfs_reflink_allocate_cow()
546 return xfs_reflink_fill_delalloc(ip, imap, cmap, shared, in xfs_reflink_allocate_cow()
551 return -EFSCORRUPTED; in xfs_reflink_allocate_cow()
555 * Cancel CoW reservations for some block range of an inode.
565 struct xfs_inode *ip, in xfs_reflink_cancel_cow_blocks() argument
571 struct xfs_ifork *ifp = xfs_ifork_ptr(ip, XFS_COW_FORK); in xfs_reflink_cancel_cow_blocks()
576 if (!xfs_inode_has_cow_data(ip)) in xfs_reflink_cancel_cow_blocks()
578 if (!xfs_iext_lookup_extent_before(ip, ifp, &end_fsb, &icur, &got)) in xfs_reflink_cancel_cow_blocks()
584 xfs_trim_extent(&del, offset_fsb, end_fsb - offset_fsb); in xfs_reflink_cancel_cow_blocks()
592 trace_xfs_reflink_cancel_cow(ip, &del); in xfs_reflink_cancel_cow_blocks()
595 xfs_bmap_del_extent_delay(ip, XFS_COW_FORK, &icur, &got, in xfs_reflink_cancel_cow_blocks()
598 ASSERT((*tpp)->t_highest_agno == NULLAGNUMBER); in xfs_reflink_cancel_cow_blocks()
616 xfs_bmap_del_extent_cow(ip, &icur, &got, &del); in xfs_reflink_cancel_cow_blocks()
619 xfs_quota_unreserve_blkres(ip, del.br_blockcount); in xfs_reflink_cancel_cow_blocks()
630 if (!ifp->if_bytes) in xfs_reflink_cancel_cow_blocks()
631 xfs_inode_clear_cowblocks_tag(ip); in xfs_reflink_cancel_cow_blocks()
643 struct xfs_inode *ip, in xfs_reflink_cancel_cow_range() argument
653 trace_xfs_reflink_cancel_cow_range(ip, offset, count); in xfs_reflink_cancel_cow_range()
654 ASSERT(ip->i_cowfp); in xfs_reflink_cancel_cow_range()
656 offset_fsb = XFS_B_TO_FSBT(ip->i_mount, offset); in xfs_reflink_cancel_cow_range()
660 end_fsb = XFS_B_TO_FSB(ip->i_mount, offset + count); in xfs_reflink_cancel_cow_range()
663 error = xfs_trans_alloc(ip->i_mount, &M_RES(ip->i_mount)->tr_write, in xfs_reflink_cancel_cow_range()
668 xfs_ilock(ip, XFS_ILOCK_EXCL); in xfs_reflink_cancel_cow_range()
669 xfs_trans_ijoin(tp, ip, 0); in xfs_reflink_cancel_cow_range()
672 error = xfs_reflink_cancel_cow_blocks(ip, &tp, offset_fsb, end_fsb, in xfs_reflink_cancel_cow_range()
679 xfs_iunlock(ip, XFS_ILOCK_EXCL); in xfs_reflink_cancel_cow_range()
684 xfs_iunlock(ip, XFS_ILOCK_EXCL); in xfs_reflink_cancel_cow_range()
686 trace_xfs_reflink_cancel_cow_range_error(ip, error, _RET_IP_); in xfs_reflink_cancel_cow_range()
697 * every remap operation and we'd like to keep the block reservation
702 struct xfs_inode *ip, in xfs_reflink_end_cow_extent() argument
708 struct xfs_mount *mp = ip->i_mount; in xfs_reflink_end_cow_extent()
710 struct xfs_ifork *ifp = xfs_ifork_ptr(ip, XFS_COW_FORK); in xfs_reflink_end_cow_extent()
716 error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, resblks, 0, in xfs_reflink_end_cow_extent()
726 xfs_ilock(ip, XFS_ILOCK_EXCL); in xfs_reflink_end_cow_extent()
727 xfs_trans_ijoin(tp, ip, 0); in xfs_reflink_end_cow_extent()
734 if (!xfs_iext_lookup_extent(ip, ifp, *offset_fsb, &icur, &got) || in xfs_reflink_end_cow_extent()
755 xfs_trim_extent(&del, *offset_fsb, end_fsb - *offset_fsb); in xfs_reflink_end_cow_extent()
757 error = xfs_iext_count_extend(tp, ip, XFS_DATA_FORK, in xfs_reflink_end_cow_extent()
764 error = xfs_bmapi_read(ip, del.br_startoff, del.br_blockcount, &data, in xfs_reflink_end_cow_extent()
773 trace_xfs_reflink_cow_remap_from(ip, &del); in xfs_reflink_end_cow_extent()
774 trace_xfs_reflink_cow_remap_to(ip, &data); in xfs_reflink_end_cow_extent()
781 xfs_bmap_unmap_extent(tp, ip, XFS_DATA_FORK, &data); in xfs_reflink_end_cow_extent()
783 xfs_trans_mod_dquot_byino(tp, ip, XFS_TRANS_DQ_BCOUNT, in xfs_reflink_end_cow_extent()
784 -data.br_blockcount); in xfs_reflink_end_cow_extent()
794 error = xfs_bunmapi(NULL, ip, data.br_startoff, in xfs_reflink_end_cow_extent()
805 xfs_bmap_map_extent(tp, ip, XFS_DATA_FORK, &del); in xfs_reflink_end_cow_extent()
807 /* Charge this new data fork mapping to the on-disk quota. */ in xfs_reflink_end_cow_extent()
808 xfs_trans_mod_dquot_byino(tp, ip, XFS_TRANS_DQ_DELBCOUNT, in xfs_reflink_end_cow_extent()
812 xfs_bmap_del_extent_cow(ip, &icur, &got, &del); in xfs_reflink_end_cow_extent()
815 xfs_iunlock(ip, XFS_ILOCK_EXCL); in xfs_reflink_end_cow_extent()
825 xfs_iunlock(ip, XFS_ILOCK_EXCL); in xfs_reflink_end_cow_extent()
834 struct xfs_inode *ip, in xfs_reflink_end_cow() argument
842 trace_xfs_reflink_end_cow(ip, offset, count); in xfs_reflink_end_cow()
844 offset_fsb = XFS_B_TO_FSBT(ip->i_mount, offset); in xfs_reflink_end_cow()
845 end_fsb = XFS_B_TO_FSB(ip->i_mount, offset + count); in xfs_reflink_end_cow()
860 * region. There are also have post-eof checks in the writeback in xfs_reflink_end_cow()
880 error = xfs_reflink_end_cow_extent(ip, &offset_fsb, end_fsb); in xfs_reflink_end_cow()
883 trace_xfs_reflink_end_cow_error(ip, error, _RET_IP_); in xfs_reflink_end_cow()
916 * Reflinking (Block) Ranges of Two Files Together
926 * - Read src's bmbt at the start of srange ("imap")
927 * - If imap doesn't exist, make imap appear to start at the end of srange
929 * - If imap starts before srange, advance imap to start at srange.
930 * - If imap goes beyond srange, truncate imap to end at the end of srange.
931 * - Punch (imap start - srange start + imap len) blocks from dest at
933 * - If imap points to a real range of pblks,
936 * (drange start + imap start - srange start)
937 * - Advance drange and srange by (imap start - srange start + imap len)
939 * Finally, if the reflink made dest longer, update both the in-core and
940 * on-disk file sizes.
946 * ----SSSSSSS-SSSSS----SSSSSS (src file)
947 * <-------------------->
951 * --DDDDDDDDDDDDDDDDDDD--DDD (dest file)
952 * <-------------------->
953 * '-' means a hole, and 'S' and 'D' are written blocks in the src and dest.
960 * ----SSSSSSS-SSSSS----SSSSSS
961 * <------->
962 * --DDDDD---------DDDDD--DDD
963 * <------->
967 * ----SSSSSSS-SSSSS----SSSSSS
968 * <------->
969 * --DDDDD--SSSSSSSDDDDD--DDD
970 * <------->
975 * ----SSSSSSS-SSSSS----SSSSSS
976 * <---->
977 * --DDDDD--SSSSSSS-SSSSS-DDD
978 * <---->
983 * ----SSSSSSS-SSSSS----SSSSSS
984 * <----->
985 * --DDDDD--SSSSSSS-SSSSS----SSS
986 * <----->
999 struct xfs_mount *mp = src->i_mount; in xfs_reflink_set_inode_flag()
1006 error = xfs_trans_alloc(mp, &M_RES(mp)->tr_ichange, 0, 0, 0, &tp); in xfs_reflink_set_inode_flag()
1011 if (src->i_ino == dest->i_ino) in xfs_reflink_set_inode_flag()
1019 src->i_diflags2 |= XFS_DIFLAG2_REFLINK; in xfs_reflink_set_inode_flag()
1025 if (src->i_ino == dest->i_ino) in xfs_reflink_set_inode_flag()
1031 dest->i_diflags2 |= XFS_DIFLAG2_REFLINK; in xfs_reflink_set_inode_flag()
1058 struct xfs_mount *mp = dest->i_mount; in xfs_reflink_update_dest()
1065 error = xfs_trans_alloc(mp, &M_RES(mp)->tr_ichange, 0, 0, 0, &tp); in xfs_reflink_update_dest()
1075 dest->i_disk_size = newlen; in xfs_reflink_update_dest()
1079 dest->i_cowextsize = cowextsize; in xfs_reflink_update_dest()
1080 dest->i_diflags2 |= XFS_DIFLAG2_COWEXTSIZE; in xfs_reflink_update_dest()
1115 error = -ENOSPC; in xfs_reflink_ag_has_free_space()
1126 struct xfs_inode *ip, in xfs_reflink_remap_extent() argument
1131 struct xfs_mount *mp = ip->i_mount; in xfs_reflink_remap_extent()
1165 error = xfs_trans_alloc_inode(ip, &M_RES(mp)->tr_write, in xfs_reflink_remap_extent()
1166 resblks + dmap->br_blockcount, 0, false, &tp); in xfs_reflink_remap_extent()
1167 if (error == -EDQUOT || error == -ENOSPC) { in xfs_reflink_remap_extent()
1169 error = xfs_trans_alloc_inode(ip, &M_RES(mp)->tr_write, in xfs_reflink_remap_extent()
1181 error = xfs_bmapi_read(ip, dmap->br_startoff, dmap->br_blockcount, in xfs_reflink_remap_extent()
1185 ASSERT(nimaps == 1 && smap.br_startoff == dmap->br_startoff); in xfs_reflink_remap_extent()
1192 dmap->br_blockcount = min(dmap->br_blockcount, smap.br_blockcount); in xfs_reflink_remap_extent()
1193 ASSERT(dmap->br_blockcount == smap.br_blockcount); in xfs_reflink_remap_extent()
1195 trace_xfs_reflink_remap_extent_dest(ip, &smap); in xfs_reflink_remap_extent()
1198 * Two extents mapped to the same physical block must not have in xfs_reflink_remap_extent()
1202 if (dmap->br_startblock == smap.br_startblock) { in xfs_reflink_remap_extent()
1203 if (dmap->br_state != smap.br_state) { in xfs_reflink_remap_extent()
1204 xfs_bmap_mark_sick(ip, XFS_DATA_FORK); in xfs_reflink_remap_extent()
1205 error = -EFSCORRUPTED; in xfs_reflink_remap_extent()
1211 if (dmap->br_state == XFS_EXT_UNWRITTEN && in xfs_reflink_remap_extent()
1218 XFS_FSB_TO_AGNO(mp, dmap->br_startblock)); in xfs_reflink_remap_extent()
1224 * Increase quota reservation if we think the quota block counter for in xfs_reflink_remap_extent()
1228 * enough quota block count reservation to handle the blocks in that in xfs_reflink_remap_extent()
1229 * extent. We log only the delta to the quota block counts, so if the in xfs_reflink_remap_extent()
1235 * the delalloc reservation gives the block count back to the quota in xfs_reflink_remap_extent()
1246 error = xfs_trans_reserve_quota_nblks(tp, ip, in xfs_reflink_remap_extent()
1247 dmap->br_blockcount, 0, false); in xfs_reflink_remap_extent()
1258 error = xfs_iext_count_extend(tp, ip, XFS_DATA_FORK, iext_delta); in xfs_reflink_remap_extent()
1267 xfs_bmap_unmap_extent(tp, ip, XFS_DATA_FORK, &smap); in xfs_reflink_remap_extent()
1269 qdelta -= smap.br_blockcount; in xfs_reflink_remap_extent()
1279 error = xfs_bunmapi(NULL, ip, smap.br_startoff, in xfs_reflink_remap_extent()
1292 xfs_bmap_map_extent(tp, ip, XFS_DATA_FORK, dmap); in xfs_reflink_remap_extent()
1293 qdelta += dmap->br_blockcount; in xfs_reflink_remap_extent()
1296 xfs_trans_mod_dquot_byino(tp, ip, XFS_TRANS_DQ_BCOUNT, qdelta); in xfs_reflink_remap_extent()
1299 newlen = XFS_FSB_TO_B(mp, dmap->br_startoff + dmap->br_blockcount); in xfs_reflink_remap_extent()
1301 if (newlen > i_size_read(VFS_I(ip))) { in xfs_reflink_remap_extent()
1302 trace_xfs_reflink_update_inode_size(ip, newlen); in xfs_reflink_remap_extent()
1303 i_size_write(VFS_I(ip), newlen); in xfs_reflink_remap_extent()
1304 ip->i_disk_size = newlen; in xfs_reflink_remap_extent()
1305 xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); in xfs_reflink_remap_extent()
1315 xfs_iunlock(ip, XFS_ILOCK_EXCL); in xfs_reflink_remap_extent()
1318 trace_xfs_reflink_remap_extent_error(ip, error, _RET_IP_); in xfs_reflink_remap_extent()
1333 struct xfs_mount *mp = src->i_mount; in xfs_reflink_remap_blocks()
1368 error = -EFSCORRUPTED; in xfs_reflink_remap_blocks()
1381 error = -EINTR; in xfs_reflink_remap_blocks()
1388 len -= imap.br_blockcount; in xfs_reflink_remap_blocks()
1396 XFS_FSB_TO_B(src->i_mount, remapped_len)); in xfs_reflink_remap_blocks()
1402 * zero any speculative post-EOF preallocations that sit between the old EOF
1407 struct xfs_inode *ip, in xfs_reflink_zero_posteof() argument
1410 loff_t isize = i_size_read(VFS_I(ip)); in xfs_reflink_zero_posteof()
1415 trace_xfs_zero_eof(ip, isize, pos - isize); in xfs_reflink_zero_posteof()
1416 return xfs_zero_range(ip, isize, pos - isize, NULL); in xfs_reflink_zero_posteof()
1427 * EOF block in the source dedupe range because it's not a complete block match,
1428 * hence can introduce a corruption into the file that has it's block replaced.
1431 * "block aligned" for the purposes of cloning entire files. However, if the
1432 * source file range includes the EOF block and it lands within the existing EOF
1436 * XFS doesn't support partial block sharing, so in both cases we have check
1438 * down to the previous whole block and ignore the partial EOF block. While this
1439 * means we can't dedupe the last block of a file, this is an acceptible
1442 * For cloning, we want to share the partial EOF block if it is also the new EOF
1443 * block of the destination file. If the partial EOF block lies inside the
1446 * -EINVAL in this case.
1468 /* Check file eligibility and prepare for block sharing. */ in xfs_reflink_remap_prep()
1469 ret = -EINVAL; in xfs_reflink_remap_prep()
1474 /* Don't share DAX file data with non-DAX file. */ in xfs_reflink_remap_prep()
1487 /* Attach dquots to dest inode before changing block map */ in xfs_reflink_remap_prep()
1493 * Zero existing post-eof speculative preallocations in the destination in xfs_reflink_remap_prep()
1511 loff_t flen = *len + (pos_out - XFS_ISIZE(dest)); in xfs_reflink_remap_prep()
1533 struct xfs_inode *ip, in xfs_reflink_inode_has_shared_extents() argument
1537 struct xfs_mount *mp = ip->i_mount; in xfs_reflink_inode_has_shared_extents()
1543 ifp = xfs_ifork_ptr(ip, XFS_DATA_FORK); in xfs_reflink_inode_has_shared_extents()
1544 error = xfs_iread_extents(tp, ip, XFS_DATA_FORK); in xfs_reflink_inode_has_shared_extents()
1549 found = xfs_iext_lookup_extent(ip, ifp, 0, &icur, &got); in xfs_reflink_inode_has_shared_extents()
1570 /* Is there still a shared block here? */ in xfs_reflink_inode_has_shared_extents()
1590 struct xfs_inode *ip, in xfs_reflink_clear_inode_flag() argument
1596 ASSERT(xfs_is_reflink_inode(ip)); in xfs_reflink_clear_inode_flag()
1598 if (!xfs_can_free_cowblocks(ip)) in xfs_reflink_clear_inode_flag()
1601 error = xfs_reflink_inode_has_shared_extents(*tpp, ip, &needs_flag); in xfs_reflink_clear_inode_flag()
1609 error = xfs_reflink_cancel_cow_blocks(ip, tpp, 0, XFS_MAX_FILEOFF, in xfs_reflink_clear_inode_flag()
1615 trace_xfs_reflink_unset_inode_flag(ip); in xfs_reflink_clear_inode_flag()
1616 ip->i_diflags2 &= ~XFS_DIFLAG2_REFLINK; in xfs_reflink_clear_inode_flag()
1617 xfs_inode_clear_cowblocks_tag(ip); in xfs_reflink_clear_inode_flag()
1618 xfs_trans_log_inode(*tpp, ip, XFS_ILOG_CORE); in xfs_reflink_clear_inode_flag()
1629 struct xfs_inode *ip) in xfs_reflink_try_clear_inode_flag() argument
1631 struct xfs_mount *mp = ip->i_mount; in xfs_reflink_try_clear_inode_flag()
1636 error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, 0, 0, 0, &tp); in xfs_reflink_try_clear_inode_flag()
1640 xfs_ilock(ip, XFS_ILOCK_EXCL); in xfs_reflink_try_clear_inode_flag()
1641 xfs_trans_ijoin(tp, ip, 0); in xfs_reflink_try_clear_inode_flag()
1643 error = xfs_reflink_clear_inode_flag(ip, &tp); in xfs_reflink_try_clear_inode_flag()
1651 xfs_iunlock(ip, XFS_ILOCK_EXCL); in xfs_reflink_try_clear_inode_flag()
1656 xfs_iunlock(ip, XFS_ILOCK_EXCL); in xfs_reflink_try_clear_inode_flag()
1661 * Pre-COW all shared blocks within a given byte range of a file and turn off
1666 struct xfs_inode *ip, in xfs_reflink_unshare() argument
1670 struct inode *inode = VFS_I(ip); in xfs_reflink_unshare()
1673 if (!xfs_is_reflink_inode(ip)) in xfs_reflink_unshare()
1676 trace_xfs_reflink_unshare(ip, offset, len); in xfs_reflink_unshare()
1689 error = filemap_write_and_wait_range(inode->i_mapping, offset, in xfs_reflink_unshare()
1690 offset + len - 1); in xfs_reflink_unshare()
1695 error = xfs_reflink_try_clear_inode_flag(ip); in xfs_reflink_unshare()
1701 trace_xfs_reflink_unshare_error(ip, error, _RET_IP_); in xfs_reflink_unshare()