<feed xmlns='http://www.w3.org/2005/Atom'>
<title>kernel/git/stable/linux.git/fs/btrfs/block-group.h, branch master</title>
<subtitle>Linux kernel stable tree</subtitle>
<id>https://git.rulkc.org/pub/scm/linux/kernel/git/stable/linux.git/atom?h=master</id>
<link rel='self' href='https://git.rulkc.org/pub/scm/linux/kernel/git/stable/linux.git/atom?h=master'/>
<link rel='alternate' type='text/html' href='https://git.rulkc.org/pub/scm/linux/kernel/git/stable/linux.git/'/>
<updated>2026-06-08T13:53:30+00:00</updated>
<entry>
<title>btrfs: use the enums instead of int type in struct btrfs_block_group fields</title>
<updated>2026-06-08T13:53:30+00:00</updated>
<author>
<name>Filipe Manana</name>
<email>fdmanana@suse.com</email>
</author>
<published>2026-04-20T10:44:07+00:00</published>
<link rel='alternate' type='text/html' href='https://git.rulkc.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=a6df0dcc23ac8be8dfb233ea7367071c1f2c9cf4'/>
<id>urn:sha1:a6df0dcc23ac8be8dfb233ea7367071c1f2c9cf4</id>
<content type='text'>
The 'disk_cache_state' and 'cached' fields are defined with an int type
but all the values we assigned to them come from the enums
btrfs_disk_cache_state and btrfs_caching_type. So change the type in the
btrfs_block_group structure from int to these enums - in practice an enum
is an int, so this is more for readability and clarity.

Reviewed-by: Qu Wenruo &lt;wqu@suse.com&gt;
Reviewed-by: Sun YangKai &lt;sunk67188@gmail.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: reduce size of struct btrfs_block_group</title>
<updated>2026-06-08T13:53:28+00:00</updated>
<author>
<name>Filipe Manana</name>
<email>fdmanana@suse.com</email>
</author>
<published>2026-04-15T11:52:16+00:00</published>
<link rel='alternate' type='text/html' href='https://git.rulkc.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=a8d1f0b5392473102f08d6f91f4dcdfaf9e29b0f'/>
<id>urn:sha1:a8d1f0b5392473102f08d6f91f4dcdfaf9e29b0f</id>
<content type='text'>
We currently have several holes in the structure:

  struct btrfs_block_group {
        struct btrfs_fs_info *     fs_info;              /*     0     8 */
        struct btrfs_inode *       inode;                /*     8     8 */
        spinlock_t                 lock __attribute__((__aligned__(4))); /*    16     4 */

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

        u64                        start;                /*    24     8 */
        u64                        length;               /*    32     8 */
        u64                        pinned;               /*    40     8 */
        u64                        reserved;             /*    48     8 */
        u64                        used;                 /*    56     8 */
        /* --- cacheline 1 boundary (64 bytes) --- */
        u64                        delalloc_bytes;       /*    64     8 */
        u64                        bytes_super;          /*    72     8 */
        u64                        flags;                /*    80     8 */
        u64                        cache_generation;     /*    88     8 */
        u64                        global_root_id;       /*    96     8 */
        u64                        remap_bytes;          /*   104     8 */
        u32                        identity_remap_count; /*   112     4 */

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

        u64                        last_used;            /*   120     8 */
        /* --- cacheline 2 boundary (128 bytes) --- */
        u64                        last_remap_bytes;     /*   128     8 */
        u32                        last_identity_remap_count; /*   136     4 */

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

        u64                        last_flags;           /*   144     8 */
        u32                        bitmap_high_thresh;   /*   152     4 */
        u32                        bitmap_low_thresh;    /*   156     4 */
        struct rw_semaphore        data_rwsem __attribute__((__aligned__(8))); /*   160    40 */
        /* --- cacheline 3 boundary (192 bytes) was 8 bytes ago --- */
        long unsigned int          full_stripe_len;      /*   200     8 */
        long unsigned int          runtime_flags;        /*   208     8 */
        unsigned int               ro;                   /*   216     4 */
        int                        disk_cache_state;     /*   220     4 */
        int                        cached;               /*   224     4 */

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

       struct btrfs_caching_control * caching_ctl;      /*   232     8 */
        struct btrfs_space_info *  space_info;           /*   240     8 */
        struct btrfs_free_space_ctl * free_space_ctl;    /*   248     8 */
        /* --- cacheline 4 boundary (256 bytes) --- */
        struct rb_node             cache_node __attribute__((__aligned__(8))); /*   256    24 */
        struct list_head           list;                 /*   280    16 */
        refcount_t                 refs __attribute__((__aligned__(4))); /*   296     4 */

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

        struct list_head           cluster_list;         /*   304    16 */
        /* --- cacheline 5 boundary (320 bytes) --- */
        struct list_head           bg_list;              /*   320    16 */
        struct list_head           ro_list;              /*   336    16 */
        atomic_t                   frozen __attribute__((__aligned__(4))); /*   352     4 */

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

        struct list_head           discard_list;         /*   360    16 */
        int                        discard_index;        /*   376     4 */

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

        /* --- cacheline 6 boundary (384 bytes) --- */
        u64                        discard_eligible_time; /*   384     8 */
        u64                        discard_cursor;       /*   392     8 */
        enum btrfs_discard_state   discard_state;        /*   400     4 */

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

        struct list_head           dirty_list;           /*   408    16 */
        struct list_head           io_list;              /*   424    16 */
        struct btrfs_io_ctl        io_ctl;               /*   440    72 */
        /* --- cacheline 8 boundary (512 bytes) --- */
        atomic_t                   reservations __attribute__((__aligned__(4))); /*   512     4 */
        atomic_t                   nocow_writers __attribute__((__aligned__(4))); /*   516     4 */
        struct mutex               free_space_lock __attribute__((__aligned__(8))); /*   520    32 */
        bool                       using_free_space_bitmaps; /*   552     1 */
        bool                       using_free_space_bitmaps_cached; /*   553     1 */

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

        int                        swap_extents;         /*   556     4 */
        u64                        alloc_offset;         /*   560     8 */
        u64                        zone_unusable;        /*   568     8 */
        /* --- cacheline 9 boundary (576 bytes) --- */
        u64                        zone_capacity;        /*   576     8 */
        u64                        meta_write_pointer;   /*   584     8 */
        struct btrfs_chunk_map *   physical_map;         /*   592     8 */
        struct list_head           active_bg_list;       /*   600    16 */
        struct work_struct         zone_finish_work;     /*   616    32 */
        /* --- cacheline 10 boundary (640 bytes) was 8 bytes ago --- */
        struct extent_buffer *     last_eb;              /*   648     8 */
        enum btrfs_block_group_size_class size_class;    /*   656     4 */

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

        u64                        reclaim_mark;         /*   664     8 */

        /* size: 672, cachelines: 11, members: 61 */
        /* sum members: 634, holes: 10, sum holes: 38 */
        /* forced alignments: 8 */
        /* last cacheline: 32 bytes */
  } __attribute__((__aligned__(8)));

Reorder some fields to eliminate the holes while keeping closely related
or frequently accessed fields together. After the reordering the size of
the structure is reduced down to 632 bytes and the number of cache lines
decreases from 11 to 10. We can still only pack 6 block groups per 4K page
but on a 64K page system we will now be able to pack 103 block groups
instead of 97. The new structure layout, on a release kernel, is the
following:

  struct btrfs_block_group {
        struct btrfs_fs_info *     fs_info;              /*     0     8 */
        struct btrfs_inode *       inode;                /*     8     8 */
        spinlock_t                 lock __attribute__((__aligned__(4))); /*    16     4 */
        unsigned int               ro;                   /*    20     4 */
        u64                        start;                /*    24     8 */
        u64                        length;               /*    32     8 */
        u64                        pinned;               /*    40     8 */
        u64                        reserved;             /*    48     8 */
        u64                        used;                 /*    56     8 */
        /* --- cacheline 1 boundary (64 bytes) --- */
        u64                        delalloc_bytes;       /*    64     8 */
        u64                        bytes_super;          /*    72     8 */
        u64                        flags;                /*    80     8 */
        u64                        cache_generation;     /*    88     8 */
        u64                        global_root_id;       /*    96     8 */
        u64                        remap_bytes;          /*   104     8 */
        u32                        identity_remap_count; /*   112     4 */
        u32                        last_identity_remap_count; /*   116     4 */
        u64                        last_used;            /*   120     8 */
        /* --- cacheline 2 boundary (128 bytes) --- */
        u64                        last_remap_bytes;     /*   128     8 */
        u64                        last_flags;           /*   136     8 */
        u32                        bitmap_high_thresh;   /*   144     4 */
        u32                        bitmap_low_thresh;    /*   148     4 */
        struct rw_semaphore        data_rwsem __attribute__((__aligned__(8))); /*   152    40 */
        /* --- cacheline 3 boundary (192 bytes) --- */
        long unsigned int          full_stripe_len;      /*   192     8 */
        long unsigned int          runtime_flags;        /*   200     8 */
        int                        disk_cache_state;     /*   208     4 */
        int                        cached;               /*   212     4 */
        struct btrfs_caching_control * caching_ctl;      /*   216     8 */
        struct btrfs_space_info *  space_info;           /*   224     8 */
        struct btrfs_free_space_ctl * free_space_ctl;    /*   232     8 */
        struct rb_node             cache_node __attribute__((__aligned__(8))); /*   240    24 */
        /* --- cacheline 4 boundary (256 bytes) was 8 bytes ago --- */
        struct list_head           list;                 /*   264    16 */
        refcount_t                 refs __attribute__((__aligned__(4))); /*   280     4 */
        atomic_t                   frozen __attribute__((__aligned__(4))); /*   284     4 */
        struct list_head           cluster_list;         /*   288    16 */
        struct list_head           bg_list;              /*   304    16 */
        /* --- cacheline 5 boundary (320 bytes) --- */
        struct list_head           ro_list;              /*   320    16 */
        struct list_head           discard_list;         /*   336    16 */
        int                        discard_index;        /*   352     4 */
        enum btrfs_discard_state   discard_state;        /*   356     4 */
        u64                        discard_eligible_time; /*   360     8 */
        u64                        discard_cursor;       /*   368     8 */
        struct list_head           dirty_list;           /*   376    16 */
        /* --- cacheline 6 boundary (384 bytes) was 8 bytes ago --- */
        struct list_head           io_list;              /*   392    16 */
        struct btrfs_io_ctl        io_ctl;               /*   408    72 */
        /* --- cacheline 7 boundary (448 bytes) was 32 bytes ago --- */
        atomic_t                   reservations __attribute__((__aligned__(4))); /*   480     4 */
        atomic_t                   nocow_writers __attribute__((__aligned__(4))); /*   484     4 */
        struct mutex               free_space_lock __attribute__((__aligned__(8))); /*   488    32 */
        /* --- cacheline 8 boundary (512 bytes) was 8 bytes ago --- */
        bool                       using_free_space_bitmaps; /*   520     1 */
        bool                       using_free_space_bitmaps_cached; /*   521     1 */

        /* XXX 2 bytes hole, try to pack */
        /* Bitfield combined with previous fields */

        static enum btrfs_block_group_size_class size_class; /*     0: 0  0 */
        int                        swap_extents;         /*   524     4 */
        u64                        alloc_offset;         /*   528     8 */
        u64                        zone_unusable;        /*   536     8 */
        u64                        zone_capacity;        /*   544     8 */
        u64                        meta_write_pointer;   /*   552     8 */
        struct btrfs_chunk_map *   physical_map;         /*   560     8 */
        struct list_head           active_bg_list;       /*   568    16 */
        /* --- cacheline 9 boundary (576 bytes) was 8 bytes ago --- */
        struct work_struct         zone_finish_work;     /*   584    32 */
        struct extent_buffer *     last_eb;              /*   616     8 */
        u64                        reclaim_mark;         /*   624     8 */

        /* size: 632, cachelines: 10, members: 60, static members: 1 */
        /* sum members: 630, holes: 1, sum holes: 2 */
        /* sum bitfield members: 8 bits (1 bytes) */
        /* forced alignments: 8 */
        /* last cacheline: 56 bytes */
  } __attribute__((__aligned__(8)));

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: use a kmem_cache for block groups</title>
<updated>2026-06-08T13:53:28+00:00</updated>
<author>
<name>Filipe Manana</name>
<email>fdmanana@suse.com</email>
</author>
<published>2026-04-15T11:26:40+00:00</published>
<link rel='alternate' type='text/html' href='https://git.rulkc.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=d293344c2249dc716d26d3d55a9261989da32c50'/>
<id>urn:sha1:d293344c2249dc716d26d3d55a9261989da32c50</id>
<content type='text'>
We are currently allocating block groups using the generic slabs, and
given that the size of btrfs_block_group structure is 672 bytes (on a
release kernel), we end up using the kmalloc-1024 slab and therefore
waste quite some memory since on a 4K page system we can only fit 4
block groups per page. The block groups are also allocated and
delallocated with some frequency, specially if we have auto reclaim
enabled.

So use a kmem_cache for block groups, this way on a 4K page system we
can fit 6 block groups per page instead of 4.

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: zoned: limit number of zones reclaimed in flush_space()</title>
<updated>2026-04-07T16:56:01+00:00</updated>
<author>
<name>Johannes Thumshirn</name>
<email>johannes.thumshirn@wdc.com</email>
</author>
<published>2026-03-05T10:06:44+00:00</published>
<link rel='alternate' type='text/html' href='https://git.rulkc.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=ad0c23c97b4e9ed8233905294dd86659009c6e8a'/>
<id>urn:sha1:ad0c23c97b4e9ed8233905294dd86659009c6e8a</id>
<content type='text'>
Limit the number of zones reclaimed in flush_space()'s RECLAIM_ZONES
state.

This prevents possibly long running reclaim sweeps to block other tasks in
the system, while the system is under pressure anyways, causing the
tasks to hang.

An example of this can be seen here, triggered by fstests generic/551:

generic/551        [   27.042349] run fstests generic/551 at 2026-02-27 11:05:30
 BTRFS: device fsid 78c16e29-20d9-4c8e-bc04-7ba431be38ff devid 1 transid 8 /dev/vdb (254:16) scanned by mount (806)
 BTRFS info (device vdb): first mount of filesystem 78c16e29-20d9-4c8e-bc04-7ba431be38ff
 BTRFS info (device vdb): using crc32c checksum algorithm
 BTRFS info (device vdb): host-managed zoned block device /dev/vdb, 64 zones of 268435456 bytes
 BTRFS info (device vdb): zoned mode enabled with zone size 268435456
 BTRFS info (device vdb): checking UUID tree
 BTRFS info (device vdb): enabling free space tree
 INFO: task kworker/u38:1:90 blocked for more than 120 seconds.
       Not tainted 7.0.0-rc1+ #345
 "echo 0 &gt; /proc/sys/kernel/hung_task_timeout_secs" disables this message.
 task:kworker/u38:1   state:D stack:0     pid:90    tgid:90    ppid:2      task_flags:0x4208060 flags:0x00080000
 Workqueue: events_unbound btrfs_async_reclaim_data_space
 Call Trace:
  &lt;TASK&gt;
  __schedule+0x34f/0xe70
  schedule+0x41/0x140
  schedule_timeout+0xa3/0x110
  ? mark_held_locks+0x40/0x70
  ? lockdep_hardirqs_on_prepare+0xd8/0x1c0
  ? trace_hardirqs_on+0x18/0x100
  ? lockdep_hardirqs_on+0x84/0x130
  ? _raw_spin_unlock_irq+0x33/0x50
  wait_for_completion+0xa4/0x150
  ? __flush_work+0x24c/0x550
  __flush_work+0x339/0x550
  ? __pfx_wq_barrier_func+0x10/0x10
  ? wait_for_completion+0x39/0x150
  flush_space+0x243/0x660
  ? find_held_lock+0x2b/0x80
  ? kvm_sched_clock_read+0x11/0x20
  ? local_clock_noinstr+0x17/0x110
  ? local_clock+0x15/0x30
  ? lock_release+0x1b7/0x4b0
  do_async_reclaim_data_space+0xe8/0x160
  btrfs_async_reclaim_data_space+0x19/0x30
  process_one_work+0x20a/0x5f0
  ? lock_is_held_type+0xcd/0x130
  worker_thread+0x1e2/0x3c0
  ? __pfx_worker_thread+0x10/0x10
  kthread+0x103/0x150
  ? __pfx_kthread+0x10/0x10
  ret_from_fork+0x20d/0x320
  ? __pfx_kthread+0x10/0x10
  ret_from_fork_asm+0x1a/0x30
  &lt;/TASK&gt;

 Showing all locks held in the system:
 1 lock held by khungtaskd/67:
  #0: ffffffff824d58e0 (rcu_read_lock){....}-{1:3}, at: debug_show_all_locks+0x3d/0x194
 2 locks held by kworker/u38:1/90:
  #0: ffff8881000aa158 ((wq_completion)events_unbound){+.+.}-{0:0}, at: process_one_work+0x3c4/0x5f0
  #1: ffffc90000c17e58 ((work_completion)(&amp;fs_info-&gt;async_data_reclaim_work)){+.+.}-{0:0}, at: process_one_work+0x1c0/0x5f0
 5 locks held by kworker/u39:1/191:
  #0: ffff8881000aa158 ((wq_completion)events_unbound){+.+.}-{0:0}, at: process_one_work+0x3c4/0x5f0
  #1: ffffc90000dfbe58 ((work_completion)(&amp;fs_info-&gt;reclaim_bgs_work)){+.+.}-{0:0}, at: process_one_work+0x1c0/0x5f0
  #2: ffff888101da0420 (sb_writers#9){.+.+}-{0:0}, at: process_one_work+0x20a/0x5f0
  #3: ffff88811040a648 (&amp;fs_info-&gt;reclaim_bgs_lock){+.+.}-{4:4}, at: btrfs_reclaim_bgs_work+0x1de/0x770
  #4: ffff888110408a18 (&amp;fs_info-&gt;cleaner_mutex){+.+.}-{4:4}, at: btrfs_relocate_block_group+0x95a/0x20f0
 1 lock held by aio-dio-write-v/980:
  #0: ffff888110093008 (&amp;sb-&gt;s_type-&gt;i_mutex_key#15){++++}-{4:4}, at: btrfs_inode_lock+0x51/0xb0

 =============================================

To prevent these long running reclaims from blocking the system, only
reclaim 5 block_groups in the RECLAIM_ZONES state of flush_space(). Also
as these reclaims are now constrained, it opens up the use for a
synchronous call to brtfs_reclaim_block_groups(), eliminating the need
to place the reclaim task on a workqueue and then flushing the workqueue
again.

Reviewed-by: Boris Burkov &lt;boris@bur.io&gt;
Signed-off-by: Johannes Thumshirn &lt;johannes.thumshirn@wdc.com&gt;
Signed-off-by: David Sterba &lt;dsterba@suse.com&gt;
</content>
</entry>
<entry>
<title>btrfs: populate fully_remapped_bgs_list on mount</title>
<updated>2026-02-03T06:54:36+00:00</updated>
<author>
<name>Mark Harmstone</name>
<email>mark@harmstone.com</email>
</author>
<published>2026-01-07T14:09:17+00:00</published>
<link rel='alternate' type='text/html' href='https://git.rulkc.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=2aef934b56b3ae07c292831cf9bf6bafcaaa005e'/>
<id>urn:sha1:2aef934b56b3ae07c292831cf9bf6bafcaaa005e</id>
<content type='text'>
Add a function btrfs_populate_fully_remapped_bgs_list() which gets
called on mount, which looks for fully remapped block groups
(i.e. identity_remap_count == 0) which haven't yet had their chunk
stripes and device extents removed.

This happens when a filesystem is unmounted while async discard has not
yet finished, as otherwise the data range occupied by the chunk stripes
would be permanently unusable.

Reviewed-by: Boris Burkov &lt;boris@bur.io&gt;
Signed-off-by: Mark Harmstone &lt;mark@harmstone.com&gt;
Signed-off-by: David Sterba &lt;dsterba@suse.com&gt;
</content>
</entry>
<entry>
<title>btrfs: handle discarding fully-remapped block groups</title>
<updated>2026-02-03T06:54:36+00:00</updated>
<author>
<name>Mark Harmstone</name>
<email>mark@harmstone.com</email>
</author>
<published>2026-01-07T14:09:16+00:00</published>
<link rel='alternate' type='text/html' href='https://git.rulkc.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=7cddbb4339d4be16aa5341e3a27e63c34d2c4e0d'/>
<id>urn:sha1:7cddbb4339d4be16aa5341e3a27e63c34d2c4e0d</id>
<content type='text'>
Discard normally works by iterating over the free-space entries of a
block group. This doesn't work for fully-remapped block groups, as we
removed their free-space entries when we started relocation.

For sync discard, call btrfs_discard_extent() when we commit the
transaction in which the last identity remap was removed.

For async discard, add a new function btrfs_trim_fully_remapped_block_group()
to be called by the discard worker, which iterates over the block
group's range using the normal async discard rules. Once we reach the
end, remove the chunk's stripes and device extents to get back its free
space.

Reviewed-by: Boris Burkov &lt;boris@bur.io&gt;
Signed-off-by: Mark Harmstone &lt;mark@harmstone.com&gt;
Signed-off-by: David Sterba &lt;dsterba@suse.com&gt;
</content>
</entry>
<entry>
<title>btrfs: handle setting up relocation of block group with remap-tree</title>
<updated>2026-02-03T06:54:35+00:00</updated>
<author>
<name>Mark Harmstone</name>
<email>mark@harmstone.com</email>
</author>
<published>2026-01-07T14:09:11+00:00</published>
<link rel='alternate' type='text/html' href='https://git.rulkc.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=b56f35560b82e7f8d79aa9ee72720b06639a473c'/>
<id>urn:sha1:b56f35560b82e7f8d79aa9ee72720b06639a473c</id>
<content type='text'>
Handle the preliminary work for relocating a block group in a filesystem
with the remap-tree flag set.

If the block group is SYSTEM btrfs_relocate_block_group() proceeds as it
does already, as bootstrapping issues mean that these block groups have
to be processed the existing way. Similarly with METADATA_REMAP blocks, which
are dealt with in a later patch.

Otherwise we walk the free-space tree for the block group in question,
recording any holes. These get converted into identity remaps and placed
in the remap tree, and the block group's REMAPPED flag is set. From now
on no new allocations are possible within this block group, and any I/O
to it will be funnelled through btrfs_translate_remap(). We store the
number of identity remaps in `identity_remap_count`, so that we know
when we've removed the last one and the block group is fully remapped.

The change in btrfs_read_roots() is because data relocations no longer
rely on the data reloc tree as a hidden subvolume in which to do
snapshots.

(Thanks to Sun YangKai for his suggestions.)

Reviewed-by: Boris Burkov &lt;boris@bur.io&gt;
Signed-off-by: Mark Harmstone &lt;mark@harmstone.com&gt;
Signed-off-by: David Sterba &lt;dsterba@suse.com&gt;
</content>
</entry>
<entry>
<title>btrfs: handle deletions from remapped block group</title>
<updated>2026-02-03T06:54:35+00:00</updated>
<author>
<name>Mark Harmstone</name>
<email>mark@harmstone.com</email>
</author>
<published>2026-01-07T14:09:10+00:00</published>
<link rel='alternate' type='text/html' href='https://git.rulkc.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=979e1dc3d69e4c825eec05d05d9567b251f6ec23'/>
<id>urn:sha1:979e1dc3d69e4c825eec05d05d9567b251f6ec23</id>
<content type='text'>
Handle the case where we free an extent from a block group that has the
REMAPPED flag set. Because the remap tree is orthogonal to the extent
tree, for data this may be within any number of identity remaps or
actual remaps. If we're freeing a metadata node, this will be wholly
inside one or the other.

btrfs_remove_extent_from_remap_tree() searches the remap tree for the
remaps that cover the range in question, then calls
remove_range_from_remap_tree() for each one, to punch a hole in the
remap and adjust the free-space tree.

For an identity remap, remove_range_from_remap_tree() will adjust the
block group's `identity_remap_count` if this changes. If it reaches
zero we mark the block group as fully remapped.

For an identity remap, remove_range_from_remap_tree() will adjust the
block group's `identity_remap_count` if this changes. If it reaches
zero we mark the block group as fully remapped.

Fully remapped block groups have their chunk stripes removed and their
device extents freed, which makes the disk space available again to the
chunk allocator. This happens asynchronously: in the cleaner thread for
sync discard and nodiscard, and (in a later patch) in the discard worker
for async discard.

Reviewed-by: Boris Burkov &lt;boris@bur.io&gt;
Signed-off-by: Mark Harmstone &lt;mark@harmstone.com&gt;
Signed-off-by: David Sterba &lt;dsterba@suse.com&gt;
</content>
</entry>
<entry>
<title>btrfs: add extended version of struct block_group_item</title>
<updated>2026-02-03T06:54:34+00:00</updated>
<author>
<name>Mark Harmstone</name>
<email>mark@harmstone.com</email>
</author>
<published>2026-01-07T14:09:07+00:00</published>
<link rel='alternate' type='text/html' href='https://git.rulkc.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=7977011460cffc6f5a0cd830584c832c4aa07076'/>
<id>urn:sha1:7977011460cffc6f5a0cd830584c832c4aa07076</id>
<content type='text'>
Add a struct btrfs_block_group_item_v2, which is used in the block group
tree if the remap-tree incompat flag is set.

This adds two new fields to the block group item: `remap_bytes` and
`identity_remap_count`.

`remap_bytes` records the amount of data that's physically within this
block group, but nominally in another, remapped block group. This is
necessary because this data will need to be moved first if this block
group is itself relocated. If `remap_bytes` &gt; 0, this is an indicator to
the relocation thread that it will need to search the remap-tree for
backrefs. A block group must also have `remap_bytes` == 0 before it can
be dropped.

`identity_remap_count` records how many identity remap items are located
in the remap tree for this block group. When relocation is begun for
this block group, this is set to the number of holes in the free-space
tree for this range. As identity remaps are converted into actual remaps
by the relocation process, this number is decreased. Once it reaches 0,
either because of relocation or because extents have been deleted, the
block group has been fully remapped and its chunk's device extents are
removed.

Reviewed-by: Boris Burkov &lt;boris@bur.io&gt;
Signed-off-by: Mark Harmstone &lt;mark@harmstone.com&gt;
Signed-off-by: David Sterba &lt;dsterba@suse.com&gt;
</content>
</entry>
<entry>
<title>btrfs: rename struct btrfs_block_group field commit_used to last_used</title>
<updated>2026-02-03T06:54:34+00:00</updated>
<author>
<name>Mark Harmstone</name>
<email>mark@harmstone.com</email>
</author>
<published>2026-01-07T14:09:06+00:00</published>
<link rel='alternate' type='text/html' href='https://git.rulkc.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=bf8ff4b9f0aa3f9e49779c8d3edbdc11caa5cd05'/>
<id>urn:sha1:bf8ff4b9f0aa3f9e49779c8d3edbdc11caa5cd05</id>
<content type='text'>
Rename the field commit_used in struct btrfs_block_group to last_used,
for clarity and consistency with the similar fields we're about to add.
It's not obvious that commit_flags means "flags as of the last commit"
rather than "flags related to a commit".

Signed-off-by: Mark Harmstone &lt;mark@harmstone.com&gt;
Signed-off-by: David Sterba &lt;dsterba@suse.com&gt;
</content>
</entry>
</feed>
