mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-04 01:49:36 +00:00
![Christoph Hellwig](/assets/img/avatar_default.png)
This adds a full fledget direct I/O implementation using the iomap interface. Full fledged in this case means all features are supported: AIO, vectored I/O, any iov_iter type including kernel pointers, bvecs and pipes, support for hole filling and async apending writes. It does not mean supporting all the warts of the old generic code. We expect i_rwsem to be held over the duration of the call, and we expect to maintain i_dio_count ourselves, and we pass on any kinds of mapping to the file system for now. The algorithm used is very simple: We use iomap_apply to iterate over the range of the I/O, and then we use the new bio_iov_iter_get_pages helper to lock down the user range for the size of the extent. bio_iov_iter_get_pages can currently lock down twice as many pages as the old direct I/O code did, which means that we will have a better batch factor for everything but overwrites of badly fragmented files. Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Kent Overstreet <kent.overstreet@gmail.com> Tested-by: Jens Axboe <axboe@fb.com> Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com> Signed-off-by: Dave Chinner <david@fromorbit.com>
97 lines
3.3 KiB
C
97 lines
3.3 KiB
C
#ifndef LINUX_IOMAP_H
|
|
#define LINUX_IOMAP_H 1
|
|
|
|
#include <linux/types.h>
|
|
|
|
struct fiemap_extent_info;
|
|
struct inode;
|
|
struct iov_iter;
|
|
struct kiocb;
|
|
struct vm_area_struct;
|
|
struct vm_fault;
|
|
|
|
/*
|
|
* Types of block ranges for iomap mappings:
|
|
*/
|
|
#define IOMAP_HOLE 0x01 /* no blocks allocated, need allocation */
|
|
#define IOMAP_DELALLOC 0x02 /* delayed allocation blocks */
|
|
#define IOMAP_MAPPED 0x03 /* blocks allocated @blkno */
|
|
#define IOMAP_UNWRITTEN 0x04 /* blocks allocated @blkno in unwritten state */
|
|
|
|
/*
|
|
* Flags for all iomap mappings:
|
|
*/
|
|
#define IOMAP_F_NEW 0x01 /* blocks have been newly allocated */
|
|
|
|
/*
|
|
* Flags that only need to be reported for IOMAP_REPORT requests:
|
|
*/
|
|
#define IOMAP_F_MERGED 0x10 /* contains multiple blocks/extents */
|
|
#define IOMAP_F_SHARED 0x20 /* block shared with another file */
|
|
|
|
/*
|
|
* Magic value for blkno:
|
|
*/
|
|
#define IOMAP_NULL_BLOCK -1LL /* blkno is not valid */
|
|
|
|
struct iomap {
|
|
sector_t blkno; /* 1st sector of mapping, 512b units */
|
|
loff_t offset; /* file offset of mapping, bytes */
|
|
u64 length; /* length of mapping, bytes */
|
|
u16 type; /* type of mapping */
|
|
u16 flags; /* flags for mapping */
|
|
struct block_device *bdev; /* block device for I/O */
|
|
};
|
|
|
|
/*
|
|
* Flags for iomap_begin / iomap_end. No flag implies a read.
|
|
*/
|
|
#define IOMAP_WRITE (1 << 0) /* writing, must allocate blocks */
|
|
#define IOMAP_ZERO (1 << 1) /* zeroing operation, may skip holes */
|
|
#define IOMAP_REPORT (1 << 2) /* report extent status, e.g. FIEMAP */
|
|
#define IOMAP_FAULT (1 << 3) /* mapping for page fault */
|
|
#define IOMAP_DIRECT (1 << 4) /* direct I/O */
|
|
|
|
struct iomap_ops {
|
|
/*
|
|
* Return the existing mapping at pos, or reserve space starting at
|
|
* pos for up to length, as long as we can do it as a single mapping.
|
|
* The actual length is returned in iomap->length.
|
|
*/
|
|
int (*iomap_begin)(struct inode *inode, loff_t pos, loff_t length,
|
|
unsigned flags, struct iomap *iomap);
|
|
|
|
/*
|
|
* Commit and/or unreserve space previous allocated using iomap_begin.
|
|
* Written indicates the length of the successful write operation which
|
|
* needs to be commited, while the rest needs to be unreserved.
|
|
* Written might be zero if no data was written.
|
|
*/
|
|
int (*iomap_end)(struct inode *inode, loff_t pos, loff_t length,
|
|
ssize_t written, unsigned flags, struct iomap *iomap);
|
|
};
|
|
|
|
ssize_t iomap_file_buffered_write(struct kiocb *iocb, struct iov_iter *from,
|
|
struct iomap_ops *ops);
|
|
int iomap_file_dirty(struct inode *inode, loff_t pos, loff_t len,
|
|
struct iomap_ops *ops);
|
|
int iomap_zero_range(struct inode *inode, loff_t pos, loff_t len,
|
|
bool *did_zero, struct iomap_ops *ops);
|
|
int iomap_truncate_page(struct inode *inode, loff_t pos, bool *did_zero,
|
|
struct iomap_ops *ops);
|
|
int iomap_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf,
|
|
struct iomap_ops *ops);
|
|
int iomap_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
|
|
loff_t start, loff_t len, struct iomap_ops *ops);
|
|
|
|
/*
|
|
* Flags for direct I/O ->end_io:
|
|
*/
|
|
#define IOMAP_DIO_UNWRITTEN (1 << 0) /* covers unwritten extent(s) */
|
|
#define IOMAP_DIO_COW (1 << 1) /* covers COW extent(s) */
|
|
typedef int (iomap_dio_end_io_t)(struct kiocb *iocb, ssize_t ret,
|
|
unsigned flags);
|
|
ssize_t iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter,
|
|
struct iomap_ops *ops, iomap_dio_end_io_t end_io);
|
|
|
|
#endif /* LINUX_IOMAP_H */
|