From: Dan Carpenter <error27@gmail.com>
To: Nikolay Borisov <nborisov@suse.com>
Cc: linux-btrfs@vger.kernel.org
Subject: [bug report] btrfs: refactor __btrfs_run_delayed_refs loop
Date: Thu, 21 May 2026 15:53:25 +0300 [thread overview]
Message-ID: <ag8ARRwykv8bpJ87@stanley.mountain> (raw)
[ 8 year old code and no one has complained... It's surprising no
one has hit this in real life. - dan ]
Hello Nikolay Borisov,
Commit 0110a4c43451 ("btrfs: refactor __btrfs_run_delayed_refs loop")
from Aug 15, 2018 (linux-next), leads to the following Smatch static
checker warning:
fs/btrfs/extent-tree.c:2131 __btrfs_run_delayed_refs()
error: 'locked_ref' dereferencing possible ERR_PTR()
fs/btrfs/extent-tree.c
2084 static noinline int __btrfs_run_delayed_refs(struct btrfs_trans_handle *trans,
2085 u64 min_bytes)
2086 {
2087 struct btrfs_fs_info *fs_info = trans->fs_info;
2088 struct btrfs_delayed_ref_root *delayed_refs;
2089 struct btrfs_delayed_ref_head *locked_ref = NULL;
2090 int ret;
2091 unsigned long count = 0;
2092 unsigned long max_count = 0;
2093 u64 bytes_processed = 0;
2094
2095 delayed_refs = &trans->transaction->delayed_refs;
2096 if (min_bytes == 0) {
2097 /*
2098 * We may be subject to a harmless race if some task is
2099 * concurrently adding or removing a delayed ref, so silence
2100 * KCSAN and similar tools.
2101 */
2102 max_count = data_race(delayed_refs->num_heads_ready);
2103 min_bytes = U64_MAX;
2104 }
2105
2106 do {
2107 if (!locked_ref) {
2108 locked_ref = btrfs_select_ref_head(fs_info, delayed_refs);
2109 if (IS_ERR_OR_NULL(locked_ref)) {
2110 if (PTR_ERR(locked_ref) == -EAGAIN) {
2111 continue;
In the old we set "locked_ref = NULL" on this path and I think we
probably should restore that line. Now it looks like a crash.
2112 } else {
2113 break;
2114 }
2115 }
2116 count++;
2117 }
2118 /*
2119 * We need to try and merge add/drops of the same ref since we
2120 * can run into issues with relocate dropping the implicit ref
2121 * and then it being added back again before the drop can
2122 * finish. If we merged anything we need to re-loop so we can
2123 * get a good ref.
2124 * Or we can get node references of the same type that weren't
2125 * merged when created due to bumps in the tree mod seq, and
2126 * we need to merge them to prevent adding an inline extent
2127 * backref before dropping it (triggering a BUG_ON at
2128 * insert_inline_extent_backref()).
2129 */
2130 spin_lock(&locked_ref->lock);
^^^^^^^^^^^^^^^^
On the next iteration &locked_ref will be ERR_PTR(-EAGAIN).
--> 2131 btrfs_merge_delayed_refs(fs_info, delayed_refs, locked_ref);
2132
2133 ret = btrfs_run_delayed_refs_for_head(trans, locked_ref, &bytes_processed);
2134 if (ret < 0 && ret != -EAGAIN) {
2135 /*
2136 * Error, btrfs_run_delayed_refs_for_head already
2137 * unlocked everything so just bail out
2138 */
2139 return ret;
2140 } else if (!ret) {
2141 /*
2142 * Success, perform the usual cleanup of a processed
2143 * head
2144 */
2145 ret = cleanup_ref_head(trans, locked_ref, &bytes_processed);
2146 if (ret > 0 ) {
2147 /* We dropped our lock, we need to loop. */
2148 ret = 0;
2149 continue;
2150 } else if (ret) {
2151 return ret;
2152 }
2153 }
2154
2155 /*
2156 * Either success case or btrfs_run_delayed_refs_for_head
2157 * returned -EAGAIN, meaning we need to select another head
2158 */
2159
2160 locked_ref = NULL;
2161 cond_resched();
2162 } while ((min_bytes != U64_MAX && bytes_processed < min_bytes) ||
2163 (max_count > 0 && count < max_count) ||
2164 locked_ref);
^^^^^^^^^^
We continue down to here and loop back since locked_ref is -EAGAIN.
2165
2166 return 0;
2167 }
This email is a free service from the Smatch-CI project [smatch.sf.net].
regards,
dan carpenter
next reply other threads:[~2026-05-21 12:53 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-21 12:53 Dan Carpenter [this message]
2026-05-21 14:44 ` [bug report] btrfs: refactor __btrfs_run_delayed_refs loop Filipe Manana
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=ag8ARRwykv8bpJ87@stanley.mountain \
--to=error27@gmail.com \
--cc=linux-btrfs@vger.kernel.org \
--cc=nborisov@suse.com \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.