Peter, Now I get 3 figures. Test case is: run 1 dd write task for 300s, with a "disturber" dd read task during roughly 120-130s. (1) balance_dirty_pages-pages.png This is the output of the original patchset. Here the "balanced ratelimit" dots are mostly accurate except when near @freerun or @limit. (2) balance_dirty_pages-pages_pure-rate-feedback.png do this change: - balanced_dirty_ratelimit = div_u64((u64)task_ratelimit * write_bw, + balanced_dirty_ratelimit = div_u64((u64)dirty_ratelimit * write_bw, dirty_rate | 1); Here the "balanced ratelimit" dots goto the opposite direction comparing to "pos ratelimit", which is the expected result discussed in the other email. Then the system got stuck in unbalanced dirty position. It's slowly moving towards the setpoint thanks to the dirty_ratelimit update policy: it only updates dirty_ratelimit when balanced_dirty_ratelimit fluctuates to the same side of task_ratelimit, hence introduced some systematical "errors" in the right direction ;) (3) balance_dirty_pages-pages_pure-rate-feedback-without-dirty_ratelimit-update-constraints.png further remove the "do conservative bdi->dirty_ratelimit updates" feature, by replacing its update policy with a direct assignment: bdi->dirty_ratelimit = max(balanced_dirty_ratelimit, 1UL); This is to check if dirty_ratelimit can still go back to the balance point without the help of the dirty_ratelimit update policy. To my surprise, dirty_ratelimit jumps to HUGE singular value and shows no sign to come back to normal.. In summary, the original patchset shows the best behavior :) Thanks, Fengguang