Skip to content
  • Paolo Valente's avatar
    block, bfq: fix unbalanced decrements of burst size · 99fead8d
    Paolo Valente authored
    The commit "block, bfq: decrease burst size when queues in burst
    exit" introduced the decrement of burst_size on the removal of a
    bfq_queue from the burst list. Unfortunately, this decrement can
    happen to be performed even when burst size is already equal to 0,
    because of unbalanced decrements. A description follows of the cause
    of these unbalanced decrements, namely a wrong assumption, and of the
    way how this wrong assumption leads to unbalanced decrements.
    
    The wrong assumption is that a bfq_queue can exit only if the process
    associated with the bfq_queue has exited. This is false, because a
    bfq_queue, say Q, may exit also as a consequence of a merge with
    another bfq_queue. In this case, Q exits because the I/O of its
    associated process has been redirected to another bfq_queue.
    
    The decrement unbalance occurs because Q may then be re-created after
    a split, and added back to the current burst list, *without*
    incrementing burst_size. burst_size is not incremented because Q is
    not a new bfq_queue added to the burst list, but a bfq_queue only
    temporarily removed from the list, and, before the commit "bfq-sq,
    bfq-mq: decrease burst size when queues in burst exit", burst_size was
    not decremented when Q was removed.
    
    This commit addresses this issue by just checking whether the exiting
    bfq_queue is a merged bfq_queue, and, in that case, not decrementing
    burst_size. Unfortunately, this still leaves room for unbalanced
    decrements, in the following rarer case: on a split, the bfq_queue
    happens to be inserted into a different burst list than that it was
    removed from when merged. If this happens, the number of elements in
    the new burst list becomes higher than burst_size (by one). When the
    bfq_queue then exits, it is of course not in a merged state any
    longer, thus burst_size is decremented, which results in an unbalanced
    decrement.  To handle this sporadic, unlucky case in a simple way,
    this commit also checks that burst_size is larger than 0 before
    decrementing it.
    
    Finally, this commit removes an useless, extra check: the check that
    the bfq_queue is sync, performed before checking whether the bfq_queue
    is in the burst list. This extra check is redundant, because only sync
    bfq_queues can be inserted into the burst list.
    
    Fixes: 7cb04004
    
     ("block, bfq: decrease burst size when queues in burst exit")
    Reported-by: default avatarPhilip Müller <philm@manjaro.org>
    Signed-off-by: default avatarPaolo Valente <paolo.valente@linaro.org>
    Signed-off-by: default avatarAngelo Ruocco <angeloruocco90@gmail.com>
    Tested-by: default avatarPhilip Müller <philm@manjaro.org>
    Tested-by: default avatarOleksandr Natalenko <oleksandr@natalenko.name>
    Tested-by: default avatarLee Tibbert <lee.tibbert@gmail.com>
    Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
    99fead8d