/* Clear the inode reflink flag if there are no shared extents. */ int xfs_reflink_clear_inode_flag( struct xfs_inode *ip, struct xfs_trans **tpp) { bool needs_flag; int error = 0; ASSERT(xfs_is_reflink_inode(ip)); error = xfs_reflink_inode_has_shared_extents(*tpp, ip, &needs_flag); if (error || needs_flag) return error; /* * We didn't find any shared blocks so turn off the reflink flag. * First, get rid of any leftover CoW mappings. */ error = xfs_reflink_cancel_cow_blocks(ip, tpp, 0, NULLFILEOFF, true); if (error) return error; /* Clear the inode flag. */ trace_xfs_reflink_unset_inode_flag(ip); ip->i_d.di_flags2 &= ~XFS_DIFLAG2_REFLINK; xfs_inode_clear_cowblocks_tag(ip); xfs_trans_ijoin(*tpp, ip, 0); xfs_trans_log_inode(*tpp, ip, XFS_ILOG_CORE); return error; }
/* Clear the inode reflink flag if there are no shared extents. */ int xfs_reflink_clear_inode_flag( struct xfs_inode *ip, struct xfs_trans **tpp) { struct xfs_mount *mp = ip->i_mount; xfs_fileoff_t fbno; xfs_filblks_t end; xfs_agnumber_t agno; xfs_agblock_t agbno; xfs_extlen_t aglen; xfs_agblock_t rbno; xfs_extlen_t rlen; struct xfs_bmbt_irec map; int nmaps; int error = 0; ASSERT(xfs_is_reflink_inode(ip)); fbno = 0; end = XFS_B_TO_FSB(mp, i_size_read(VFS_I(ip))); while (end - fbno > 0) { nmaps = 1; /* * Look for extents in the file. Skip holes, delalloc, or * unwritten extents; they can't be reflinked. */ error = xfs_bmapi_read(ip, fbno, end - fbno, &map, &nmaps, 0); if (error) return error; if (nmaps == 0) break; if (!xfs_bmap_is_real_extent(&map)) goto next; agno = XFS_FSB_TO_AGNO(mp, map.br_startblock); agbno = XFS_FSB_TO_AGBNO(mp, map.br_startblock); aglen = map.br_blockcount; error = xfs_reflink_find_shared(mp, agno, agbno, aglen, &rbno, &rlen, false); if (error) return error; /* Is there still a shared block here? */ if (rbno != NULLAGBLOCK) return 0; next: fbno = map.br_startoff + map.br_blockcount; } /* * We didn't find any shared blocks so turn off the reflink flag. * First, get rid of any leftover CoW mappings. */ error = xfs_reflink_cancel_cow_blocks(ip, tpp, 0, NULLFILEOFF, true); if (error) return error; /* Clear the inode flag. */ trace_xfs_reflink_unset_inode_flag(ip); ip->i_d.di_flags2 &= ~XFS_DIFLAG2_REFLINK; xfs_inode_clear_cowblocks_tag(ip); xfs_trans_ijoin(*tpp, ip, 0); xfs_trans_log_inode(*tpp, ip, XFS_ILOG_CORE); return error; }