From patchwork Mon Jul 29 16:19:49 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Howells X-Patchwork-Id: 13745304 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 88663C3DA7E for ; Mon, 29 Jul 2024 16:22:53 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 158216B00B8; Mon, 29 Jul 2024 12:22:53 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 107A36B00BA; Mon, 29 Jul 2024 12:22:53 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id EC34B6B00BB; Mon, 29 Jul 2024 12:22:52 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0016.hostedemail.com [216.40.44.16]) by kanga.kvack.org (Postfix) with ESMTP id C50006B00B8 for ; Mon, 29 Jul 2024 12:22:52 -0400 (EDT) Received: from smtpin03.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay06.hostedemail.com (Postfix) with ESMTP id 7E5CCA3D88 for ; Mon, 29 Jul 2024 16:22:52 +0000 (UTC) X-FDA: 82393308984.03.B674963 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by imf10.hostedemail.com (Postfix) with ESMTP id C639BC000C for ; Mon, 29 Jul 2024 16:22:50 +0000 (UTC) Authentication-Results: imf10.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=W3Fim3P2; spf=pass (imf10.hostedemail.com: domain of dhowells@redhat.com designates 170.10.133.124 as permitted sender) smtp.mailfrom=dhowells@redhat.com; dmarc=pass (policy=none) header.from=redhat.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1722270144; 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=gkUmafKnkjrKfRYrg113wMsu3lfIhzrdFfYQD3AXCyI=; b=aDLoE8l3M1lT9A7HjDPrP4yJUcgY/IJgm1t+CclpmbXCXVxeBcAEcioiXgeasIQjF2huXt yyqAHq3xvuqJKTSANxygeTPdWyvW1ccLcYFmVOk3ymRpuVBcgsWXey/cdEc3wSQulHiYJN +jq1dtziL3yKwVp4NBnsMY2qhD27ZTo= ARC-Authentication-Results: i=1; imf10.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=W3Fim3P2; spf=pass (imf10.hostedemail.com: domain of dhowells@redhat.com designates 170.10.133.124 as permitted sender) smtp.mailfrom=dhowells@redhat.com; dmarc=pass (policy=none) header.from=redhat.com ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1722270144; a=rsa-sha256; cv=none; b=noE5r5wU+itxA05mahX4vd6ZG/PvXgf5l6lq/z4U7RgPLHN4BQho0OqC8JiuJn5nTZqJhx Xfcn63FD6A5jE0GLVCiW8Oa8S6QqiYc3aPs2J2nfVTF1tZKN/UEoSyOoubg8X/NhpKkAn6 r5EEaGRLtRy5q8NbqnEk5HjAQl23D7k= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1722270170; 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=gkUmafKnkjrKfRYrg113wMsu3lfIhzrdFfYQD3AXCyI=; b=W3Fim3P2TpveinLInmVvkhXAkG+Z0vPtP27Hg7oCyReV0uSTroGB0yAx/N39TrBaAoWQTx Rz2oOGjI5gqvLe8rqCo5MGiVwhZ+xCwObaqhmUR0LCDpgDowMcKQF7MzG03l2tLhvlp/Ow 5EAEn6+mkhPlu+Gm+yInaIbhspUaXGA= Received: from mx-prod-mc-05.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-632-Tsf-DznPP_awNvwyCq8cTw-1; Mon, 29 Jul 2024 12:22:45 -0400 X-MC-Unique: Tsf-DznPP_awNvwyCq8cTw-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-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 0862E1955F6A; Mon, 29 Jul 2024 16:22:43 +0000 (UTC) Received: from warthog.procyon.org.uk.com (unknown [10.42.28.216]) by mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 2E6E81955D42; Mon, 29 Jul 2024 16:22:36 +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 20/24] cachefiles, netfs: Fix write to partial block at EOF Date: Mon, 29 Jul 2024 17:19:49 +0100 Message-ID: <20240729162002.3436763-21-dhowells@redhat.com> In-Reply-To: <20240729162002.3436763-1-dhowells@redhat.com> References: <20240729162002.3436763-1-dhowells@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.15 X-Rspamd-Server: rspam03 X-Rspam-User: X-Rspamd-Queue-Id: C639BC000C X-Stat-Signature: i3ar51dp1ecnxp8d3ygmbz51kduyjg3f X-HE-Tag: 1722270170-100762 X-HE-Meta: U2FsdGVkX19MNTtbdRdfUxpjNUG56xSy9WMbofdL9Qyjy1mpK8eFqSMitWe9VcEXQiaUFl3byAS6CVJ911C3HIjRZcaLqPpiMoNSia8bqxB+aazYzgcd2lwZDzqhbMQtCeHJlvXFMY2IheVmHPfKYqL75x/nNIMzmnzG+43PyP58EkVowgVAb/HbFcigt6wq0LT3nLuaCnKDKpZe/ydCsEEhwkmZKXT0cJUdwGK5MG7reKekt87vmAoQ8yuvlNvqX+C8PgPUth8hU5BJto4mzfjQ42bH9Bh2N/TOHxkRxUcDWJ7nmtBQtbr1JjkhVacCNspjdh7LTdBhQHW7VjIXq9s9IOnx4vhBj0yhup+kbrwU8NwWZ07IQ5ltN2NhM1MaaVug0gLPaLPJwyrR0YatgcmWtzea7VcKmLGrOFONEtT1inBhtspPMqpR4Xz9mwvoERzzOkS0+9N9pMXRzWlUmbfjUjeOqUm31kkPjGKJqM/OS4LbxmEXKUdHjxLpq5Nj/1GHgbdIoQVZW0iwo24hRsGfZ40DUmgzEjZy/cYdzlT0DkS8opUzQ3y2MsGTn4ayHYqzjCn64t3oyBTw7kWoYrWZIp7Ek9quC6HHVCNCDiHqAEkwwrOBAGBOmiVg64cIIxokNuyE9sn+KBjRALo1ueAfohNMiWOU8yWGB9TyGWeieLJqUK5OuhXr9TVtJAAAgT/3feP6C5ZhVNppz0lx2HR6KDnr7GoPSizmwfiH9yDvDdhw3iyBuwY3dlt9sIjUWNEJ2GqGLbAp30NTu7fFcN8yPx/DkTGtYlnfhg76RZOopKR0bekUaIWRttoJXCaENG1x7FyHXwrEbaVOivuryDedHNcHMwr+zeaY3tNe25/3MmGuDGZHhd7Ik75IurlDsCk9qXTjVuSJcu9BtOkbQUrsfbmM6B9tssSNa8W6QLT3E42jnDgxnO0VLM3mGH9dLwXR7BN7bc6cnfYIaFf a2G/OmkL bRdBc+oA5O9SWvOoj+YrhfJ4edhSDQyPhET9P3RIHeOYJZK8b0apNjv541RNSCrbOwu7NNVo0auYMOZxd4n4+JsY3TUeYldCrxYs9Jolb7FBK54MBLEw/1RscbVcA4SDZRJx+6L2Je8GqQJGN6KGmPSERFi39+RYPuaonyVhEECFwVuRsBx4JQhdLVz4CdniRYbuS2/p/3rIKebEsSauUcAnn1NCHb7HLOJJmUoUfW1Yvr6eulTiFOTYvODON2iUIjsjQJxOhqAQUa5qC0d84zJEOwl3Uv/1vdC3omPhNZ/n0v8QMqPZijfI5oYLgzNhudmxGo7hyDTM2d+aDg6Udc2cmmUfSFseQArfiDVx+W1h/wQM= 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/write_issue.c | 5 ++--- include/linux/netfs.h | 2 +- 3 files changed, 17 insertions(+), 4 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/write_issue.c b/fs/netfs/write_issue.c index 43cec03c6514..87a5aeb77073 100644 --- a/fs/netfs/write_issue.c +++ b/fs/netfs/write_issue.c @@ -280,6 +280,7 @@ static 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 || @@ -421,7 +422,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) || @@ -429,7 +429,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; } } @@ -459,10 +458,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 be1686f0fe34..d34ef6beed62 100644 --- a/include/linux/netfs.h +++ b/include/linux/netfs.h @@ -137,7 +137,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 */