<feed xmlns='http://www.w3.org/2005/Atom'>
<title>kernel/fs/btrfs/delayed-inode.h, branch linux-rolling-stable</title>
<subtitle>Hosts the 0x221E linux distro kernel.</subtitle>
<id>https://universe.0xinfinity.dev/distro/kernel/atom?h=linux-rolling-stable</id>
<link rel='self' href='https://universe.0xinfinity.dev/distro/kernel/atom?h=linux-rolling-stable'/>
<link rel='alternate' type='text/html' href='https://universe.0xinfinity.dev/distro/kernel/'/>
<updated>2025-10-22T07:40:04Z</updated>
<entry>
<title>btrfs: fix delayed_node ref_tracker use after free</title>
<updated>2025-10-22T07:40:04Z</updated>
<author>
<name>Leo Martins</name>
<email>loemra.dev@gmail.com</email>
</author>
<published>2025-10-20T23:16:15Z</published>
<link rel='alternate' type='text/html' href='https://universe.0xinfinity.dev/distro/kernel/commit/?id=0fd7e7a1ad7c5fb8801a9c1661fc4e1ae4d9b655'/>
<id>urn:sha1:0fd7e7a1ad7c5fb8801a9c1661fc4e1ae4d9b655</id>
<content type='text'>
Move the print before releasing the delayed node.

In my initial testing there was a bug that was causing delayed_nodes
to not get freed which is why I put the print after the release. This
obviously neglects the case where the delayed node is properly freed.

Add condition to make sure we only print if we have more than one
reference to the delayed_node to prevent printing when we only have
the reference taken in btrfs_kill_all_delayed_nodes().

Fixes: b767a28d6154 ("btrfs: print leaked references in kill_all_delayed_nodes()")
Tested-by: Christoph Hellwig &lt;hch@lst.de&gt;
Signed-off-by: Leo Martins &lt;loemra.dev@gmail.com&gt;
Reviewed-by: David Sterba &lt;dsterba@suse.com&gt;
Signed-off-by: David Sterba &lt;dsterba@suse.com&gt;
</content>
</entry>
<entry>
<title>btrfs: add mount option for ref_tracker</title>
<updated>2025-09-22T08:54:32Z</updated>
<author>
<name>Leo Martins</name>
<email>loemra.dev@gmail.com</email>
</author>
<published>2025-08-12T23:04:41Z</published>
<link rel='alternate' type='text/html' href='https://universe.0xinfinity.dev/distro/kernel/commit/?id=46d33a0cc484ceb11aa47166e66d349ab3074eef'/>
<id>urn:sha1:46d33a0cc484ceb11aa47166e66d349ab3074eef</id>
<content type='text'>
The ref_tracker infrastructure aids debugging but is not enabled by
default as it has a performance impact. Add mount option 'ref_tracker'
so it can be selectively enabled on a filesystem. Currently it track
references of 'delayed inodes'.

Signed-off-by: Leo Martins &lt;loemra.dev@gmail.com&gt;
Reviewed-by: David Sterba &lt;dsterba@suse.com&gt;
Signed-off-by: David Sterba &lt;dsterba@suse.com&gt;
</content>
</entry>
<entry>
<title>btrfs: print leaked references in kill_all_delayed_nodes()</title>
<updated>2025-09-22T08:54:32Z</updated>
<author>
<name>Leo Martins</name>
<email>loemra.dev@gmail.com</email>
</author>
<published>2025-08-12T23:04:40Z</published>
<link rel='alternate' type='text/html' href='https://universe.0xinfinity.dev/distro/kernel/commit/?id=b767a28d6154986929a2231d48b637b18b2aabb3'/>
<id>urn:sha1:b767a28d6154986929a2231d48b637b18b2aabb3</id>
<content type='text'>
We are seeing soft lockups in kill_all_delayed_nodes due to a
delayed_node with a lingering reference count of 1. Printing at this
point will reveal the guilty stack trace. If the delayed_node has no
references there should be no output.

Signed-off-by: Leo Martins &lt;loemra.dev@gmail.com&gt;
Reviewed-by: David Sterba &lt;dsterba@suse.com&gt;
Signed-off-by: David Sterba &lt;dsterba@suse.com&gt;
</content>
</entry>
<entry>
<title>btrfs: implement ref_tracker for delayed_nodes</title>
<updated>2025-09-22T08:54:32Z</updated>
<author>
<name>Leo Martins</name>
<email>loemra.dev@gmail.com</email>
</author>
<published>2025-08-12T23:04:39Z</published>
<link rel='alternate' type='text/html' href='https://universe.0xinfinity.dev/distro/kernel/commit/?id=e8513c012de75fd65e2df5499572bc6ef3f6e409'/>
<id>urn:sha1:e8513c012de75fd65e2df5499572bc6ef3f6e409</id>
<content type='text'>
Add ref_tracker infrastructure for struct btrfs_delayed_node.

It is a response to the largest btrfs related crash in our fleet.  We're
seeing soft lockups in btrfs_kill_all_delayed_nodes() that seem to be a
result of delayed_nodes not being released properly.

A ref_tracker object is allocated on reference count increases and freed
on reference count decreases. The ref_tracker object stores a stack
trace of where it is allocated. The ref_tracker_dir object is embedded
in btrfs_delayed_node and keeps track of all current and some old/freed
ref_tracker objects. When a leak is detected we can print the stack
traces for all ref_trackers that have not yet been freed.

Here is a common example of taking a reference to a delayed_node and
freeing it with ref_tracker.

    struct btrfs_ref_tracker tracker;
    struct btrfs_delayed_node *node;

    node = btrfs_get_delayed_node(inode, &amp;tracker);
    // use delayed_node...
    btrfs_release_delayed_node(node, &amp;tracker);

There are two special cases where the delayed_node reference is "long
lived", meaning that the thread that takes the reference and the thread
that releases the reference are different. The 'inode_cache_tracker'
tracks the delayed_node stored in btrfs_inode. The 'node_list_tracker'
tracks the delayed_node stored in the btrfs_delayed_root
node_list/prepare_list. These trackers are embedded in the
btrfs_delayed_node.

btrfs_ref_tracker and btrfs_ref_tracker_dir are wrappers that either
compile to the corresponding ref_tracker structs or empty structs
depending on CONFIG_BTRFS_DEBUG. There are also btrfs wrappers for
the ref_tracker API.

Signed-off-by: Leo Martins &lt;loemra.dev@gmail.com&gt;
Reviewed-by: David Sterba &lt;dsterba@suse.com&gt;
Signed-off-by: David Sterba &lt;dsterba@suse.com&gt;
</content>
</entry>
<entry>
<title>btrfs: make btrfs_readdir_delayed_dir_index() return a bool instead</title>
<updated>2025-07-21T21:53:30Z</updated>
<author>
<name>Filipe Manana</name>
<email>fdmanana@suse.com</email>
</author>
<published>2025-05-31T14:56:46Z</published>
<link rel='alternate' type='text/html' href='https://universe.0xinfinity.dev/distro/kernel/commit/?id=41e4ea0bf5558c03c8e7e3fc45ddf61da00e7c80'/>
<id>urn:sha1:41e4ea0bf5558c03c8e7e3fc45ddf61da00e7c80</id>
<content type='text'>
There's no need to return errors, all we do is return 1 or 0 depending
on whether we should or should not stop iterating over delayed dir
indexes. So change the function to return bool instead of an int.

Reviewed-by: Boris Burkov &lt;boris@bur.io&gt;
Signed-off-by: Filipe Manana &lt;fdmanana@suse.com&gt;
Reviewed-by: David Sterba &lt;dsterba@suse.com&gt;
Signed-off-by: David Sterba &lt;dsterba@suse.com&gt;
</content>
</entry>
<entry>
<title>btrfs: make btrfs_should_delete_dir_index() return a bool instead</title>
<updated>2025-07-21T21:53:30Z</updated>
<author>
<name>Filipe Manana</name>
<email>fdmanana@suse.com</email>
</author>
<published>2025-05-31T14:41:41Z</published>
<link rel='alternate' type='text/html' href='https://universe.0xinfinity.dev/distro/kernel/commit/?id=4106eb9bdae662e6ba14f1b55a33c8a2489ff86b'/>
<id>urn:sha1:4106eb9bdae662e6ba14f1b55a33c8a2489ff86b</id>
<content type='text'>
There's no need to return errors and we currently return 1 in case the
index should be deleted and 0 otherwise, so change the return type from
int to bool as this is a boolean function and it's more clear this way.

Reviewed-by: Boris Burkov &lt;boris@bur.io&gt;
Signed-off-by: Filipe Manana &lt;fdmanana@suse.com&gt;
Reviewed-by: David Sterba &lt;dsterba@suse.com&gt;
Signed-off-by: David Sterba &lt;dsterba@suse.com&gt;
</content>
</entry>
<entry>
<title>btrfs: pass struct btrfs_inode to btrfs_fill_inode()</title>
<updated>2025-03-18T19:35:43Z</updated>
<author>
<name>David Sterba</name>
<email>dsterba@suse.com</email>
</author>
<published>2025-02-18T00:10:59Z</published>
<link rel='alternate' type='text/html' href='https://universe.0xinfinity.dev/distro/kernel/commit/?id=a0680a946f199f6328c82175f4a77db1e9d66bf5'/>
<id>urn:sha1:a0680a946f199f6328c82175f4a77db1e9d66bf5</id>
<content type='text'>
Pass a struct btrfs_inode to btrfs_fill_inode() as it's an internal
interface, allowing to remove some use of BTRFS_I.

Reviewed-by: Johannes Thumshirn &lt;johannes.thumshirn@wdc.com&gt;
Signed-off-by: David Sterba &lt;dsterba@suse.com&gt;
</content>
</entry>
<entry>
<title>btrfs: remove hole from struct btrfs_delayed_node</title>
<updated>2024-11-11T13:34:22Z</updated>
<author>
<name>Filipe Manana</name>
<email>fdmanana@suse.com</email>
</author>
<published>2024-11-05T11:56:45Z</published>
<link rel='alternate' type='text/html' href='https://universe.0xinfinity.dev/distro/kernel/commit/?id=a20725e1e7014642fc8ba4c7dd2c4ef6d4ec56a9'/>
<id>urn:sha1:a20725e1e7014642fc8ba4c7dd2c4ef6d4ec56a9</id>
<content type='text'>
On x86_64 and a release kernel, there's a 4 bytes hole in the structure
after the ref count field:

  struct btrfs_delayed_node {
          u64                        inode_id;             /*     0     8 */
          u64                        bytes_reserved;       /*     8     8 */
          struct btrfs_root *        root;                 /*    16     8 */
          struct list_head           n_list;               /*    24    16 */
          struct list_head           p_list;               /*    40    16 */
          struct rb_root_cached      ins_root;             /*    56    16 */
          /* --- cacheline 1 boundary (64 bytes) was 8 bytes ago --- */
          struct rb_root_cached      del_root;             /*    72    16 */
          struct mutex               mutex;                /*    88    32 */
          struct btrfs_inode_item    inode_item;           /*   120   160 */
          /* --- cacheline 4 boundary (256 bytes) was 24 bytes ago --- */
          refcount_t                 refs;                 /*   280     4 */

          /* XXX 4 bytes hole, try to pack */

          u64                        index_cnt;            /*   288     8 */
          long unsigned int          flags;                /*   296     8 */
          int                        count;                /*   304     4 */
          u32                        curr_index_batch_size; /*   308     4 */
          u32                        index_item_leaves;    /*   312     4 */

          /* size: 320, cachelines: 5, members: 15 */
          /* sum members: 312, holes: 1, sum holes: 4 */
          /* padding: 4 */
  };

Move the 'count' field, which is 4 bytes long, to just below the ref count
field, so we eliminate the hole and reduce the structure size from 320
bytes down to 312 bytes:

  struct btrfs_delayed_node {
          u64                        inode_id;             /*     0     8 */
          u64                        bytes_reserved;       /*     8     8 */
          struct btrfs_root *        root;                 /*    16     8 */
          struct list_head           n_list;               /*    24    16 */
          struct list_head           p_list;               /*    40    16 */
          struct rb_root_cached      ins_root;             /*    56    16 */
          /* --- cacheline 1 boundary (64 bytes) was 8 bytes ago --- */
          struct rb_root_cached      del_root;             /*    72    16 */
          struct mutex               mutex;                /*    88    32 */
          struct btrfs_inode_item    inode_item;           /*   120   160 */
          /* --- cacheline 4 boundary (256 bytes) was 24 bytes ago --- */
          refcount_t                 refs;                 /*   280     4 */
          int                        count;                /*   284     4 */
          u64                        index_cnt;            /*   288     8 */
          long unsigned int          flags;                /*   296     8 */
          u32                        curr_index_batch_size; /*   304     4 */
          u32                        index_item_leaves;    /*   308     4 */

          /* size: 312, cachelines: 5, members: 15 */
          /* last cacheline: 56 bytes */
  };

This now allows to have 13 delayed nodes per 4K page instead of 12.

Reviewed-by: Qu Wenruo &lt;wqu@suse.com&gt;
Signed-off-by: Filipe Manana &lt;fdmanana@suse.com&gt;
Reviewed-by: David Sterba &lt;dsterba@suse.com&gt;
Signed-off-by: David Sterba &lt;dsterba@suse.com&gt;
</content>
</entry>
<entry>
<title>btrfs: pass a btrfs_inode to btrfs_readdir_get_delayed_items()</title>
<updated>2024-07-11T13:33:28Z</updated>
<author>
<name>David Sterba</name>
<email>dsterba@suse.com</email>
</author>
<published>2022-06-15T13:03:11Z</published>
<link rel='alternate' type='text/html' href='https://universe.0xinfinity.dev/distro/kernel/commit/?id=a0d7e98ced3e4c45284b268bc0867b51f0e093d6'/>
<id>urn:sha1:a0d7e98ced3e4c45284b268bc0867b51f0e093d6</id>
<content type='text'>
Pass a struct btrfs_inode to btrfs_readdir_get_delayed_items() as it's
an internal interface, allowing to remove some use of BTRFS_I.

Reviewed-by: Boris Burkov &lt;boris@bur.io&gt;
Signed-off-by: David Sterba &lt;dsterba@suse.com&gt;
</content>
</entry>
<entry>
<title>btrfs: pass a btrfs_inode to btrfs_readdir_put_delayed_items()</title>
<updated>2024-07-11T13:33:28Z</updated>
<author>
<name>David Sterba</name>
<email>dsterba@suse.com</email>
</author>
<published>2022-06-15T13:11:38Z</published>
<link rel='alternate' type='text/html' href='https://universe.0xinfinity.dev/distro/kernel/commit/?id=849c01ae90efcf273a9c26e305d5d42862f8f3e8'/>
<id>urn:sha1:849c01ae90efcf273a9c26e305d5d42862f8f3e8</id>
<content type='text'>
Pass a struct btrfs_inode to btrfs_readdir_put_delayed_items() as it's
an internal interface, allowing to remove some use of BTRFS_I.

Reviewed-by: Boris Burkov &lt;boris@bur.io&gt;
Signed-off-by: David Sterba &lt;dsterba@suse.com&gt;
</content>
</entry>
</feed>
