diff options
Diffstat (limited to 'fs/xfs/scrub/bmap.c')
-rw-r--r-- | fs/xfs/scrub/bmap.c | 22 |
1 files changed, 22 insertions, 0 deletions
diff --git a/fs/xfs/scrub/bmap.c b/fs/xfs/scrub/bmap.c index cd6ec11c5b24..1ee080608c1f 100644 --- a/fs/xfs/scrub/bmap.c +++ b/fs/xfs/scrub/bmap.c @@ -29,6 +29,7 @@ int xchk_setup_inode_bmap( struct xfs_scrub *sc) { + bool is_repair = false; int error; error = xchk_get_inode(sc); @@ -37,6 +38,10 @@ xchk_setup_inode_bmap( xchk_ilock(sc, XFS_IOLOCK_EXCL | XFS_MMAPLOCK_EXCL); +#ifdef CONFIG_XFS_REPAIR + is_repair = (sc->sm->sm_flags & XFS_SCRUB_IFLAG_REPAIR); +#endif + /* * We don't want any ephemeral data fork updates sitting around * while we inspect block mappings, so wait for directio to finish @@ -46,6 +51,14 @@ xchk_setup_inode_bmap( sc->sm->sm_type == XFS_SCRUB_TYPE_BMBTD) { struct address_space *mapping = VFS_I(sc->ip)->i_mapping; + /* Break all our leases, we're going to mess with things. */ + if (is_repair) { + error = xfs_break_layouts(VFS_I(sc->ip), + &sc->ilock_flags, BREAK_UNMAP); + if (error) + goto out; + } + inode_dio_wait(VFS_I(sc->ip)); /* @@ -66,6 +79,15 @@ xchk_setup_inode_bmap( error = filemap_fdatawait_keep_errors(mapping); if (error && (error != -ENOSPC && error != -EIO)) goto out; + + /* Drop the page cache if we're repairing block mappings. */ + if (is_repair) { + error = invalidate_inode_pages2( + VFS_I(sc->ip)->i_mapping); + if (error) + goto out; + } + } /* Got the inode, lock it and we're ready to go. */ |