Re: [PATCH v6 0/3] memcg,writeback: flush foreign bdev mappings separately
Julian Sun <[email protected]>
| Newsgroups | org.kernel.vger.linux-fsdevel,org.kernel.vger.cgroups,org.kernel.vger.linux-block,org.kvack.linux-mm |
|---|---|
| Message-ID | <[email protected]> |
On 9/18/26 6:53 AM, Andrew Morton wrote: > On Thu, 17 Sep 2026 14:57:56 +0800 Julian Sun <[email protected]> wrote: > >> Hi, >> >> >> Measured impact >> =============== >> >> The synthetic test used a VM with 4 vCPUs, 8 GiB RAM, ext4 and cgroup >> v2, with device write bandwidth capped at 200 MiB/s. Background fio >> repeatedly overwrote a 256 MiB file using buffered I/O, while >> foreground fio performed sequential direct writes. Four memcgs >> generated metadata and buffered writes to trigger foreign flushes. >> >> We measured completed block writes to the background fio file, >> including final sync, and foreground fio bandwidth, latency and >> completion time. >> >> Across three runs per kernel, mean background file write I/O decreased >> by 72.7%, foreground bandwidth increased by 23.0%, and completion time >> decreased by 18.8%. >> >> Metric Baseline Patched Change >> Background file write I/O (GiB) 6.154 1.680 -72.7% >> Foreground bandwidth (MiB/s) 150.29 184.81 +23.0% >> Foreground completion time (s) 109.203 88.652 -18.8% >> Foreground mean latency (ms) 212.84 172.74 -18.8% > > Thanks. > > As I understand it, this is basically ext4-specific. > > I don't think btrfs or xfs mess with the bdev address_space at all? > But google tells me that "roughly 70% to 80% of all Linux machines use > ext4 as their primary or root file system", so there is that. Yes, most of our systems still use ext4. > >> Approach >> ======== >> >> Following Jan's suggestion, this series records foreign bdev targets >> separately and flushes their mappings instead of their owner wbs. This >> preserves a way for dirty throttling to initiate bdev writeback while >> avoiding owner-wide writeback triggered by these records. The existing >> foreign-wb mechanism remains unchanged for other inodes. >> >> Tracking is best effort: each memcg keeps a bounded set of device >> numbers without persistent device or inode references. Closed devices >> and devices with a busy open_mutex are skipped. Device removal and >> device-number reuse may race with lookup. > > This part looks plain nasty. Why are we messing with dev_t's and > risking these races? > > At the very least, this description should explain the reasoning behind > this decision at some length. > > Surely it's cleaner and safer to grab a ref on something (the bdev > inode?) and hang onto that object. Use it for these operations, let it > go at the appropriate time. Clearly there's something wrong with that > approach, but what? This follows the existing foreign-writeback mechanism's best-effort design: it records IDs without holding any references and tolerates occasional stale hints. I followed the same approach for bdev tracking by recording dev_t. Taking a device reference would introduce additional lifetime management. If we acquire a reference during foreign tracking but the memcg does not enter dirty throttling for a long time, no foreign flush would consume the record and release the reference, then delaying final device-object release. A timeout mechanism would only limit this delay, not eliminate it. There is also a locking issue: dropping a record happens under mapping->i_pages, but dropping the last reference may sleep. We would therefore need to restructure the release path, adding concurrency and lifetime-management complexity. Recording only dev_t follows the existing mechanism's best-effort design. Device-number reuse may cause a stale record to trigger writeback of the new device's own mapping. In my view, this occasional unnecessary writeback is an acceptable trade-off for avoiding the complexity above. > >> Flushes run asynchronously on a dedicated workqueue to isolate these >> frequently triggered tasks from existing workqueue users. If workqueue >> allocation fails, the existing foreign-wb mechanism remains in use. > > Unclear what this means. If a kmalloc/etc fails then we fall back to > the current (mainline) behavior? Fair enough, failure of small > kmallocs are so rare. The main problem is testing the failure-path > code! Yes, if allocation of memcg_bdev_frn_wq in mem_cgroup_init() fails, foreign writeback falls back to the existing mechanism. The workqueue is allocated once during initialization. The new tracking and work- queueing paths use preallocated per-memcg slots and perform no dynamic allocation at runtime. please see patch 2 for more details. I tested this failure path by forcing the workqueue pointer to NULL and the results were as expected.> > > Also, and most importantly, what the heck is "frn"? Would the world > end if you did s/frn/foreign/g? Emmm, the naming follows the existing code. I'll rename the new uses of "frn" to "foreign" in the next version. Renaming the existing code would be a separate cleanup patch; I'd prefer not to mix that into this fix series. Thanks, -- Julian Sun <[email protected]>