* [PATCH v4] Return bytes transferred for partial direct I/O
@ 2017-10-01 19:51 Goldwyn Rodrigues
2017-10-23 16:24 ` Goldwyn Rodrigues
0 siblings, 1 reply; 2+ messages in thread
From: Goldwyn Rodrigues @ 2017-10-01 19:51 UTC (permalink / raw)
To: linux-fsdevel; +Cc: hch, viro, Goldwyn Rodrigues
From: Goldwyn Rodrigues <rgoldwyn@suse.com>
In case direct I/O encounters an error midway, it returns the error.
Instead it should be returning the number of bytes transferred so far.
Test case for filesystems (with ENOSPC):
1. Create an almost full filesystem
2. Create a file, say /mnt/lastfile, until the filesystem is full.
3. Direct write() with count > sizeof /mnt/lastfile.
Result: write() returns -ENOSPC. However, file content has data written
in step 3.
Signed-off-by: Goldwyn Rodrigues <rgoldwyn@suse.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Changes since v1:
- incorporated iomap and block devices
Changes since v2:
- realized that file size was not increasing when performing a (partial)
direct I/O because end_io function was receiving the error instead of
size. Fixed.
Changes since v3:
- [hch] initialize transferred with dio->size and use transferred instead
of dio->size.
---
fs/block_dev.c | 2 +-
fs/direct-io.c | 4 +---
fs/iomap.c | 20 ++++++++++----------
3 files changed, 12 insertions(+), 14 deletions(-)
diff --git a/fs/block_dev.c b/fs/block_dev.c
index 93d088ffc05c..1c6640ffb929 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -421,7 +421,7 @@ __blkdev_direct_IO(struct kiocb *iocb, struct iov_iter *iter, int nr_pages)
if (!ret)
ret = blk_status_to_errno(dio->bio.bi_status);
- if (likely(!ret))
+ if (likely(dio->size))
ret = dio->size;
bio_put(&dio->bio);
diff --git a/fs/direct-io.c b/fs/direct-io.c
index 5fa2211e49ae..0fc1789498ae 100644
--- a/fs/direct-io.c
+++ b/fs/direct-io.c
@@ -255,8 +255,6 @@ static ssize_t dio_complete(struct dio *dio, ssize_t ret, bool is_async)
ret = dio->page_errors;
if (ret == 0)
ret = dio->io_error;
- if (ret == 0)
- ret = transferred;
if (dio->end_io) {
int err;
@@ -284,7 +282,7 @@ static ssize_t dio_complete(struct dio *dio, ssize_t ret, bool is_async)
}
kmem_cache_free(dio_cache, dio);
- return ret;
+ return transferred ? transferred : ret;
}
static void dio_aio_complete_work(struct work_struct *work)
diff --git a/fs/iomap.c b/fs/iomap.c
index 269b24a01f32..0e046e0a32ff 100644
--- a/fs/iomap.c
+++ b/fs/iomap.c
@@ -713,29 +713,29 @@ struct iomap_dio {
static ssize_t iomap_dio_complete(struct iomap_dio *dio)
{
struct kiocb *iocb = dio->iocb;
- ssize_t ret;
+ ssize_t err;
+ ssize_t transferred = dio->size;
if (dio->end_io) {
- ret = dio->end_io(iocb,
- dio->error ? dio->error : dio->size,
+ err = dio->end_io(iocb,
+ transferred ? transferred : dio->error,
dio->flags);
} else {
- ret = dio->error;
+ err = dio->error;
}
- if (likely(!ret)) {
- ret = dio->size;
+ if (likely(transferred)) {
/* check for short read */
- if (iocb->ki_pos + ret > dio->i_size &&
+ if (iocb->ki_pos + transferred > dio->i_size &&
!(dio->flags & IOMAP_DIO_WRITE))
- ret = dio->i_size - iocb->ki_pos;
- iocb->ki_pos += ret;
+ transferred = dio->i_size - iocb->ki_pos;
+ iocb->ki_pos += transferred;
}
inode_dio_end(file_inode(iocb->ki_filp));
kfree(dio);
- return ret;
+ return transferred ? transferred : err;
}
static void iomap_dio_complete_work(struct work_struct *work)
--
2.14.1
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [PATCH v4] Return bytes transferred for partial direct I/O
2017-10-01 19:51 [PATCH v4] Return bytes transferred for partial direct I/O Goldwyn Rodrigues
@ 2017-10-23 16:24 ` Goldwyn Rodrigues
0 siblings, 0 replies; 2+ messages in thread
From: Goldwyn Rodrigues @ 2017-10-23 16:24 UTC (permalink / raw)
To: Al Viro, Linux FS-devel Mailing List
Al,
A gentle reminder... Could you please include this patch if you have no
objections to it?
On 10/01/2017 02:51 PM, Goldwyn Rodrigues wrote:
> From: Goldwyn Rodrigues <rgoldwyn@suse.com>
>
> In case direct I/O encounters an error midway, it returns the error.
> Instead it should be returning the number of bytes transferred so far.
>
> Test case for filesystems (with ENOSPC):
> 1. Create an almost full filesystem
> 2. Create a file, say /mnt/lastfile, until the filesystem is full.
> 3. Direct write() with count > sizeof /mnt/lastfile.
>
> Result: write() returns -ENOSPC. However, file content has data written
> in step 3.
>
> Signed-off-by: Goldwyn Rodrigues <rgoldwyn@suse.com>
> Reviewed-by: Christoph Hellwig <hch@lst.de>
>
> Changes since v1:
> - incorporated iomap and block devices
>
> Changes since v2:
> - realized that file size was not increasing when performing a (partial)
> direct I/O because end_io function was receiving the error instead of
> size. Fixed.
>
> Changes since v3:
> - [hch] initialize transferred with dio->size and use transferred instead
> of dio->size.
>
> ---
> fs/block_dev.c | 2 +-
> fs/direct-io.c | 4 +---
> fs/iomap.c | 20 ++++++++++----------
> 3 files changed, 12 insertions(+), 14 deletions(-)
>
> diff --git a/fs/block_dev.c b/fs/block_dev.c
> index 93d088ffc05c..1c6640ffb929 100644
> --- a/fs/block_dev.c
> +++ b/fs/block_dev.c
> @@ -421,7 +421,7 @@ __blkdev_direct_IO(struct kiocb *iocb, struct iov_iter *iter, int nr_pages)
>
> if (!ret)
> ret = blk_status_to_errno(dio->bio.bi_status);
> - if (likely(!ret))
> + if (likely(dio->size))
> ret = dio->size;
>
> bio_put(&dio->bio);
> diff --git a/fs/direct-io.c b/fs/direct-io.c
> index 5fa2211e49ae..0fc1789498ae 100644
> --- a/fs/direct-io.c
> +++ b/fs/direct-io.c
> @@ -255,8 +255,6 @@ static ssize_t dio_complete(struct dio *dio, ssize_t ret, bool is_async)
> ret = dio->page_errors;
> if (ret == 0)
> ret = dio->io_error;
> - if (ret == 0)
> - ret = transferred;
>
> if (dio->end_io) {
> int err;
> @@ -284,7 +282,7 @@ static ssize_t dio_complete(struct dio *dio, ssize_t ret, bool is_async)
> }
>
> kmem_cache_free(dio_cache, dio);
> - return ret;
> + return transferred ? transferred : ret;
> }
>
> static void dio_aio_complete_work(struct work_struct *work)
> diff --git a/fs/iomap.c b/fs/iomap.c
> index 269b24a01f32..0e046e0a32ff 100644
> --- a/fs/iomap.c
> +++ b/fs/iomap.c
> @@ -713,29 +713,29 @@ struct iomap_dio {
> static ssize_t iomap_dio_complete(struct iomap_dio *dio)
> {
> struct kiocb *iocb = dio->iocb;
> - ssize_t ret;
> + ssize_t err;
> + ssize_t transferred = dio->size;
>
> if (dio->end_io) {
> - ret = dio->end_io(iocb,
> - dio->error ? dio->error : dio->size,
> + err = dio->end_io(iocb,
> + transferred ? transferred : dio->error,
> dio->flags);
> } else {
> - ret = dio->error;
> + err = dio->error;
> }
>
> - if (likely(!ret)) {
> - ret = dio->size;
> + if (likely(transferred)) {
> /* check for short read */
> - if (iocb->ki_pos + ret > dio->i_size &&
> + if (iocb->ki_pos + transferred > dio->i_size &&
> !(dio->flags & IOMAP_DIO_WRITE))
> - ret = dio->i_size - iocb->ki_pos;
> - iocb->ki_pos += ret;
> + transferred = dio->i_size - iocb->ki_pos;
> + iocb->ki_pos += transferred;
> }
>
> inode_dio_end(file_inode(iocb->ki_filp));
> kfree(dio);
>
> - return ret;
> + return transferred ? transferred : err;
> }
>
> static void iomap_dio_complete_work(struct work_struct *work)
>
--
Goldwyn
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2017-10-23 16:25 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-10-01 19:51 [PATCH v4] Return bytes transferred for partial direct I/O Goldwyn Rodrigues
2017-10-23 16:24 ` Goldwyn Rodrigues
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).