David Howells <dhowells@xxxxxxxxxx> wrote: > Would it be possible to get an IOCB_NO_READ_HOLE flag that causes a read to > either fail entirely if there's a hole in the file or to stop at the hole, > possibly returning -ENODATA if the hole is at the front of the file? > > Looking at iomap_dio_iter(), IOMAP_HOLE should be enabled in > iomap_iter::iomap.type for this? Is it that simple? Actually, that's not the right thing. How about the attached - at least for direct I/O? David --- commit 522d2834f9994b82b1fa1f1eeeb48ede16b327c7 Author: David Howells <dhowells@xxxxxxxxxx> Date: Fri Sep 17 11:33:41 2021 +0100 iomap: Implement IOCB_NO_READ_HOLE diff --git a/fs/iomap/direct-io.c b/fs/iomap/direct-io.c index 4ecd255e0511..d2309dec27c4 100644 --- a/fs/iomap/direct-io.c +++ b/fs/iomap/direct-io.c @@ -18,6 +18,7 @@ * Private flags for iomap_dio, must not overlap with the public ones in * iomap.h: */ +#define IOMAP_DIO_NO_READ_HOLE (1 << 27) #define IOMAP_DIO_WRITE_FUA (1 << 28) #define IOMAP_DIO_NEED_SYNC (1 << 29) #define IOMAP_DIO_WRITE (1 << 30) @@ -412,6 +413,8 @@ static loff_t iomap_dio_iter(const struct iomap_iter *iter, case IOMAP_HOLE: if (WARN_ON_ONCE(dio->flags & IOMAP_DIO_WRITE)) return -EIO; + if (dio->flags & IOMAP_DIO_NO_READ_HOLE) + return dio->size ? 0 : -ENODATA; return iomap_dio_hole_iter(iter, dio); case IOMAP_UNWRITTEN: if (!(dio->flags & IOMAP_DIO_WRITE)) @@ -503,6 +506,8 @@ __iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter, if (iter_is_iovec(iter)) dio->flags |= IOMAP_DIO_DIRTY; + if (iocb->ki_flags & IOCB_NO_READ_HOLE) + dio->flags |= IOMAP_DIO_NO_READ_HOLE; } else { iomi.flags |= IOMAP_WRITE; dio->flags |= IOMAP_DIO_WRITE; diff --git a/include/linux/fs.h b/include/linux/fs.h index e7a633353fd2..f4c8ca22531d 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -321,6 +321,7 @@ enum rw_hint { #define IOCB_NOIO (1 << 20) /* can use bio alloc cache */ #define IOCB_ALLOC_CACHE (1 << 21) +#define IOCB_NO_READ_HOLE (1 << 22) /* Don't read from a hole */ struct kiocb { struct file *ki_filp;