/* 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; }
/* * If the reflink iflag disagrees with a scan for shared data fork extents, * either flag an error (shared extents w/ no flag) or a preen (flag set w/o * any shared extents). We already checked for reflink iflag set on a non * reflink filesystem. */ static void xchk_inode_check_reflink_iflag( struct xfs_scrub *sc, xfs_ino_t ino) { struct xfs_mount *mp = sc->mp; bool has_shared; int error; if (!xfs_sb_version_hasreflink(&mp->m_sb)) return; error = xfs_reflink_inode_has_shared_extents(sc->tp, sc->ip, &has_shared); if (!xchk_xref_process_error(sc, XFS_INO_TO_AGNO(mp, ino), XFS_INO_TO_AGBNO(mp, ino), &error)) return; if (xfs_is_reflink_inode(sc->ip) && !has_shared) xchk_ino_set_preen(sc, ino); else if (!xfs_is_reflink_inode(sc->ip) && has_shared) xchk_ino_set_corrupt(sc, ino); }