Lines Matching +full:ip +full:- +full:blocks
1 // SPDX-License-Identifier: GPL-2.0+
39 * Copy on Write of Shared Blocks
42 * the same physical blocks. This means that a write to one file must not
43 * alter the blocks in a different file; the way that we'll do that is
44 * through the use of a copy-on-write mechanism. At a high level, that
50 * of disk blocks to dirty-but-not-yet-mapped file blocks as long as
56 * create a delalloc mapping, which is a regular in-core extent, but without
58 * a flag that this is a delalloc mapping, and a worst-case estimate of how
59 * many blocks might be required to put the mapping into the BMBT.) delalloc
68 * D: --RRRRRRSSSRRRRRRRR--- (data fork)
69 * C: ------DDDDDDD--------- (CoW fork)
73 * allocating blocks and replacing the delalloc mapping with real ones.
77 * D: --RRRRRRSSSRRRRRRRR---
78 * C: ------UUUUUUU---------
80 * We want to adapt the delalloc mechanism for copy-on-write, since the
82 * and allocating the blocks) are exactly the same as delalloc except that
90 * Block-aligned directio writes will use the same mechanism as buffered
98 * D: --RRRRRRSSSRRRRRRRR---
99 * C: ------UUrrUUU---------
105 * that cover the file blocks that we just CoW'd. For each extent, simply
109 * only to remap the blocks that we've actually written out -- we must
110 * never remap delalloc reservations nor CoW staging blocks that have
114 * D: --RRRRRRrrSRRRRRRRR---
115 * C: ------UU--UUU---------
121 * remember the presence of unwritten blocks and CoW blocks with a single
127 * Given a file mapping for the data device, find the lowest-numbered run of
128 * shared blocks within that mapping and return it in shared_offset/shared_len.
132 * blocks. If there are no shared extents, shared_offset and shared_len will be
150 pag = xfs_perag_get(mp, XFS_FSB_TO_AGNO(mp, irec->br_startblock)); in xfs_reflink_find_shared()
151 orig_bno = XFS_FSB_TO_AGBNO(mp, irec->br_startblock); in xfs_reflink_find_shared()
158 error = xfs_refcount_find_shared(cur, orig_bno, irec->br_blockcount, in xfs_reflink_find_shared()
164 *shared_offset = found_bno - orig_bno; in xfs_reflink_find_shared()
171 * Given a file mapping for the rt device, find the lowest-numbered run of
172 * shared blocks within that mapping and return it in shared_offset/shared_len.
176 * blocks. If there are no shared extents, shared_offset and shared_len will be
201 orig_bno = xfs_rtb_to_rgbno(mp, irec->br_startblock); in xfs_reflink_find_rtshared()
202 rtg = xfs_rtgroup_get(mp, xfs_rtb_to_rgno(mp, irec->br_startblock)); in xfs_reflink_find_rtshared()
206 error = xfs_refcount_find_shared(cur, orig_bno, irec->br_blockcount, in xfs_reflink_find_rtshared()
213 *shared_offset = found_bno - orig_bno; in xfs_reflink_find_rtshared()
220 * find the lowest-numbered extent of shared blocks that coincides with
229 struct xfs_inode *ip, in xfs_reflink_trim_around_shared() argument
233 struct xfs_mount *mp = ip->i_mount; in xfs_reflink_trim_around_shared()
238 if (!xfs_is_cow_inode(ip) || !xfs_bmap_is_written_extent(irec)) { in xfs_reflink_trim_around_shared()
243 trace_xfs_reflink_trim_around_shared(ip, irec); in xfs_reflink_trim_around_shared()
245 if (XFS_IS_REALTIME_INODE(ip)) in xfs_reflink_trim_around_shared()
255 /* No shared blocks at all. */ in xfs_reflink_trim_around_shared()
264 irec->br_blockcount = shared_len; in xfs_reflink_trim_around_shared()
273 irec->br_blockcount = shared_offset; in xfs_reflink_trim_around_shared()
281 struct xfs_inode *ip, in xfs_bmap_trim_cow() argument
286 if (xfs_is_always_cow_inode(ip) && in xfs_bmap_trim_cow()
287 !isnullstartblock(imap->br_startblock)) { in xfs_bmap_trim_cow()
293 return xfs_reflink_trim_around_shared(ip, imap, shared); in xfs_bmap_trim_cow()
298 struct xfs_inode *ip, in xfs_reflink_convert_cow_locked() argument
308 if (!xfs_iext_lookup_extent(ip, ip->i_cowfp, offset_fsb, &icur, &got)) in xfs_reflink_convert_cow_locked()
317 return -EIO; in xfs_reflink_convert_cow_locked()
324 error = xfs_bmap_add_extent_unwritten_real(NULL, ip, in xfs_reflink_convert_cow_locked()
329 } while (xfs_iext_next_extent(ip->i_cowfp, &icur, &got)); in xfs_reflink_convert_cow_locked()
337 struct xfs_inode *ip, in xfs_reflink_convert_cow() argument
341 struct xfs_mount *mp = ip->i_mount; in xfs_reflink_convert_cow()
344 xfs_filblks_t count_fsb = end_fsb - offset_fsb; in xfs_reflink_convert_cow()
349 xfs_ilock(ip, XFS_ILOCK_EXCL); in xfs_reflink_convert_cow()
350 error = xfs_reflink_convert_cow_locked(ip, offset_fsb, count_fsb); in xfs_reflink_convert_cow()
351 xfs_iunlock(ip, XFS_ILOCK_EXCL); in xfs_reflink_convert_cow()
362 struct xfs_inode *ip, in xfs_find_trim_cow_extent() argument
368 xfs_fileoff_t offset_fsb = imap->br_startoff; in xfs_find_trim_cow_extent()
369 xfs_filblks_t count_fsb = imap->br_blockcount; in xfs_find_trim_cow_extent()
378 if (!xfs_iext_lookup_extent(ip, ip->i_cowfp, offset_fsb, &icur, cmap)) in xfs_find_trim_cow_extent()
379 cmap->br_startoff = offset_fsb + count_fsb; in xfs_find_trim_cow_extent()
380 if (cmap->br_startoff > offset_fsb) { in xfs_find_trim_cow_extent()
381 xfs_trim_extent(imap, imap->br_startoff, in xfs_find_trim_cow_extent()
382 cmap->br_startoff - imap->br_startoff); in xfs_find_trim_cow_extent()
383 return xfs_bmap_trim_cow(ip, imap, shared); in xfs_find_trim_cow_extent()
387 if (isnullstartblock(cmap->br_startblock)) { in xfs_find_trim_cow_extent()
388 xfs_trim_extent(imap, cmap->br_startoff, cmap->br_blockcount); in xfs_find_trim_cow_extent()
392 /* real extent found - no need to allocate */ in xfs_find_trim_cow_extent()
400 struct xfs_inode *ip, in xfs_reflink_convert_unwritten() argument
405 xfs_fileoff_t offset_fsb = imap->br_startoff; in xfs_reflink_convert_unwritten()
406 xfs_filblks_t count_fsb = imap->br_blockcount; in xfs_reflink_convert_unwritten()
419 if (!convert_now || cmap->br_state == XFS_EXT_NORM) in xfs_reflink_convert_unwritten()
422 trace_xfs_reflink_convert_cow(ip, cmap); in xfs_reflink_convert_unwritten()
424 error = xfs_reflink_convert_cow_locked(ip, offset_fsb, count_fsb); in xfs_reflink_convert_unwritten()
426 cmap->br_state = XFS_EXT_NORM; in xfs_reflink_convert_unwritten()
433 struct xfs_inode *ip, in xfs_reflink_fill_cow_hole() argument
440 struct xfs_mount *mp = ip->i_mount; in xfs_reflink_fill_cow_hole()
448 resaligned = xfs_aligned_fsb_count(imap->br_startoff, in xfs_reflink_fill_cow_hole()
449 imap->br_blockcount, xfs_get_cowextsz_hint(ip)); in xfs_reflink_fill_cow_hole()
450 if (XFS_IS_REALTIME_INODE(ip)) { in xfs_reflink_fill_cow_hole()
458 xfs_iunlock(ip, *lockmode); in xfs_reflink_fill_cow_hole()
461 error = xfs_trans_alloc_inode(ip, &M_RES(mp)->tr_write, dblocks, in xfs_reflink_fill_cow_hole()
468 error = xfs_find_trim_cow_extent(ip, imap, cmap, shared, &found); in xfs_reflink_fill_cow_hole()
477 /* Allocate the entire reservation as unwritten blocks. */ in xfs_reflink_fill_cow_hole()
479 error = xfs_bmapi_write(tp, ip, imap->br_startoff, imap->br_blockcount, in xfs_reflink_fill_cow_hole()
485 xfs_inode_set_cowblocks_tag(ip); in xfs_reflink_fill_cow_hole()
491 return xfs_reflink_convert_unwritten(ip, imap, cmap, convert_now); in xfs_reflink_fill_cow_hole()
500 struct xfs_inode *ip, in xfs_reflink_fill_delalloc() argument
507 struct xfs_mount *mp = ip->i_mount; in xfs_reflink_fill_delalloc()
514 xfs_iunlock(ip, *lockmode); in xfs_reflink_fill_delalloc()
517 error = xfs_trans_alloc_inode(ip, &M_RES(mp)->tr_write, 0, 0, in xfs_reflink_fill_delalloc()
524 error = xfs_find_trim_cow_extent(ip, imap, cmap, shared, in xfs_reflink_fill_delalloc()
534 ASSERT(isnullstartblock(cmap->br_startblock) || in xfs_reflink_fill_delalloc()
535 cmap->br_startblock == DELAYSTARTBLOCK); in xfs_reflink_fill_delalloc()
541 error = xfs_bmapi_write(tp, ip, cmap->br_startoff, in xfs_reflink_fill_delalloc()
542 cmap->br_blockcount, in xfs_reflink_fill_delalloc()
548 xfs_inode_set_cowblocks_tag(ip); in xfs_reflink_fill_delalloc()
552 } while (cmap->br_startoff + cmap->br_blockcount <= imap->br_startoff); in xfs_reflink_fill_delalloc()
554 return xfs_reflink_convert_unwritten(ip, imap, cmap, convert_now); in xfs_reflink_fill_delalloc()
561 /* Allocate all CoW reservations covering a range of blocks in a file. */
564 struct xfs_inode *ip, in xfs_reflink_allocate_cow() argument
574 xfs_assert_ilocked(ip, XFS_ILOCK_EXCL); in xfs_reflink_allocate_cow()
575 if (!ip->i_cowfp) { in xfs_reflink_allocate_cow()
576 ASSERT(!xfs_is_reflink_inode(ip)); in xfs_reflink_allocate_cow()
577 xfs_ifork_init_cow(ip); in xfs_reflink_allocate_cow()
580 error = xfs_find_trim_cow_extent(ip, imap, cmap, shared, &found); in xfs_reflink_allocate_cow()
586 return xfs_reflink_convert_unwritten(ip, imap, cmap, in xfs_reflink_allocate_cow()
593 if (cmap->br_startoff > imap->br_startoff) in xfs_reflink_allocate_cow()
594 return xfs_reflink_fill_cow_hole(ip, imap, cmap, shared, in xfs_reflink_allocate_cow()
601 if (isnullstartblock(cmap->br_startblock) || in xfs_reflink_allocate_cow()
602 cmap->br_startblock == DELAYSTARTBLOCK) in xfs_reflink_allocate_cow()
603 return xfs_reflink_fill_delalloc(ip, imap, cmap, shared, in xfs_reflink_allocate_cow()
608 return -EFSCORRUPTED; in xfs_reflink_allocate_cow()
622 struct xfs_inode *ip, in xfs_reflink_cancel_cow_blocks() argument
628 struct xfs_ifork *ifp = xfs_ifork_ptr(ip, XFS_COW_FORK); in xfs_reflink_cancel_cow_blocks()
631 bool isrt = XFS_IS_REALTIME_INODE(ip); in xfs_reflink_cancel_cow_blocks()
634 if (!xfs_inode_has_cow_data(ip)) in xfs_reflink_cancel_cow_blocks()
636 if (!xfs_iext_lookup_extent_before(ip, ifp, &end_fsb, &icur, &got)) in xfs_reflink_cancel_cow_blocks()
642 xfs_trim_extent(&del, offset_fsb, end_fsb - offset_fsb); in xfs_reflink_cancel_cow_blocks()
650 trace_xfs_reflink_cancel_cow(ip, &del); in xfs_reflink_cancel_cow_blocks()
653 xfs_bmap_del_extent_delay(ip, XFS_COW_FORK, &icur, &got, in xfs_reflink_cancel_cow_blocks()
656 ASSERT((*tpp)->t_highest_agno == NULLAGNUMBER); in xfs_reflink_cancel_cow_blocks()
675 xfs_bmap_del_extent_cow(ip, &icur, &got, &del); in xfs_reflink_cancel_cow_blocks()
678 xfs_quota_unreserve_blkres(ip, del.br_blockcount); in xfs_reflink_cancel_cow_blocks()
689 if (!ifp->if_bytes) in xfs_reflink_cancel_cow_blocks()
690 xfs_inode_clear_cowblocks_tag(ip); in xfs_reflink_cancel_cow_blocks()
702 struct xfs_inode *ip, in xfs_reflink_cancel_cow_range() argument
712 trace_xfs_reflink_cancel_cow_range(ip, offset, count); in xfs_reflink_cancel_cow_range()
713 ASSERT(ip->i_cowfp); in xfs_reflink_cancel_cow_range()
715 offset_fsb = XFS_B_TO_FSBT(ip->i_mount, offset); in xfs_reflink_cancel_cow_range()
719 end_fsb = XFS_B_TO_FSB(ip->i_mount, offset + count); in xfs_reflink_cancel_cow_range()
722 error = xfs_trans_alloc(ip->i_mount, &M_RES(ip->i_mount)->tr_write, in xfs_reflink_cancel_cow_range()
727 xfs_ilock(ip, XFS_ILOCK_EXCL); in xfs_reflink_cancel_cow_range()
728 xfs_trans_ijoin(tp, ip, 0); in xfs_reflink_cancel_cow_range()
731 error = xfs_reflink_cancel_cow_blocks(ip, &tp, offset_fsb, end_fsb, in xfs_reflink_cancel_cow_range()
738 xfs_iunlock(ip, XFS_ILOCK_EXCL); in xfs_reflink_cancel_cow_range()
743 xfs_iunlock(ip, XFS_ILOCK_EXCL); in xfs_reflink_cancel_cow_range()
745 trace_xfs_reflink_cancel_cow_range_error(ip, error, _RET_IP_); in xfs_reflink_cancel_cow_range()
759 struct xfs_inode *ip, in xfs_reflink_update_quota() argument
761 int64_t blocks) in xfs_reflink_update_quota() argument
765 if (XFS_IS_REALTIME_INODE(ip)) { in xfs_reflink_update_quota()
772 xfs_trans_mod_dquot_byino(tp, ip, qflag, blocks); in xfs_reflink_update_quota()
775 # define xfs_reflink_update_quota(tp, ip, is_cow, blocks) ((void)0) argument
784 * transaction because we can end up merging and splitting bmbt blocks for
790 struct xfs_inode *ip, in xfs_reflink_end_cow_extent() argument
796 struct xfs_mount *mp = ip->i_mount; in xfs_reflink_end_cow_extent()
798 struct xfs_ifork *ifp = xfs_ifork_ptr(ip, XFS_COW_FORK); in xfs_reflink_end_cow_extent()
801 bool isrt = XFS_IS_REALTIME_INODE(ip); in xfs_reflink_end_cow_extent()
805 error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, resblks, 0, in xfs_reflink_end_cow_extent()
815 xfs_ilock(ip, XFS_ILOCK_EXCL); in xfs_reflink_end_cow_extent()
816 xfs_trans_ijoin(tp, ip, 0); in xfs_reflink_end_cow_extent()
823 if (!xfs_iext_lookup_extent(ip, ifp, *offset_fsb, &icur, &got) || in xfs_reflink_end_cow_extent()
844 xfs_trim_extent(&del, *offset_fsb, end_fsb - *offset_fsb); in xfs_reflink_end_cow_extent()
846 error = xfs_iext_count_extend(tp, ip, XFS_DATA_FORK, in xfs_reflink_end_cow_extent()
853 error = xfs_bmapi_read(ip, del.br_startoff, del.br_blockcount, &data, in xfs_reflink_end_cow_extent()
862 trace_xfs_reflink_cow_remap_from(ip, &del); in xfs_reflink_end_cow_extent()
863 trace_xfs_reflink_cow_remap_to(ip, &data); in xfs_reflink_end_cow_extent()
870 xfs_bmap_unmap_extent(tp, ip, XFS_DATA_FORK, &data); in xfs_reflink_end_cow_extent()
872 xfs_reflink_update_quota(tp, ip, false, -data.br_blockcount); in xfs_reflink_end_cow_extent()
882 error = xfs_bunmapi(NULL, ip, data.br_startoff, in xfs_reflink_end_cow_extent()
893 /* Map the new blocks into the data fork. */ in xfs_reflink_end_cow_extent()
894 xfs_bmap_map_extent(tp, ip, XFS_DATA_FORK, &del); in xfs_reflink_end_cow_extent()
896 /* Charge this new data fork mapping to the on-disk quota. */ in xfs_reflink_end_cow_extent()
897 xfs_reflink_update_quota(tp, ip, true, del.br_blockcount); in xfs_reflink_end_cow_extent()
900 xfs_bmap_del_extent_cow(ip, &icur, &got, &del); in xfs_reflink_end_cow_extent()
903 xfs_iunlock(ip, XFS_ILOCK_EXCL); in xfs_reflink_end_cow_extent()
913 xfs_iunlock(ip, XFS_ILOCK_EXCL); in xfs_reflink_end_cow_extent()
922 struct xfs_inode *ip, in xfs_reflink_end_cow() argument
930 trace_xfs_reflink_end_cow(ip, offset, count); in xfs_reflink_end_cow()
932 offset_fsb = XFS_B_TO_FSBT(ip->i_mount, offset); in xfs_reflink_end_cow()
933 end_fsb = XFS_B_TO_FSB(ip->i_mount, offset + count); in xfs_reflink_end_cow()
948 * region. There are also have post-eof checks in the writeback in xfs_reflink_end_cow()
965 * blocks will be remapped. in xfs_reflink_end_cow()
968 error = xfs_reflink_end_cow_extent(ip, &offset_fsb, end_fsb); in xfs_reflink_end_cow()
971 trace_xfs_reflink_end_cow_error(ip, error, _RET_IP_); in xfs_reflink_end_cow()
976 * Free all CoW staging blocks that are still referenced by the ondisk refcount
1019 * logical blocks in dest and src touched by the reflink operation.
1022 * - Read src's bmbt at the start of srange ("imap")
1023 * - If imap doesn't exist, make imap appear to start at the end of srange
1025 * - If imap starts before srange, advance imap to start at srange.
1026 * - If imap goes beyond srange, truncate imap to end at the end of srange.
1027 * - Punch (imap start - srange start + imap len) blocks from dest at
1029 * - If imap points to a real range of pblks,
1032 * (drange start + imap start - srange start)
1033 * - Advance drange and srange by (imap start - srange start + imap len)
1035 * Finally, if the reflink made dest longer, update both the in-core and
1036 * on-disk file sizes.
1042 * ----SSSSSSS-SSSSS----SSSSSS (src file)
1043 * <-------------------->
1047 * --DDDDDDDDDDDDDDDDDDD--DDD (dest file)
1048 * <-------------------->
1049 * '-' means a hole, and 'S' and 'D' are written blocks in the src and dest.
1054 * unmap more blocks from the destination file than we remap.
1056 * ----SSSSSSS-SSSSS----SSSSSS
1057 * <------->
1058 * --DDDDD---------DDDDD--DDD
1059 * <------->
1063 * ----SSSSSSS-SSSSS----SSSSSS
1064 * <------->
1065 * --DDDDD--SSSSSSSDDDDD--DDD
1066 * <------->
1071 * ----SSSSSSS-SSSSS----SSSSSS
1072 * <---->
1073 * --DDDDD--SSSSSSS-SSSSS-DDD
1074 * <---->
1079 * ----SSSSSSS-SSSSS----SSSSSS
1080 * <----->
1081 * --DDDDD--SSSSSSS-SSSSS----SSS
1082 * <----->
1095 struct xfs_mount *mp = src->i_mount; in xfs_reflink_set_inode_flag()
1102 error = xfs_trans_alloc(mp, &M_RES(mp)->tr_ichange, 0, 0, 0, &tp); in xfs_reflink_set_inode_flag()
1107 if (src->i_ino == dest->i_ino) in xfs_reflink_set_inode_flag()
1115 src->i_diflags2 |= XFS_DIFLAG2_REFLINK; in xfs_reflink_set_inode_flag()
1121 if (src->i_ino == dest->i_ino) in xfs_reflink_set_inode_flag()
1127 dest->i_diflags2 |= XFS_DIFLAG2_REFLINK; in xfs_reflink_set_inode_flag()
1154 struct xfs_mount *mp = dest->i_mount; in xfs_reflink_update_dest()
1161 error = xfs_trans_alloc(mp, &M_RES(mp)->tr_ichange, 0, 0, 0, &tp); in xfs_reflink_update_dest()
1171 dest->i_disk_size = newlen; in xfs_reflink_update_dest()
1175 dest->i_cowextsize = cowextsize; in xfs_reflink_update_dest()
1176 dest->i_diflags2 |= XFS_DIFLAG2_COWEXTSIZE; in xfs_reflink_update_dest()
1200 struct xfs_inode *ip, in xfs_reflink_ag_has_free_space() argument
1209 if (XFS_IS_REALTIME_INODE(ip)) { in xfs_reflink_ag_has_free_space()
1216 error = -ENOSPC; in xfs_reflink_ag_has_free_space()
1225 error = -ENOSPC; in xfs_reflink_ag_has_free_space()
1232 * the number of blocks that were actually remapped.
1236 struct xfs_inode *ip, in xfs_reflink_remap_extent() argument
1241 struct xfs_mount *mp = ip->i_mount; in xfs_reflink_remap_extent()
1249 bool isrt = XFS_IS_REALTIME_INODE(ip); in xfs_reflink_remap_extent()
1276 if (XFS_IS_REALTIME_INODE(ip)) { in xfs_reflink_remap_extent()
1278 rblocks = dmap->br_blockcount; in xfs_reflink_remap_extent()
1280 dblocks = resblks + dmap->br_blockcount; in xfs_reflink_remap_extent()
1283 error = xfs_trans_alloc_inode(ip, &M_RES(mp)->tr_write, in xfs_reflink_remap_extent()
1285 if (error == -EDQUOT || error == -ENOSPC) { in xfs_reflink_remap_extent()
1287 error = xfs_trans_alloc_inode(ip, &M_RES(mp)->tr_write, in xfs_reflink_remap_extent()
1299 error = xfs_bmapi_read(ip, dmap->br_startoff, dmap->br_blockcount, in xfs_reflink_remap_extent()
1303 ASSERT(nimaps == 1 && smap.br_startoff == dmap->br_startoff); in xfs_reflink_remap_extent()
1307 * We can only remap as many blocks as the smaller of the two extent in xfs_reflink_remap_extent()
1310 dmap->br_blockcount = min(dmap->br_blockcount, smap.br_blockcount); in xfs_reflink_remap_extent()
1311 ASSERT(dmap->br_blockcount == smap.br_blockcount); in xfs_reflink_remap_extent()
1313 trace_xfs_reflink_remap_extent_dest(ip, &smap); in xfs_reflink_remap_extent()
1320 if (dmap->br_startblock == smap.br_startblock) { in xfs_reflink_remap_extent()
1321 if (dmap->br_state != smap.br_state) { in xfs_reflink_remap_extent()
1322 xfs_bmap_mark_sick(ip, XFS_DATA_FORK); in xfs_reflink_remap_extent()
1323 error = -EFSCORRUPTED; in xfs_reflink_remap_extent()
1329 if (dmap->br_state == XFS_EXT_UNWRITTEN && in xfs_reflink_remap_extent()
1335 error = xfs_reflink_ag_has_free_space(mp, ip, in xfs_reflink_remap_extent()
1336 dmap->br_startblock); in xfs_reflink_remap_extent()
1346 * enough quota block count reservation to handle the blocks in that in xfs_reflink_remap_extent()
1348 * extent we're unmapping also has blocks allocated to it, we don't in xfs_reflink_remap_extent()
1364 if (XFS_IS_REALTIME_INODE(ip)) { in xfs_reflink_remap_extent()
1366 rblocks = dmap->br_blockcount; in xfs_reflink_remap_extent()
1368 dblocks = dmap->br_blockcount; in xfs_reflink_remap_extent()
1371 error = xfs_trans_reserve_quota_nblks(tp, ip, dblocks, rblocks, in xfs_reflink_remap_extent()
1383 error = xfs_iext_count_extend(tp, ip, XFS_DATA_FORK, iext_delta); in xfs_reflink_remap_extent()
1392 xfs_bmap_unmap_extent(tp, ip, XFS_DATA_FORK, &smap); in xfs_reflink_remap_extent()
1394 qdelta -= smap.br_blockcount; in xfs_reflink_remap_extent()
1404 error = xfs_bunmapi(NULL, ip, smap.br_startoff, in xfs_reflink_remap_extent()
1417 xfs_bmap_map_extent(tp, ip, XFS_DATA_FORK, dmap); in xfs_reflink_remap_extent()
1418 qdelta += dmap->br_blockcount; in xfs_reflink_remap_extent()
1421 xfs_reflink_update_quota(tp, ip, false, qdelta); in xfs_reflink_remap_extent()
1424 newlen = XFS_FSB_TO_B(mp, dmap->br_startoff + dmap->br_blockcount); in xfs_reflink_remap_extent()
1426 if (newlen > i_size_read(VFS_I(ip))) { in xfs_reflink_remap_extent()
1427 trace_xfs_reflink_update_inode_size(ip, newlen); in xfs_reflink_remap_extent()
1428 i_size_write(VFS_I(ip), newlen); in xfs_reflink_remap_extent()
1429 ip->i_disk_size = newlen; in xfs_reflink_remap_extent()
1430 xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); in xfs_reflink_remap_extent()
1440 xfs_iunlock(ip, XFS_ILOCK_EXCL); in xfs_reflink_remap_extent()
1443 trace_xfs_reflink_remap_extent_error(ip, error, _RET_IP_); in xfs_reflink_remap_extent()
1458 struct xfs_mount *mp = src->i_mount; in xfs_reflink_remap_blocks()
1493 error = -EFSCORRUPTED; in xfs_reflink_remap_blocks()
1506 error = -EINTR; in xfs_reflink_remap_blocks()
1513 len -= imap.br_blockcount; in xfs_reflink_remap_blocks()
1521 XFS_FSB_TO_B(src->i_mount, remapped_len)); in xfs_reflink_remap_blocks()
1527 * zero any speculative post-EOF preallocations that sit between the old EOF
1532 struct xfs_inode *ip, in xfs_reflink_zero_posteof() argument
1535 loff_t isize = i_size_read(VFS_I(ip)); in xfs_reflink_zero_posteof()
1540 trace_xfs_zero_eof(ip, isize, pos - isize); in xfs_reflink_zero_posteof()
1541 return xfs_zero_range(ip, isize, pos - isize, NULL); in xfs_reflink_zero_posteof()
1550 * The VFS allows partial EOF blocks to "match" for dedupe even though it hasn't
1555 * In similar fashion, the VFS file cloning also allows partial EOF blocks to be
1571 * -EINVAL in this case.
1594 ret = -EINVAL; in xfs_reflink_remap_prep()
1599 /* Don't share DAX file data with non-DAX file. */ in xfs_reflink_remap_prep()
1618 * Zero existing post-eof speculative preallocations in the destination in xfs_reflink_remap_prep()
1625 /* Set flags and remap blocks. */ in xfs_reflink_remap_prep()
1631 * If pos_out > EOF, we may have dirtied blocks between EOF and in xfs_reflink_remap_prep()
1636 loff_t flen = *len + (pos_out - XFS_ISIZE(dest)); in xfs_reflink_remap_prep()
1658 struct xfs_inode *ip, in xfs_reflink_inode_has_shared_extents() argument
1662 struct xfs_mount *mp = ip->i_mount; in xfs_reflink_inode_has_shared_extents()
1668 ifp = xfs_ifork_ptr(ip, XFS_DATA_FORK); in xfs_reflink_inode_has_shared_extents()
1669 error = xfs_iread_extents(tp, ip, XFS_DATA_FORK); in xfs_reflink_inode_has_shared_extents()
1674 found = xfs_iext_lookup_extent(ip, ifp, 0, &icur, &got); in xfs_reflink_inode_has_shared_extents()
1682 if (XFS_IS_REALTIME_INODE(ip)) in xfs_reflink_inode_has_shared_extents()
1711 struct xfs_inode *ip, in xfs_reflink_clear_inode_flag() argument
1717 ASSERT(xfs_is_reflink_inode(ip)); in xfs_reflink_clear_inode_flag()
1719 if (!xfs_can_free_cowblocks(ip)) in xfs_reflink_clear_inode_flag()
1722 error = xfs_reflink_inode_has_shared_extents(*tpp, ip, &needs_flag); in xfs_reflink_clear_inode_flag()
1727 * We didn't find any shared blocks so turn off the reflink flag. in xfs_reflink_clear_inode_flag()
1730 error = xfs_reflink_cancel_cow_blocks(ip, tpp, 0, XFS_MAX_FILEOFF, in xfs_reflink_clear_inode_flag()
1736 trace_xfs_reflink_unset_inode_flag(ip); in xfs_reflink_clear_inode_flag()
1737 ip->i_diflags2 &= ~XFS_DIFLAG2_REFLINK; in xfs_reflink_clear_inode_flag()
1738 xfs_inode_clear_cowblocks_tag(ip); in xfs_reflink_clear_inode_flag()
1739 xfs_trans_log_inode(*tpp, ip, XFS_ILOG_CORE); in xfs_reflink_clear_inode_flag()
1750 struct xfs_inode *ip) in xfs_reflink_try_clear_inode_flag() argument
1752 struct xfs_mount *mp = ip->i_mount; in xfs_reflink_try_clear_inode_flag()
1757 error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, 0, 0, 0, &tp); in xfs_reflink_try_clear_inode_flag()
1761 xfs_ilock(ip, XFS_ILOCK_EXCL); in xfs_reflink_try_clear_inode_flag()
1762 xfs_trans_ijoin(tp, ip, 0); in xfs_reflink_try_clear_inode_flag()
1764 error = xfs_reflink_clear_inode_flag(ip, &tp); in xfs_reflink_try_clear_inode_flag()
1772 xfs_iunlock(ip, XFS_ILOCK_EXCL); in xfs_reflink_try_clear_inode_flag()
1777 xfs_iunlock(ip, XFS_ILOCK_EXCL); in xfs_reflink_try_clear_inode_flag()
1782 * Pre-COW all shared blocks within a given byte range of a file and turn off
1783 * the reflink flag if we unshare all of the file's blocks.
1787 struct xfs_inode *ip, in xfs_reflink_unshare() argument
1791 struct inode *inode = VFS_I(ip); in xfs_reflink_unshare()
1794 if (!xfs_is_reflink_inode(ip)) in xfs_reflink_unshare()
1797 trace_xfs_reflink_unshare(ip, offset, len); in xfs_reflink_unshare()
1810 error = filemap_write_and_wait_range(inode->i_mapping, offset, in xfs_reflink_unshare()
1811 offset + len - 1); in xfs_reflink_unshare()
1816 error = xfs_reflink_try_clear_inode_flag(ip); in xfs_reflink_unshare()
1822 trace_xfs_reflink_unshare_error(ip, error, _RET_IP_); in xfs_reflink_unshare()
1842 * because we would have to perform CoW-around for unaligned write in xfs_reflink_supports_rextsize()