From: David Sterba <dsterba@suse.com>
To: linux-btrfs@vger.kernel.org
Cc: David Sterba <dsterba@suse.com>
Subject: [PATCH v2 1/2] btrfs: validate negative error number passed to btrfs_abort_transaction()
Date: Thu, 7 May 2026 19:59:31 +0200 [thread overview]
Message-ID: <922da1b5b5bb4daaa55df0be99e48b2685c67751.1778176579.git.dsterba@suse.com> (raw)
In-Reply-To: <cover.1778176579.git.dsterba@suse.com>
In preparation to encode more information to the error value add a step
that verifies if the value is valid (i.e. < 0). This works for
compile-time and runtime (in debugging mode).
The compile-time check recognizes direct constants and defines an array
type. An invalid condition leads to negative array size which is caught
by compiler.
The runtime check constructs the array type from the condition and only
verifies the correct size, as we don't need to tweak the size to be
negative.
The sizeof() expressions do not generate any code. In the debugging
config the warning adds about 9KiB of btrfs.ko code size.
The array size trick is needed as we can't use static_array(), not even
with __builtin_constant_p().
Sample error message:
In file included from inode.c:40:
inode.c: In function ‘__cow_file_range_inline’:
transaction.h:261:26: error: size of unnamed array is negative
261 | (void)sizeof(char[-!(__builtin_constant_p(error) ? (error) < 0 : 1)]); \
| ^
transaction.h:275:9: note: in expansion of macro ‘VERIFY_NEGATIVE_ERROR’
275 | VERIFY_NEGATIVE_ERROR(error); \
| ^~~~~~~~~~~~~~~~~~~~~
inode.c:665:17: note: in expansion of macro ‘btrfs_abort_transaction’
665 | btrfs_abort_transaction(trans, 17);
| ^~~~~~~~~~~~~~~~~~~~~~~
Signed-off-by: David Sterba <dsterba@suse.com>
---
fs/btrfs/transaction.h | 24 ++++++++++++++++++++++++
1 file changed, 24 insertions(+)
diff --git a/fs/btrfs/transaction.h b/fs/btrfs/transaction.h
index f1cb05460cec..72ab32c8ddca 100644
--- a/fs/btrfs/transaction.h
+++ b/fs/btrfs/transaction.h
@@ -242,6 +242,29 @@ static inline bool btrfs_abort_should_print_stack(int error)
return true;
}
+/*
+ * Compile-time and run-time verification of error passed to transaction abort.
+ * Direct constants will be caught at compile time, errors read from variables
+ * can be caught only at run-time and will warn under debugging config.
+ *
+ * How verification works:
+ * - accepted builtin constants are all -EIO and such
+ * - for compile-time check, invalid condition produces a negative-sized array
+ * type, valid zero-sized
+ * - when a variable is passed as error the first check is a no-op
+ * - with enabled debugging, the second array type size is constructed from the
+ * real variable value, valid condition produces array of size 1
+ * - sizeof(type) does not generate any code
+ */
+#define VERIFY_NEGATIVE_ERROR(error) \
+do { \
+ (void)sizeof(char[-!(__builtin_constant_p(error) ? (error) < 0 : 1)]); \
+ if (IS_ENABLED(CONFIG_BTRFS_DEBUG)) { \
+ if (sizeof(char[(error) < 0]) != 1) \
+ DEBUG_WARN("error >= 0 passed to btrfs_abort_transaction()"); \
+ } \
+} while(0)
+
/*
* Call btrfs_abort_transaction as early as possible when an error condition is
* detected, that way the exact stack trace is reported for some errors.
@@ -249,6 +272,7 @@ static inline bool btrfs_abort_should_print_stack(int error)
#define btrfs_abort_transaction(trans, error) \
do { \
bool __first = false; \
+ VERIFY_NEGATIVE_ERROR(error); \
/* Report first abort since mount */ \
if (!test_and_set_bit(BTRFS_FS_STATE_TRANS_ABORTED, \
&((trans)->fs_info->fs_state))) { \
--
2.53.0
next prev parent reply other threads:[~2026-05-07 18:00 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-07 17:59 [PATCH v2 0/2] Transaction abort macro optimizations David Sterba
2026-05-07 17:59 ` David Sterba [this message]
2026-05-07 17:59 ` [PATCH v2 2/2] btrfs: simplify how first hit is passed to __btrfs_abort_transaction() David Sterba
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=922da1b5b5bb4daaa55df0be99e48b2685c67751.1778176579.git.dsterba@suse.com \
--to=dsterba@suse.com \
--cc=linux-btrfs@vger.kernel.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