No description
  • C 96.8%
  • Assembly 0.9%
  • Rust 0.7%
  • Shell 0.6%
  • Python 0.5%
  • Other 0.3%
Find a file
Boris Burkov 7d59377ada btrfs: fix qgroup_snapshot_quick_inherit() squota bug
[ Upstream commit 7ee19a59a7 ]

qgroup_snapshot_quick_inherit() detects conditions where the snapshot
destination would land in the same parent qgroup as the snapshot source
subvolume. In this case we can avoid costly qgroup calculations and just
add the nodesize of the new snapshot to the parent.

However, in the case of squotas this is actually a double count, and
also an undercount for deeper qgroup nestings.

The following annotated script shows the issue:

  btrfs quota enable --simple "$mnt"

  # Create 2-level qgroup hierarchy
  btrfs qgroup create 2/100 "$mnt"  # Q2 (level 2)
  btrfs qgroup create 1/100 "$mnt"  # Q1 (level 1)
  btrfs qgroup assign 1/100 2/100 "$mnt"

  # Create base subvolume
  btrfs subvolume create "$mnt/base" >/dev/null
  base_id=$(btrfs subvolume show "$mnt/base" | grep 'Subvolume ID:' | awk '{print $3}')

  # Create intermediate snapshot and add to Q1
  btrfs subvolume snapshot "$mnt/base" "$mnt/intermediate" >/dev/null
  inter_id=$(btrfs subvolume show "$mnt/intermediate" | grep 'Subvolume ID:' | awk '{print $3}')
  btrfs qgroup assign "0/$inter_id" 1/100 "$mnt"

  # Create working snapshot with --inherit (auto-adds to Q1)
  # src=intermediate (in only Q1)
  # dst=snap (inheriting only into Q1)
  # This double counts the 16k nodesize of the snapshot in Q1, and
  # undercounts it in Q2.
  btrfs subvolume snapshot -i 1/100 "$mnt/intermediate" "$mnt/snap" >/dev/null
  snap_id=$(btrfs subvolume show "$mnt/snap" | grep 'Subvolume ID:' | awk '{print $3}')

  # Fully complete snapshot creation
  sync

  # Delete working snapshot
  # Q1 and Q2 will lose the full snap usage
  btrfs subvolume delete "$mnt/snap" >/dev/null

  # Delete intermediate and remove from Q1
  # Q1 and Q2 will lose the full intermediate usage
  btrfs qgroup remove "0/$inter_id" 1/100 "$mnt"
  btrfs subvolume delete "$mnt/intermediate" >/dev/null

  # Q1 should be at 0, but still has 16k. Q2 is "correct" at 0 (for now...)

  # Trigger cleaner, wait for deletions
  mount -o remount,sync=1 "$mnt"
  btrfs subvolume sync "$mnt" "$snap_id"
  btrfs subvolume sync "$mnt" "$inter_id"

  # Remove Q1 from Q2
  # Frees 16k more from Q2, underflowing it to 16EiB
  btrfs qgroup remove 1/100 2/100 "$mnt"

  # And show the bad state:
  btrfs qgroup show -pc "$mnt"

        Qgroupid    Referenced    Exclusive Parent   Child   Path
        --------    ----------    --------- ------   -----   ----
        0/5           16.00KiB     16.00KiB -        -       <toplevel>
        0/256         16.00KiB     16.00KiB -        -       base
        1/100         16.00KiB     16.00KiB -        -       <0 member qgroups>
        2/100         16.00EiB     16.00EiB -        -       <0 member qgroups>

Fix this by simply not doing this quick inheritance with squotas.

I suspect that it is also wrong in normal qgroups to not recurse up the
qgroup tree in the quick inherit case, though other consistency checks
will likely fix it anyway.

Fixes: b20fe56cd2 ("btrfs: qgroup: allow quick inherit if snapshot is created and added to the same parent")
Reviewed-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: Boris Burkov <boris@bur.io>
Signed-off-by: David Sterba <dsterba@suse.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
History 2026-01-17 16:35:18 +01:00
arch alpha: don't reference obsolete termio struct for TC* constants 2026-01-17 16:35:16 +01:00
block block: fix NULL pointer dereference in blk_zone_reset_all_bio_endio() 2026-01-08 10:17:21 +01:00
certs sign-file,extract-cert: use pkcs11 provider for OPENSSL MAJOR >= 3 2024-09-20 19:52:48 +03:00
crypto crypto: seqiv - Do not use req->iv after crypto_aead_encrypt 2026-01-08 10:16:43 +01:00
Documentation dt-bindings: PCI: qcom,pcie-sm8550: Add missing required power-domains and resets 2026-01-02 12:57:27 +01:00
drivers scsi: Revert "scsi: libsas: Fix exp-attached device scan after probe failure scanned in again after probe failed" 2026-01-17 16:35:18 +01:00
fs btrfs: fix qgroup_snapshot_quick_inherit() squota bug 2026-01-17 16:35:18 +01:00
include drm/atomic-helper: Export and namespace some functions 2026-01-17 16:35:13 +01:00
init printk changes for 6.18 2025-10-04 11:13:11 -07:00
io_uring io_uring/io-wq: fix incorrect io_wq_for_each_worker() termination logic 2026-01-17 16:35:14 +01:00
ipc namespace-6.18-rc1 2025-09-29 11:20:29 -07:00
kernel PM: hibernate: Fix crash when freeing invalid crypto compressor 2026-01-17 16:35:14 +01:00
lib lib/crypto: aes: Fix missing MMU protection for AES S-box 2026-01-17 16:35:12 +01:00
LICENSES LICENSES: Replace the obsolete address of the FSF in the GFDL-1.2 2025-07-24 11:15:39 +02:00
mm mm/damon/tests/core-kunit: handle alloc failures on damon_test_split_regions_of() 2026-01-08 10:17:21 +01:00
net libceph: make calc_target() set t->paused, not just clear it 2026-01-17 16:35:15 +01:00
rust rust: maple_tree: rcu_read_lock() in destructor to silence lockdep 2026-01-08 10:17:11 +01:00
samples samples/ftrace: Adjust LoongArch register restore order in direct calls 2026-01-08 10:17:11 +01:00
scripts mcb: Add missing modpost build support 2026-01-08 10:16:47 +01:00
security kernel/kexec: change the prototype of kimage_map_segment() 2026-01-08 10:17:10 +01:00
sound ALSA: hda/realtek: Add support for ASUS UM3406GA 2026-01-17 16:35:17 +01:00
tools selftests/mm: fix thread state check in uffd-unit-tests 2026-01-08 10:17:11 +01:00
usr gen_init_cpio: Ignore fsync() returning EINVAL on pipes 2025-10-07 09:53:05 -07:00
virt KVM: Fix last_boosted_vcpu index assignment bug 2026-01-02 12:57:21 +01:00
.clang-format memblock: drop for_each_free_mem_pfn_range_in_zone_from() 2025-09-14 08:49:03 +03:00
.clippy.toml rust: clean Rust 1.88.0's warning about clippy::disallowed_macros configuration 2025-05-07 00:11:47 +02:00
.cocciconfig scripts: add Linux .cocciconfig for coccinelle 2016-07-22 12:13:39 +02:00
.editorconfig .editorconfig: remove trim_trailing_whitespace option 2024-06-13 16:47:52 +02:00
.get_maintainer.ignore MAINTAINERS: remove Alyssa Rosenzweig 2025-09-18 21:17:31 +02:00
.gitattributes .gitattributes: set diff driver for Rust source code files 2023-05-31 17:48:25 +02:00
.gitignore .gitignore: ignore compile_commands.json globally 2025-08-12 15:53:55 -07:00
.mailmap 8 hotfixes. 4 are cc:stable, 7 are against mm/. 2025-11-26 12:38:05 -08:00
.pylintrc tools: docs: parse-headers.py: move it from sphinx dir 2025-08-29 15:54:42 -06:00
.rustfmt.toml rust: add .rustfmt.toml 2022-09-28 09:02:20 +02:00
COPYING COPYING: state that all contributions really are covered by this file 2020-02-10 13:32:20 -08:00
CREDITS MAINTAINERS: mark ISDN subsystem as orphan 2025-10-27 17:49:45 -07:00
Kbuild sched: Make migrate_{en,dis}able() inline 2025-09-25 09:57:16 +02:00
Kconfig io_uring: Rename KConfig to Kconfig 2025-02-19 14:53:27 -07:00
MAINTAINERS soc: fixes for 6.18, part 4 2025-11-28 09:57:31 -08:00
Makefile Linux 6.18.5 2026-01-11 15:26:20 +01:00
README README: Fix spelling 2024-03-18 03:36:32 -06:00

Linux kernel
============

There are several guides for kernel developers and users. These guides can
be rendered in a number of formats, like HTML and PDF. Please read
Documentation/admin-guide/README.rst first.

In order to build the documentation, use ``make htmldocs`` or
``make pdfdocs``.  The formatted documentation can also be read online at:

    https://www.kernel.org/doc/html/latest/

There are various text files in the Documentation/ subdirectory,
several of them using the reStructuredText markup notation.

Please read the Documentation/process/changes.rst file, as it contains the
requirements for building and running the kernel, and information about
the problems which may result by upgrading your kernel.