diff options
author | Keith Busch <keith.busch@intel.com> | 2014-09-10 19:21:14 -0400 |
---|---|---|
committer | Jens Axboe <axboe@fb.com> | 2014-11-04 15:17:09 -0500 |
commit | 1b9dbf7fe02d85f70e8efc1c12c070206c0d5c5f (patch) | |
tree | c1fc5b8c2d57092781eeee197cb6dc84c3e2f1b8 /drivers/block | |
parent | 7be50e93fbc281967589a04be5b1125539b0d0e2 (diff) |
NVMe: Add revalidate_disk callback
This adds a callback to revalidate the disk and change its block size
and capacity if needed. Before, a user would have to remove + rescan
an entire device if they changed the logical block size using an NVMe
Format or other vendor specific command; now they can just run something
that issues the BLKRRPART IOCTL, like
# hdparm -z /dev/nvmeXnY
This can also be used in response to the 1.2 Spec's Namespace Attribute
Change asynchronous event.
Signed-off-by: Keith Busch <keith.busch@intel.com>
Signed-off-by: Matthew Wilcox <matthew.r.wilcox@intel.com>
Signed-off-by: Jens Axboe <axboe@fb.com>
Diffstat (limited to 'drivers/block')
-rw-r--r-- | drivers/block/nvme-core.c | 30 |
1 files changed, 30 insertions, 0 deletions
diff --git a/drivers/block/nvme-core.c b/drivers/block/nvme-core.c index 16a886c2b73d..93ee55ee3775 100644 --- a/drivers/block/nvme-core.c +++ b/drivers/block/nvme-core.c | |||
@@ -1853,6 +1853,35 @@ static int nvme_getgeo(struct block_device *bd, struct hd_geometry *geo) | |||
1853 | return 0; | 1853 | return 0; |
1854 | } | 1854 | } |
1855 | 1855 | ||
1856 | static int nvme_revalidate_disk(struct gendisk *disk) | ||
1857 | { | ||
1858 | struct nvme_ns *ns = disk->private_data; | ||
1859 | struct nvme_dev *dev = ns->dev; | ||
1860 | struct nvme_id_ns *id; | ||
1861 | dma_addr_t dma_addr; | ||
1862 | int lbaf; | ||
1863 | |||
1864 | id = dma_alloc_coherent(&dev->pci_dev->dev, 4096, &dma_addr, | ||
1865 | GFP_KERNEL); | ||
1866 | if (!id) { | ||
1867 | dev_warn(&dev->pci_dev->dev, "%s: Memory alocation failure\n", | ||
1868 | __func__); | ||
1869 | return 0; | ||
1870 | } | ||
1871 | |||
1872 | if (nvme_identify(dev, ns->ns_id, 0, dma_addr)) | ||
1873 | goto free; | ||
1874 | |||
1875 | lbaf = id->flbas & 0xf; | ||
1876 | ns->lba_shift = id->lbaf[lbaf].ds; | ||
1877 | |||
1878 | blk_queue_logical_block_size(ns->queue, 1 << ns->lba_shift); | ||
1879 | set_capacity(disk, le64_to_cpup(&id->nsze) << (ns->lba_shift - 9)); | ||
1880 | free: | ||
1881 | dma_free_coherent(&dev->pci_dev->dev, 4096, id, dma_addr); | ||
1882 | return 0; | ||
1883 | } | ||
1884 | |||
1856 | static const struct block_device_operations nvme_fops = { | 1885 | static const struct block_device_operations nvme_fops = { |
1857 | .owner = THIS_MODULE, | 1886 | .owner = THIS_MODULE, |
1858 | .ioctl = nvme_ioctl, | 1887 | .ioctl = nvme_ioctl, |
@@ -1860,6 +1889,7 @@ static const struct block_device_operations nvme_fops = { | |||
1860 | .open = nvme_open, | 1889 | .open = nvme_open, |
1861 | .release = nvme_release, | 1890 | .release = nvme_release, |
1862 | .getgeo = nvme_getgeo, | 1891 | .getgeo = nvme_getgeo, |
1892 | .revalidate_disk= nvme_revalidate_disk, | ||
1863 | }; | 1893 | }; |
1864 | 1894 | ||
1865 | static void nvme_resubmit_iods(struct nvme_queue *nvmeq) | 1895 | static void nvme_resubmit_iods(struct nvme_queue *nvmeq) |