• Home
  • Raw
  • Download

Lines Matching +full:ip +full:- +full:blocks

1 // SPDX-License-Identifier: GPL-2.0+
45 * Copy on Write of Shared Blocks
48 * the same physical blocks. This means that a write to one file must not
49 * alter the blocks in a different file; the way that we'll do that is
50 * through the use of a copy-on-write mechanism. At a high level, that
56 * of disk blocks to dirty-but-not-yet-mapped file blocks as long as
62 * create a delalloc mapping, which is a regular in-core extent, but without
64 * a flag that this is a delalloc mapping, and a worst-case estimate of how
65 * many blocks might be required to put the mapping into the BMBT.) delalloc
74 * D: --RRRRRRSSSRRRRRRRR--- (data fork)
75 * C: ------DDDDDDD--------- (CoW fork)
79 * allocating blocks and replacing the delalloc mapping with real ones.
83 * D: --RRRRRRSSSRRRRRRRR---
84 * C: ------UUUUUUU---------
86 * We want to adapt the delalloc mechanism for copy-on-write, since the
88 * and allocating the blocks) are exactly the same as delalloc except that
96 * Block-aligned directio writes will use the same mechanism as buffered
104 * D: --RRRRRRSSSRRRRRRRR---
105 * C: ------UUrrUUU---------
111 * that cover the file blocks that we just CoW'd. For each extent, simply
115 * only to remap the blocks that we've actually written out -- we must
116 * never remap delalloc reservations nor CoW staging blocks that have
120 * D: --RRRRRRrrSRRRRRRRR---
121 * C: ------UU--UUU---------
127 * remember the presence of unwritten blocks and CoW blocks with a single
133 * Given an AG extent, find the lowest-numbered run of shared blocks
136 * shared blocks. If there are no shared extents, fbno and flen will
158 return -ENOMEM; in xfs_reflink_find_shared()
174 * find the lowest-numbered extent of shared blocks that coincides with
183 struct xfs_inode *ip, in xfs_reflink_trim_around_shared() argument
196 if (!xfs_is_reflink_inode(ip) || !xfs_bmap_is_real_extent(irec)) { in xfs_reflink_trim_around_shared()
201 trace_xfs_reflink_trim_around_shared(ip, irec); in xfs_reflink_trim_around_shared()
203 agno = XFS_FSB_TO_AGNO(ip->i_mount, irec->br_startblock); in xfs_reflink_trim_around_shared()
204 agbno = XFS_FSB_TO_AGBNO(ip->i_mount, irec->br_startblock); in xfs_reflink_trim_around_shared()
205 aglen = irec->br_blockcount; in xfs_reflink_trim_around_shared()
207 error = xfs_reflink_find_shared(ip->i_mount, NULL, agno, agbno, in xfs_reflink_trim_around_shared()
214 /* No shared blocks at all. */ in xfs_reflink_trim_around_shared()
223 irec->br_blockcount = flen; in xfs_reflink_trim_around_shared()
235 irec->br_blockcount = fbno - agbno; in xfs_reflink_trim_around_shared()
243 * if imap->br_startoff points to a shared extent reserve space for it in the
246 * Note that imap will always contain the block numbers for the existing blocks
247 * in the data fork, as the upper layers need them for read-modify-write
252 struct xfs_inode *ip, in xfs_reflink_reserve_cow() argument
256 struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, XFS_COW_FORK); in xfs_reflink_reserve_cow()
265 * so that we also unshared block adjacent to shared blocks instead in xfs_reflink_reserve_cow()
266 * of just the shared blocks themselves. Second the lookup in the in xfs_reflink_reserve_cow()
271 if (!xfs_iext_lookup_extent(ip, ifp, imap->br_startoff, &icur, &got)) in xfs_reflink_reserve_cow()
273 if (!eof && got.br_startoff <= imap->br_startoff) { in xfs_reflink_reserve_cow()
274 trace_xfs_reflink_cow_found(ip, imap); in xfs_reflink_reserve_cow()
282 error = xfs_reflink_trim_around_shared(ip, imap, shared, &trimmed); in xfs_reflink_reserve_cow()
291 * Fork all the shared blocks from our write offset until the end of in xfs_reflink_reserve_cow()
294 error = xfs_qm_dqattach_locked(ip, false); in xfs_reflink_reserve_cow()
298 error = xfs_bmapi_reserve_delalloc(ip, XFS_COW_FORK, imap->br_startoff, in xfs_reflink_reserve_cow()
299 imap->br_blockcount, 0, &got, &icur, eof); in xfs_reflink_reserve_cow()
300 if (error == -ENOSPC || error == -EDQUOT) in xfs_reflink_reserve_cow()
301 trace_xfs_reflink_cow_enospc(ip, imap); in xfs_reflink_reserve_cow()
306 trace_xfs_reflink_cow_alloc(ip, &got); in xfs_reflink_reserve_cow()
313 struct xfs_inode *ip, in xfs_reflink_convert_cow_extent() argument
320 if (imap->br_state == XFS_EXT_NORM) in xfs_reflink_convert_cow_extent()
324 trace_xfs_reflink_convert_cow(ip, imap); in xfs_reflink_convert_cow_extent()
325 if (imap->br_blockcount == 0) in xfs_reflink_convert_cow_extent()
327 return xfs_bmapi_write(NULL, ip, imap->br_startoff, imap->br_blockcount, in xfs_reflink_convert_cow_extent()
335 struct xfs_inode *ip, in xfs_reflink_convert_cow() argument
339 struct xfs_mount *mp = ip->i_mount; in xfs_reflink_convert_cow()
342 xfs_filblks_t count_fsb = end_fsb - offset_fsb; in xfs_reflink_convert_cow()
348 xfs_ilock(ip, XFS_ILOCK_EXCL); in xfs_reflink_convert_cow()
349 error = xfs_bmapi_write(NULL, ip, offset_fsb, count_fsb, in xfs_reflink_convert_cow()
352 xfs_iunlock(ip, XFS_ILOCK_EXCL); in xfs_reflink_convert_cow()
363 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()
380 if (!xfs_iext_lookup_extent(ip, ip->i_cowfp, offset_fsb, &icur, &got) || in xfs_find_trim_cow_extent()
382 return xfs_reflink_trim_around_shared(ip, imap, shared, &trimmed); in xfs_find_trim_cow_extent()
390 /* real extent found - no need to allocate */ in xfs_find_trim_cow_extent()
397 /* Allocate all CoW reservations covering a range of blocks in a file. */
400 struct xfs_inode *ip, in xfs_reflink_allocate_cow() argument
405 struct xfs_mount *mp = ip->i_mount; in xfs_reflink_allocate_cow()
406 xfs_fileoff_t offset_fsb = imap->br_startoff; in xfs_reflink_allocate_cow()
407 xfs_filblks_t count_fsb = imap->br_blockcount; in xfs_reflink_allocate_cow()
414 ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); in xfs_reflink_allocate_cow()
415 ASSERT(xfs_is_reflink_inode(ip)); in xfs_reflink_allocate_cow()
417 error = xfs_find_trim_cow_extent(ip, imap, shared, &found); in xfs_reflink_allocate_cow()
423 resaligned = xfs_aligned_fsb_count(imap->br_startoff, in xfs_reflink_allocate_cow()
424 imap->br_blockcount, xfs_get_cowextsz_hint(ip)); in xfs_reflink_allocate_cow()
427 xfs_iunlock(ip, *lockmode); in xfs_reflink_allocate_cow()
428 error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, resblks, 0, 0, &tp); in xfs_reflink_allocate_cow()
430 xfs_ilock(ip, *lockmode); in xfs_reflink_allocate_cow()
435 error = xfs_qm_dqattach_locked(ip, false); in xfs_reflink_allocate_cow()
442 error = xfs_find_trim_cow_extent(ip, imap, shared, &found); in xfs_reflink_allocate_cow()
450 error = xfs_trans_reserve_quota_nblks(tp, ip, resblks, 0, in xfs_reflink_allocate_cow()
455 xfs_trans_ijoin(tp, ip, 0); in xfs_reflink_allocate_cow()
457 /* Allocate the entire reservation as unwritten blocks. */ in xfs_reflink_allocate_cow()
459 error = xfs_bmapi_write(tp, ip, imap->br_startoff, imap->br_blockcount, in xfs_reflink_allocate_cow()
465 xfs_inode_set_cowblocks_tag(ip); in xfs_reflink_allocate_cow()
475 return -ENOSPC; in xfs_reflink_allocate_cow()
477 return xfs_reflink_convert_cow_extent(ip, imap, offset_fsb, count_fsb); in xfs_reflink_allocate_cow()
480 xfs_trans_unreserve_quota_nblks(tp, ip, (long)resblks, 0, in xfs_reflink_allocate_cow()
498 struct xfs_inode *ip, in xfs_reflink_cancel_cow_blocks() argument
504 struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, XFS_COW_FORK); in xfs_reflink_cancel_cow_blocks()
509 if (!xfs_inode_has_cow_data(ip)) in xfs_reflink_cancel_cow_blocks()
511 if (!xfs_iext_lookup_extent_before(ip, ifp, &end_fsb, &icur, &got)) in xfs_reflink_cancel_cow_blocks()
517 xfs_trim_extent(&del, offset_fsb, end_fsb - offset_fsb); in xfs_reflink_cancel_cow_blocks()
525 trace_xfs_reflink_cancel_cow(ip, &del); in xfs_reflink_cancel_cow_blocks()
528 error = xfs_bmap_del_extent_delay(ip, XFS_COW_FORK, in xfs_reflink_cancel_cow_blocks()
533 ASSERT((*tpp)->t_firstblock == NULLFSBLOCK); in xfs_reflink_cancel_cow_blocks()
550 xfs_bmap_del_extent_cow(ip, &icur, &got, &del); in xfs_reflink_cancel_cow_blocks()
553 error = xfs_trans_reserve_quota_nblks(NULL, ip, in xfs_reflink_cancel_cow_blocks()
554 -(long)del.br_blockcount, 0, in xfs_reflink_cancel_cow_blocks()
568 if (!ifp->if_bytes) in xfs_reflink_cancel_cow_blocks()
569 xfs_inode_clear_cowblocks_tag(ip); in xfs_reflink_cancel_cow_blocks()
581 struct xfs_inode *ip, in xfs_reflink_cancel_cow_range() argument
591 trace_xfs_reflink_cancel_cow_range(ip, offset, count); in xfs_reflink_cancel_cow_range()
592 ASSERT(xfs_is_reflink_inode(ip)); in xfs_reflink_cancel_cow_range()
594 offset_fsb = XFS_B_TO_FSBT(ip->i_mount, offset); in xfs_reflink_cancel_cow_range()
598 end_fsb = XFS_B_TO_FSB(ip->i_mount, offset + count); in xfs_reflink_cancel_cow_range()
601 error = xfs_trans_alloc(ip->i_mount, &M_RES(ip->i_mount)->tr_write, in xfs_reflink_cancel_cow_range()
606 xfs_ilock(ip, XFS_ILOCK_EXCL); in xfs_reflink_cancel_cow_range()
607 xfs_trans_ijoin(tp, ip, 0); in xfs_reflink_cancel_cow_range()
610 error = xfs_reflink_cancel_cow_blocks(ip, &tp, offset_fsb, end_fsb, in xfs_reflink_cancel_cow_range()
617 xfs_iunlock(ip, XFS_ILOCK_EXCL); in xfs_reflink_cancel_cow_range()
622 xfs_iunlock(ip, XFS_ILOCK_EXCL); in xfs_reflink_cancel_cow_range()
624 trace_xfs_reflink_cancel_cow_range_error(ip, error, _RET_IP_); in xfs_reflink_cancel_cow_range()
633 struct xfs_inode *ip, in xfs_reflink_end_cow() argument
637 struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, XFS_COW_FORK); in xfs_reflink_end_cow()
647 trace_xfs_reflink_end_cow(ip, offset, count); in xfs_reflink_end_cow()
650 if (ifp->if_bytes == 0) in xfs_reflink_end_cow()
653 offset_fsb = XFS_B_TO_FSBT(ip->i_mount, offset); in xfs_reflink_end_cow()
654 end_fsb = XFS_B_TO_FSB(ip->i_mount, offset + count); in xfs_reflink_end_cow()
658 * unlikely ever to have to remap 16T worth of single-block in xfs_reflink_end_cow()
659 * extents, so just cap the worst case extent count to 2^32-1. in xfs_reflink_end_cow()
660 * Stick a warning in just in case, and avoid 64-bit division. in xfs_reflink_end_cow()
663 if (end_fsb - offset_fsb > UINT_MAX) { in xfs_reflink_end_cow()
664 error = -EFSCORRUPTED; in xfs_reflink_end_cow()
665 xfs_force_shutdown(ip->i_mount, SHUTDOWN_CORRUPT_INCORE); in xfs_reflink_end_cow()
669 resblks = XFS_NEXTENTADD_SPACE_RES(ip->i_mount, in xfs_reflink_end_cow()
670 (unsigned int)(end_fsb - offset_fsb), in xfs_reflink_end_cow()
672 error = xfs_trans_alloc(ip->i_mount, &M_RES(ip->i_mount)->tr_write, in xfs_reflink_end_cow()
677 xfs_ilock(ip, XFS_ILOCK_EXCL); in xfs_reflink_end_cow()
678 xfs_trans_ijoin(tp, ip, 0); in xfs_reflink_end_cow()
685 if (!xfs_iext_lookup_extent_before(ip, ifp, &end_fsb, &icur, &got)) in xfs_reflink_end_cow()
691 xfs_trim_extent(&del, offset_fsb, end_fsb - offset_fsb); in xfs_reflink_end_cow()
705 /* Unmap the old blocks in the data fork. */ in xfs_reflink_end_cow()
706 ASSERT(tp->t_firstblock == NULLFSBLOCK); in xfs_reflink_end_cow()
708 error = __xfs_bunmapi(tp, ip, del.br_startoff, &rlen, 0, 1); in xfs_reflink_end_cow()
715 del.br_blockcount - rlen); in xfs_reflink_end_cow()
717 trace_xfs_reflink_cow_remap(ip, &del); in xfs_reflink_end_cow()
725 /* Map the new blocks into the data fork. */ in xfs_reflink_end_cow()
726 error = xfs_bmap_map_extent(tp, ip, &del); in xfs_reflink_end_cow()
730 /* Charge this new data fork mapping to the on-disk quota. */ in xfs_reflink_end_cow()
731 xfs_trans_mod_dquot_byino(tp, ip, XFS_TRANS_DQ_DELBCOUNT, in xfs_reflink_end_cow()
735 xfs_bmap_del_extent_cow(ip, &icur, &got, &del); in xfs_reflink_end_cow()
749 xfs_iunlock(ip, XFS_ILOCK_EXCL); in xfs_reflink_end_cow()
756 xfs_iunlock(ip, XFS_ILOCK_EXCL); in xfs_reflink_end_cow()
758 trace_xfs_reflink_end_cow_error(ip, error, _RET_IP_); in xfs_reflink_end_cow()
772 if (!xfs_sb_version_hasreflink(&mp->m_sb)) in xfs_reflink_recover_cow()
775 for (agno = 0; agno < mp->m_sb.sb_agcount; agno++) { in xfs_reflink_recover_cow()
792 * logical blocks in dest and src touched by the reflink operation.
795 * - Read src's bmbt at the start of srange ("imap")
796 * - If imap doesn't exist, make imap appear to start at the end of srange
798 * - If imap starts before srange, advance imap to start at srange.
799 * - If imap goes beyond srange, truncate imap to end at the end of srange.
800 * - Punch (imap start - srange start + imap len) blocks from dest at
802 * - If imap points to a real range of pblks,
805 * (drange start + imap start - srange start)
806 * - Advance drange and srange by (imap start - srange start + imap len)
808 * Finally, if the reflink made dest longer, update both the in-core and
809 * on-disk file sizes.
815 * ----SSSSSSS-SSSSS----SSSSSS (src file)
816 * <-------------------->
820 * --DDDDDDDDDDDDDDDDDDD--DDD (dest file)
821 * <-------------------->
822 * '-' means a hole, and 'S' and 'D' are written blocks in the src and dest.
827 * unmap more blocks from the destination file than we remap.
829 * ----SSSSSSS-SSSSS----SSSSSS
830 * <------->
831 * --DDDDD---------DDDDD--DDD
832 * <------->
836 * ----SSSSSSS-SSSSS----SSSSSS
837 * <------->
838 * --DDDDD--SSSSSSSDDDDD--DDD
839 * <------->
844 * ----SSSSSSS-SSSSS----SSSSSS
845 * <---->
846 * --DDDDD--SSSSSSS-SSSSS-DDD
847 * <---->
852 * ----SSSSSSS-SSSSS----SSSSSS
853 * <----->
854 * --DDDDD--SSSSSSS-SSSSS----SSS
855 * <----->
868 struct xfs_mount *mp = src->i_mount; in xfs_reflink_set_inode_flag()
875 error = xfs_trans_alloc(mp, &M_RES(mp)->tr_ichange, 0, 0, 0, &tp); in xfs_reflink_set_inode_flag()
880 if (src->i_ino == dest->i_ino) in xfs_reflink_set_inode_flag()
888 src->i_d.di_flags2 |= XFS_DIFLAG2_REFLINK; in xfs_reflink_set_inode_flag()
894 if (src->i_ino == dest->i_ino) in xfs_reflink_set_inode_flag()
900 dest->i_d.di_flags2 |= XFS_DIFLAG2_REFLINK; in xfs_reflink_set_inode_flag()
927 struct xfs_mount *mp = dest->i_mount; in xfs_reflink_update_dest()
934 error = xfs_trans_alloc(mp, &M_RES(mp)->tr_ichange, 0, 0, 0, &tp); in xfs_reflink_update_dest()
944 dest->i_d.di_size = newlen; in xfs_reflink_update_dest()
948 dest->i_d.di_cowextsize = cowextsize; in xfs_reflink_update_dest()
949 dest->i_d.di_flags2 |= XFS_DIFLAG2_COWEXTSIZE; in xfs_reflink_update_dest()
982 if (!xfs_sb_version_hasrmapbt(&mp->m_sb)) in xfs_reflink_ag_has_free_space()
988 error = -ENOSPC; in xfs_reflink_ag_has_free_space()
994 * Unmap a range of blocks from a file, then map other blocks into the hole.
995 * The range to unmap is (destoff : destoff + srcioff + irec->br_blockcount).
996 * The extent irec is mapped into dest at irec->br_startoff.
1000 struct xfs_inode *ip, in xfs_reflink_remap_extent() argument
1005 struct xfs_mount *mp = ip->i_mount; in xfs_reflink_remap_extent()
1016 unmap_len = irec->br_startoff + irec->br_blockcount - destoff; in xfs_reflink_remap_extent()
1017 trace_xfs_reflink_punch_range(ip, destoff, unmap_len); in xfs_reflink_remap_extent()
1022 XFS_FSB_TO_AGNO(mp, irec->br_startblock)); in xfs_reflink_remap_extent()
1028 resblks = XFS_EXTENTADD_SPACE_RES(ip->i_mount, XFS_DATA_FORK); in xfs_reflink_remap_extent()
1029 error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, resblks, 0, 0, &tp); in xfs_reflink_remap_extent()
1033 xfs_ilock(ip, XFS_ILOCK_EXCL); in xfs_reflink_remap_extent()
1034 xfs_trans_ijoin(tp, ip, 0); in xfs_reflink_remap_extent()
1039 * at least enough blocks for that split. If the extent being mapped in xfs_reflink_remap_extent()
1044 qres += irec->br_blockcount; in xfs_reflink_remap_extent()
1045 error = xfs_trans_reserve_quota_nblks(tp, ip, qres, 0, in xfs_reflink_remap_extent()
1050 trace_xfs_reflink_remap(ip, irec->br_startoff, in xfs_reflink_remap_extent()
1051 irec->br_blockcount, irec->br_startblock); in xfs_reflink_remap_extent()
1053 /* Unmap the old blocks in the data fork. */ in xfs_reflink_remap_extent()
1056 ASSERT(tp->t_firstblock == NULLFSBLOCK); in xfs_reflink_remap_extent()
1057 error = __xfs_bunmapi(tp, ip, destoff, &rlen, 0, 1); in xfs_reflink_remap_extent()
1065 uirec.br_startblock = irec->br_startblock + rlen; in xfs_reflink_remap_extent()
1066 uirec.br_startoff = irec->br_startoff + rlen; in xfs_reflink_remap_extent()
1067 uirec.br_blockcount = unmap_len - rlen; in xfs_reflink_remap_extent()
1068 uirec.br_state = irec->br_state; in xfs_reflink_remap_extent()
1075 trace_xfs_reflink_remap(ip, uirec.br_startoff, in xfs_reflink_remap_extent()
1083 /* Map the new blocks into the data fork. */ in xfs_reflink_remap_extent()
1084 error = xfs_bmap_map_extent(tp, ip, &uirec); in xfs_reflink_remap_extent()
1089 xfs_trans_mod_dquot_byino(tp, ip, XFS_TRANS_DQ_BCOUNT, in xfs_reflink_remap_extent()
1096 if (newlen > i_size_read(VFS_I(ip))) { in xfs_reflink_remap_extent()
1097 trace_xfs_reflink_update_inode_size(ip, newlen); in xfs_reflink_remap_extent()
1098 i_size_write(VFS_I(ip), newlen); in xfs_reflink_remap_extent()
1099 ip->i_d.di_size = newlen; in xfs_reflink_remap_extent()
1100 xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); in xfs_reflink_remap_extent()
1111 xfs_iunlock(ip, XFS_ILOCK_EXCL); in xfs_reflink_remap_extent()
1118 xfs_iunlock(ip, XFS_ILOCK_EXCL); in xfs_reflink_remap_extent()
1120 trace_xfs_reflink_remap_extent_error(ip, error, _RET_IP_); in xfs_reflink_remap_extent()
1161 range_len = imap.br_startoff + imap.br_blockcount - srcoff; in xfs_reflink_remap_blocks()
1162 imap.br_startoff += destoff - srcoff; in xfs_reflink_remap_blocks()
1171 error = -EINTR; in xfs_reflink_remap_blocks()
1178 len -= range_len; in xfs_reflink_remap_blocks()
1212 if (error == -EWOULDBLOCK) { in xfs_iolock_two_inodes_and_break_layout()
1254 * zero any speculative post-EOF preallocations that sit between the old EOF
1259 struct xfs_inode *ip, in xfs_reflink_zero_posteof() argument
1262 loff_t isize = i_size_read(VFS_I(ip)); in xfs_reflink_zero_posteof()
1267 trace_xfs_zero_eof(ip, isize, pos - isize); in xfs_reflink_zero_posteof()
1268 return iomap_zero_range(VFS_I(ip), isize, pos - isize, NULL, in xfs_reflink_zero_posteof()
1278 * The VFS allows partial EOF blocks to "match" for dedupe even though it hasn't
1283 * In similar fashion, the VFS file cloning also allows partial EOF blocks to be
1299 * -EINVAL in this case.
1315 u64 blkmask = i_blocksize(inode_in) - 1; in xfs_reflink_remap_prep()
1329 ret = -EINVAL; in xfs_reflink_remap_prep()
1356 ret = -EINVAL; in xfs_reflink_remap_prep()
1367 * Zero existing post-eof speculative preallocations in the destination in xfs_reflink_remap_prep()
1374 /* Set flags and remap blocks. */ in xfs_reflink_remap_prep()
1380 * If pos_out > EOF, we may have dirtied blocks between EOF and in xfs_reflink_remap_prep()
1385 loff_t flen = *len + (pos_out - XFS_ISIZE(dest)); in xfs_reflink_remap_prep()
1400 if (!(file_out->f_mode & FMODE_NOCMTIME)) { in xfs_reflink_remap_prep()
1423 * Link a range of blocks from one file to another.
1438 struct xfs_mount *mp = src->i_mount; in xfs_reflink_remap_range()
1444 if (!xfs_sb_version_hasreflink(&mp->m_sb)) in xfs_reflink_remap_range()
1445 return -EOPNOTSUPP; in xfs_reflink_remap_range()
1448 return -EIO; in xfs_reflink_remap_range()
1473 (src->i_d.di_flags2 & XFS_DIFLAG2_COWEXTSIZE) && in xfs_reflink_remap_range()
1475 !(dest->i_d.di_flags2 & XFS_DIFLAG2_COWEXTSIZE)) in xfs_reflink_remap_range()
1476 cowextsize = src->i_d.di_cowextsize; in xfs_reflink_remap_range()
1489 * The user wants to preemptively CoW all shared blocks in this file,
1492 * mentioned in the refcount tree, then read those blocks into the
1498 struct xfs_inode *ip, in xfs_reflink_dirty_extents() argument
1503 struct xfs_mount *mp = ip->i_mount; in xfs_reflink_dirty_extents()
1515 while (end - fbno > 0) { in xfs_reflink_dirty_extents()
1521 error = xfs_bmapi_read(ip, fbno, end - fbno, map, &nmaps, 0); in xfs_reflink_dirty_extents()
1543 xfs_iunlock(ip, XFS_ILOCK_EXCL); in xfs_reflink_dirty_extents()
1545 (rbno - agbno)); in xfs_reflink_dirty_extents()
1548 flen = isize - fpos; in xfs_reflink_dirty_extents()
1549 error = iomap_file_dirty(VFS_I(ip), fpos, flen, in xfs_reflink_dirty_extents()
1551 xfs_ilock(ip, XFS_ILOCK_EXCL); in xfs_reflink_dirty_extents()
1555 map[1].br_blockcount -= (rbno - agbno + rlen); in xfs_reflink_dirty_extents()
1556 map[1].br_startoff += (rbno - agbno + rlen); in xfs_reflink_dirty_extents()
1557 map[1].br_startblock += (rbno - agbno + rlen); in xfs_reflink_dirty_extents()
1571 struct xfs_inode *ip, in xfs_reflink_inode_has_shared_extents() argument
1575 struct xfs_mount *mp = ip->i_mount; in xfs_reflink_inode_has_shared_extents()
1586 ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK); in xfs_reflink_inode_has_shared_extents()
1587 if (!(ifp->if_flags & XFS_IFEXTENTS)) { in xfs_reflink_inode_has_shared_extents()
1588 error = xfs_iread_extents(tp, ip, XFS_DATA_FORK); in xfs_reflink_inode_has_shared_extents()
1594 found = xfs_iext_lookup_extent(ip, ifp, 0, &icur, &got); in xfs_reflink_inode_has_shared_extents()
1627 struct xfs_inode *ip, in xfs_reflink_clear_inode_flag() argument
1633 ASSERT(xfs_is_reflink_inode(ip)); in xfs_reflink_clear_inode_flag()
1635 error = xfs_reflink_inode_has_shared_extents(*tpp, ip, &needs_flag); in xfs_reflink_clear_inode_flag()
1640 * We didn't find any shared blocks so turn off the reflink flag. in xfs_reflink_clear_inode_flag()
1643 error = xfs_reflink_cancel_cow_blocks(ip, tpp, 0, NULLFILEOFF, true); in xfs_reflink_clear_inode_flag()
1648 trace_xfs_reflink_unset_inode_flag(ip); in xfs_reflink_clear_inode_flag()
1649 ip->i_d.di_flags2 &= ~XFS_DIFLAG2_REFLINK; in xfs_reflink_clear_inode_flag()
1650 xfs_inode_clear_cowblocks_tag(ip); in xfs_reflink_clear_inode_flag()
1651 xfs_trans_log_inode(*tpp, ip, XFS_ILOG_CORE); in xfs_reflink_clear_inode_flag()
1662 struct xfs_inode *ip) in xfs_reflink_try_clear_inode_flag() argument
1664 struct xfs_mount *mp = ip->i_mount; in xfs_reflink_try_clear_inode_flag()
1669 error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, 0, 0, 0, &tp); in xfs_reflink_try_clear_inode_flag()
1673 xfs_ilock(ip, XFS_ILOCK_EXCL); in xfs_reflink_try_clear_inode_flag()
1674 xfs_trans_ijoin(tp, ip, 0); in xfs_reflink_try_clear_inode_flag()
1676 error = xfs_reflink_clear_inode_flag(ip, &tp); in xfs_reflink_try_clear_inode_flag()
1684 xfs_iunlock(ip, XFS_ILOCK_EXCL); in xfs_reflink_try_clear_inode_flag()
1689 xfs_iunlock(ip, XFS_ILOCK_EXCL); in xfs_reflink_try_clear_inode_flag()
1694 * Pre-COW all shared blocks within a given byte range of a file and turn off
1695 * the reflink flag if we unshare all of the file's blocks.
1699 struct xfs_inode *ip, in xfs_reflink_unshare() argument
1703 struct xfs_mount *mp = ip->i_mount; in xfs_reflink_unshare()
1709 if (!xfs_is_reflink_inode(ip)) in xfs_reflink_unshare()
1712 trace_xfs_reflink_unshare(ip, offset, len); in xfs_reflink_unshare()
1714 inode_dio_wait(VFS_I(ip)); in xfs_reflink_unshare()
1717 xfs_ilock(ip, XFS_ILOCK_EXCL); in xfs_reflink_unshare()
1719 isize = i_size_read(VFS_I(ip)); in xfs_reflink_unshare()
1721 error = xfs_reflink_dirty_extents(ip, fbno, end, isize); in xfs_reflink_unshare()
1724 xfs_iunlock(ip, XFS_ILOCK_EXCL); in xfs_reflink_unshare()
1727 error = filemap_write_and_wait(VFS_I(ip)->i_mapping); in xfs_reflink_unshare()
1732 error = xfs_reflink_try_clear_inode_flag(ip); in xfs_reflink_unshare()
1739 xfs_iunlock(ip, XFS_ILOCK_EXCL); in xfs_reflink_unshare()
1741 trace_xfs_reflink_unshare_error(ip, error, _RET_IP_); in xfs_reflink_unshare()