From patchwork Wed Aug 14 20:38:41 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Howells X-Patchwork-Id: 13764103 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6D73CC531DC for ; Wed, 14 Aug 2024 20:41:48 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id F3DB16B00B9; Wed, 14 Aug 2024 16:41:47 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id EF1176B00BA; Wed, 14 Aug 2024 16:41:47 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id D67F46B00BB; Wed, 14 Aug 2024 16:41:47 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0012.hostedemail.com [216.40.44.12]) by kanga.kvack.org (Postfix) with ESMTP id B84756B00B9 for ; Wed, 14 Aug 2024 16:41:47 -0400 (EDT) Received: from smtpin21.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay09.hostedemail.com (Postfix) with ESMTP id 6F47880D55 for ; Wed, 14 Aug 2024 20:41:47 +0000 (UTC) X-FDA: 82452022254.21.186AA16 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by imf16.hostedemail.com (Postfix) with ESMTP id B79AE180005 for ; Wed, 14 Aug 2024 20:41:45 +0000 (UTC) Authentication-Results: imf16.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=Taf89cgu; dmarc=pass (policy=none) header.from=redhat.com; spf=pass (imf16.hostedemail.com: domain of dhowells@redhat.com designates 170.10.129.124 as permitted sender) smtp.mailfrom=dhowells@redhat.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1723668025; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=Iwp88PKNI4mMdeB9eXHleWn+X4nv/CC8OxS+odKjs5Q=; b=KNZ+bN6odaTjt7DMywmE/FaYrYDgTf/X4g0FZKvHmVYUgBA79mZWd+v0YjvqSs2BVu5vsq 3CkT7rNq5TlLaQjC8H+qFbkxWzBA3+49tDdKk0/rMH9vAI26IoL+p8W+QaeCZHhUg8ESd9 JGRTHMRBoThhl69a2Ds7B19HhhxTN2E= ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1723668025; a=rsa-sha256; cv=none; b=5hlinmiOAVBcpGYP1VwRRe9eGdkQq1vjl7vhtYBwKv2xwX9/3lzWwKEWRu75YrSE4P6w8g wwmbbMJNfnePuwv9v5yBge6+NQkKZNdWS7HB/JPKciOuUA8ulh8bGeyoiVfXnL1SryTeCN 7ZNaL4xu1YO5U8m0tnpYOuE3FDJsUTg= ARC-Authentication-Results: i=1; imf16.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=Taf89cgu; dmarc=pass (policy=none) header.from=redhat.com; spf=pass (imf16.hostedemail.com: domain of dhowells@redhat.com designates 170.10.129.124 as permitted sender) smtp.mailfrom=dhowells@redhat.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1723668105; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=Iwp88PKNI4mMdeB9eXHleWn+X4nv/CC8OxS+odKjs5Q=; b=Taf89cgulJcW8+J0vrn/XsgfQPNl9Yhn0dSYrL+CW53SBQc1iLCeAovMYHSDD9z0JFaqbh 2Lqe/DUaz2bhPimQ/7WqS21K3DImwu5TYgz90NpYuHJtLGtdd+uAw8amhWsVrjcW6oZFgd Xk5NB5yFADfXp5OHYlMGQxegmG50SZs= Received: from mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-689-7X87DD1LN9GwpLr3LM1nyg-1; Wed, 14 Aug 2024 16:41:41 -0400 X-MC-Unique: 7X87DD1LN9GwpLr3LM1nyg-1 Received: from mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.15]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 47CCD1954B11; Wed, 14 Aug 2024 20:41:38 +0000 (UTC) Received: from warthog.procyon.org.uk.com (unknown [10.42.28.30]) by mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id C92FB1955E8C; Wed, 14 Aug 2024 20:41:32 +0000 (UTC) From: David Howells To: Christian Brauner , Steve French , Matthew Wilcox Cc: David Howells , Jeff Layton , Gao Xiang , Dominique Martinet , Marc Dionne , Paulo Alcantara , Shyam Prasad N , Tom Talpey , Eric Van Hensbergen , Ilya Dryomov , netfs@lists.linux.dev, linux-afs@lists.infradead.org, linux-cifs@vger.kernel.org, linux-nfs@vger.kernel.org, ceph-devel@vger.kernel.org, v9fs@lists.linux.dev, linux-erofs@lists.ozlabs.org, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v2 21/25] cachefiles, netfs: Fix write to partial block at EOF Date: Wed, 14 Aug 2024 21:38:41 +0100 Message-ID: <20240814203850.2240469-22-dhowells@redhat.com> In-Reply-To: <20240814203850.2240469-1-dhowells@redhat.com> References: <20240814203850.2240469-1-dhowells@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.15 X-Rspamd-Server: rspam07 X-Rspamd-Queue-Id: B79AE180005 X-Stat-Signature: qdt45k1jwznu3iish47jy7btzy4bazsj X-Rspam-User: X-HE-Tag: 1723668105-605412 X-HE-Meta: U2FsdGVkX19N+ZwegHcOayNNOiDZb+97a77xAqGKP3RLyoX9fwcUngzlFtLj7yvctiBAEv8/NiTlBKHTIuTP7vR4p0ad+9Y7OxdDEHnX9A7+gwcbNt3BISMnYnmNcECPgW0pMRXRDAShYLyyQwyxLpApMGqd3cCCUdArUgVunRNy1T2KyBdmVjYHDe1G1R1xybcY7eJXELJiuxnzxvck/wGXPZgc4Tiueeauwylu4DAbDVMj8YOdKOZSV14/dFMx0eRRIt9CWMwhIEIS7aNVn/jzoYe0Xg6jHdnSG2lAMdUcRDGGE/Vr3kmVnoJDcJa/ibiptpnpbSmZauo2hCUEF5gJ5zXwstoRhyQ9/wB/MM93JYdBOVq/6DaEj21rUj2SEA1M7JEPcPDmRXUEztoGhBd/Kt6qbiiPhio8odUbcBGxFI+TW9qMGCRErqMCDRRfd0m/CVH8kDnTcaoROy5ikKROjm3bKXmNHPrrWcVSA6fySnILJOd8ZDA7erzNo/tAe7hJoYsRm2mn52j3hA0pCTXiW0GjVvT2NgV72kg6oxxYBaiDaJjrEhh4cNOXtNXnZz4w5UxjnrEotREsyvj7gKY2KpirOTtVCbAdw/jITeohxd1+cLTrqh9sj12INX5bAoVsEhr/pt5GRHOtN4CKj2CP++bmyQOx+2WoEod5b+G5O+dkQEWsVvMfkNjSWJ0p/7dfe91C/6oj4poLWU0WY0nzUtL2jPt63kyv5MWON83+P8+2hMYlE8x7YwBZ6+R8nFrVrywCk5eGBgJ4bSgEB6OObZvNt7AsqKmuIPRwMiqbeCpJbq32EGwogPtIkzzSVe3Y4MZv9mvTnRHJ7XAIvN0Q53fZOqgLGYLMRsKBf8MJdPJVJB2d+8Mp4EkIY0wuj764Q33kDlRapMMwppb+FczzbPRqInKZxQqJgftGhtvEMDAAJaKdqzbRwqC+yX0xBlxJvIo2ZX0yMeZPxIO 9bNGH8fG GO3GEJrdtPffPGrpQ43r1UbRp1eDZZmshTrz4Jr0S2/68znGp4rYT/PSTfoEM38qyAv2seyXeCjmOJ2UneMOdYhcVb7uqbGHqVFuBNbyegNDRKsTrW/fAMd4fKnE7vjNbnYy7fUTJ6s4OES72FxygjqqjAQsI9HdtWrO+sQE1dDmzJF+r5v1tosnQrZ7lLMZMf3/39ypzjMn3eQJY9EHqkd4Nux9gJL8Bm8kUwDqc3V3dc6V2+ijw7Ha9keUBwTfcaASjwBVgXUaQ8dp5koUFcXocKxA5bVtaE/U9K2ztU2gSVY1ezxYzI5gEMqKx3PUPhSeKGX3eLt5dAB68muIUB7cJWKkQA6AyGgUlg2CNqjNUMc8= X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: List-Subscribe: List-Unsubscribe: Because it uses DIO writes, cachefiles is unable to make a write to the backing file if that write is not aligned to and sized according to the backing file's DIO block alignment. This makes it tricky to handle a write to the cache where the EOF on the network file is not correctly aligned. To get around this, netfslib attempts to tell the driver it is calling how much more data there is available beyond the EOF that it can use to pad the write (netfslib preclears the part of the folio above the EOF). However, it tries to tell the cache what the maximum length is, but doesn't calculate this correctly; and, in any case, cachefiles actually ignores the value and just skips the block. Fix this by: (1) Change the value passed to indicate the amount of extra data that can be added to the operation (now ->submit_extendable_to). This is much simpler to calculate as it's just the end of the folio minus the top of the data within the folio - rather than having to account for data spread over multiple folios. (2) Make cachefiles add some of this data if the subrequest it is given ends at the network file's i_size if the extra data is sufficient to pad out to a whole block. Signed-off-by: David Howells cc: Jeff Layton cc: netfs@lists.linux.dev cc: linux-fsdevel@vger.kernel.org --- fs/cachefiles/io.c | 14 ++++++++++++++ fs/netfs/read_pgpriv2.c | 4 ++-- fs/netfs/write_issue.c | 5 ++--- include/linux/netfs.h | 2 +- 4 files changed, 19 insertions(+), 6 deletions(-) diff --git a/fs/cachefiles/io.c b/fs/cachefiles/io.c index 5b82ba7785cd..6a821a959b59 100644 --- a/fs/cachefiles/io.c +++ b/fs/cachefiles/io.c @@ -648,6 +648,7 @@ static void cachefiles_issue_write(struct netfs_io_subrequest *subreq) struct netfs_cache_resources *cres = &wreq->cache_resources; struct cachefiles_object *object = cachefiles_cres_object(cres); struct cachefiles_cache *cache = object->volume->cache; + struct netfs_io_stream *stream = &wreq->io_streams[subreq->stream_nr]; const struct cred *saved_cred; size_t off, pre, post, len = subreq->len; loff_t start = subreq->start; @@ -661,6 +662,7 @@ static void cachefiles_issue_write(struct netfs_io_subrequest *subreq) if (off) { pre = CACHEFILES_DIO_BLOCK_SIZE - off; if (pre >= len) { + fscache_count_dio_misfit(); netfs_write_subrequest_terminated(subreq, len, false); return; } @@ -671,10 +673,22 @@ static void cachefiles_issue_write(struct netfs_io_subrequest *subreq) } /* We also need to end on the cache granularity boundary */ + if (start + len == wreq->i_size) { + size_t part = len % CACHEFILES_DIO_BLOCK_SIZE; + size_t need = CACHEFILES_DIO_BLOCK_SIZE - part; + + if (part && stream->submit_extendable_to >= need) { + len += need; + subreq->len += need; + subreq->io_iter.count += need; + } + } + post = len & (CACHEFILES_DIO_BLOCK_SIZE - 1); if (post) { len -= post; if (len == 0) { + fscache_count_dio_misfit(); netfs_write_subrequest_terminated(subreq, post, false); return; } diff --git a/fs/netfs/read_pgpriv2.c b/fs/netfs/read_pgpriv2.c index 9439461d535f..ba5af89d37fa 100644 --- a/fs/netfs/read_pgpriv2.c +++ b/fs/netfs/read_pgpriv2.c @@ -97,7 +97,7 @@ static int netfs_pgpriv2_copy_folio(struct netfs_io_request *wreq, struct folio if (netfs_buffer_append_folio(wreq, folio, false) < 0) return -ENOMEM; - cache->submit_max_len = fsize; + cache->submit_extendable_to = fsize; cache->submit_off = 0; cache->submit_len = flen; @@ -112,10 +112,10 @@ static int netfs_pgpriv2_copy_folio(struct netfs_io_request *wreq, struct folio wreq->io_iter.iov_offset = cache->submit_off; atomic64_set(&wreq->issued_to, fpos + cache->submit_off); + cache->submit_extendable_to = fsize - cache->submit_off; part = netfs_advance_write(wreq, cache, fpos + cache->submit_off, cache->submit_len, to_eof); cache->submit_off += part; - cache->submit_max_len -= part; if (part > cache->submit_len) cache->submit_len = 0; else diff --git a/fs/netfs/write_issue.c b/fs/netfs/write_issue.c index 975436d3dc3f..f7d59f0bb8c2 100644 --- a/fs/netfs/write_issue.c +++ b/fs/netfs/write_issue.c @@ -283,6 +283,7 @@ int netfs_advance_write(struct netfs_io_request *wreq, _debug("part %zx/%zx %zx/%zx", subreq->len, stream->sreq_max_len, part, len); subreq->len += part; subreq->nr_segs++; + stream->submit_extendable_to -= part; if (subreq->len >= stream->sreq_max_len || subreq->nr_segs >= stream->sreq_max_segs || @@ -424,7 +425,6 @@ static int netfs_write_folio(struct netfs_io_request *wreq, */ for (int s = 0; s < NR_IO_STREAMS; s++) { stream = &wreq->io_streams[s]; - stream->submit_max_len = fsize; stream->submit_off = foff; stream->submit_len = flen; if ((stream->source == NETFS_WRITE_TO_CACHE && streamw) || @@ -432,7 +432,6 @@ static int netfs_write_folio(struct netfs_io_request *wreq, fgroup == NETFS_FOLIO_COPY_TO_CACHE)) { stream->submit_off = UINT_MAX; stream->submit_len = 0; - stream->submit_max_len = 0; } } @@ -462,10 +461,10 @@ static int netfs_write_folio(struct netfs_io_request *wreq, wreq->io_iter.iov_offset = stream->submit_off; atomic64_set(&wreq->issued_to, fpos + stream->submit_off); + stream->submit_extendable_to = fsize - stream->submit_off; part = netfs_advance_write(wreq, stream, fpos + stream->submit_off, stream->submit_len, to_eof); stream->submit_off += part; - stream->submit_max_len -= part; if (part > stream->submit_len) stream->submit_len = 0; else diff --git a/include/linux/netfs.h b/include/linux/netfs.h index c0f0c9c87d86..5eaceef41e6c 100644 --- a/include/linux/netfs.h +++ b/include/linux/netfs.h @@ -135,7 +135,7 @@ struct netfs_io_stream { unsigned int sreq_max_segs; /* 0 or max number of segments in an iterator */ unsigned int submit_off; /* Folio offset we're submitting from */ unsigned int submit_len; /* Amount of data left to submit */ - unsigned int submit_max_len; /* Amount I/O can be rounded up to */ + unsigned int submit_extendable_to; /* Amount I/O can be rounded up to */ void (*prepare_write)(struct netfs_io_subrequest *subreq); void (*issue_write)(struct netfs_io_subrequest *subreq); /* Collection tracking */