Could we get an IOCB_NO_READ_HOLE?

3 messages, 2 authors, 2021-09-17 · open the first message on its own page

Could we get an IOCB_NO_READ_HOLE?

From: David Howells <dhowells@redhat.com>
Date: 2021-09-17 10:27:52

Hi Christoph,

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?

David

Re: Could we get an IOCB_NO_READ_HOLE?

From: David Howells <dhowells@redhat.com>
Date: 2021-09-17 10:44:08

David Howells [off-list ref] 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 [off-list ref]
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;

Re: Could we get an IOCB_NO_READ_HOLE?

From: Christoph Hellwig <hch@lst.de>
Date: 2021-09-17 11:04:59

On Fri, Sep 17, 2021 at 11:43:59AM +0100, David Howells wrote:
David Howells [off-list ref] wrote:
quoted
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?
This looks pretty reasonable.  We'll just need to make sure to reject
the flag for the many file operations instances that do not support it.
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help