NVMe: Create discard zero quirk white list
authorKeith Busch <keith.busch@intel.com>
Fri, 4 Mar 2016 20:15:17 +0000 (13:15 -0700)
committerJens Axboe <axboe@fb.com>
Tue, 8 Mar 2016 15:32:40 +0000 (08:32 -0700)
The NVMe specification does not require discarded blocks return zeroes on
read, but provides that behavior as a possibility. Some applications more
efficiently use an SSD if reads on discarded blocks were deterministically
zero, based on the "discard_zeroes_data" queue attribute.

There is no specification defined way to determine device behavior on
discarded blocks, so the driver always left the queue setting disabled. We
can only know behavior based on individual device models, so this patch
adds a flag to the NVMe "quirk" list that vendors may set if they know
their controller works that way. The patch also sets the new flag for one
such known device.

Signed-off-by: Keith Busch <keith.busch@intel.com>
Suggested-by: Artur Paszkiewicz <artur.paszkiewicz@intel.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com>
Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de>
Reviewed-by: Sagi Grimberg <sagig@mellanox.com>
Signed-off-by: Jens Axboe <axboe@fb.com>
drivers/nvme/host/core.c
drivers/nvme/host/nvme.h
drivers/nvme/host/pci.c

index f08dccee81438fcc4cc42ea86ab25fd71ef30ec4..4304be00e556862bf853c45b2070dcc3c9231514 100644 (file)
@@ -582,8 +582,14 @@ static void nvme_init_integrity(struct nvme_ns *ns)
 
 static void nvme_config_discard(struct nvme_ns *ns)
 {
+       struct nvme_ctrl *ctrl = ns->ctrl;
        u32 logical_block_size = queue_logical_block_size(ns->queue);
-       ns->queue->limits.discard_zeroes_data = 0;
+
+       if (ctrl->quirks & NVME_QUIRK_DISCARD_ZEROES)
+               ns->queue->limits.discard_zeroes_data = 1;
+       else
+               ns->queue->limits.discard_zeroes_data = 0;
+
        ns->queue->limits.discard_alignment = logical_block_size;
        ns->queue->limits.discard_granularity = logical_block_size;
        blk_queue_max_discard_sectors(ns->queue, 0xffffffff);
index 9b71fa8c75e4d3237fee89f624567c56001d2c4b..a402a0ebf471526e1a5f296ce44336de75921772 100644 (file)
@@ -59,6 +59,12 @@ enum nvme_quirks {
         * correctly.
         */
        NVME_QUIRK_IDENTIFY_CNS                 = (1 << 1),
+
+       /*
+        * The controller deterministically returns O's on reads to discarded
+        * logical blocks.
+        */
+       NVME_QUIRK_DISCARD_ZEROES               = (1 << 2),
 };
 
 struct nvme_ctrl {
index d47b08783110fdb3133008e2d097c73a4a409100..74514c7674290ee90255183d11a4c3b11c48ce7b 100644 (file)
@@ -2130,7 +2130,8 @@ static const struct pci_error_handlers nvme_err_handler = {
 
 static const struct pci_device_id nvme_id_table[] = {
        { PCI_VDEVICE(INTEL, 0x0953),
-               .driver_data = NVME_QUIRK_STRIPE_SIZE, },
+               .driver_data = NVME_QUIRK_STRIPE_SIZE |
+                               NVME_QUIRK_DISCARD_ZEROES, },
        { PCI_VDEVICE(INTEL, 0x5845),   /* Qemu emulated controller */
                .driver_data = NVME_QUIRK_IDENTIFY_CNS, },
        { PCI_DEVICE_CLASS(PCI_CLASS_STORAGE_EXPRESS, 0xffffff) },