0

These are old fusion-io PCIe drives which otherwise are long lasting SLC/MLC available in great quantities for cheap but of course being old lack support. I was using few with older Linux kernel v5.10 but was forced to upgrade to v5.19 due WiFi module support and performance fixes.

Apparently I discovered some changes were made to kernel v5.19 making compilation impossible without changes. I don't have large experience with coding beyond embedded system but definitely I am not Linux kernel/driver developer.

Long story short, I made the driver work, it is compiling, loading and in general working but I have concerns as to some guessing and figuring it out and how "unsafe" it became.

Specifically this may affect data in transit on device detach, does not happen every day but data is data.

What I discovered: pci_*() got replaced with dma_*(), PDE_DATA with pde_data (key change!), PCI_DMA_* with DMA_* and considerable changes to block device queue flags and functions to operate them where some were removed.

-    blk_queue_flag_set(QUEUE_FLAG_DISCARD, rq);
+    blk_queue_max_discard_sectors(rq, 0);

-    pci_unmap_sg(lsg->pci_dev, lsg->sl, lsg->num_entries,
-                 lsg->pci_dir == IODRIVE_DMA_DIR_READ ? PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE);
+    dma_unmap_sg(&lsg->pci_dev->dev, lsg->sl, lsg->num_entries,
+                 lsg->pci_dir == IODRIVE_DMA_DIR_READ ? DMA_FROM_DEVICE : DMA_TO_DEVICE);

-    return PDE_DATA(ip);
+    return pde_data(ip);

-    return pci_set_dma_mask((struct pci_dev *)pdev, mask);
+    return dma_set_mask(&((struct pci_dev *)pdev)->dev, mask);

These were the easier changes, but there are also changes to allocation of queues. And here I have some questions.

QUEUE_FLAG_DISCARD is no longer available, do I get similar result with blk_queue_max_discard_sectors(rq, 0);?

QUEUE_FLAG_DEAD is no longer available, do I get similar result with blk_queue_flag_set(QUEUE_FLAG_DYING, disk->rq);? Assume should stop accepting new IO as it is DYING and prevent data loss?

And here is the main culprit, blk_cleanup_queue() is also not directly available anymore in v5.19. For now I have removed this completely and wondering how bad it is. I tried with blk_mq_destroy_queue() but since entire driver is built around blk_queue_make_request() when I trigger blk_mq_destroy_queue(disk->rq); I get exception and stack trace points to blk_mq_destroy, quite sure because driver is not using blk_mq_init_queue()?

How bad is to leave it like this? Drive gets detached without exceptions but disk->rq = NULL; clears only rq, not queues. But is del_gendisk(disk->gd); not clearing all disk related data/structures?

void kfio_destroy_disk(kfio_disk_t *disk, destroy_type_t dt)
{
    if (disk->gd != NULL) {
        set_capacity(disk->gd, 0);

        if (disk->queue_lock != NULL)
            fusion_spin_lock_irqsave(disk->queue_lock);

        /* Stop delivery of new io from user. */
//      set_bit(QUEUE_FLAG_DEAD, &disk->rq->queue_flags);
        blk_queue_flag_set(QUEUE_FLAG_DYING, disk->rq);
        /*
         * Prevent request_fn callback from interfering with
         * the queue shutdown.
         */
        blk_mq_stop_hw_queues(disk->rq);
        /*
         * The queue is stopped and dead and no new user requests will be
         * coming to it anymore. Fetch remaining already queued requests
         * and fail them,
         */
        if (use_workqueue == USE_QUEUE_RQ)
            kfio_kill_requests(disk->rq);
        if (use_workqueue != USE_QUEUE_RQ) {
            /* Fail all bio's already on internal bio queue. */
            struct bio *bio;

            while ((bio = disk->bio_head) != NULL) {
                disk->bio_head = bio->bi_next;
                __kfio_bio_complete(bio,  0, -EIO);
            }
            disk->bio_tail = NULL;
        }

        if (disk->queue_lock != NULL)
            fusion_spin_unlock_irqrestore(disk->queue_lock);

        del_gendisk(disk->gd);

        put_disk(disk->gd);
        disk->gd = NULL;
    }

    if (disk->rq != NULL) {
//      blk_mq_destroy_queue(disk->rq);
//      blk_cleanup_queue(disk->rq);
        disk->rq = NULL;
    }

    fusion_condvar_destroy(&disk->state_cv);
    fusion_cv_lock_destroy(&disk->state_lk);
}
0andriy
  • 4,183
  • 1
  • 24
  • 37
mmx01
  • 1
  • 1

0 Answers0