• Keith Busch's avatar
    nvme: Fix memory order on async queue deletion · 8c325770
    Keith Busch authored
    This patch is a fix specific to the 3.19 - 4.4 kernels. The 4.5 kernel
    inadvertently fixed this bug differently (db3cbfff), but is not
    a stable candidate due it being a complicated re-write of the entire
    feature.
    
    This patch fixes a potential timing bug with nvme's asynchronous queue
    deletion, which causes an allocated request to be accidentally released
    due to the ordering of the shared completion context among the sq/cq
    pair. The completion context saves the request that issued the queue
    deletion. If the submission side deletion happens to reset the active
    request, the completion side will release the wrong request tag back into
    the pool of available tags. This means the driver will create multiple
    commands with the same tag, corrupting the queue context.
    
    The error is observable in the kernel logs like:
    
      "nvme XX:YY:ZZ completed id XX twice on qid:0"
    
    In this particular case, this message occurs because the queue is
    corrupted.
    
    The following timing sequence demonstrates the error:
    
      CPU A                                 CPU B
      -----------------------               -----------------------------
      nvme_irq
       nvme_process_cq
        async_completion
         queue_kthread_work  ----------->   nvme_del_sq_work_handler
                                             nvme_delete_cq
                                              adapter_async_del_queue
                                               nvme_submit_admin_async_cmd
                                                cmdinfo->req = req;
    
         blk_mq_free_request(cmdinfo->req); <-- wrong request!!!
    
    This patch fixes the bug by releasing the request in the completion side
    prior to waking the submission thread, such that that thread can't muck
    with the shared completion context.
    
    Fixes: a4aea562
    
     ("NVMe: Convert to blk-mq")
    Signed-off-by: default avatarKeith Busch <keith.busch@intel.com>
    Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
    8c325770
pci.c 87.6 KB