linux/fs/xfs/xfs_iomap.h
Christoph Hellwig 60271ab79d xfs: fix SEEK_DATA for speculative COW fork preallocation
We speculatively allocate extents in the COW fork to reduce
fragmentation.  But when we write data into such COW fork blocks that
do now shadow an allocation in the data fork SEEK_DATA will not
correctly report it, as it only looks at the data fork extents.
The only reason why that hasn't been an issue so far is because
we even use these speculative COW fork preallocations over holes in
the data fork at all for buffered writes, and blocks in the COW
fork that are written by direct writes are moved into the data
fork immediately at I/O completion time.

Add a new set of iomap_ops for SEEK_HOLE/SEEK_DATA which looks into
both the COW and data fork, and reports all COW extents as unwritten
to the iomap layer.  While this isn't strictly true for COW fork
extents that were already converted to real extents, the practical
semantics that you can't read data from them until they are moved
into the data fork are very similar, and this will force the iomap
layer into probing the extents for actually present data.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
2019-02-21 07:55:07 -08:00

47 lines
1.1 KiB
C

// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2003-2005 Silicon Graphics, Inc.
* All Rights Reserved.
*/
#ifndef __XFS_IOMAP_H__
#define __XFS_IOMAP_H__
#include <linux/iomap.h>
struct xfs_inode;
struct xfs_bmbt_irec;
int xfs_iomap_write_direct(struct xfs_inode *, xfs_off_t, size_t,
struct xfs_bmbt_irec *, int);
int xfs_iomap_write_unwritten(struct xfs_inode *, xfs_off_t, xfs_off_t, bool);
int xfs_bmbt_to_iomap(struct xfs_inode *, struct iomap *,
struct xfs_bmbt_irec *, bool shared);
xfs_extlen_t xfs_eof_alignment(struct xfs_inode *ip, xfs_extlen_t extsize);
static inline xfs_filblks_t
xfs_aligned_fsb_count(
xfs_fileoff_t offset_fsb,
xfs_filblks_t count_fsb,
xfs_extlen_t extsz)
{
if (extsz) {
xfs_extlen_t align;
div_u64_rem(offset_fsb, extsz, &align);
if (align)
count_fsb += align;
div_u64_rem(count_fsb, extsz, &align);
if (align)
count_fsb += extsz - align;
}
return count_fsb;
}
extern const struct iomap_ops xfs_iomap_ops;
extern const struct iomap_ops xfs_seek_iomap_ops;
extern const struct iomap_ops xfs_xattr_iomap_ops;
#endif /* __XFS_IOMAP_H__*/