Message ID | 20240212163101.19614-6-mathieu.desnoyers@efficios.com |
---|---|
State | New |
Headers |
Return-Path: <linux-kernel+bounces-61984-ouuuleilei=gmail.com@vger.kernel.org> Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:7300:bc8a:b0:106:860b:bbdd with SMTP id dn10csp33103dyb; Mon, 12 Feb 2024 08:39:20 -0800 (PST) X-Forwarded-Encrypted: i=3; AJvYcCWzr4CHYI34haAuPsEXBv77KsXtKyrQwYTeDhka4H896noVq/BpaTQxkQdltX2stLLFYEQj5UByNuDhQpXcOuQnU4x85A== X-Google-Smtp-Source: AGHT+IG+M/bDd/y9lIRfLIi1MsrH2isgvDuk3S9VrW3GqBQUhxFEHXZVglu6tfBEc2seldIMEKjM X-Received: by 2002:a17:907:20a8:b0:a3b:f72d:9c2b with SMTP id pw8-20020a17090720a800b00a3bf72d9c2bmr5411609ejb.39.1707755960176; Mon, 12 Feb 2024 08:39:20 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1707755960; cv=pass; d=google.com; s=arc-20160816; b=P2R3deFb9Q7+KD62eG2Zzw4X8vK0DLOZ1rwT45eiowFeJBQH9JYIX3QkH7W9B2PtrR /P0EmfeatAFCZd4rXl6TxvhbDg+9SuH93uKG6y8xmKQ4hf6pidXNZ6AqGhWprAjzyqL4 +Ems4eijxUQHq63kHMnxbXqJyfmRBTJ0Lt4Aw5I0ppd60MQQ/lIuol1E3zdQUMI7P0oN B3sbfCIgrnDoTkUupREjI6VpFtzfeZfZwG0NOl6BqeR7ExMXGutmVTegVga9nem+tb0Z Dy0V8UFr3SqGn8VYDwgULJW/lC0sAIwvd8n2c4Ng6NcoYGs8cXNxyMRVGvB3Y035UBJH /lXg== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:list-unsubscribe :list-subscribe:list-id:precedence:references:in-reply-to:message-id :date:subject:cc:to:from:dkim-signature; bh=LrfbZ9w6kDnIojd6eWFMBZSElaByAfgavWve+3WLmSw=; fh=d4jGx+DJ1kcLAuzbQyAC1NJeLxVxKTTtO2W7WKf5gxk=; b=gtRWjIkZqE2QTIEseaYFdmXhsbWGc0rbw1XX0ncC2ecqP8IsRHmckWMdg/gAFqRdHf fJC5ipVwroCcM0YLnSjBKrmpcpHKOgPgXlImBA/mwzl/4Jss5P3NPY2Vfg2dg/EabUwo 7MQ7yxBB1KRBOqIWUTmTIHekzJEuHnpwsK0NkghlaIjPZKnHTT69iuIqw3OJCmNg7z03 saIHBT+n042bjJI8GvjPScoiqqKOH1s7EKOkq0QvoHYnMpQl1PBvtVexlEZGytMGdjQz XbRjY6GBDT34HJsGjL3giBS/AIXz6sQhRvUagP4xMGdrhX+sJQ950OvoXZspHsjG+KVX FQyw==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@efficios.com header.s=smtpout1 header.b="B/pnnO95"; arc=pass (i=1 spf=pass spfdomain=efficios.com dkim=pass dkdomain=efficios.com dmarc=pass fromdomain=efficios.com); spf=pass (google.com: domain of linux-kernel+bounces-61984-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:4601:e00::3 as permitted sender) smtp.mailfrom="linux-kernel+bounces-61984-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=efficios.com X-Forwarded-Encrypted: i=2; AJvYcCU77PKTSvz5wfanufq/ewALOxIBuuhFjLAkO4SiVhLZ0ZWg3GmzrVrKRVk/d6K3qGxbGrR142d7lZoLR+EpiY+8mK/vBA== Received: from am.mirrors.kernel.org (am.mirrors.kernel.org. [2604:1380:4601:e00::3]) by mx.google.com with ESMTPS id f5-20020a170906560500b00a3c20791506si338686ejq.341.2024.02.12.08.39.19 for <ouuuleilei@gmail.com> (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 12 Feb 2024 08:39:20 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-61984-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:4601:e00::3 as permitted sender) client-ip=2604:1380:4601:e00::3; Authentication-Results: mx.google.com; dkim=pass header.i=@efficios.com header.s=smtpout1 header.b="B/pnnO95"; arc=pass (i=1 spf=pass spfdomain=efficios.com dkim=pass dkdomain=efficios.com dmarc=pass fromdomain=efficios.com); spf=pass (google.com: domain of linux-kernel+bounces-61984-ouuuleilei=gmail.com@vger.kernel.org designates 2604:1380:4601:e00::3 as permitted sender) smtp.mailfrom="linux-kernel+bounces-61984-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=efficios.com Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by am.mirrors.kernel.org (Postfix) with ESMTPS id C6B8F1F23A60 for <ouuuleilei@gmail.com>; Mon, 12 Feb 2024 16:39:19 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id B8FA5524AC; Mon, 12 Feb 2024 16:31:12 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=efficios.com header.i=@efficios.com header.b="B/pnnO95" Received: from smtpout.efficios.com (smtpout.efficios.com [167.114.26.122]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1DF2D1E89B; Mon, 12 Feb 2024 16:31:06 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=167.114.26.122 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1707755469; cv=none; b=lDWtFfPg9KZIwmsHSNJfjZLhljHu3wHebo/3EjIRnC5KlBijSBpxB4ha5IBNpylScIyppX6GuR8iC466a8kn15QbGDRGnMBuVG+gHrYG8RGVs88zQDeRYrvga/4ao+WTWnpUI4cnOKw8qEzNr4SUVVTma1sxylbah5LbydPpk38= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1707755469; c=relaxed/simple; bh=/grdS8Lpv8iOI39Sws5KokxIBSxOa0HOFRuTqUntpHw=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=SKr3mM+e3CGSAV7KRx240uyfox096oO/YRcDaGbRSCKN5X96mWtTupPWUKNgK1SsXsNJ54AurVR5D9J/dLR4tHg/38twq66zf5g4Ud1AgaqpX8pKHg+D6zFfvpgx97uge0ESd+B85y9KVEZ1uFkLMWCM/WoCBubIFK0WFIaUMSk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=efficios.com; spf=pass smtp.mailfrom=efficios.com; dkim=pass (2048-bit key) header.d=efficios.com header.i=@efficios.com header.b=B/pnnO95; arc=none smtp.client-ip=167.114.26.122 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=efficios.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=efficios.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=efficios.com; s=smtpout1; t=1707755465; bh=/grdS8Lpv8iOI39Sws5KokxIBSxOa0HOFRuTqUntpHw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=B/pnnO95L1htB3hWWCF4AF8YB2ZjXV07XWuDFRuNTVg9v/lCje1jgMnLoFbNO/rkr l83/diGRpiByxq3cGzsx1L01iER9LPjT73JHfiI9hLUTgB8++idtYRY1VGF0vKZYbG MQXDKfayzT9Nb7t2SUnoFVE3ci4tnEMHm2bcA57ycTxSieBqyrz3tpFzi8TjsMfGxQ O3lr2cR3pWBPK4+6Eb+d/efb8ER8prBbyRRucJ5UkXiULs6b6sshscN9zB/HkWGm8a cEJbx86f7+QkM3fNR2e1Whfi3EPzdnGG8qLQaVs6kZD7GvN1u9pfj5r7L/QWqQp25H k9nmoHUHNr+kw== Received: from thinkos.internal.efficios.com (192-222-143-198.qc.cable.ebox.net [192.222.143.198]) by smtpout.efficios.com (Postfix) with ESMTPSA id 4TYVMF1V3MzXxh; Mon, 12 Feb 2024 11:31:05 -0500 (EST) From: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> To: Dan Williams <dan.j.williams@intel.com>, Arnd Bergmann <arnd@arndb.de>, Dave Chinner <david@fromorbit.com> Cc: linux-kernel@vger.kernel.org, Mathieu Desnoyers <mathieu.desnoyers@efficios.com>, Andrew Morton <akpm@linux-foundation.org>, Linus Torvalds <torvalds@linux-foundation.org>, Vishal Verma <vishal.l.verma@intel.com>, Dave Jiang <dave.jiang@intel.com>, Matthew Wilcox <willy@infradead.org>, Russell King <linux@armlinux.org.uk>, linux-arch@vger.kernel.org, linux-cxl@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, linux-xfs@vger.kernel.org, dm-devel@lists.linux.dev, nvdimm@lists.linux.dev, linux-s390@vger.kernel.org, Alasdair Kergon <agk@redhat.com>, Mike Snitzer <snitzer@kernel.org>, Mikulas Patocka <mpatocka@redhat.com> Subject: [PATCH v5 5/8] virtio: Treat alloc_dax() -EOPNOTSUPP failure as non-fatal Date: Mon, 12 Feb 2024 11:30:58 -0500 Message-Id: <20240212163101.19614-6-mathieu.desnoyers@efficios.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20240212163101.19614-1-mathieu.desnoyers@efficios.com> References: <20240212163101.19614-1-mathieu.desnoyers@efficios.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: <linux-kernel.vger.kernel.org> List-Subscribe: <mailto:linux-kernel+subscribe@vger.kernel.org> List-Unsubscribe: <mailto:linux-kernel+unsubscribe@vger.kernel.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1790711913642346347 X-GMAIL-MSGID: 1790711913642346347 |
Series |
Introduce cpu_dcache_is_aliasing() to fix DAX regression
|
|
Commit Message
Mathieu Desnoyers
Feb. 12, 2024, 4:30 p.m. UTC
In preparation for checking whether the architecture has data cache aliasing within alloc_dax(), modify the error handling of virtio virtio_fs_setup_dax() to treat alloc_dax() -EOPNOTSUPP failure as non-fatal. Co-developed-by: Dan Williams <dan.j.williams@intel.com> Signed-off-by: Dan Williams <dan.j.williams@intel.com> Fixes: d92576f1167c ("dax: does not work correctly with virtual aliasing caches") Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> Cc: Alasdair Kergon <agk@redhat.com> Cc: Mike Snitzer <snitzer@kernel.org> Cc: Mikulas Patocka <mpatocka@redhat.com> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Dan Williams <dan.j.williams@intel.com> Cc: Vishal Verma <vishal.l.verma@intel.com> Cc: Dave Jiang <dave.jiang@intel.com> Cc: Matthew Wilcox <willy@infradead.org> Cc: Arnd Bergmann <arnd@arndb.de> Cc: Russell King <linux@armlinux.org.uk> Cc: linux-arch@vger.kernel.org Cc: linux-cxl@vger.kernel.org Cc: linux-fsdevel@vger.kernel.org Cc: linux-mm@kvack.org Cc: linux-xfs@vger.kernel.org Cc: dm-devel@lists.linux.dev Cc: nvdimm@lists.linux.dev --- fs/fuse/virtio_fs.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-)
Comments
Mathieu Desnoyers wrote: > In preparation for checking whether the architecture has data cache > aliasing within alloc_dax(), modify the error handling of virtio > virtio_fs_setup_dax() to treat alloc_dax() -EOPNOTSUPP failure as > non-fatal. > > Co-developed-by: Dan Williams <dan.j.williams@intel.com> > Signed-off-by: Dan Williams <dan.j.williams@intel.com> > Fixes: d92576f1167c ("dax: does not work correctly with virtual aliasing caches") > Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> > Cc: Alasdair Kergon <agk@redhat.com> > Cc: Mike Snitzer <snitzer@kernel.org> > Cc: Mikulas Patocka <mpatocka@redhat.com> > Cc: Andrew Morton <akpm@linux-foundation.org> > Cc: Linus Torvalds <torvalds@linux-foundation.org> > Cc: Dan Williams <dan.j.williams@intel.com> > Cc: Vishal Verma <vishal.l.verma@intel.com> > Cc: Dave Jiang <dave.jiang@intel.com> > Cc: Matthew Wilcox <willy@infradead.org> > Cc: Arnd Bergmann <arnd@arndb.de> > Cc: Russell King <linux@armlinux.org.uk> > Cc: linux-arch@vger.kernel.org > Cc: linux-cxl@vger.kernel.org > Cc: linux-fsdevel@vger.kernel.org > Cc: linux-mm@kvack.org > Cc: linux-xfs@vger.kernel.org > Cc: dm-devel@lists.linux.dev > Cc: nvdimm@lists.linux.dev > --- > fs/fuse/virtio_fs.c | 15 +++++++++++---- > 1 file changed, 11 insertions(+), 4 deletions(-) > > diff --git a/fs/fuse/virtio_fs.c b/fs/fuse/virtio_fs.c > index 5f1be1da92ce..f9acd9972af2 100644 > --- a/fs/fuse/virtio_fs.c > +++ b/fs/fuse/virtio_fs.c > @@ -16,6 +16,7 @@ > #include <linux/fs_context.h> > #include <linux/fs_parser.h> > #include <linux/highmem.h> > +#include <linux/cleanup.h> > #include <linux/uio.h> > #include "fuse_i.h" > > @@ -795,8 +796,11 @@ static void virtio_fs_cleanup_dax(void *data) > put_dax(dax_dev); > } > > +DEFINE_FREE(cleanup_dax, struct dax_dev *, if (!IS_ERR(_T)) virtio_fs_cleanup_dax(_T)) > + > static int virtio_fs_setup_dax(struct virtio_device *vdev, struct virtio_fs *fs) > { > + struct dax_device *dax_dev __free(cleanup_dax) = ERR_PTR(-EOPNOTSUPP); > struct virtio_shm_region cache_reg; > struct dev_pagemap *pgmap; > bool have_cache; > @@ -804,6 +808,12 @@ static int virtio_fs_setup_dax(struct virtio_device *vdev, struct virtio_fs *fs) > if (!IS_ENABLED(CONFIG_FUSE_DAX)) > return 0; > > + dax_dev = alloc_dax(fs, &virtio_fs_dax_ops); > + if (IS_ERR(dax_dev)) { > + int rc = PTR_ERR(dax_dev); > + return rc == -EOPNOTSUPP ? 0 : rc; > + } > + > /* Get cache region */ > have_cache = virtio_get_shm_region(vdev, &cache_reg, > (u8)VIRTIO_FS_SHMCAP_ID_CACHE); > @@ -849,10 +859,7 @@ static int virtio_fs_setup_dax(struct virtio_device *vdev, struct virtio_fs *fs) > dev_dbg(&vdev->dev, "%s: window kaddr 0x%px phys_addr 0x%llx len 0x%llx\n", > __func__, fs->window_kaddr, cache_reg.addr, cache_reg.len); > > - fs->dax_dev = alloc_dax(fs, &virtio_fs_dax_ops); > - if (IS_ERR(fs->dax_dev)) > - return PTR_ERR(fs->dax_dev); > - > + fs->dax_dev = no_free_ptr(dax_dev); This works because the internals of virtio_fs_cleanup_dax(), "kill_dax() and put_dax()", know how to handle a NULL @dax_dev. It is still early days with the "cleanup" helpers, but I wonder if anyone else cares that the DEFINE_FREE() above does not check for NULL? I think it is ok, but wanted to point that out for the virtiofs folks and wonder what the style should be for things like this going forward. Other growing pains with "cleanup.h" and ERR_PTR is happening over here: http://lore.kernel.org/r/65ca861e14779_5a7f2949e@dwillia2-xfh.jf.intel.com.notmuch ..and that arrived at a similar style as is being used in this patch. In both cases the cleanup function is called on exit with a NULL argument.
On Mon, 12 Feb 2024 at 14:04, Dan Williams <dan.j.williams@intel.com> wrote: > > This works because the internals of virtio_fs_cleanup_dax(), "kill_dax() > and put_dax()", know how to handle a NULL @dax_dev. It is still early > days with the "cleanup" helpers, but I wonder if anyone else cares that > the DEFINE_FREE() above does not check for NULL? Well, the main reason for DEFINE_FREE() to check for NULL is not correctness, but code generation. See the comment about kfree() in <linux/cleanup.h>: * NOTE: the DEFINE_FREE()'s @free expression includes a NULL test even though * kfree() is fine to be called with a NULL value. This is on purpose. This way * the compiler sees the end of our alloc_obj() function as [...] with the full explanation there. Now, whether the code wants to actually use the cleanup() helpers for a single use-case is debatable. But yes, if it does, I suspect it should use !IS_ERR_OR_NULL(ptr). Linus
[ add Lukas ] Linus Torvalds wrote: > On Mon, 12 Feb 2024 at 14:04, Dan Williams <dan.j.williams@intel.com> wrote: > > > > This works because the internals of virtio_fs_cleanup_dax(), "kill_dax() > > and put_dax()", know how to handle a NULL @dax_dev. It is still early > > days with the "cleanup" helpers, but I wonder if anyone else cares that > > the DEFINE_FREE() above does not check for NULL? > > Well, the main reason for DEFINE_FREE() to check for NULL is not > correctness, but code generation. See the comment about kfree() in > <linux/cleanup.h>: > > * NOTE: the DEFINE_FREE()'s @free expression includes a NULL test even though > * kfree() is fine to be called with a NULL value. This is on purpose. This way > * the compiler sees the end of our alloc_obj() function as [...] > > with the full explanation there. > > Now, whether the code wants to actually use the cleanup() helpers for > a single use-case is debatable. > > But yes, if it does, I suspect it should use !IS_ERR_OR_NULL(ptr).o I am trying to arrive at a common recommendation given Lukas found that IS_ERR_OR_NULL() resulted in unwanted NULL checks emitted in the assembly [1]. He is doing something similar: http://lore.kernel.org/r/4143b15418c4ecf87ddeceb36813943c3ede17aa.1707734526.git.lukas@wunner.de ..and introduced an assume() helper. However, Lukas, I think Linus is right, your DEFINE_FREE() should use IS_ERR_OR_NULL(). I.e. the problem is trying to use __free(x509_free_certificate) in x509_cert_parse(). > --- a/crypto/asymmetric_keys/x509_cert_parser.c > +++ b/crypto/asymmetric_keys/x509_cert_parser.c > @@ -60,24 +60,24 @@ void x509_free_certificate(struct x509_certificate *cert) > */ > struct x509_certificate *x509_cert_parse(const void *data, size_t datalen) > { > - struct x509_certificate *cert; > - struct x509_parse_context *ctx; > + struct x509_certificate *cert __free(x509_free_certificate); ..make this: struct x509_certificate *cert __free(kfree); ..and Mathieu, this should be IS_ERR_OR_NULL() to skip an unnecessary call to virtio_fs_cleanup_dax() at function exit that the compiler should elide.
On Mon, Feb 12, 2024 at 03:02:46PM -0800, Dan Williams wrote: > However, Lukas, I think Linus is right, your DEFINE_FREE() should use > IS_ERR_OR_NULL(). Uh... that's a negative, sir. ;) IS_ERR_OR_NULL() results in... * a superfluous NULL pointer check in x509_key_preparse() and * a superfluous IS_ERR check in x509_cert_parse(). IS_ERR() results *only* in... * a superfluous IS_ERR check in x509_cert_parse(). I can get rid of the IS_ERR() check by using assume(). I can *not* get rid of the NULL pointer check because the compiler is compiled with -fno-delete-null-pointer-checks. (The compiler seems to ignore __attribute__((returns_nonnull)) due to that.) > I.e. the problem is trying to use > __free(x509_free_certificate) in x509_cert_parse(). > > > --- a/crypto/asymmetric_keys/x509_cert_parser.c > > +++ b/crypto/asymmetric_keys/x509_cert_parser.c > > @@ -60,24 +60,24 @@ void x509_free_certificate(struct x509_certificate *cert) > > */ > > struct x509_certificate *x509_cert_parse(const void *data, size_t datalen) > > { > > - struct x509_certificate *cert; > > - struct x509_parse_context *ctx; > > + struct x509_certificate *cert __free(x509_free_certificate); > > ...make this: > > struct x509_certificate *cert __free(kfree); That doesn't work I'm afraid. x509_cert_parse() needs x509_free_certificate() to be called in the error path, not kfree(). See the existing code in current mainline: x509_cert_parse() populates three sub-allocations in struct x509_certificate (pub, sig, id) and two sub-sub-allocations (pub->key, pub->params). So I'd have to add five additional local variables which get freed by __cleanup(). One of them (pub->key) requires kfree_sensitive() instead of kfree(), so I'd need an extra DEFINE_FREE() for that. I haven't tried it but I suspect the result would look terrible and David Howells wouldn't like it. > ...and Mathieu, this should be IS_ERR_OR_NULL() to skip an unnecessary > call to virtio_fs_cleanup_dax() at function exit that the compiler > should elide. My recommendation is to check for !IS_ERR() in the DEFINE_FREE() clause and amend virtio_fs_cleanup_dax() with a "if (!dax_dev) return;" for defensiveness in case someone calls it with a NULL pointer. That's the best solution I could come up with for the x509_certificate conversion. Note that even with superfluous checks avoided, __cleanup() causes gcc-12 to always generate two return paths. It's very visible in the generated code that all the stack unwinding code gets duplicated in every function using __cleanup(). The existing Assembler code of x509_key_preparse() and x509_cert_parse(), without __cleanup() invocation, has only a single return path. So __cleanup() bloats the code regardless of superfluous checks, but future gcc versions might avoid that. clang-15 generates much more compact code (vmlinux is a couple hundred kBytes smaller), but does weird things such as inlining x509_free_certificate() in x509_cert_parse(). As you may have guessed, I've spent an inordinate amount of time down that rabbit hole. ;( Thanks, Lukas
On Mon, Feb 12, 2024 at 11:30:58AM -0500, Mathieu Desnoyers wrote: > In preparation for checking whether the architecture has data cache > aliasing within alloc_dax(), modify the error handling of virtio > virtio_fs_setup_dax() to treat alloc_dax() -EOPNOTSUPP failure as > non-fatal. > > Co-developed-by: Dan Williams <dan.j.williams@intel.com> > Signed-off-by: Dan Williams <dan.j.williams@intel.com> > Fixes: d92576f1167c ("dax: does not work correctly with virtual aliasing caches") That's a v4.0 commit, yet this patch uses DEFINE_FREE() which is only available in v6.6 but not any earlier stable kernels. So the Fixes tag feels a bit weird. Apart from that, Reviewed-by: Lukas Wunner <lukas@wunner.de>
Lukas Wunner wrote: > On Mon, Feb 12, 2024 at 03:02:46PM -0800, Dan Williams wrote: > > However, Lukas, I think Linus is right, your DEFINE_FREE() should use > > IS_ERR_OR_NULL(). > > Uh... that's a negative, sir. ;) > > IS_ERR_OR_NULL() results in... > * a superfluous NULL pointer check in x509_key_preparse() and > * a superfluous IS_ERR check in x509_cert_parse(). > > IS_ERR() results *only* in... > * a superfluous IS_ERR check in x509_cert_parse(). > > I can get rid of the IS_ERR() check by using assume(). > > I can *not* get rid of the NULL pointer check because the compiler > is compiled with -fno-delete-null-pointer-checks. (The compiler > seems to ignore __attribute__((returns_nonnull)) due to that.) > > > > I.e. the problem is trying to use > > __free(x509_free_certificate) in x509_cert_parse(). > > > > > --- a/crypto/asymmetric_keys/x509_cert_parser.c > > > +++ b/crypto/asymmetric_keys/x509_cert_parser.c > > > @@ -60,24 +60,24 @@ void x509_free_certificate(struct x509_certificate *cert) > > > */ > > > struct x509_certificate *x509_cert_parse(const void *data, size_t datalen) > > > { > > > - struct x509_certificate *cert; > > > - struct x509_parse_context *ctx; > > > + struct x509_certificate *cert __free(x509_free_certificate); > > > > ...make this: > > > > struct x509_certificate *cert __free(kfree); > > That doesn't work I'm afraid. x509_cert_parse() needs > x509_free_certificate() to be called in the error path, > not kfree(). See the existing code in current mainline: > > x509_cert_parse() populates three sub-allocations in > struct x509_certificate (pub, sig, id) and two > sub-sub-allocations (pub->key, pub->params). > > So I'd have to add five additional local variables which > get freed by __cleanup(). One of them (pub->key) requires > kfree_sensitive() instead of kfree(), so I'd need an extra > DEFINE_FREE() for that. > > I haven't tried it but I suspect the result would look > terrible and David Howells wouldn't like it. Ugh, that's what I was afraid of, so these cases are different. > > ...and Mathieu, this should be IS_ERR_OR_NULL() to skip an unnecessary > > call to virtio_fs_cleanup_dax() at function exit that the compiler > > should elide. > > My recommendation is to check for !IS_ERR() in the DEFINE_FREE() clause > and amend virtio_fs_cleanup_dax() with a "if (!dax_dev) return;" for > defensiveness in case someone calls it with a NULL pointer. The internal calls (kill_dax(), put_dax()) check for NULL already, so I don't think that's needed. > That's the best solution I could come up with for the x509_certificate > conversion. > > Note that even with superfluous checks avoided, __cleanup() causes > gcc-12 to always generate two return paths. It's very visible in > the generated code that all the stack unwinding code gets duplicated > in every function using __cleanup(). The existing Assembler code > of x509_key_preparse() and x509_cert_parse(), without __cleanup() > invocation, has only a single return path. I saw that too, some NULL checks can indeed be elided with a NULL check in the DEFINE_FREE(), but the multiple exit paths still someimtes result in __cleanup() using functions being larger than the goto equivalent. > So __cleanup() bloats the code regardless of superfluous checks, > but future gcc versions might avoid that. clang-15 generates much > more compact code (vmlinux is a couple hundred kBytes smaller), > but does weird things such as inlining x509_free_certificate() > in x509_cert_parse(). > > As you may have guessed, I've spent an inordinate amount of time > down that rabbit hole. ;( Hey, this is new and interesting stuff, glad we are grappling with it at this level.
On 2024-02-13 01:25, Lukas Wunner wrote: > On Mon, Feb 12, 2024 at 11:30:58AM -0500, Mathieu Desnoyers wrote: >> In preparation for checking whether the architecture has data cache >> aliasing within alloc_dax(), modify the error handling of virtio >> virtio_fs_setup_dax() to treat alloc_dax() -EOPNOTSUPP failure as >> non-fatal. >> >> Co-developed-by: Dan Williams <dan.j.williams@intel.com> >> Signed-off-by: Dan Williams <dan.j.williams@intel.com> >> Fixes: d92576f1167c ("dax: does not work correctly with virtual aliasing caches") > > That's a v4.0 commit, yet this patch uses DEFINE_FREE() which is > only available in v6.6 but not any earlier stable kernels. I asked this question to Greg KH before creating this patch, and his answer was to implement my fix for master, and stable kernels would take care of backporting all the required dependencies. Now if I look at latest 6.1, 5.15, 5.10, 5.4, 4.19 stable kernels, none seem to have include/linux/cleanup.h today. But I suspect that sooner or later relevant master branch fixes will require stable kernels to backport cleanup.h, so why not do it now ? Thanks, Mathieu > > So the Fixes tag feels a bit weird. > > Apart from that, > Reviewed-by: Lukas Wunner <lukas@wunner.de>
On 2024-02-12 18:02, Dan Williams wrote: [...] > ...and Mathieu, this should be IS_ERR_OR_NULL() to skip an unnecessary > call to virtio_fs_cleanup_dax() at function exit that the compiler > should elide. OK, so I'll go back to the previous approach for v6: DEFINE_FREE(cleanup_dax, struct dax_dev *, if (!IS_ERR_OR_NULL(_T)) virtio_fs_cleanup_dax(_T)) and define the variable as: struct dax_device *dax_dev __free(cleanup_dax) = NULL; Thanks, Mathieu
On Tue, Feb 13, 2024 at 02:46:05PM -0500, Mathieu Desnoyers wrote: > On 2024-02-13 01:25, Lukas Wunner wrote: > > On Mon, Feb 12, 2024 at 11:30:58AM -0500, Mathieu Desnoyers wrote: > > > In preparation for checking whether the architecture has data cache > > > aliasing within alloc_dax(), modify the error handling of virtio > > > virtio_fs_setup_dax() to treat alloc_dax() -EOPNOTSUPP failure as > > > non-fatal. > > > > > > Co-developed-by: Dan Williams <dan.j.williams@intel.com> > > > Signed-off-by: Dan Williams <dan.j.williams@intel.com> > > > Fixes: d92576f1167c ("dax: does not work correctly with virtual aliasing caches") > > > > That's a v4.0 commit, yet this patch uses DEFINE_FREE() which is > > only available in v6.6 but not any earlier stable kernels. > > I asked this question to Greg KH before creating this patch, and his > answer was to implement my fix for master, and stable kernels would take > care of backporting all the required dependencies. That is correct. > Now if I look at latest 6.1, 5.15, 5.10, 5.4, 4.19 stable kernels, > none seem to have include/linux/cleanup.h today. But I suspect that > sooner or later relevant master branch fixes will require stable > kernels to backport cleanup.h, so why not do it now ? Yes, eventually we will need to backport cleanup.h to the older kernel trees, I know of many patches "in flight" that are using it, so it's not unique to this one at all, so this is fine to have. Remember, make changes for Linus's tree, don't go through any gyrations to make things special for stable releases, that's something to only consider later on, if you want to. stable kernels should have no affect on developers OTHER than a simple cc: stable tag on stuff that they know should be backported, unless they really want to do more than that, that's up to them. thanks, greg k-h
diff --git a/fs/fuse/virtio_fs.c b/fs/fuse/virtio_fs.c index 5f1be1da92ce..f9acd9972af2 100644 --- a/fs/fuse/virtio_fs.c +++ b/fs/fuse/virtio_fs.c @@ -16,6 +16,7 @@ #include <linux/fs_context.h> #include <linux/fs_parser.h> #include <linux/highmem.h> +#include <linux/cleanup.h> #include <linux/uio.h> #include "fuse_i.h" @@ -795,8 +796,11 @@ static void virtio_fs_cleanup_dax(void *data) put_dax(dax_dev); } +DEFINE_FREE(cleanup_dax, struct dax_dev *, if (!IS_ERR(_T)) virtio_fs_cleanup_dax(_T)) + static int virtio_fs_setup_dax(struct virtio_device *vdev, struct virtio_fs *fs) { + struct dax_device *dax_dev __free(cleanup_dax) = ERR_PTR(-EOPNOTSUPP); struct virtio_shm_region cache_reg; struct dev_pagemap *pgmap; bool have_cache; @@ -804,6 +808,12 @@ static int virtio_fs_setup_dax(struct virtio_device *vdev, struct virtio_fs *fs) if (!IS_ENABLED(CONFIG_FUSE_DAX)) return 0; + dax_dev = alloc_dax(fs, &virtio_fs_dax_ops); + if (IS_ERR(dax_dev)) { + int rc = PTR_ERR(dax_dev); + return rc == -EOPNOTSUPP ? 0 : rc; + } + /* Get cache region */ have_cache = virtio_get_shm_region(vdev, &cache_reg, (u8)VIRTIO_FS_SHMCAP_ID_CACHE); @@ -849,10 +859,7 @@ static int virtio_fs_setup_dax(struct virtio_device *vdev, struct virtio_fs *fs) dev_dbg(&vdev->dev, "%s: window kaddr 0x%px phys_addr 0x%llx len 0x%llx\n", __func__, fs->window_kaddr, cache_reg.addr, cache_reg.len); - fs->dax_dev = alloc_dax(fs, &virtio_fs_dax_ops); - if (IS_ERR(fs->dax_dev)) - return PTR_ERR(fs->dax_dev); - + fs->dax_dev = no_free_ptr(dax_dev); return devm_add_action_or_reset(&vdev->dev, virtio_fs_cleanup_dax, fs->dax_dev); }