Lines Matching +full:ip +full:- +full:blocks
1 // SPDX-License-Identifier: GPL-2.0+
34 * Copy on Write of Shared Blocks
37 * the same physical blocks. This means that a write to one file must not
38 * alter the blocks in a different file; the way that we'll do that is
39 * through the use of a copy-on-write mechanism. At a high level, that
45 * of disk blocks to dirty-but-not-yet-mapped file blocks as long as
51 * create a delalloc mapping, which is a regular in-core extent, but without
53 * a flag that this is a delalloc mapping, and a worst-case estimate of how
54 * many blocks might be required to put the mapping into the BMBT.) delalloc
63 * D: --RRRRRRSSSRRRRRRRR--- (data fork)
64 * C: ------DDDDDDD--------- (CoW fork)
68 * allocating blocks and replacing the delalloc mapping with real ones.
72 * D: --RRRRRRSSSRRRRRRRR---
73 * C: ------UUUUUUU---------
75 * We want to adapt the delalloc mechanism for copy-on-write, since the
77 * and allocating the blocks) are exactly the same as delalloc except that
85 * Block-aligned directio writes will use the same mechanism as buffered
93 * D: --RRRRRRSSSRRRRRRRR---
94 * C: ------UUrrUUU---------
100 * that cover the file blocks that we just CoW'd. For each extent, simply
104 * only to remap the blocks that we've actually written out -- we must
105 * never remap delalloc reservations nor CoW staging blocks that have
109 * D: --RRRRRRrrSRRRRRRRR---
110 * C: ------UU--UUU---------
116 * remember the presence of unwritten blocks and CoW blocks with a single
122 * Given an AG extent, find the lowest-numbered run of shared blocks
125 * shared blocks. If there are no shared extents, fbno and flen will
146 cur = xfs_refcountbt_init_cursor(pag->pag_mount, tp, agbp, pag); in xfs_reflink_find_shared()
160 * find the lowest-numbered extent of shared blocks that coincides with
169 struct xfs_inode *ip, in xfs_reflink_trim_around_shared() argument
173 struct xfs_mount *mp = ip->i_mount; in xfs_reflink_trim_around_shared()
182 if (!xfs_is_cow_inode(ip) || !xfs_bmap_is_written_extent(irec)) { in xfs_reflink_trim_around_shared()
187 trace_xfs_reflink_trim_around_shared(ip, irec); in xfs_reflink_trim_around_shared()
189 pag = xfs_perag_get(mp, XFS_FSB_TO_AGNO(mp, irec->br_startblock)); in xfs_reflink_trim_around_shared()
190 agbno = XFS_FSB_TO_AGBNO(mp, irec->br_startblock); in xfs_reflink_trim_around_shared()
191 aglen = irec->br_blockcount; in xfs_reflink_trim_around_shared()
201 /* No shared blocks at all. */ in xfs_reflink_trim_around_shared()
212 irec->br_blockcount = flen; in xfs_reflink_trim_around_shared()
223 irec->br_blockcount = fbno - agbno; in xfs_reflink_trim_around_shared()
229 struct xfs_inode *ip, in xfs_bmap_trim_cow() argument
234 if (xfs_is_always_cow_inode(ip) && in xfs_bmap_trim_cow()
235 !isnullstartblock(imap->br_startblock)) { in xfs_bmap_trim_cow()
241 return xfs_reflink_trim_around_shared(ip, imap, shared); in xfs_bmap_trim_cow()
246 struct xfs_inode *ip, in xfs_reflink_convert_cow_locked() argument
256 if (!xfs_iext_lookup_extent(ip, ip->i_cowfp, offset_fsb, &icur, &got)) in xfs_reflink_convert_cow_locked()
265 return -EIO; in xfs_reflink_convert_cow_locked()
272 error = xfs_bmap_add_extent_unwritten_real(NULL, ip, in xfs_reflink_convert_cow_locked()
277 } while (xfs_iext_next_extent(ip->i_cowfp, &icur, &got)); in xfs_reflink_convert_cow_locked()
285 struct xfs_inode *ip, in xfs_reflink_convert_cow() argument
289 struct xfs_mount *mp = ip->i_mount; in xfs_reflink_convert_cow()
292 xfs_filblks_t count_fsb = end_fsb - offset_fsb; in xfs_reflink_convert_cow()
297 xfs_ilock(ip, XFS_ILOCK_EXCL); in xfs_reflink_convert_cow()
298 error = xfs_reflink_convert_cow_locked(ip, offset_fsb, count_fsb); in xfs_reflink_convert_cow()
299 xfs_iunlock(ip, XFS_ILOCK_EXCL); in xfs_reflink_convert_cow()
310 struct xfs_inode *ip, in xfs_find_trim_cow_extent() argument
316 xfs_fileoff_t offset_fsb = imap->br_startoff; in xfs_find_trim_cow_extent()
317 xfs_filblks_t count_fsb = imap->br_blockcount; in xfs_find_trim_cow_extent()
326 if (!xfs_iext_lookup_extent(ip, ip->i_cowfp, offset_fsb, &icur, cmap)) in xfs_find_trim_cow_extent()
327 cmap->br_startoff = offset_fsb + count_fsb; in xfs_find_trim_cow_extent()
328 if (cmap->br_startoff > offset_fsb) { in xfs_find_trim_cow_extent()
329 xfs_trim_extent(imap, imap->br_startoff, in xfs_find_trim_cow_extent()
330 cmap->br_startoff - imap->br_startoff); in xfs_find_trim_cow_extent()
331 return xfs_bmap_trim_cow(ip, imap, shared); in xfs_find_trim_cow_extent()
335 if (isnullstartblock(cmap->br_startblock)) { in xfs_find_trim_cow_extent()
336 xfs_trim_extent(imap, cmap->br_startoff, cmap->br_blockcount); in xfs_find_trim_cow_extent()
340 /* real extent found - no need to allocate */ in xfs_find_trim_cow_extent()
348 struct xfs_inode *ip, in xfs_reflink_convert_unwritten() argument
353 xfs_fileoff_t offset_fsb = imap->br_startoff; in xfs_reflink_convert_unwritten()
354 xfs_filblks_t count_fsb = imap->br_blockcount; in xfs_reflink_convert_unwritten()
367 if (!convert_now || cmap->br_state == XFS_EXT_NORM) in xfs_reflink_convert_unwritten()
370 trace_xfs_reflink_convert_cow(ip, cmap); in xfs_reflink_convert_unwritten()
372 error = xfs_reflink_convert_cow_locked(ip, offset_fsb, count_fsb); in xfs_reflink_convert_unwritten()
374 cmap->br_state = XFS_EXT_NORM; in xfs_reflink_convert_unwritten()
381 struct xfs_inode *ip, in xfs_reflink_fill_cow_hole() argument
388 struct xfs_mount *mp = ip->i_mount; in xfs_reflink_fill_cow_hole()
396 resaligned = xfs_aligned_fsb_count(imap->br_startoff, in xfs_reflink_fill_cow_hole()
397 imap->br_blockcount, xfs_get_cowextsz_hint(ip)); in xfs_reflink_fill_cow_hole()
400 xfs_iunlock(ip, *lockmode); in xfs_reflink_fill_cow_hole()
403 error = xfs_trans_alloc_inode(ip, &M_RES(mp)->tr_write, resblks, 0, in xfs_reflink_fill_cow_hole()
410 error = xfs_find_trim_cow_extent(ip, imap, cmap, shared, &found); in xfs_reflink_fill_cow_hole()
419 /* Allocate the entire reservation as unwritten blocks. */ in xfs_reflink_fill_cow_hole()
421 error = xfs_bmapi_write(tp, ip, imap->br_startoff, imap->br_blockcount, in xfs_reflink_fill_cow_hole()
427 xfs_inode_set_cowblocks_tag(ip); in xfs_reflink_fill_cow_hole()
437 return -ENOSPC; in xfs_reflink_fill_cow_hole()
440 return xfs_reflink_convert_unwritten(ip, imap, cmap, convert_now); in xfs_reflink_fill_cow_hole()
449 struct xfs_inode *ip, in xfs_reflink_fill_delalloc() argument
456 struct xfs_mount *mp = ip->i_mount; in xfs_reflink_fill_delalloc()
463 xfs_iunlock(ip, *lockmode); in xfs_reflink_fill_delalloc()
466 error = xfs_trans_alloc_inode(ip, &M_RES(mp)->tr_write, 0, 0, in xfs_reflink_fill_delalloc()
473 error = xfs_find_trim_cow_extent(ip, imap, cmap, shared, in xfs_reflink_fill_delalloc()
483 ASSERT(isnullstartblock(cmap->br_startblock) || in xfs_reflink_fill_delalloc()
484 cmap->br_startblock == DELAYSTARTBLOCK); in xfs_reflink_fill_delalloc()
490 error = xfs_bmapi_write(tp, ip, cmap->br_startoff, in xfs_reflink_fill_delalloc()
491 cmap->br_blockcount, in xfs_reflink_fill_delalloc()
497 xfs_inode_set_cowblocks_tag(ip); in xfs_reflink_fill_delalloc()
507 return -ENOSPC; in xfs_reflink_fill_delalloc()
508 } while (cmap->br_startoff + cmap->br_blockcount <= imap->br_startoff); in xfs_reflink_fill_delalloc()
510 return xfs_reflink_convert_unwritten(ip, imap, cmap, convert_now); in xfs_reflink_fill_delalloc()
517 /* Allocate all CoW reservations covering a range of blocks in a file. */
520 struct xfs_inode *ip, in xfs_reflink_allocate_cow() argument
530 ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); in xfs_reflink_allocate_cow()
531 if (!ip->i_cowfp) { in xfs_reflink_allocate_cow()
532 ASSERT(!xfs_is_reflink_inode(ip)); in xfs_reflink_allocate_cow()
533 xfs_ifork_init_cow(ip); in xfs_reflink_allocate_cow()
536 error = xfs_find_trim_cow_extent(ip, imap, cmap, shared, &found); in xfs_reflink_allocate_cow()
542 return xfs_reflink_convert_unwritten(ip, imap, cmap, in xfs_reflink_allocate_cow()
549 if (cmap->br_startoff > imap->br_startoff) in xfs_reflink_allocate_cow()
550 return xfs_reflink_fill_cow_hole(ip, imap, cmap, shared, in xfs_reflink_allocate_cow()
557 if (isnullstartblock(cmap->br_startblock) || in xfs_reflink_allocate_cow()
558 cmap->br_startblock == DELAYSTARTBLOCK) in xfs_reflink_allocate_cow()
559 return xfs_reflink_fill_delalloc(ip, imap, cmap, shared, in xfs_reflink_allocate_cow()
564 return -EFSCORRUPTED; in xfs_reflink_allocate_cow()
578 struct xfs_inode *ip, in xfs_reflink_cancel_cow_blocks() argument
584 struct xfs_ifork *ifp = xfs_ifork_ptr(ip, XFS_COW_FORK); in xfs_reflink_cancel_cow_blocks()
589 if (!xfs_inode_has_cow_data(ip)) in xfs_reflink_cancel_cow_blocks()
591 if (!xfs_iext_lookup_extent_before(ip, ifp, &end_fsb, &icur, &got)) in xfs_reflink_cancel_cow_blocks()
597 xfs_trim_extent(&del, offset_fsb, end_fsb - offset_fsb); in xfs_reflink_cancel_cow_blocks()
605 trace_xfs_reflink_cancel_cow(ip, &del); in xfs_reflink_cancel_cow_blocks()
608 error = xfs_bmap_del_extent_delay(ip, XFS_COW_FORK, in xfs_reflink_cancel_cow_blocks()
613 ASSERT((*tpp)->t_highest_agno == NULLAGNUMBER); in xfs_reflink_cancel_cow_blocks()
631 xfs_bmap_del_extent_cow(ip, &icur, &got, &del); in xfs_reflink_cancel_cow_blocks()
634 error = xfs_quota_unreserve_blkres(ip, in xfs_reflink_cancel_cow_blocks()
648 if (!ifp->if_bytes) in xfs_reflink_cancel_cow_blocks()
649 xfs_inode_clear_cowblocks_tag(ip); in xfs_reflink_cancel_cow_blocks()
661 struct xfs_inode *ip, in xfs_reflink_cancel_cow_range() argument
671 trace_xfs_reflink_cancel_cow_range(ip, offset, count); in xfs_reflink_cancel_cow_range()
672 ASSERT(ip->i_cowfp); in xfs_reflink_cancel_cow_range()
674 offset_fsb = XFS_B_TO_FSBT(ip->i_mount, offset); in xfs_reflink_cancel_cow_range()
678 end_fsb = XFS_B_TO_FSB(ip->i_mount, offset + count); in xfs_reflink_cancel_cow_range()
681 error = xfs_trans_alloc(ip->i_mount, &M_RES(ip->i_mount)->tr_write, in xfs_reflink_cancel_cow_range()
686 xfs_ilock(ip, XFS_ILOCK_EXCL); in xfs_reflink_cancel_cow_range()
687 xfs_trans_ijoin(tp, ip, 0); in xfs_reflink_cancel_cow_range()
690 error = xfs_reflink_cancel_cow_blocks(ip, &tp, offset_fsb, end_fsb, in xfs_reflink_cancel_cow_range()
697 xfs_iunlock(ip, XFS_ILOCK_EXCL); in xfs_reflink_cancel_cow_range()
702 xfs_iunlock(ip, XFS_ILOCK_EXCL); in xfs_reflink_cancel_cow_range()
704 trace_xfs_reflink_cancel_cow_range_error(ip, error, _RET_IP_); in xfs_reflink_cancel_cow_range()
714 * transaction because we can end up merging and splitting bmbt blocks for
720 struct xfs_inode *ip, in xfs_reflink_end_cow_extent() argument
726 struct xfs_mount *mp = ip->i_mount; in xfs_reflink_end_cow_extent()
728 struct xfs_ifork *ifp = xfs_ifork_ptr(ip, XFS_COW_FORK); in xfs_reflink_end_cow_extent()
734 if (ifp->if_bytes == 0) { in xfs_reflink_end_cow_extent()
740 error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, resblks, 0, in xfs_reflink_end_cow_extent()
750 xfs_ilock(ip, XFS_ILOCK_EXCL); in xfs_reflink_end_cow_extent()
751 xfs_trans_ijoin(tp, ip, 0); in xfs_reflink_end_cow_extent()
753 error = xfs_iext_count_may_overflow(ip, XFS_DATA_FORK, in xfs_reflink_end_cow_extent()
755 if (error == -EFBIG) in xfs_reflink_end_cow_extent()
756 error = xfs_iext_count_upgrade(tp, ip, in xfs_reflink_end_cow_extent()
766 if (!xfs_iext_lookup_extent(ip, ifp, *offset_fsb, &icur, &got) || in xfs_reflink_end_cow_extent()
787 xfs_trim_extent(&del, *offset_fsb, end_fsb - *offset_fsb); in xfs_reflink_end_cow_extent()
791 error = xfs_bmapi_read(ip, del.br_startoff, del.br_blockcount, &data, in xfs_reflink_end_cow_extent()
800 trace_xfs_reflink_cow_remap_from(ip, &del); in xfs_reflink_end_cow_extent()
801 trace_xfs_reflink_cow_remap_to(ip, &data); in xfs_reflink_end_cow_extent()
808 xfs_bmap_unmap_extent(tp, ip, &data); in xfs_reflink_end_cow_extent()
810 xfs_trans_mod_dquot_byino(tp, ip, XFS_TRANS_DQ_BCOUNT, in xfs_reflink_end_cow_extent()
811 -data.br_blockcount); in xfs_reflink_end_cow_extent()
821 error = xfs_bunmapi(NULL, ip, data.br_startoff, in xfs_reflink_end_cow_extent()
831 /* Map the new blocks into the data fork. */ in xfs_reflink_end_cow_extent()
832 xfs_bmap_map_extent(tp, ip, &del); in xfs_reflink_end_cow_extent()
834 /* Charge this new data fork mapping to the on-disk quota. */ in xfs_reflink_end_cow_extent()
835 xfs_trans_mod_dquot_byino(tp, ip, XFS_TRANS_DQ_DELBCOUNT, in xfs_reflink_end_cow_extent()
839 xfs_bmap_del_extent_cow(ip, &icur, &got, &del); in xfs_reflink_end_cow_extent()
842 xfs_iunlock(ip, XFS_ILOCK_EXCL); in xfs_reflink_end_cow_extent()
852 xfs_iunlock(ip, XFS_ILOCK_EXCL); in xfs_reflink_end_cow_extent()
861 struct xfs_inode *ip, in xfs_reflink_end_cow() argument
869 trace_xfs_reflink_end_cow(ip, offset, count); in xfs_reflink_end_cow()
871 offset_fsb = XFS_B_TO_FSBT(ip->i_mount, offset); in xfs_reflink_end_cow()
872 end_fsb = XFS_B_TO_FSB(ip->i_mount, offset + count); in xfs_reflink_end_cow()
887 * region. There are also have post-eof checks in the writeback in xfs_reflink_end_cow()
904 * blocks will be remapped. in xfs_reflink_end_cow()
907 error = xfs_reflink_end_cow_extent(ip, &offset_fsb, end_fsb); in xfs_reflink_end_cow()
910 trace_xfs_reflink_end_cow_error(ip, error, _RET_IP_); in xfs_reflink_end_cow()
915 * Free all CoW staging blocks that are still referenced by the ondisk refcount
950 * logical blocks in dest and src touched by the reflink operation.
953 * - Read src's bmbt at the start of srange ("imap")
954 * - If imap doesn't exist, make imap appear to start at the end of srange
956 * - If imap starts before srange, advance imap to start at srange.
957 * - If imap goes beyond srange, truncate imap to end at the end of srange.
958 * - Punch (imap start - srange start + imap len) blocks from dest at
960 * - If imap points to a real range of pblks,
963 * (drange start + imap start - srange start)
964 * - Advance drange and srange by (imap start - srange start + imap len)
966 * Finally, if the reflink made dest longer, update both the in-core and
967 * on-disk file sizes.
973 * ----SSSSSSS-SSSSS----SSSSSS (src file)
974 * <-------------------->
978 * --DDDDDDDDDDDDDDDDDDD--DDD (dest file)
979 * <-------------------->
980 * '-' means a hole, and 'S' and 'D' are written blocks in the src and dest.
985 * unmap more blocks from the destination file than we remap.
987 * ----SSSSSSS-SSSSS----SSSSSS
988 * <------->
989 * --DDDDD---------DDDDD--DDD
990 * <------->
994 * ----SSSSSSS-SSSSS----SSSSSS
995 * <------->
996 * --DDDDD--SSSSSSSDDDDD--DDD
997 * <------->
1002 * ----SSSSSSS-SSSSS----SSSSSS
1003 * <---->
1004 * --DDDDD--SSSSSSS-SSSSS-DDD
1005 * <---->
1010 * ----SSSSSSS-SSSSS----SSSSSS
1011 * <----->
1012 * --DDDDD--SSSSSSS-SSSSS----SSS
1013 * <----->
1026 struct xfs_mount *mp = src->i_mount; in xfs_reflink_set_inode_flag()
1033 error = xfs_trans_alloc(mp, &M_RES(mp)->tr_ichange, 0, 0, 0, &tp); in xfs_reflink_set_inode_flag()
1038 if (src->i_ino == dest->i_ino) in xfs_reflink_set_inode_flag()
1046 src->i_diflags2 |= XFS_DIFLAG2_REFLINK; in xfs_reflink_set_inode_flag()
1052 if (src->i_ino == dest->i_ino) in xfs_reflink_set_inode_flag()
1058 dest->i_diflags2 |= XFS_DIFLAG2_REFLINK; in xfs_reflink_set_inode_flag()
1085 struct xfs_mount *mp = dest->i_mount; in xfs_reflink_update_dest()
1092 error = xfs_trans_alloc(mp, &M_RES(mp)->tr_ichange, 0, 0, 0, &tp); in xfs_reflink_update_dest()
1102 dest->i_disk_size = newlen; in xfs_reflink_update_dest()
1106 dest->i_cowextsize = cowextsize; in xfs_reflink_update_dest()
1107 dest->i_diflags2 |= XFS_DIFLAG2_COWEXTSIZE; in xfs_reflink_update_dest()
1142 error = -ENOSPC; in xfs_reflink_ag_has_free_space()
1149 * the number of blocks that were actually remapped.
1153 struct xfs_inode *ip, in xfs_reflink_remap_extent() argument
1158 struct xfs_mount *mp = ip->i_mount; in xfs_reflink_remap_extent()
1192 error = xfs_trans_alloc_inode(ip, &M_RES(mp)->tr_write, in xfs_reflink_remap_extent()
1193 resblks + dmap->br_blockcount, 0, false, &tp); in xfs_reflink_remap_extent()
1194 if (error == -EDQUOT || error == -ENOSPC) { in xfs_reflink_remap_extent()
1196 error = xfs_trans_alloc_inode(ip, &M_RES(mp)->tr_write, in xfs_reflink_remap_extent()
1208 error = xfs_bmapi_read(ip, dmap->br_startoff, dmap->br_blockcount, in xfs_reflink_remap_extent()
1212 ASSERT(nimaps == 1 && smap.br_startoff == dmap->br_startoff); in xfs_reflink_remap_extent()
1216 * We can only remap as many blocks as the smaller of the two extent in xfs_reflink_remap_extent()
1219 dmap->br_blockcount = min(dmap->br_blockcount, smap.br_blockcount); in xfs_reflink_remap_extent()
1220 ASSERT(dmap->br_blockcount == smap.br_blockcount); in xfs_reflink_remap_extent()
1222 trace_xfs_reflink_remap_extent_dest(ip, &smap); in xfs_reflink_remap_extent()
1229 if (dmap->br_startblock == smap.br_startblock) { in xfs_reflink_remap_extent()
1230 if (dmap->br_state != smap.br_state) in xfs_reflink_remap_extent()
1231 error = -EFSCORRUPTED; in xfs_reflink_remap_extent()
1236 if (dmap->br_state == XFS_EXT_UNWRITTEN && in xfs_reflink_remap_extent()
1243 XFS_FSB_TO_AGNO(mp, dmap->br_startblock)); in xfs_reflink_remap_extent()
1253 * enough quota block count reservation to handle the blocks in that in xfs_reflink_remap_extent()
1255 * extent we're unmapping also has blocks allocated to it, we don't in xfs_reflink_remap_extent()
1271 error = xfs_trans_reserve_quota_nblks(tp, ip, in xfs_reflink_remap_extent()
1272 dmap->br_blockcount, 0, false); in xfs_reflink_remap_extent()
1283 error = xfs_iext_count_may_overflow(ip, XFS_DATA_FORK, iext_delta); in xfs_reflink_remap_extent()
1284 if (error == -EFBIG) in xfs_reflink_remap_extent()
1285 error = xfs_iext_count_upgrade(tp, ip, iext_delta); in xfs_reflink_remap_extent()
1294 xfs_bmap_unmap_extent(tp, ip, &smap); in xfs_reflink_remap_extent()
1296 qdelta -= smap.br_blockcount; in xfs_reflink_remap_extent()
1306 error = xfs_bunmapi(NULL, ip, smap.br_startoff, in xfs_reflink_remap_extent()
1319 xfs_bmap_map_extent(tp, ip, dmap); in xfs_reflink_remap_extent()
1320 qdelta += dmap->br_blockcount; in xfs_reflink_remap_extent()
1323 xfs_trans_mod_dquot_byino(tp, ip, XFS_TRANS_DQ_BCOUNT, qdelta); in xfs_reflink_remap_extent()
1326 newlen = XFS_FSB_TO_B(mp, dmap->br_startoff + dmap->br_blockcount); in xfs_reflink_remap_extent()
1328 if (newlen > i_size_read(VFS_I(ip))) { in xfs_reflink_remap_extent()
1329 trace_xfs_reflink_update_inode_size(ip, newlen); in xfs_reflink_remap_extent()
1330 i_size_write(VFS_I(ip), newlen); in xfs_reflink_remap_extent()
1331 ip->i_disk_size = newlen; in xfs_reflink_remap_extent()
1332 xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); in xfs_reflink_remap_extent()
1342 xfs_iunlock(ip, XFS_ILOCK_EXCL); in xfs_reflink_remap_extent()
1345 trace_xfs_reflink_remap_extent_error(ip, error, _RET_IP_); in xfs_reflink_remap_extent()
1360 struct xfs_mount *mp = src->i_mount; in xfs_reflink_remap_blocks()
1394 error = -EFSCORRUPTED; in xfs_reflink_remap_blocks()
1407 error = -EINTR; in xfs_reflink_remap_blocks()
1414 len -= imap.br_blockcount; in xfs_reflink_remap_blocks()
1421 XFS_FSB_TO_B(src->i_mount, remapped_len)); in xfs_reflink_remap_blocks()
1427 * zero any speculative post-EOF preallocations that sit between the old EOF
1432 struct xfs_inode *ip, in xfs_reflink_zero_posteof() argument
1435 loff_t isize = i_size_read(VFS_I(ip)); in xfs_reflink_zero_posteof()
1440 trace_xfs_zero_eof(ip, isize, pos - isize); in xfs_reflink_zero_posteof()
1441 return xfs_zero_range(ip, isize, pos - isize, NULL); in xfs_reflink_zero_posteof()
1450 * The VFS allows partial EOF blocks to "match" for dedupe even though it hasn't
1455 * In similar fashion, the VFS file cloning also allows partial EOF blocks to be
1471 * -EINVAL in this case.
1494 ret = -EINVAL; in xfs_reflink_remap_prep()
1499 /* Don't share DAX file data with non-DAX file. */ in xfs_reflink_remap_prep()
1518 * Zero existing post-eof speculative preallocations in the destination in xfs_reflink_remap_prep()
1525 /* Set flags and remap blocks. */ in xfs_reflink_remap_prep()
1531 * If pos_out > EOF, we may have dirtied blocks between EOF and in xfs_reflink_remap_prep()
1536 loff_t flen = *len + (pos_out - XFS_ISIZE(dest)); in xfs_reflink_remap_prep()
1558 struct xfs_inode *ip, in xfs_reflink_inode_has_shared_extents() argument
1562 struct xfs_mount *mp = ip->i_mount; in xfs_reflink_inode_has_shared_extents()
1568 ifp = xfs_ifork_ptr(ip, XFS_DATA_FORK); in xfs_reflink_inode_has_shared_extents()
1569 error = xfs_iread_extents(tp, ip, XFS_DATA_FORK); in xfs_reflink_inode_has_shared_extents()
1574 found = xfs_iext_lookup_extent(ip, ifp, 0, &icur, &got); in xfs_reflink_inode_has_shared_extents()
1615 struct xfs_inode *ip, in xfs_reflink_clear_inode_flag() argument
1621 ASSERT(xfs_is_reflink_inode(ip)); in xfs_reflink_clear_inode_flag()
1623 error = xfs_reflink_inode_has_shared_extents(*tpp, ip, &needs_flag); in xfs_reflink_clear_inode_flag()
1628 * We didn't find any shared blocks so turn off the reflink flag. in xfs_reflink_clear_inode_flag()
1631 error = xfs_reflink_cancel_cow_blocks(ip, tpp, 0, XFS_MAX_FILEOFF, in xfs_reflink_clear_inode_flag()
1637 trace_xfs_reflink_unset_inode_flag(ip); in xfs_reflink_clear_inode_flag()
1638 ip->i_diflags2 &= ~XFS_DIFLAG2_REFLINK; in xfs_reflink_clear_inode_flag()
1639 xfs_inode_clear_cowblocks_tag(ip); in xfs_reflink_clear_inode_flag()
1640 xfs_trans_log_inode(*tpp, ip, XFS_ILOG_CORE); in xfs_reflink_clear_inode_flag()
1651 struct xfs_inode *ip) in xfs_reflink_try_clear_inode_flag() argument
1653 struct xfs_mount *mp = ip->i_mount; in xfs_reflink_try_clear_inode_flag()
1658 error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, 0, 0, 0, &tp); in xfs_reflink_try_clear_inode_flag()
1662 xfs_ilock(ip, XFS_ILOCK_EXCL); in xfs_reflink_try_clear_inode_flag()
1663 xfs_trans_ijoin(tp, ip, 0); in xfs_reflink_try_clear_inode_flag()
1665 error = xfs_reflink_clear_inode_flag(ip, &tp); in xfs_reflink_try_clear_inode_flag()
1673 xfs_iunlock(ip, XFS_ILOCK_EXCL); in xfs_reflink_try_clear_inode_flag()
1678 xfs_iunlock(ip, XFS_ILOCK_EXCL); in xfs_reflink_try_clear_inode_flag()
1683 * Pre-COW all shared blocks within a given byte range of a file and turn off
1684 * the reflink flag if we unshare all of the file's blocks.
1688 struct xfs_inode *ip, in xfs_reflink_unshare() argument
1692 struct inode *inode = VFS_I(ip); in xfs_reflink_unshare()
1695 if (!xfs_is_reflink_inode(ip)) in xfs_reflink_unshare()
1698 trace_xfs_reflink_unshare(ip, offset, len); in xfs_reflink_unshare()
1711 error = filemap_write_and_wait_range(inode->i_mapping, offset, in xfs_reflink_unshare()
1712 offset + len - 1); in xfs_reflink_unshare()
1717 error = xfs_reflink_try_clear_inode_flag(ip); in xfs_reflink_unshare()
1723 trace_xfs_reflink_unshare_error(ip, error, _RET_IP_); in xfs_reflink_unshare()