From: Andreas Gruenbacher <agruenba@redhat.com>
To: Christoph Hellwig <hch@infradead.org>
Cc: Matthew Wilcox <willy@infradead.org>,
"Darrick J. Wong" <djwong@kernel.org>,
Linus Torvalds <torvalds@linux-foundation.org>,
linux-xfs@vger.kernel.org,
linux-fsdevel <linux-fsdevel@vger.kernel.org>
Subject: Re: [PATCH] iomap: iomap_write_end cleanup
Date: Wed, 4 May 2022 19:21:31 +0200 [thread overview]
Message-ID: <CAHc6FU4psuQKXgueM6wH9pPMho+J1Rr2Xpbxx16N6fpX0FuJvw@mail.gmail.com> (raw)
In-Reply-To: <YnKMFNtBshOa1eWs@infradead.org>
On Wed, May 4, 2022 at 4:22 PM Christoph Hellwig <hch@infradead.org> wrote:
> On Wed, May 04, 2022 at 01:27:36AM +0100, Matthew Wilcox wrote:
> > This is one of the things I noticed when folioising iomap and didn't
> > get round to cleaning up, but I feel like we should change the calling
> > convention here to bool (true = success, false = fail). Changing
> > block_write_end() might not be on the cards, unless someone's really
> > motivated, but we can at least change iomap_write_end() to not have this
> > stupid calling convention.
>
> I kinda hate the bools for something that is not a simple
>
> if (foo()))
> return;
>
> as propagating them is a bit of a mess. I do however thing that
> switching to 0 / -errno might work nicely here, completely untested
> patch below:
This doesn't really strike me as better, just different.
> diff --git a/fs/iomap/buffered-io.c b/fs/iomap/buffered-io.c
> index 8bc0989cf447fa..764174e2f1a183 100644
> --- a/fs/iomap/buffered-io.c
> +++ b/fs/iomap/buffered-io.c
> @@ -685,13 +685,13 @@ static size_t __iomap_write_end(struct inode *inode, loff_t pos, size_t len,
> * redo the whole thing.
> */
> if (unlikely(copied < len && !folio_test_uptodate(folio)))
> - return 0;
> + return -EIO;
> iomap_set_range_uptodate(folio, iop, offset_in_folio(folio, pos), len);
> filemap_dirty_folio(inode->i_mapping, folio);
> - return copied;
> + return 0;
> }
>
> -static size_t iomap_write_end_inline(const struct iomap_iter *iter,
> +static void iomap_write_end_inline(const struct iomap_iter *iter,
> struct folio *folio, loff_t pos, size_t copied)
> {
> const struct iomap *iomap = &iter->iomap;
> @@ -706,23 +706,22 @@ static size_t iomap_write_end_inline(const struct iomap_iter *iter,
> kunmap_local(addr);
>
> mark_inode_dirty(iter->inode);
> - return copied;
> }
>
> -/* Returns the number of bytes copied. May be 0. Cannot be an errno. */
> -static size_t iomap_write_end(struct iomap_iter *iter, loff_t pos, size_t len,
> +static int iomap_write_end(struct iomap_iter *iter, loff_t pos, size_t len,
> size_t copied, struct folio *folio)
> {
> const struct iomap_page_ops *page_ops = iter->iomap.page_ops;
> const struct iomap *srcmap = iomap_iter_srcmap(iter);
> loff_t old_size = iter->inode->i_size;
> - size_t ret;
> + int ret = 0;
>
> if (srcmap->type == IOMAP_INLINE) {
> - ret = iomap_write_end_inline(iter, folio, pos, copied);
> + iomap_write_end_inline(iter, folio, pos, copied);
> } else if (srcmap->flags & IOMAP_F_BUFFER_HEAD) {
> - ret = block_write_end(NULL, iter->inode->i_mapping, pos, len,
> - copied, &folio->page, NULL);
> + if (block_write_end(NULL, iter->inode->i_mapping, pos, len,
> + copied, &folio->page, NULL) < len)
> + ret = -EIO;
> } else {
> ret = __iomap_write_end(iter->inode, pos, len, copied, folio);
> }
> @@ -732,8 +731,8 @@ static size_t iomap_write_end(struct iomap_iter *iter, loff_t pos, size_t len,
> * cache. It's up to the file system to write the updated size to disk,
> * preferably after I/O completion so that no stale data is exposed.
> */
> - if (pos + ret > old_size) {
> - i_size_write(iter->inode, pos + ret);
> + if (!ret && pos + len > old_size) {
> + i_size_write(iter->inode, pos + len);
> iter->iomap.flags |= IOMAP_F_SIZE_CHANGED;
> }
> folio_unlock(folio);
> @@ -741,10 +740,11 @@ static size_t iomap_write_end(struct iomap_iter *iter, loff_t pos, size_t len,
> if (old_size < pos)
> pagecache_isize_extended(iter->inode, old_size, pos);
> if (page_ops && page_ops->page_done)
> - page_ops->page_done(iter->inode, pos, ret, &folio->page);
> + page_ops->page_done(iter->inode, pos, ret ? ret : len,
> + &folio->page);
> folio_put(folio);
>
> - if (ret < len)
> + if (ret)
> iomap_write_failed(iter->inode, pos, len);
> return ret;
> }
> @@ -754,7 +754,7 @@ static loff_t iomap_write_iter(struct iomap_iter *iter, struct iov_iter *i)
> loff_t length = iomap_length(iter);
> loff_t pos = iter->pos;
> ssize_t written = 0;
> - long status = 0;
> + int status = 0;
>
> do {
> struct folio *folio;
> @@ -792,26 +792,24 @@ static loff_t iomap_write_iter(struct iomap_iter *iter, struct iov_iter *i)
> copied = copy_page_from_iter_atomic(page, offset, bytes, i);
>
> status = iomap_write_end(iter, pos, bytes, copied, folio);
> -
> - if (unlikely(copied != status))
> - iov_iter_revert(i, copied - status);
> -
> - cond_resched();
> - if (unlikely(status == 0)) {
> + if (unlikely(status)) {
> /*
> * A short copy made iomap_write_end() reject the
> * thing entirely. Might be memory poisoning
> * halfway through, might be a race with munmap,
> * might be severe memory pressure.
> */
> - if (copied)
> + if (copied) {
> + iov_iter_revert(i, copied);
> bytes = copied;
> + }
> goto again;
> }
> - pos += status;
> - written += status;
> - length -= status;
> + pos += bytes;
> + written += bytes;
> + length -= bytes;
Ought to turn 'status' into 'copied' here, not 'bytes'.
>
> + cond_resched();
> balance_dirty_pages_ratelimited(iter->inode->i_mapping);
> } while (iov_iter_count(i) && length);
>
> @@ -844,7 +842,6 @@ static loff_t iomap_unshare_iter(struct iomap_iter *iter)
> const struct iomap *srcmap = iomap_iter_srcmap(iter);
> loff_t pos = iter->pos;
> loff_t length = iomap_length(iter);
> - long status = 0;
> loff_t written = 0;
>
> /* don't bother with blocks that are not shared to start with */
> @@ -858,20 +855,21 @@ static loff_t iomap_unshare_iter(struct iomap_iter *iter)
> unsigned long offset = offset_in_page(pos);
> unsigned long bytes = min_t(loff_t, PAGE_SIZE - offset, length);
> struct folio *folio;
> + int status;
>
> status = iomap_write_begin(iter, pos, bytes, &folio);
> if (unlikely(status))
> return status;
>
> status = iomap_write_end(iter, pos, bytes, bytes, folio);
> - if (WARN_ON_ONCE(status == 0))
> - return -EIO;
> + if (WARN_ON_ONCE(status))
> + return status;
>
> cond_resched();
>
> - pos += status;
> - written += status;
> - length -= status;
> + pos += bytes;
> + written += bytes;
> + length -= bytes;
>
> balance_dirty_pages_ratelimited(iter->inode->i_mapping);
> } while (length);
> @@ -925,9 +923,9 @@ static loff_t iomap_zero_iter(struct iomap_iter *iter, bool *did_zero)
> folio_zero_range(folio, offset, bytes);
> folio_mark_accessed(folio);
>
> - bytes = iomap_write_end(iter, pos, bytes, bytes, folio);
> - if (WARN_ON_ONCE(bytes == 0))
> - return -EIO;
> + status = iomap_write_end(iter, pos, bytes, bytes, folio);
> + if (WARN_ON_ONCE(status))
> + return status;
>
> pos += bytes;
> length -= bytes;
>
Thanks,
Andreas
next prev parent reply other threads:[~2022-05-04 18:02 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-05-03 21:37 [PATCH] iomap: iomap_write_end cleanup Andreas Gruenbacher
2022-05-03 21:52 ` Matthew Wilcox
2022-05-03 22:15 ` Andreas Gruenbacher
2022-05-03 23:02 ` Darrick J. Wong
2022-05-04 0:27 ` Matthew Wilcox
2022-05-04 14:22 ` Christoph Hellwig
2022-05-04 17:21 ` Andreas Gruenbacher [this message]
2022-05-04 8:02 ` Andreas Gruenbacher
2022-05-04 14:13 ` Christoph Hellwig
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=CAHc6FU4psuQKXgueM6wH9pPMho+J1Rr2Xpbxx16N6fpX0FuJvw@mail.gmail.com \
--to=agruenba@redhat.com \
--cc=djwong@kernel.org \
--cc=hch@infradead.org \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-xfs@vger.kernel.org \
--cc=torvalds@linux-foundation.org \
--cc=willy@infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).