All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/2] btrfs: fix incorrect barrier usage in relocation
@ 2026-06-12 12:13 fdmanana
  2026-06-12 12:13 ` [PATCH 1/2] btrfs: fix reloc root cleanup in merge_reloc_roots() fdmanana
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: fdmanana @ 2026-06-12 12:13 UTC (permalink / raw)
  To: linux-btrfs

From: Filipe Manana <fdmanana@suse.com>

Sashiko recently detected we are not correctly using memory barriers
in the relocation code, and these patches address that. Details in
the change logs.

Filipe Manana (2):
  btrfs: fix reloc root cleanup in merge_reloc_roots()
  btrfs: fix memory barrier order in reloc_root_is_dead()

 fs/btrfs/relocation.c | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

-- 
2.47.2


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 1/2] btrfs: fix reloc root cleanup in merge_reloc_roots()
  2026-06-12 12:13 [PATCH 0/2] btrfs: fix incorrect barrier usage in relocation fdmanana
@ 2026-06-12 12:13 ` fdmanana
  2026-06-12 12:13 ` [PATCH 2/2] btrfs: fix memory barrier order in reloc_root_is_dead() fdmanana
  2026-06-12 17:28 ` [PATCH 0/2] btrfs: fix incorrect barrier usage in relocation Boris Burkov
  2 siblings, 0 replies; 7+ messages in thread
From: fdmanana @ 2026-06-12 12:13 UTC (permalink / raw)
  To: linux-btrfs

From: Filipe Manana <fdmanana@suse.com>

If the root we got has zero root refs in its root item, we are resetting
the root's ->reloc_root without using barriers like we do everywhere else.
Sashiko complained about this while reviewing another patch, and it's
correct (see the Link tag below).

Also, we should not clear BTRFS_ROOT_DEAD_RELOC_TREE from the root unless
the root points to the reloc root we have.

Fix this by using clear_reloc_root(), which issues the memory barrier
after setting the root's ->reloc_root to NULL and before clearing the bit
BTRFS_ROOT_DEAD_RELOC_TREE from the root.

Link: https://sashiko.dev/#/patchset/cf84f1a217c719e25b6b69e4298dd7afd36c9427.1781194426.git.fdmanana%40suse.com
Signed-off-by: Filipe Manana <fdmanana@suse.com>
---
 fs/btrfs/relocation.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c
index 74687c75f763..6b5a59cb21bb 100644
--- a/fs/btrfs/relocation.c
+++ b/fs/btrfs/relocation.c
@@ -1950,11 +1950,10 @@ void merge_reloc_roots(struct reloc_control *rc)
 		} else {
 			if (!IS_ERR(root)) {
 				if (root->reloc_root == reloc_root) {
-					root->reloc_root = NULL;
+					clear_reloc_root(root);
+					/* Drop the ref for root->reloc_root. */
 					btrfs_put_root(reloc_root);
 				}
-				clear_bit(BTRFS_ROOT_DEAD_RELOC_TREE,
-					  &root->state);
 				btrfs_put_root(root);
 			}
 
-- 
2.47.2


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 2/2] btrfs: fix memory barrier order in reloc_root_is_dead()
  2026-06-12 12:13 [PATCH 0/2] btrfs: fix incorrect barrier usage in relocation fdmanana
  2026-06-12 12:13 ` [PATCH 1/2] btrfs: fix reloc root cleanup in merge_reloc_roots() fdmanana
@ 2026-06-12 12:13 ` fdmanana
  2026-06-12 19:13   ` kernel test robot
  2026-06-12 20:45   ` kernel test robot
  2026-06-12 17:28 ` [PATCH 0/2] btrfs: fix incorrect barrier usage in relocation Boris Burkov
  2 siblings, 2 replies; 7+ messages in thread
From: fdmanana @ 2026-06-12 12:13 UTC (permalink / raw)
  To: linux-btrfs

From: Filipe Manana <fdmanana@suse.com>

When we set a root's reloc_root to NULL, we do it like this:

   static void clear_reloc_root(struct btrfs_root *root)
   {
       root->reloc_root = NULL;
       /*
        * Need barrier to ensure clear_bit() only happens after
        * root->reloc_root = NULL. Pairs with have_reloc_root().
        */
        smp_wmb();
        clear_bit(BTRFS_ROOT_DEAD_RELOC_TREE, &root->state);
   }

So that a NULL reloc_root is always seen before seeing that the bit
BTRFS_ROOT_DEAD_RELOC_TREE was cleared.

But on the read side we have:

   static bool reloc_root_is_dead(const struct btrfs_root *root)
   {
        smp_rmb();
        if (test_bit(BTRFS_ROOT_DEAD_RELOC_TREE, &root->state))
            return true;
        return false;
   }

And then callers of reloc_root_is_dead() access root->reloc_root.

Because the read memory barrier is placed before testing the bit, the CPU
is completely free to speculatively reorder those two loads. It can read
root->reloc_root before it actually checks the dead tree bit.

Sashiko reported this as an existing problem in another patch review, see
the link in the Link tag below.

Fix this by moving the read memory barrier to happen after testing the bit
and update the comment to reflect current reality.

Link: https://sashiko.dev/#/patchset/cf84f1a217c719e25b6b69e4298dd7afd36c9427.1781194426.git.fdmanana%40suse.com
Signed-off-by: Filipe Manana <fdmanana@suse.com>
---
 fs/btrfs/relocation.c | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c
index 6b5a59cb21bb..00993505c9c3 100644
--- a/fs/btrfs/relocation.c
+++ b/fs/btrfs/relocation.c
@@ -339,14 +339,15 @@ static struct btrfs_backref_node *walk_down_backref(
 
 static bool reloc_root_is_dead(const struct btrfs_root *root)
 {
+	if (test_bit(BTRFS_ROOT_DEAD_RELOC_TREE, &root->state))
+		return true;
 	/*
-	 * Pair with set_bit/clear_bit in clean_dirty_subvols and
-	 * btrfs_update_reloc_root. We need to see the updated bit before
-	 * trying to access reloc_root
+	 * Pairs with set_bit/clear_bit in clear_reloc_root() and
+	 * btrfs_update_reloc_root(). We need to see the updated bit before
+	 * trying to access root->reloc_root in our callers.
 	 */
 	smp_rmb();
-	if (test_bit(BTRFS_ROOT_DEAD_RELOC_TREE, &root->state))
-		return true;
+
 	return false;
 }
 
-- 
2.47.2


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH 0/2] btrfs: fix incorrect barrier usage in relocation
  2026-06-12 12:13 [PATCH 0/2] btrfs: fix incorrect barrier usage in relocation fdmanana
  2026-06-12 12:13 ` [PATCH 1/2] btrfs: fix reloc root cleanup in merge_reloc_roots() fdmanana
  2026-06-12 12:13 ` [PATCH 2/2] btrfs: fix memory barrier order in reloc_root_is_dead() fdmanana
@ 2026-06-12 17:28 ` Boris Burkov
  2 siblings, 0 replies; 7+ messages in thread
From: Boris Burkov @ 2026-06-12 17:28 UTC (permalink / raw)
  To: fdmanana; +Cc: linux-btrfs

On Fri, Jun 12, 2026 at 01:13:55PM +0100, fdmanana@kernel.org wrote:
> From: Filipe Manana <fdmanana@suse.com>
> 
> Sashiko recently detected we are not correctly using memory barriers
> in the relocation code, and these patches address that. Details in
> the change logs.

Reviewed-by: Boris Burkov <boris@bur.io>

> 
> Filipe Manana (2):
>   btrfs: fix reloc root cleanup in merge_reloc_roots()
>   btrfs: fix memory barrier order in reloc_root_is_dead()
> 
>  fs/btrfs/relocation.c | 16 ++++++++--------
>  1 file changed, 8 insertions(+), 8 deletions(-)
> 
> -- 
> 2.47.2
> 

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 2/2] btrfs: fix memory barrier order in reloc_root_is_dead()
  2026-06-12 12:13 ` [PATCH 2/2] btrfs: fix memory barrier order in reloc_root_is_dead() fdmanana
@ 2026-06-12 19:13   ` kernel test robot
  2026-06-12 19:24     ` Filipe Manana
  2026-06-12 20:45   ` kernel test robot
  1 sibling, 1 reply; 7+ messages in thread
From: kernel test robot @ 2026-06-12 19:13 UTC (permalink / raw)
  To: fdmanana, linux-btrfs; +Cc: llvm, oe-kbuild-all

Hi Filipe,

kernel test robot noticed the following build errors:

[auto build test ERROR on kdave/for-next]
[also build test ERROR on linus/master v7.1-rc7 next-20260611]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/fdmanana-kernel-org/btrfs-fix-reloc-root-cleanup-in-merge_reloc_roots/20260612-202603
base:   https://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux.git for-next
patch link:    https://lore.kernel.org/r/62602395bf1488aa81645ea59e22405d6c06d3f7.1781263239.git.fdmanana%40suse.com
patch subject: [PATCH 2/2] btrfs: fix memory barrier order in reloc_root_is_dead()
config: x86_64-kexec (https://download.01.org/0day-ci/archive/20260612/202606122155.6ncF2GHC-lkp@intel.com/config)
compiler: clang version 22.0.0git (https://github.com/llvm/llvm-project f43d6834093b19baf79beda8c0337ab020ac5f17)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260612/202606122155.6ncF2GHC-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202606122155.6ncF2GHC-lkp@intel.com/

All errors (new ones prefixed by >>):

>> fs/btrfs/relocation.c:1928:6: error: call to undeclared function 'clear_reloc_root'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
    1928 |                                         clear_reloc_root(root);
         |                                         ^
   fs/btrfs/relocation.c:1928:6: note: did you mean 'create_reloc_root'?
   fs/btrfs/relocation.c:631:27: note: 'create_reloc_root' declared here
     631 | static struct btrfs_root *create_reloc_root(struct btrfs_trans_handle *trans,
         |                           ^
   1 error generated.


vim +/clear_reloc_root +1928 fs/btrfs/relocation.c

  1867	
  1868	static noinline_for_stack
  1869	void merge_reloc_roots(struct reloc_control *rc)
  1870	{
  1871		struct btrfs_fs_info *fs_info = rc->extent_root->fs_info;
  1872		struct btrfs_root *root;
  1873		struct btrfs_root *reloc_root;
  1874		LIST_HEAD(reloc_roots);
  1875		bool found = false;
  1876		int ret = 0;
  1877	again:
  1878		root = rc->extent_root;
  1879	
  1880		/*
  1881		 * this serializes us with btrfs_record_root_in_transaction,
  1882		 * we have to make sure nobody is in the middle of
  1883		 * adding their roots to the list while we are
  1884		 * doing this splice
  1885		 */
  1886		mutex_lock(&fs_info->reloc_mutex);
  1887		list_splice_init(&rc->reloc_roots, &reloc_roots);
  1888		mutex_unlock(&fs_info->reloc_mutex);
  1889	
  1890		while (!list_empty(&reloc_roots)) {
  1891			found = true;
  1892			reloc_root = list_first_entry(&reloc_roots, struct btrfs_root, root_list);
  1893	
  1894			root = btrfs_get_fs_root(fs_info, reloc_root->root_key.offset,
  1895						 false);
  1896			if (btrfs_root_refs(&reloc_root->root_item) > 0) {
  1897				if (WARN_ON(IS_ERR(root))) {
  1898					/*
  1899					 * For recovery we read the fs roots on mount,
  1900					 * and if we didn't find the root then we marked
  1901					 * the reloc root as a garbage root.  For normal
  1902					 * relocation obviously the root should exist in
  1903					 * memory.  However there's no reason we can't
  1904					 * handle the error properly here just in case.
  1905					 */
  1906					ret = PTR_ERR(root);
  1907					goto out;
  1908				}
  1909				if (WARN_ON(root->reloc_root != reloc_root)) {
  1910					/*
  1911					 * This can happen if on-disk metadata has some
  1912					 * corruption, e.g. bad reloc tree key offset.
  1913					 */
  1914					ret = -EINVAL;
  1915					goto out;
  1916				}
  1917				ret = merge_reloc_root(rc, root);
  1918				btrfs_put_root(root);
  1919				if (ret) {
  1920					if (list_empty(&reloc_root->root_list))
  1921						list_add_tail(&reloc_root->root_list,
  1922							      &reloc_roots);
  1923					goto out;
  1924				}
  1925			} else {
  1926				if (!IS_ERR(root)) {
  1927					if (root->reloc_root == reloc_root) {
> 1928						clear_reloc_root(root);
  1929						/* Drop the ref for root->reloc_root. */
  1930						btrfs_put_root(reloc_root);
  1931					}
  1932					btrfs_put_root(root);
  1933				}
  1934	
  1935				list_del_init(&reloc_root->root_list);
  1936				/* Don't forget to queue this reloc root for cleanup */
  1937				list_add_tail(&reloc_root->reloc_dirty_list,
  1938					      &rc->dirty_subvol_roots);
  1939			}
  1940		}
  1941	
  1942		if (found) {
  1943			found = false;
  1944			goto again;
  1945		}
  1946	out:
  1947		if (ret) {
  1948			btrfs_handle_fs_error(fs_info, ret, NULL);
  1949			free_reloc_roots(&reloc_roots);
  1950	
  1951			/* new reloc root may be added */
  1952			mutex_lock(&fs_info->reloc_mutex);
  1953			list_splice_init(&rc->reloc_roots, &reloc_roots);
  1954			mutex_unlock(&fs_info->reloc_mutex);
  1955			free_reloc_roots(&reloc_roots);
  1956		}
  1957	
  1958		/*
  1959		 * We used to have
  1960		 *
  1961		 * BUG_ON(!RB_EMPTY_ROOT(&rc->reloc_root_tree.rb_root));
  1962		 *
  1963		 * here, but it's wrong.  If we fail to start the transaction in
  1964		 * prepare_to_merge() we will have only 0 ref reloc roots, none of which
  1965		 * have actually been removed from the reloc_root_tree rb tree.  This is
  1966		 * fine because we're bailing here, and we hold a reference on the root
  1967		 * for the list that holds it, so these roots will be cleaned up when we
  1968		 * do the reloc_dirty_list afterwards.  Meanwhile the root->reloc_root
  1969		 * will be cleaned up on unmount.
  1970		 *
  1971		 * The remaining nodes will be cleaned up by put_reloc_control().
  1972		 */
  1973	}
  1974	

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 2/2] btrfs: fix memory barrier order in reloc_root_is_dead()
  2026-06-12 19:13   ` kernel test robot
@ 2026-06-12 19:24     ` Filipe Manana
  0 siblings, 0 replies; 7+ messages in thread
From: Filipe Manana @ 2026-06-12 19:24 UTC (permalink / raw)
  To: kernel test robot; +Cc: linux-btrfs, llvm, oe-kbuild-all

On Fri, Jun 12, 2026 at 8:13 PM kernel test robot <lkp@intel.com> wrote:
>
> Hi Filipe,
>
> kernel test robot noticed the following build errors:
>
> [auto build test ERROR on kdave/for-next]
> [also build test ERROR on linus/master v7.1-rc7 next-20260611]
> [If your patch is applied to the wrong git tree, kindly drop us a note.
> And when submitting patch, we suggest to use '--base' as documented in
> https://git-scm.com/docs/git-format-patch#_base_tree_information]
>
> url:    https://github.com/intel-lab-lkp/linux/commits/fdmanana-kernel-org/btrfs-fix-reloc-root-cleanup-in-merge_reloc_roots/20260612-202603
> base:   https://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux.git for-next
> patch link:    https://lore.kernel.org/r/62602395bf1488aa81645ea59e22405d6c06d3f7.1781263239.git.fdmanana%40suse.com
> patch subject: [PATCH 2/2] btrfs: fix memory barrier order in reloc_root_is_dead()
> config: x86_64-kexec (https://download.01.org/0day-ci/archive/20260612/202606122155.6ncF2GHC-lkp@intel.com/config)
> compiler: clang version 22.0.0git (https://github.com/llvm/llvm-project f43d6834093b19baf79beda8c0337ab020ac5f17)
> reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260612/202606122155.6ncF2GHC-lkp@intel.com/reproduce)
>
> If you fix the issue in a separate patch/commit (i.e. not just a new version of
> the same patch/commit), kindly add following tags
> | Reported-by: kernel test robot <lkp@intel.com>
> | Closes: https://lore.kernel.org/oe-kbuild-all/202606122155.6ncF2GHC-lkp@intel.com/
>
> All errors (new ones prefixed by >>):
>
> >> fs/btrfs/relocation.c:1928:6: error: call to undeclared function 'clear_reloc_root'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
>     1928 |                                         clear_reloc_root(root);
>          |                                         ^
>    fs/btrfs/relocation.c:1928:6: note: did you mean 'create_reloc_root'?
>    fs/btrfs/relocation.c:631:27: note: 'create_reloc_root' declared here
>      631 | static struct btrfs_root *create_reloc_root(struct btrfs_trans_handle *trans,
>          |                           ^
>    1 error generated.

This is because it depends on a patch that is in the giithub for-next
branch but not yet in Linus' tree or linux-next:

https://lore.kernel.org/linux-btrfs/cf84f1a217c719e25b6b69e4298dd7afd36c9427.1781194426.git.fdmanana@suse.com/
https://github.com/btrfs/linux/commits/for-next/


>
>
> vim +/clear_reloc_root +1928 fs/btrfs/relocation.c
>
>   1867
>   1868  static noinline_for_stack
>   1869  void merge_reloc_roots(struct reloc_control *rc)
>   1870  {
>   1871          struct btrfs_fs_info *fs_info = rc->extent_root->fs_info;
>   1872          struct btrfs_root *root;
>   1873          struct btrfs_root *reloc_root;
>   1874          LIST_HEAD(reloc_roots);
>   1875          bool found = false;
>   1876          int ret = 0;
>   1877  again:
>   1878          root = rc->extent_root;
>   1879
>   1880          /*
>   1881           * this serializes us with btrfs_record_root_in_transaction,
>   1882           * we have to make sure nobody is in the middle of
>   1883           * adding their roots to the list while we are
>   1884           * doing this splice
>   1885           */
>   1886          mutex_lock(&fs_info->reloc_mutex);
>   1887          list_splice_init(&rc->reloc_roots, &reloc_roots);
>   1888          mutex_unlock(&fs_info->reloc_mutex);
>   1889
>   1890          while (!list_empty(&reloc_roots)) {
>   1891                  found = true;
>   1892                  reloc_root = list_first_entry(&reloc_roots, struct btrfs_root, root_list);
>   1893
>   1894                  root = btrfs_get_fs_root(fs_info, reloc_root->root_key.offset,
>   1895                                           false);
>   1896                  if (btrfs_root_refs(&reloc_root->root_item) > 0) {
>   1897                          if (WARN_ON(IS_ERR(root))) {
>   1898                                  /*
>   1899                                   * For recovery we read the fs roots on mount,
>   1900                                   * and if we didn't find the root then we marked
>   1901                                   * the reloc root as a garbage root.  For normal
>   1902                                   * relocation obviously the root should exist in
>   1903                                   * memory.  However there's no reason we can't
>   1904                                   * handle the error properly here just in case.
>   1905                                   */
>   1906                                  ret = PTR_ERR(root);
>   1907                                  goto out;
>   1908                          }
>   1909                          if (WARN_ON(root->reloc_root != reloc_root)) {
>   1910                                  /*
>   1911                                   * This can happen if on-disk metadata has some
>   1912                                   * corruption, e.g. bad reloc tree key offset.
>   1913                                   */
>   1914                                  ret = -EINVAL;
>   1915                                  goto out;
>   1916                          }
>   1917                          ret = merge_reloc_root(rc, root);
>   1918                          btrfs_put_root(root);
>   1919                          if (ret) {
>   1920                                  if (list_empty(&reloc_root->root_list))
>   1921                                          list_add_tail(&reloc_root->root_list,
>   1922                                                        &reloc_roots);
>   1923                                  goto out;
>   1924                          }
>   1925                  } else {
>   1926                          if (!IS_ERR(root)) {
>   1927                                  if (root->reloc_root == reloc_root) {
> > 1928                                          clear_reloc_root(root);
>   1929                                          /* Drop the ref for root->reloc_root. */
>   1930                                          btrfs_put_root(reloc_root);
>   1931                                  }
>   1932                                  btrfs_put_root(root);
>   1933                          }
>   1934
>   1935                          list_del_init(&reloc_root->root_list);
>   1936                          /* Don't forget to queue this reloc root for cleanup */
>   1937                          list_add_tail(&reloc_root->reloc_dirty_list,
>   1938                                        &rc->dirty_subvol_roots);
>   1939                  }
>   1940          }
>   1941
>   1942          if (found) {
>   1943                  found = false;
>   1944                  goto again;
>   1945          }
>   1946  out:
>   1947          if (ret) {
>   1948                  btrfs_handle_fs_error(fs_info, ret, NULL);
>   1949                  free_reloc_roots(&reloc_roots);
>   1950
>   1951                  /* new reloc root may be added */
>   1952                  mutex_lock(&fs_info->reloc_mutex);
>   1953                  list_splice_init(&rc->reloc_roots, &reloc_roots);
>   1954                  mutex_unlock(&fs_info->reloc_mutex);
>   1955                  free_reloc_roots(&reloc_roots);
>   1956          }
>   1957
>   1958          /*
>   1959           * We used to have
>   1960           *
>   1961           * BUG_ON(!RB_EMPTY_ROOT(&rc->reloc_root_tree.rb_root));
>   1962           *
>   1963           * here, but it's wrong.  If we fail to start the transaction in
>   1964           * prepare_to_merge() we will have only 0 ref reloc roots, none of which
>   1965           * have actually been removed from the reloc_root_tree rb tree.  This is
>   1966           * fine because we're bailing here, and we hold a reference on the root
>   1967           * for the list that holds it, so these roots will be cleaned up when we
>   1968           * do the reloc_dirty_list afterwards.  Meanwhile the root->reloc_root
>   1969           * will be cleaned up on unmount.
>   1970           *
>   1971           * The remaining nodes will be cleaned up by put_reloc_control().
>   1972           */
>   1973  }
>   1974
>
> --
> 0-DAY CI Kernel Test Service
> https://github.com/intel/lkp-tests/wiki

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 2/2] btrfs: fix memory barrier order in reloc_root_is_dead()
  2026-06-12 12:13 ` [PATCH 2/2] btrfs: fix memory barrier order in reloc_root_is_dead() fdmanana
  2026-06-12 19:13   ` kernel test robot
@ 2026-06-12 20:45   ` kernel test robot
  1 sibling, 0 replies; 7+ messages in thread
From: kernel test robot @ 2026-06-12 20:45 UTC (permalink / raw)
  To: fdmanana, linux-btrfs; +Cc: oe-kbuild-all

Hi Filipe,

kernel test robot noticed the following build errors:

[auto build test ERROR on kdave/for-next]
[also build test ERROR on linus/master v7.1-rc7 next-20260612]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/fdmanana-kernel-org/btrfs-fix-reloc-root-cleanup-in-merge_reloc_roots/20260612-202603
base:   https://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux.git for-next
patch link:    https://lore.kernel.org/r/62602395bf1488aa81645ea59e22405d6c06d3f7.1781263239.git.fdmanana%40suse.com
patch subject: [PATCH 2/2] btrfs: fix memory barrier order in reloc_root_is_dead()
config: x86_64-rhel-9.4 (https://download.01.org/0day-ci/archive/20260612/202606122213.j2TtzMBn-lkp@intel.com/config)
compiler: gcc-14 (Debian 14.2.0-19) 14.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260612/202606122213.j2TtzMBn-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202606122213.j2TtzMBn-lkp@intel.com/

All errors (new ones prefixed by >>):

   fs/btrfs/relocation.c: In function 'merge_reloc_roots':
>> fs/btrfs/relocation.c:1928:41: error: implicit declaration of function 'clear_reloc_root'; did you mean 'create_reloc_root'? [-Wimplicit-function-declaration]
    1928 |                                         clear_reloc_root(root);
         |                                         ^~~~~~~~~~~~~~~~
         |                                         create_reloc_root


vim +1928 fs/btrfs/relocation.c

  1867	
  1868	static noinline_for_stack
  1869	void merge_reloc_roots(struct reloc_control *rc)
  1870	{
  1871		struct btrfs_fs_info *fs_info = rc->extent_root->fs_info;
  1872		struct btrfs_root *root;
  1873		struct btrfs_root *reloc_root;
  1874		LIST_HEAD(reloc_roots);
  1875		bool found = false;
  1876		int ret = 0;
  1877	again:
  1878		root = rc->extent_root;
  1879	
  1880		/*
  1881		 * this serializes us with btrfs_record_root_in_transaction,
  1882		 * we have to make sure nobody is in the middle of
  1883		 * adding their roots to the list while we are
  1884		 * doing this splice
  1885		 */
  1886		mutex_lock(&fs_info->reloc_mutex);
  1887		list_splice_init(&rc->reloc_roots, &reloc_roots);
  1888		mutex_unlock(&fs_info->reloc_mutex);
  1889	
  1890		while (!list_empty(&reloc_roots)) {
  1891			found = true;
  1892			reloc_root = list_first_entry(&reloc_roots, struct btrfs_root, root_list);
  1893	
  1894			root = btrfs_get_fs_root(fs_info, reloc_root->root_key.offset,
  1895						 false);
  1896			if (btrfs_root_refs(&reloc_root->root_item) > 0) {
  1897				if (WARN_ON(IS_ERR(root))) {
  1898					/*
  1899					 * For recovery we read the fs roots on mount,
  1900					 * and if we didn't find the root then we marked
  1901					 * the reloc root as a garbage root.  For normal
  1902					 * relocation obviously the root should exist in
  1903					 * memory.  However there's no reason we can't
  1904					 * handle the error properly here just in case.
  1905					 */
  1906					ret = PTR_ERR(root);
  1907					goto out;
  1908				}
  1909				if (WARN_ON(root->reloc_root != reloc_root)) {
  1910					/*
  1911					 * This can happen if on-disk metadata has some
  1912					 * corruption, e.g. bad reloc tree key offset.
  1913					 */
  1914					ret = -EINVAL;
  1915					goto out;
  1916				}
  1917				ret = merge_reloc_root(rc, root);
  1918				btrfs_put_root(root);
  1919				if (ret) {
  1920					if (list_empty(&reloc_root->root_list))
  1921						list_add_tail(&reloc_root->root_list,
  1922							      &reloc_roots);
  1923					goto out;
  1924				}
  1925			} else {
  1926				if (!IS_ERR(root)) {
  1927					if (root->reloc_root == reloc_root) {
> 1928						clear_reloc_root(root);
  1929						/* Drop the ref for root->reloc_root. */
  1930						btrfs_put_root(reloc_root);
  1931					}
  1932					btrfs_put_root(root);
  1933				}
  1934	
  1935				list_del_init(&reloc_root->root_list);
  1936				/* Don't forget to queue this reloc root for cleanup */
  1937				list_add_tail(&reloc_root->reloc_dirty_list,
  1938					      &rc->dirty_subvol_roots);
  1939			}
  1940		}
  1941	
  1942		if (found) {
  1943			found = false;
  1944			goto again;
  1945		}
  1946	out:
  1947		if (ret) {
  1948			btrfs_handle_fs_error(fs_info, ret, NULL);
  1949			free_reloc_roots(&reloc_roots);
  1950	
  1951			/* new reloc root may be added */
  1952			mutex_lock(&fs_info->reloc_mutex);
  1953			list_splice_init(&rc->reloc_roots, &reloc_roots);
  1954			mutex_unlock(&fs_info->reloc_mutex);
  1955			free_reloc_roots(&reloc_roots);
  1956		}
  1957	
  1958		/*
  1959		 * We used to have
  1960		 *
  1961		 * BUG_ON(!RB_EMPTY_ROOT(&rc->reloc_root_tree.rb_root));
  1962		 *
  1963		 * here, but it's wrong.  If we fail to start the transaction in
  1964		 * prepare_to_merge() we will have only 0 ref reloc roots, none of which
  1965		 * have actually been removed from the reloc_root_tree rb tree.  This is
  1966		 * fine because we're bailing here, and we hold a reference on the root
  1967		 * for the list that holds it, so these roots will be cleaned up when we
  1968		 * do the reloc_dirty_list afterwards.  Meanwhile the root->reloc_root
  1969		 * will be cleaned up on unmount.
  1970		 *
  1971		 * The remaining nodes will be cleaned up by put_reloc_control().
  1972		 */
  1973	}
  1974	

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2026-06-12 20:46 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-12 12:13 [PATCH 0/2] btrfs: fix incorrect barrier usage in relocation fdmanana
2026-06-12 12:13 ` [PATCH 1/2] btrfs: fix reloc root cleanup in merge_reloc_roots() fdmanana
2026-06-12 12:13 ` [PATCH 2/2] btrfs: fix memory barrier order in reloc_root_is_dead() fdmanana
2026-06-12 19:13   ` kernel test robot
2026-06-12 19:24     ` Filipe Manana
2026-06-12 20:45   ` kernel test robot
2026-06-12 17:28 ` [PATCH 0/2] btrfs: fix incorrect barrier usage in relocation Boris Burkov

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.