linux-fsdevel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/1] iomap: Direct I/O for inline data
@ 2018-06-27  0:39 Andreas Gruenbacher
  2018-06-27  0:39 ` [PATCH 1/1] " Andreas Gruenbacher
  2018-06-27 11:14 ` [PATCH 0/1] " Andreas Gruenbacher
  0 siblings, 2 replies; 13+ messages in thread
From: Andreas Gruenbacher @ 2018-06-27  0:39 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: cluster-devel, linux-ext4, linux-fsdevel, Andreas Gruenbacher

Here's a patch that implements direct I/O for inline data.  Direct I/O
to inline data is a bit weird because it's not direct in the usual
sense, but since Christoph's been asking for it ...

The usual alignment restrictions to the logical block size of the
underlying block device still apply.  I don't see a reason for changing
that; the resulting behavior would only become very weird for no
benefit.

I've tested this against a hacked-up version of gfs2.  However, the
"real" gfs2 will keep falling back to buffered I/O for writes to inline
data: gfs2 takes a shared lock during direct I/O, and writing to the
inode under that shared lock is not allowed.  Ext4 may become the first
actual user of this part of the patch.

Thanks,
Andreas

Andreas Gruenbacher (1):
  iomap: Direct I/O to inline data

 fs/iomap.c | 28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)

-- 
2.17.1

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH 1/1] iomap: Direct I/O for inline data
  2018-06-27  0:39 [PATCH 0/1] iomap: Direct I/O for inline data Andreas Gruenbacher
@ 2018-06-27  0:39 ` Andreas Gruenbacher
  2018-06-27  1:44   ` kbuild test robot
  2018-06-29  8:56   ` Christoph Hellwig
  2018-06-27 11:14 ` [PATCH 0/1] " Andreas Gruenbacher
  1 sibling, 2 replies; 13+ messages in thread
From: Andreas Gruenbacher @ 2018-06-27  0:39 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: cluster-devel, linux-ext4, linux-fsdevel, Andreas Gruenbacher

Add support for reading from and writing to inline data to iomap_dio_rw.
This saves filesystems from having to implement fallback code for this
case.

The inline data is actually cached in the inode, so the I/O is only
direct in the sense that it doesn't go through the page cache.  The same
alignment restrictions as to non-inline data apply.

Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
---
 fs/iomap.c | 28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)

diff --git a/fs/iomap.c b/fs/iomap.c
index d393bb0c7384..74668b3ca2ed 100644
--- a/fs/iomap.c
+++ b/fs/iomap.c
@@ -1231,6 +1231,32 @@ iomap_dio_zero(struct iomap_dio *dio, struct iomap *iomap, loff_t pos,
 	return submit_bio(bio);
 }
 
+static loff_t iomap_dio_actor_inline(struct inode *inode, struct iomap_dio *dio,
+		struct iomap *iomap, loff_t pos, loff_t length)
+{
+	struct iov_iter *iter = dio->submit.iter;
+	size_t copied;
+
+	BUG_ON(pos + length > PAGE_SIZE - offset_in_page(iomap->inline_data));
+
+	if (dio->flags & IOMAP_DIO_WRITE) {
+		loff_t size = inode->i_size;
+
+		if (pos > size)
+			memset(iomap->inline_data + size, 0, pos - size);
+		copied = copy_from_iter(iomap->inline_data + pos, length, iter);
+		if (copied) {
+			if (pos + copied > size)
+				i_size_write(inode, pos + copied);
+			mark_inode_dirty(inode);
+		}
+	} else {
+		copied = copy_to_iter(iomap->inline_data + pos, length, iter);
+	}
+	dio->size += copied;
+	return copied;
+}
+
 static loff_t
 iomap_dio_actor(struct inode *inode, loff_t pos, loff_t length,
 		void *data, struct iomap *iomap)
@@ -1281,6 +1307,8 @@ iomap_dio_actor(struct inode *inode, loff_t pos, loff_t length,
 				use_fua = true;
 		}
 		break;
+	case IOMAP_INLINE:
+		return iomap_dio_actor_inline(inode, dio, iomap, pos, length);
 	default:
 		WARN_ON_ONCE(1);
 		return -EIO;
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [PATCH 1/1] iomap: Direct I/O for inline data
  2018-06-27  0:39 ` [PATCH 1/1] " Andreas Gruenbacher
@ 2018-06-27  1:44   ` kbuild test robot
  2018-06-29  8:56   ` Christoph Hellwig
  1 sibling, 0 replies; 13+ messages in thread
From: kbuild test robot @ 2018-06-27  1:44 UTC (permalink / raw)
  To: Andreas Gruenbacher
  Cc: kbuild-all, Christoph Hellwig, cluster-devel, linux-ext4,
	linux-fsdevel, Andreas Gruenbacher

[-- Attachment #1: Type: text/plain, Size: 3195 bytes --]

Hi Andreas,

I love your patch! Yet something to improve:

[auto build test ERROR on linus/master]
[also build test ERROR on v4.18-rc2 next-20180626]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Andreas-Gruenbacher/iomap-Direct-I-O-for-inline-data/20180627-084229
config: x86_64-randconfig-x015-201825 (attached as .config)
compiler: gcc-7 (Debian 7.3.0-16) 7.3.0
reproduce:
        # save the attached .config to linux build tree
        make ARCH=x86_64 

All error/warnings (new ones prefixed by >>):

   In file included from include/linux/kernel.h:10:0,
                    from include/linux/list.h:9,
                    from include/linux/module.h:9,
                    from fs/iomap.c:14:
   fs/iomap.c: In function 'iomap_dio_actor_inline':
>> fs/iomap.c:971:56: error: 'struct iomap' has no member named 'inline_data'
     BUG_ON(pos + length > PAGE_SIZE - offset_in_page(iomap->inline_data));
                                                           ^
   include/linux/compiler.h:77:42: note: in definition of macro 'unlikely'
    # define unlikely(x) __builtin_expect(!!(x), 0)
                                             ^
>> fs/iomap.c:971:2: note: in expansion of macro 'BUG_ON'
     BUG_ON(pos + length > PAGE_SIZE - offset_in_page(iomap->inline_data));
     ^~~~~~
>> fs/iomap.c:971:36: note: in expansion of macro 'offset_in_page'
     BUG_ON(pos + length > PAGE_SIZE - offset_in_page(iomap->inline_data));
                                       ^~~~~~~~~~~~~~
   fs/iomap.c:977:16: error: 'struct iomap' has no member named 'inline_data'
       memset(iomap->inline_data + size, 0, pos - size);
                   ^~
   fs/iomap.c:978:32: error: 'struct iomap' has no member named 'inline_data'
      copied = copy_from_iter(iomap->inline_data + pos, length, iter);
                                   ^~
   fs/iomap.c:985:30: error: 'struct iomap' has no member named 'inline_data'
      copied = copy_to_iter(iomap->inline_data + pos, length, iter);
                                 ^~

vim +971 fs/iomap.c

   964	
   965	static loff_t iomap_dio_actor_inline(struct inode *inode, struct iomap_dio *dio,
   966			struct iomap *iomap, loff_t pos, loff_t length)
   967	{
   968		struct iov_iter *iter = dio->submit.iter;
   969		size_t copied;
   970	
 > 971		BUG_ON(pos + length > PAGE_SIZE - offset_in_page(iomap->inline_data));
   972	
   973		if (dio->flags & IOMAP_DIO_WRITE) {
   974			loff_t size = inode->i_size;
   975	
   976			if (pos > size)
   977				memset(iomap->inline_data + size, 0, pos - size);
   978			copied = copy_from_iter(iomap->inline_data + pos, length, iter);
   979			if (copied) {
   980				if (pos + copied > size)
   981					i_size_write(inode, pos + copied);
   982				mark_inode_dirty(inode);
   983			}
   984		} else {
   985			copied = copy_to_iter(iomap->inline_data + pos, length, iter);
   986		}
   987		dio->size += copied;
   988		return copied;
   989	}
   990	

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 27637 bytes --]

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 0/1] iomap: Direct I/O for inline data
  2018-06-27  0:39 [PATCH 0/1] iomap: Direct I/O for inline data Andreas Gruenbacher
  2018-06-27  0:39 ` [PATCH 1/1] " Andreas Gruenbacher
@ 2018-06-27 11:14 ` Andreas Gruenbacher
  2018-06-29  8:43   ` Christoph Hellwig
  1 sibling, 1 reply; 13+ messages in thread
From: Andreas Gruenbacher @ 2018-06-27 11:14 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: cluster-devel, linux-ext4, linux-fsdevel, Andreas Gruenbacher

On 27 June 2018 at 02:39, Andreas Gruenbacher <agruenba@redhat.com> wrote:
> Here's a patch that implements direct I/O for inline data.  Direct I/O
> to inline data is a bit weird because it's not direct in the usual
> sense, but since Christoph's been asking for it ...
>
> The usual alignment restrictions to the logical block size of the
> underlying block device still apply.  I don't see a reason for changing
> that; the resulting behavior would only become very weird for no
> benefit.
>
> I've tested this against a hacked-up version of gfs2.  However, the
> "real" gfs2 will keep falling back to buffered I/O for writes to inline
> data: gfs2 takes a shared lock during direct I/O, and writing to the
> inode under that shared lock is not allowed.  Ext4 may become the first
> actual user of this part of the patch.

One further issue is the alignment check in iomap_dio_actor:

>        if ((pos | length | align) & ((1 << blkbits) - 1))
>                return -EINVAL;

For inline data, iomap->length is set to the file size. iomap_apply
truncates the requested length down to that, so iomap_dio_actor sees
the truncated length instead of the requested length and fails with
-EINVAL. This causes tests like the following to fail (also see
xfstest generic/120):

  xfs_io -fd -c 'truncate 300' -c 'pread -v 0 4096' /mnt/test/foo

A possible fix is to change the alignment check in iomap_dio_actor as follows:

-       if ((pos | length | align) & ((1 << blkbits) - 1))
+       if ((pos | align) & ((1 << blkbits) - 1))
+               return -EINVAL;
+       if (length & ((1 << blkbits) - 1) &&
+           pos + length != iomap->offset + iomap->length)
                return -EINVAL;

Moving the alignment check from iomap_dio_actor to iomap_dio_rw isn't
that easy because iomap->bdev isn't known there.

Any thoughts?

Thanks,
Andreas

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 0/1] iomap: Direct I/O for inline data
  2018-06-27 11:14 ` [PATCH 0/1] " Andreas Gruenbacher
@ 2018-06-29  8:43   ` Christoph Hellwig
  2018-06-29 11:01     ` Andreas Gruenbacher
  0 siblings, 1 reply; 13+ messages in thread
From: Christoph Hellwig @ 2018-06-29  8:43 UTC (permalink / raw)
  To: Andreas Gruenbacher
  Cc: Christoph Hellwig, cluster-devel, linux-ext4, linux-fsdevel

> A possible fix is to change the alignment check in iomap_dio_actor as follows:
> 
> -       if ((pos | length | align) & ((1 << blkbits) - 1))
> +       if ((pos | align) & ((1 << blkbits) - 1))
> +               return -EINVAL;
> +       if (length & ((1 << blkbits) - 1) &&
> +           pos + length != iomap->offset + iomap->length)
>                 return -EINVAL;
> 
> Moving the alignment check from iomap_dio_actor to iomap_dio_rw isn't
> that easy because iomap->bdev isn't known there.

Just make the check conditional on iomap->type != IOMAP_INLINE
as alignment checks on inline data don't make much sense.

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 1/1] iomap: Direct I/O for inline data
  2018-06-27  0:39 ` [PATCH 1/1] " Andreas Gruenbacher
  2018-06-27  1:44   ` kbuild test robot
@ 2018-06-29  8:56   ` Christoph Hellwig
  2018-06-29 14:40     ` Andreas Gruenbacher
  1 sibling, 1 reply; 13+ messages in thread
From: Christoph Hellwig @ 2018-06-29  8:56 UTC (permalink / raw)
  To: Andreas Gruenbacher
  Cc: Christoph Hellwig, cluster-devel, linux-ext4, linux-fsdevel

This looks generally fine.  But I think it might be worth refactoring
iomap_dio_actor a bit first, e.g. something like this new patch
before yours, which would also nicely solve your alignmnet concern
(entirely untested for now):

---
>From f8c58ffe79df63d23332376ce481cdc4753cc567 Mon Sep 17 00:00:00 2001
From: Christoph Hellwig <hch@lst.de>
Date: Fri, 29 Jun 2018 10:54:10 +0200
Subject: iomap: refactor iomap_dio_actor

Split the function up into two helpers for the bio based I/O and hole
case, and a small helper to call the two.  This separates the code a
little better in preparation for supporting I/O to inline data.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 fs/iomap.c | 88 ++++++++++++++++++++++++++++++++----------------------
 1 file changed, 52 insertions(+), 36 deletions(-)

diff --git a/fs/iomap.c b/fs/iomap.c
index 7d1e9f45f098..f05c83773cbf 100644
--- a/fs/iomap.c
+++ b/fs/iomap.c
@@ -963,10 +963,9 @@ iomap_dio_zero(struct iomap_dio *dio, struct iomap *iomap, loff_t pos,
 }
 
 static loff_t
-iomap_dio_actor(struct inode *inode, loff_t pos, loff_t length,
-		void *data, struct iomap *iomap)
+iomap_dio_bio_actor(struct inode *inode, loff_t pos, loff_t length,
+		struct iomap_dio *dio, struct iomap *iomap)
 {
-	struct iomap_dio *dio = data;
 	unsigned int blkbits = blksize_bits(bdev_logical_block_size(iomap->bdev));
 	unsigned int fs_block_size = i_blocksize(inode), pad;
 	unsigned int align = iov_iter_alignment(dio->submit.iter);
@@ -980,41 +979,27 @@ iomap_dio_actor(struct inode *inode, loff_t pos, loff_t length,
 	if ((pos | length | align) & ((1 << blkbits) - 1))
 		return -EINVAL;
 
-	switch (iomap->type) {
-	case IOMAP_HOLE:
-		if (WARN_ON_ONCE(dio->flags & IOMAP_DIO_WRITE))
-			return -EIO;
-		/*FALLTHRU*/
-	case IOMAP_UNWRITTEN:
-		if (!(dio->flags & IOMAP_DIO_WRITE)) {
-			length = iov_iter_zero(length, dio->submit.iter);
-			dio->size += length;
-			return length;
-		}
+	if (iomap->type == IOMAP_UNWRITTEN) {
 		dio->flags |= IOMAP_DIO_UNWRITTEN;
 		need_zeroout = true;
-		break;
-	case IOMAP_MAPPED:
-		if (iomap->flags & IOMAP_F_SHARED)
-			dio->flags |= IOMAP_DIO_COW;
-		if (iomap->flags & IOMAP_F_NEW) {
-			need_zeroout = true;
-		} else {
-			/*
-			 * Use a FUA write if we need datasync semantics, this
-			 * is a pure data IO that doesn't require any metadata
-			 * updates and the underlying device supports FUA. This
-			 * allows us to avoid cache flushes on IO completion.
-			 */
-			if (!(iomap->flags & (IOMAP_F_SHARED|IOMAP_F_DIRTY)) &&
-			    (dio->flags & IOMAP_DIO_WRITE_FUA) &&
-			    blk_queue_fua(bdev_get_queue(iomap->bdev)))
-				use_fua = true;
-		}
-		break;
-	default:
-		WARN_ON_ONCE(1);
-		return -EIO;
+	}
+
+	if (iomap->flags & IOMAP_F_SHARED)
+		dio->flags |= IOMAP_DIO_COW;
+
+	if (iomap->flags & IOMAP_F_NEW) {
+		need_zeroout = true;
+	} else {
+		/*
+		 * Use a FUA write if we need datasync semantics, this
+		 * is a pure data IO that doesn't require any metadata
+		 * updates and the underlying device supports FUA. This
+		 * allows us to avoid cache flushes on IO completion.
+		 */
+		if (!(iomap->flags & (IOMAP_F_SHARED|IOMAP_F_DIRTY)) &&
+		    (dio->flags & IOMAP_DIO_WRITE_FUA) &&
+		    blk_queue_fua(bdev_get_queue(iomap->bdev)))
+			use_fua = true;
 	}
 
 	/*
@@ -1093,6 +1078,37 @@ iomap_dio_actor(struct inode *inode, loff_t pos, loff_t length,
 	return copied;
 }
 
+static loff_t
+iomap_dio_hole_actor(loff_t length, struct iomap_dio *dio)
+{
+	length = iov_iter_zero(length, dio->submit.iter);
+	dio->size += length;
+	return length;
+}
+
+static loff_t
+iomap_dio_actor(struct inode *inode, loff_t pos, loff_t length,
+		void *data, struct iomap *iomap)
+{
+	struct iomap_dio *dio = data;
+
+	switch (iomap->type) {
+	case IOMAP_HOLE:
+		if (WARN_ON_ONCE(dio->flags & IOMAP_DIO_WRITE))
+			return -EIO;
+		return iomap_dio_hole_actor(length, dio);
+	case IOMAP_UNWRITTEN:
+		if (!(dio->flags & IOMAP_DIO_WRITE))
+			return iomap_dio_hole_actor(length, dio);
+		return iomap_dio_bio_actor(inode, pos, length, dio, iomap);
+	case IOMAP_MAPPED:
+		return iomap_dio_bio_actor(inode, pos, length, dio, iomap);
+	default:
+		WARN_ON_ONCE(1);
+		return -EIO;
+	}
+}
+
 /*
  * iomap_dio_rw() always completes O_[D]SYNC writes regardless of whether the IO
  * is being issued as AIO or not.  This allows us to optimise pure data writes
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [PATCH 0/1] iomap: Direct I/O for inline data
  2018-06-29  8:43   ` Christoph Hellwig
@ 2018-06-29 11:01     ` Andreas Gruenbacher
  0 siblings, 0 replies; 13+ messages in thread
From: Andreas Gruenbacher @ 2018-06-29 11:01 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: cluster-devel, linux-ext4, linux-fsdevel

On 29 June 2018 at 10:43, Christoph Hellwig <hch@lst.de> wrote:
>> A possible fix is to change the alignment check in iomap_dio_actor as follows:
>>
>> -       if ((pos | length | align) & ((1 << blkbits) - 1))
>> +       if ((pos | align) & ((1 << blkbits) - 1))
>> +               return -EINVAL;
>> +       if (length & ((1 << blkbits) - 1) &&
>> +           pos + length != iomap->offset + iomap->length)
>>                 return -EINVAL;
>>
>> Moving the alignment check from iomap_dio_actor to iomap_dio_rw isn't
>> that easy because iomap->bdev isn't known there.
>
> Just make the check conditional on iomap->type != IOMAP_INLINE
> as alignment checks on inline data don't make much sense.

Yeah, probably.

Thanks,
Andreas

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 1/1] iomap: Direct I/O for inline data
  2018-06-29  8:56   ` Christoph Hellwig
@ 2018-06-29 14:40     ` Andreas Gruenbacher
  2018-06-29 16:01       ` Christoph Hellwig
  2018-07-01  6:29       ` Christoph Hellwig
  0 siblings, 2 replies; 13+ messages in thread
From: Andreas Gruenbacher @ 2018-06-29 14:40 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: cluster-devel, linux-ext4, linux-fsdevel

On 29 June 2018 at 10:56, Christoph Hellwig <hch@lst.de> wrote:
> This looks generally fine.  But I think it might be worth refactoring
> iomap_dio_actor a bit first, e.g. something like this new patch
> before yours, which would also nicely solve your alignmnet concern
> (entirely untested for now):

This looks correct. I've rebased my patches on top of it and I ran the
xfstest auto group on gfs2 and xfs on top.

Can you push this to your gfs2-iomap branch? I'll then repost an
updated version of "iomap: Direct I/O for inline data".

> ---
> From f8c58ffe79df63d23332376ce481cdc4753cc567 Mon Sep 17 00:00:00 2001
> From: Christoph Hellwig <hch@lst.de>
> Date: Fri, 29 Jun 2018 10:54:10 +0200
> Subject: iomap: refactor iomap_dio_actor
>
> Split the function up into two helpers for the bio based I/O and hole
> case, and a small helper to call the two.  This separates the code a
> little better in preparation for supporting I/O to inline data.
>
> Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Andreas Gruenbacher <agruenba@redhat.com>

> ---
>  fs/iomap.c | 88 ++++++++++++++++++++++++++++++++----------------------
>  1 file changed, 52 insertions(+), 36 deletions(-)
>
> diff --git a/fs/iomap.c b/fs/iomap.c
> index 7d1e9f45f098..f05c83773cbf 100644
> --- a/fs/iomap.c
> +++ b/fs/iomap.c
> @@ -963,10 +963,9 @@ iomap_dio_zero(struct iomap_dio *dio, struct iomap *iomap, loff_t pos,
>  }
>
>  static loff_t
> -iomap_dio_actor(struct inode *inode, loff_t pos, loff_t length,
> -               void *data, struct iomap *iomap)
> +iomap_dio_bio_actor(struct inode *inode, loff_t pos, loff_t length,
> +               struct iomap_dio *dio, struct iomap *iomap)
>  {
> -       struct iomap_dio *dio = data;
>         unsigned int blkbits = blksize_bits(bdev_logical_block_size(iomap->bdev));
>         unsigned int fs_block_size = i_blocksize(inode), pad;
>         unsigned int align = iov_iter_alignment(dio->submit.iter);
> @@ -980,41 +979,27 @@ iomap_dio_actor(struct inode *inode, loff_t pos, loff_t length,
>         if ((pos | length | align) & ((1 << blkbits) - 1))
>                 return -EINVAL;
>
> -       switch (iomap->type) {
> -       case IOMAP_HOLE:
> -               if (WARN_ON_ONCE(dio->flags & IOMAP_DIO_WRITE))
> -                       return -EIO;
> -               /*FALLTHRU*/
> -       case IOMAP_UNWRITTEN:
> -               if (!(dio->flags & IOMAP_DIO_WRITE)) {
> -                       length = iov_iter_zero(length, dio->submit.iter);
> -                       dio->size += length;
> -                       return length;
> -               }
> +       if (iomap->type == IOMAP_UNWRITTEN) {
>                 dio->flags |= IOMAP_DIO_UNWRITTEN;
>                 need_zeroout = true;
> -               break;
> -       case IOMAP_MAPPED:
> -               if (iomap->flags & IOMAP_F_SHARED)
> -                       dio->flags |= IOMAP_DIO_COW;
> -               if (iomap->flags & IOMAP_F_NEW) {
> -                       need_zeroout = true;
> -               } else {
> -                       /*
> -                        * Use a FUA write if we need datasync semantics, this
> -                        * is a pure data IO that doesn't require any metadata
> -                        * updates and the underlying device supports FUA. This
> -                        * allows us to avoid cache flushes on IO completion.
> -                        */
> -                       if (!(iomap->flags & (IOMAP_F_SHARED|IOMAP_F_DIRTY)) &&
> -                           (dio->flags & IOMAP_DIO_WRITE_FUA) &&
> -                           blk_queue_fua(bdev_get_queue(iomap->bdev)))
> -                               use_fua = true;
> -               }
> -               break;
> -       default:
> -               WARN_ON_ONCE(1);
> -               return -EIO;
> +       }
> +
> +       if (iomap->flags & IOMAP_F_SHARED)
> +               dio->flags |= IOMAP_DIO_COW;
> +
> +       if (iomap->flags & IOMAP_F_NEW) {
> +               need_zeroout = true;
> +       } else {
> +               /*
> +                * Use a FUA write if we need datasync semantics, this
> +                * is a pure data IO that doesn't require any metadata
> +                * updates and the underlying device supports FUA. This
> +                * allows us to avoid cache flushes on IO completion.
> +                */
> +               if (!(iomap->flags & (IOMAP_F_SHARED|IOMAP_F_DIRTY)) &&
> +                   (dio->flags & IOMAP_DIO_WRITE_FUA) &&
> +                   blk_queue_fua(bdev_get_queue(iomap->bdev)))
> +                       use_fua = true;
>         }
>
>         /*
> @@ -1093,6 +1078,37 @@ iomap_dio_actor(struct inode *inode, loff_t pos, loff_t length,
>         return copied;
>  }
>
> +static loff_t
> +iomap_dio_hole_actor(loff_t length, struct iomap_dio *dio)
> +{
> +       length = iov_iter_zero(length, dio->submit.iter);
> +       dio->size += length;
> +       return length;
> +}

Just a minor nit: iomap_dio_hole_actor should come before iomap_dio_bio_actor.

> +
> +static loff_t
> +iomap_dio_actor(struct inode *inode, loff_t pos, loff_t length,
> +               void *data, struct iomap *iomap)
> +{
> +       struct iomap_dio *dio = data;
> +
> +       switch (iomap->type) {
> +       case IOMAP_HOLE:
> +               if (WARN_ON_ONCE(dio->flags & IOMAP_DIO_WRITE))
> +                       return -EIO;
> +               return iomap_dio_hole_actor(length, dio);
> +       case IOMAP_UNWRITTEN:
> +               if (!(dio->flags & IOMAP_DIO_WRITE))
> +                       return iomap_dio_hole_actor(length, dio);
> +               return iomap_dio_bio_actor(inode, pos, length, dio, iomap);
> +       case IOMAP_MAPPED:
> +               return iomap_dio_bio_actor(inode, pos, length, dio, iomap);
> +       default:
> +               WARN_ON_ONCE(1);
> +               return -EIO;
> +       }
> +}
> +
>  /*
>   * iomap_dio_rw() always completes O_[D]SYNC writes regardless of whether the IO
>   * is being issued as AIO or not.  This allows us to optimise pure data writes
> --
> 2.17.1
>

Thanks,
Andreas

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 1/1] iomap: Direct I/O for inline data
  2018-06-29 14:40     ` Andreas Gruenbacher
@ 2018-06-29 16:01       ` Christoph Hellwig
  2018-06-29 17:02         ` Andreas Gruenbacher
  2018-07-01  6:29       ` Christoph Hellwig
  1 sibling, 1 reply; 13+ messages in thread
From: Christoph Hellwig @ 2018-06-29 16:01 UTC (permalink / raw)
  To: Andreas Gruenbacher
  Cc: Christoph Hellwig, cluster-devel, linux-ext4, linux-fsdevel

On Fri, Jun 29, 2018 at 04:40:40PM +0200, Andreas Gruenbacher wrote:
> On 29 June 2018 at 10:56, Christoph Hellwig <hch@lst.de> wrote:
> > This looks generally fine.  But I think it might be worth refactoring
> > iomap_dio_actor a bit first, e.g. something like this new patch
> > before yours, which would also nicely solve your alignmnet concern
> > (entirely untested for now):
> 
> This looks correct. I've rebased my patches on top of it and I ran the
> xfstest auto group on gfs2 and xfs on top.
> 
> Can you push this to your gfs2-iomap branch? I'll then repost an
> updated version of "iomap: Direct I/O for inline data".

Darrick now has a real iomap merge branch which replaced it.  Before
formally submitting the patch I'd also like to verify that it does
not regress for XFS by doing a full xfstests run.

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 1/1] iomap: Direct I/O for inline data
  2018-06-29 16:01       ` Christoph Hellwig
@ 2018-06-29 17:02         ` Andreas Gruenbacher
  2018-07-01  6:13           ` Christoph Hellwig
  0 siblings, 1 reply; 13+ messages in thread
From: Andreas Gruenbacher @ 2018-06-29 17:02 UTC (permalink / raw)
  To: Darrick J. Wong
  Cc: cluster-devel, linux-ext4, linux-fsdevel, Christoph Hellwig

On 29 June 2018 at 18:01, Christoph Hellwig <hch@lst.de> wrote:
> On Fri, Jun 29, 2018 at 04:40:40PM +0200, Andreas Gruenbacher wrote:
>> On 29 June 2018 at 10:56, Christoph Hellwig <hch@lst.de> wrote:
>> > This looks generally fine.  But I think it might be worth refactoring
>> > iomap_dio_actor a bit first, e.g. something like this new patch
>> > before yours, which would also nicely solve your alignmnet concern
>> > (entirely untested for now):
>>
>> This looks correct. I've rebased my patches on top of it and I ran the
>> xfstest auto group on gfs2 and xfs on top.
>>
>> Can you push this to your gfs2-iomap branch? I'll then repost an
>> updated version of "iomap: Direct I/O for inline data".
>
> Darrick now has a real iomap merge branch which replaced it.

Where is it? Not in
https://git.kernel.org/pub/scm/linux/kernel/git/djwong/xfs-linux.git
it seems.

>  Before formally submitting the patch I'd also like to verify that it does
> not regress for XFS by doing a full xfstests run.

Thanks,
Andreas

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 1/1] iomap: Direct I/O for inline data
  2018-06-29 17:02         ` Andreas Gruenbacher
@ 2018-07-01  6:13           ` Christoph Hellwig
  0 siblings, 0 replies; 13+ messages in thread
From: Christoph Hellwig @ 2018-07-01  6:13 UTC (permalink / raw)
  To: Andreas Gruenbacher
  Cc: Darrick J. Wong, cluster-devel, linux-ext4, linux-fsdevel,
	Christoph Hellwig

On Fri, Jun 29, 2018 at 07:02:07PM +0200, Andreas Gruenbacher wrote:
> On 29 June 2018 at 18:01, Christoph Hellwig <hch@lst.de> wrote:
> > On Fri, Jun 29, 2018 at 04:40:40PM +0200, Andreas Gruenbacher wrote:
> >> On 29 June 2018 at 10:56, Christoph Hellwig <hch@lst.de> wrote:
> >> > This looks generally fine.  But I think it might be worth refactoring
> >> > iomap_dio_actor a bit first, e.g. something like this new patch
> >> > before yours, which would also nicely solve your alignmnet concern
> >> > (entirely untested for now):
> >>
> >> This looks correct. I've rebased my patches on top of it and I ran the
> >> xfstest auto group on gfs2 and xfs on top.
> >>
> >> Can you push this to your gfs2-iomap branch? I'll then repost an
> >> updated version of "iomap: Direct I/O for inline data".
> >
> > Darrick now has a real iomap merge branch which replaced it.
> 
> Where is it? Not in
> https://git.kernel.org/pub/scm/linux/kernel/git/djwong/xfs-linux.git
> it seems.

https://git.kernel.org/pub/scm/fs/xfs/xfs-linux.git/log/?h=iomap-4.19-merge

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 1/1] iomap: Direct I/O for inline data
  2018-06-29 14:40     ` Andreas Gruenbacher
  2018-06-29 16:01       ` Christoph Hellwig
@ 2018-07-01  6:29       ` Christoph Hellwig
  2018-07-01 21:44         ` Andreas Gruenbacher
  1 sibling, 1 reply; 13+ messages in thread
From: Christoph Hellwig @ 2018-07-01  6:29 UTC (permalink / raw)
  To: Andreas Gruenbacher
  Cc: Christoph Hellwig, cluster-devel, linux-ext4, linux-fsdevel

On Fri, Jun 29, 2018 at 04:40:40PM +0200, Andreas Gruenbacher wrote:
> On 29 June 2018 at 10:56, Christoph Hellwig <hch@lst.de> wrote:
> > This looks generally fine.  But I think it might be worth refactoring
> > iomap_dio_actor a bit first, e.g. something like this new patch
> > before yours, which would also nicely solve your alignmnet concern
> > (entirely untested for now):
> 
> This looks correct. I've rebased my patches on top of it and I ran the
> xfstest auto group on gfs2 and xfs on top.

As I've just been rebasing the iomap work I've done the work already,
does the version below work for you?

---
>From 5e8a0f157629bb8850b8d8fe049bb896730f0da7 Mon Sep 17 00:00:00 2001
From: Andreas Gruenbacher <agruenba@redhat.com>
Date: Sun, 1 Jul 2018 08:26:22 +0200
Subject: iomap: support direct I/O to inline data

Add support for reading from and writing to inline data to iomap_dio_rw.
This saves filesystems from having to implement fallback code for this
case.

The inline data is actually cached in the inode, so the I/O is only
direct in the sense that it doesn't go through the page cache.

Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
---
 fs/iomap.c | 29 +++++++++++++++++++++++++++++
 1 file changed, 29 insertions(+)

diff --git a/fs/iomap.c b/fs/iomap.c
index 4d8ff0f5ecc9..98a1fdd5c091 100644
--- a/fs/iomap.c
+++ b/fs/iomap.c
@@ -1450,6 +1450,33 @@ iomap_dio_hole_actor(loff_t length, struct iomap_dio *dio)
 	return length;
 }
 
+static loff_t
+iomap_dio_inline_actor(struct inode *inode, loff_t pos, loff_t length,
+		struct iomap_dio *dio, struct iomap *iomap)
+{
+	struct iov_iter *iter = dio->submit.iter;
+	size_t copied;
+
+	BUG_ON(pos + length > PAGE_SIZE - offset_in_page(iomap->inline_data));
+
+	if (dio->flags & IOMAP_DIO_WRITE) {
+		loff_t size = inode->i_size;
+
+		if (pos > size)
+			memset(iomap->inline_data + size, 0, pos - size);
+		copied = copy_from_iter(iomap->inline_data + pos, length, iter);
+		if (copied) {
+			if (pos + copied > size)
+				i_size_write(inode, pos + copied);
+			mark_inode_dirty(inode);
+		}
+	} else {
+		copied = copy_to_iter(iomap->inline_data + pos, length, iter);
+	}
+	dio->size += copied;
+	return copied;
+}
+
 static loff_t
 iomap_dio_actor(struct inode *inode, loff_t pos, loff_t length,
 		void *data, struct iomap *iomap)
@@ -1467,6 +1494,8 @@ iomap_dio_actor(struct inode *inode, loff_t pos, loff_t length,
 		return iomap_dio_bio_actor(inode, pos, length, dio, iomap);
 	case IOMAP_MAPPED:
 		return iomap_dio_bio_actor(inode, pos, length, dio, iomap);
+	case IOMAP_INLINE:
+		return iomap_dio_inline_actor(inode, pos, length, dio, iomap);
 	default:
 		WARN_ON_ONCE(1);
 		return -EIO;
-- 
2.18.0

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [PATCH 1/1] iomap: Direct I/O for inline data
  2018-07-01  6:29       ` Christoph Hellwig
@ 2018-07-01 21:44         ` Andreas Gruenbacher
  0 siblings, 0 replies; 13+ messages in thread
From: Andreas Gruenbacher @ 2018-07-01 21:44 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: cluster-devel, linux-ext4, linux-fsdevel

On 1 July 2018 at 08:29, Christoph Hellwig <hch@lst.de> wrote:
> On Fri, Jun 29, 2018 at 04:40:40PM +0200, Andreas Gruenbacher wrote:
>> On 29 June 2018 at 10:56, Christoph Hellwig <hch@lst.de> wrote:
>> > This looks generally fine.  But I think it might be worth refactoring
>> > iomap_dio_actor a bit first, e.g. something like this new patch
>> > before yours, which would also nicely solve your alignmnet concern
>> > (entirely untested for now):
>>
>> This looks correct. I've rebased my patches on top of it and I ran the
>> xfstest auto group on gfs2 and xfs on top.
>
> As I've just been rebasing the iomap work I've done the work already,
> does the version below work for you?

Yes, it does.

> ---
> From 5e8a0f157629bb8850b8d8fe049bb896730f0da7 Mon Sep 17 00:00:00 2001
> From: Andreas Gruenbacher <agruenba@redhat.com>
> Date: Sun, 1 Jul 2018 08:26:22 +0200
> Subject: iomap: support direct I/O to inline data
>
> Add support for reading from and writing to inline data to iomap_dio_rw.
> This saves filesystems from having to implement fallback code for this
> case.
>
> The inline data is actually cached in the inode, so the I/O is only
> direct in the sense that it doesn't go through the page cache.
>
> Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
> ---
>  fs/iomap.c | 29 +++++++++++++++++++++++++++++
>  1 file changed, 29 insertions(+)
>
> diff --git a/fs/iomap.c b/fs/iomap.c
> index 4d8ff0f5ecc9..98a1fdd5c091 100644
> --- a/fs/iomap.c
> +++ b/fs/iomap.c
> @@ -1450,6 +1450,33 @@ iomap_dio_hole_actor(loff_t length, struct iomap_dio *dio)
>         return length;
>  }
>
> +static loff_t
> +iomap_dio_inline_actor(struct inode *inode, loff_t pos, loff_t length,
> +               struct iomap_dio *dio, struct iomap *iomap)
> +{
> +       struct iov_iter *iter = dio->submit.iter;
> +       size_t copied;
> +
> +       BUG_ON(pos + length > PAGE_SIZE - offset_in_page(iomap->inline_data));
> +
> +       if (dio->flags & IOMAP_DIO_WRITE) {
> +               loff_t size = inode->i_size;
> +
> +               if (pos > size)
> +                       memset(iomap->inline_data + size, 0, pos - size);
> +               copied = copy_from_iter(iomap->inline_data + pos, length, iter);
> +               if (copied) {
> +                       if (pos + copied > size)
> +                               i_size_write(inode, pos + copied);
> +                       mark_inode_dirty(inode);
> +               }
> +       } else {
> +               copied = copy_to_iter(iomap->inline_data + pos, length, iter);
> +       }
> +       dio->size += copied;
> +       return copied;
> +}
> +
>  static loff_t
>  iomap_dio_actor(struct inode *inode, loff_t pos, loff_t length,
>                 void *data, struct iomap *iomap)
> @@ -1467,6 +1494,8 @@ iomap_dio_actor(struct inode *inode, loff_t pos, loff_t length,
>                 return iomap_dio_bio_actor(inode, pos, length, dio, iomap);
>         case IOMAP_MAPPED:
>                 return iomap_dio_bio_actor(inode, pos, length, dio, iomap);
> +       case IOMAP_INLINE:
> +               return iomap_dio_inline_actor(inode, pos, length, dio, iomap);
>         default:
>                 WARN_ON_ONCE(1);
>                 return -EIO;
> --
> 2.18.0
>

Thanks,
Andreas

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2018-07-01 21:44 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-06-27  0:39 [PATCH 0/1] iomap: Direct I/O for inline data Andreas Gruenbacher
2018-06-27  0:39 ` [PATCH 1/1] " Andreas Gruenbacher
2018-06-27  1:44   ` kbuild test robot
2018-06-29  8:56   ` Christoph Hellwig
2018-06-29 14:40     ` Andreas Gruenbacher
2018-06-29 16:01       ` Christoph Hellwig
2018-06-29 17:02         ` Andreas Gruenbacher
2018-07-01  6:13           ` Christoph Hellwig
2018-07-01  6:29       ` Christoph Hellwig
2018-07-01 21:44         ` Andreas Gruenbacher
2018-06-27 11:14 ` [PATCH 0/1] " Andreas Gruenbacher
2018-06-29  8:43   ` Christoph Hellwig
2018-06-29 11:01     ` Andreas Gruenbacher

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).