summaryrefslogtreecommitdiff
path: root/tools/lib/python
diff options
context:
space:
mode:
authorNickolai Zeldovich <nickolai@csail.mit.edu>2026-10-16 23:06:20 -0400
committerAndrew Morton <akpm@linux-foundation.org>2026-10-24 01:56:39 -0700
commitb428f1966821cd285957fb41a621141b22622a7d (patch)
tree862dda7b768ea4409c2887000d66a64033db0b79 /tools/lib/python
parent1a2993227e8a27fc4cdea305bbdae82d290bc885 (diff)
mm: bdi: reset min_ratio after the sysfs attributes are gone
A write to /sys/class/bdi/<dev>/min_ratio (or min_ratio_fine or min_bytes) that races with the removal of the device leaves the global sum of minimum dirty shares charged for a bdi that no longer exists. Until the next reboot, that share of the dirty threshold is withheld from every other bdi (__wb_calc_thresh() scales by 100 % minus the sum), and a later min_ratio store on any bdi that would push the sum to 100 % fails with EINVAL although every bdi reads 0. Root privilege is needed for the store; the removal is any del_gendisk() (a disk or loop device going away) or the unmount of a filesystem with its own bdi. On an x86_64 defconfig kernel (v7.3-rc7), 2000 rounds of LOOP_CTL_ADD/LOOP_CTL_REMOVE on one loop device with a second thread writing 50 to its min_ratio leak the share on the first round the store lands in the window; afterwards `echo 99 > min_ratio` on another loop device fails with EINVAL. With the fix the same run keeps the sum at 0 and the store succeeds. Affected since v5.16, when the reset in bdi_unregister() was added. bdi_unregister() gives the bdi's share back with bdi_set_min_ratio(bdi, 0) and only then calls device_unregister(), which removes the sysfs attributes. A min_ratio_store() that gets its kernfs active reference before the removal runs to completion after the reset: __bdi_set_min_ratio() takes bdi_lock, sees bdi->min_ratio == 0, adds the new value to bdi_min_ratio and stores it in the bdi, which bdi_put() then frees. Nothing gives that share back. Move the reset after device_unregister(): once the attributes are gone no store can run, and bdi_set_min_ratio() needs nothing from the device. Found while formally verifying bdi_unregister() against the kernel binary. Link: https://lore.kernel.org/20261017030620.793108-1-nickolai@csail.mit.edu Fixes: 3c376dfafbf7 ("mm: bdi: initialize bdi_min_ratio when bdi is unregistered") Signed-off-by: Nickolai Zeldovich <nickolai@csail.mit.edu> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Reviewed-by: Jan Kara <jack@suse.cz> Assisted-by: LLM Cc: David Hildenbrand <david@kernel.org> Cc: Lorenzo Stoakes <ljs@kernel.org> Cc: Liam R. Howlett <liam@infradead.org> Cc: Vlastimil Babka <vbabka@kernel.org> Cc: Mike Rapoport <rppt@kernel.org> Cc: Suren Baghdasaryan <surenb@google.com> Cc: Michal Hocko <mhocko@suse.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Manjong Lee <mj0123.lee@samsung.com>
Diffstat (limited to 'tools/lib/python')
0 files changed, 0 insertions, 0 deletions