• Tejun Heo's avatar
    blk-mq: decouble blk-mq freezing from generic bypassing · 780db207
    Tejun Heo authored
    blk_mq freezing is entangled with generic bypassing which bypasses
    blkcg and io scheduler and lets IO requests fall through the block
    layer to the drivers in FIFO order.  This allows forward progress on
    IOs with the advanced features disabled so that those features can be
    configured or altered without worrying about stalling IO which may
    lead to deadlock through memory allocation.
    
    However, generic bypassing doesn't quite fit blk-mq.  blk-mq currently
    doesn't make use of blkcg or ioscheds and it maps bypssing to
    freezing, which blocks request processing and drains all the in-flight
    ones.  This causes problems as bypassing assumes that request
    processing is online.  blk-mq works around this by conditionally
    allowing request processing for the problem case - during queue
    initialization.
    
    Another weirdity is that except for during queue cleanup, bypassing
    started on the generic side prevents blk-mq from processing new
    requests but doesn't drain the in-flight ones.  This shouldn't break
    anything but again highlights that something isn't quite right here.
    
    The root cause is conflating blk-mq freezing and generic bypassing
    which are two different mechanisms.  The only intersecting purpose
    that they serve is during queue cleanup.  Let's properly separate
    blk-mq freezing from generic bypassing and simply use it where
    necessary.
    
    * request_queue->mq_freeze_depth is added and
      blk_mq_[un]freeze_queue() now operate on this counter instead of
      ->bypass_depth.  The replacement for QUEUE_FLAG_BYPASS isn't added
      but the counter is tested directly.  This will be further updated by
      later changes.
    
    * blk_mq_drain_queue() is dropped and "__" prefix is dropped from
      blk_mq_freeze_queue().  Queue cleanup path now calls
      blk_mq_freeze_queue() directly.
    
    * blk_queue_enter()'s fast path condition is simplified to simply
      check @q->mq_freeze_depth.  Previously, the condition was
    
    	!blk_queue_dying(q) &&
    	    (!blk_queue_bypass(q) || !blk_queue_init_done(q))
    
      mq_freeze_depth is incremented right after dying is set and
      blk_queue_init_done() exception isn't necessary as blk-mq doesn't
      start frozen, which only leaves the blk_queue_bypass() test which
      can be replaced by @q->mq_freeze_depth test.
    
    This change simplifies the code and reduces confusion in the area.
    Signed-off-by: default avatarTejun Heo <tj@kernel.org>
    Cc: Jens Axboe <axboe@kernel.dk>
    Cc: Nicholas A. Bellinger <nab@linux-iscsi.org>
    Signed-off-by: default avatarJens Axboe <axboe@fb.com>
    780db207
blk-mq.h 3.12 KB