/* * Invalidate buffers for per-AG btree blocks we're dumping. This function * is not intended for use with file data repairs; we have bunmapi for that. */ int xrep_invalidate_blocks( struct xfs_scrub *sc, struct xfs_bitmap *bitmap) { struct xfs_bitmap_range *bmr; struct xfs_bitmap_range *n; struct xfs_buf *bp; xfs_fsblock_t fsbno; /* * For each block in each extent, see if there's an incore buffer for * exactly that block; if so, invalidate it. The buffer cache only * lets us look for one buffer at a time, so we have to look one block * at a time. Avoid invalidating AG headers and post-EOFS blocks * because we never own those; and if we can't TRYLOCK the buffer we * assume it's owned by someone else. */ for_each_xfs_bitmap_block(fsbno, bmr, n, bitmap) { /* Skip AG headers and post-EOFS blocks */ if (!xfs_verify_fsbno(sc->mp, fsbno)) continue; bp = xfs_buf_incore(sc->mp->m_ddev_targp, XFS_FSB_TO_DADDR(sc->mp, fsbno), XFS_FSB_TO_BB(sc->mp, 1), XBF_TRYLOCK); if (bp) { xfs_trans_bjoin(sc->tp, bp); xfs_trans_binval(sc->tp, bp); } } return 0; }
/* * Remove the value associated with an attribute by deleting the * out-of-line buffer that it is stored on. */ int xfs_attr_rmtval_remove( struct xfs_da_args *args) { struct xfs_mount *mp = args->dp->i_mount; xfs_dablk_t lblkno; int blkcnt; int error; int done; trace_xfs_attr_rmtval_remove(args); /* * Roll through the "value", invalidating the attribute value's blocks. */ lblkno = args->rmtblkno; blkcnt = args->rmtblkcnt; while (blkcnt > 0) { struct xfs_bmbt_irec map; struct xfs_buf *bp; xfs_daddr_t dblkno; int dblkcnt; int nmap; /* * Try to remember where we decided to put the value. */ nmap = 1; error = xfs_bmapi_read(args->dp, (xfs_fileoff_t)lblkno, blkcnt, &map, &nmap, XFS_BMAPI_ATTRFORK); if (error) return error; ASSERT(nmap == 1); ASSERT((map.br_startblock != DELAYSTARTBLOCK) && (map.br_startblock != HOLESTARTBLOCK)); dblkno = XFS_FSB_TO_DADDR(mp, map.br_startblock), dblkcnt = XFS_FSB_TO_BB(mp, map.br_blockcount); /* * If the "remote" value is in the cache, remove it. */ bp = xfs_buf_incore(mp->m_ddev_targp, dblkno, dblkcnt, XBF_TRYLOCK); if (bp) { xfs_buf_stale(bp); xfs_buf_relse(bp); bp = NULL; } lblkno += map.br_blockcount; blkcnt -= map.br_blockcount; } /* * Keep de-allocating extents until the remote-value region is gone. */ lblkno = args->rmtblkno; blkcnt = args->rmtblkcnt; done = 0; while (!done) { error = xfs_bunmapi(args->trans, args->dp, lblkno, blkcnt, XFS_BMAPI_ATTRFORK, 1, &done); if (error) goto out_defer_cancel; error = xfs_defer_finish(&args->trans); if (error) return error; /* * Close out trans and start the next one in the chain. */ error = xfs_trans_roll_inode(&args->trans, args->dp); if (error) return error; } return 0; out_defer_cancel: xfs_defer_cancel(args->trans); return error; }