On Fri, 2024-04-26 at 12:15 +0100, David Howells wrote: > In netfs_perform_write(), when the file is marked NETFS_ICTX_WRITETHROUGH > or O_*SYNC or RWF_*SYNC was specified, write-through caching is performed > on a buffered file. When setting up for write-through, we flush any > conflicting writes in the region and wait for the write to complete, > failing if there's a write error to return. > > The issue arises if we're writing at or above the EOF position because we > skip the flush and - more importantly - the wait. This becomes a problem > if there's a partial folio at the end of the file that is being written out > and we want to make a write to it too. Both the already-running write and > the write we start both want to clear the writeback mark, but whoever is > second causes a warning looking something like: > > ------------[ cut here ]------------ > R=00000012: folio 11 is not under writeback > WARNING: CPU: 34 PID: 654 at fs/netfs/write_collect.c:105 > ... > CPU: 34 PID: 654 Comm: kworker/u386:27 Tainted: G S ... > ... > Workqueue: events_unbound netfs_write_collection_worker > ... > RIP: 0010:netfs_writeback_lookup_folio > > Fix this by making the flush-and-wait unconditional. It will do nothing if > there are no folios in the pagecache and will return quickly if there are > no folios in the region specified. > > Further, move the WBC attachment above the flush call as the flush is going > to attach a WBC and detach it again if it is not present - and since we > need one anyway we might as well share it. > > Fixes: 41d8e7673a77 ("netfs: Implement a write-through caching option") > Reported-by: kernel test robot <oliver.sang@xxxxxxxxx> > Closes: https://lore.kernel.org/oe-lkp/202404161031.468b84f-oliver.sang@xxxxxxxxx > Signed-off-by: David Howells <dhowells@xxxxxxxxxx> > cc: Eric Van Hensbergen <ericvh@xxxxxxxxxx> > cc: Latchesar Ionkov <lucho@xxxxxxxxxx> > cc: Dominique Martinet <asmadeus@xxxxxxxxxxxxx> > cc: Christian Schoenebeck <linux_oss@xxxxxxxxxxxxx> > cc: Marc Dionne <marc.dionne@xxxxxxxxxxxx> > cc: netfs@xxxxxxxxxxxxxxx > cc: linux-fsdevel@xxxxxxxxxxxxxxx > cc: linux-mm@xxxxxxxxx > cc: v9fs@xxxxxxxxxxxxxxx > cc: linux-afs@xxxxxxxxxxxxxxxxxxx > cc: linux-cifs@xxxxxxxxxxxxxxx > --- > fs/netfs/buffered_write.c | 13 ++++++------- > 1 file changed, 6 insertions(+), 7 deletions(-) > > diff --git a/fs/netfs/buffered_write.c b/fs/netfs/buffered_write.c > index 9a0d32e4b422..07aff231926c 100644 > --- a/fs/netfs/buffered_write.c > +++ b/fs/netfs/buffered_write.c > @@ -172,15 +172,14 @@ ssize_t netfs_perform_write(struct kiocb *iocb, struct iov_iter *iter, > if (unlikely(test_bit(NETFS_ICTX_WRITETHROUGH, &ctx->flags) || > iocb->ki_flags & (IOCB_DSYNC | IOCB_SYNC)) > ) { > - if (pos < i_size_read(inode)) { > - ret = filemap_write_and_wait_range(mapping, pos, pos + iter->count); > - if (ret < 0) { > - goto out; > - } > - } > - > wbc_attach_fdatawrite_inode(&wbc, mapping->host); > > + ret = filemap_write_and_wait_range(mapping, pos, pos + iter->count); > + if (ret < 0) { > + wbc_detach_inode(&wbc); > + goto out; > + } > + > wreq = netfs_begin_writethrough(iocb, iter->count); > if (IS_ERR(wreq)) { > wbc_detach_inode(&wbc); > Reviewed-by: Jeffrey Layton <jlayton@xxxxxxxxxx>