aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block
diff options
context:
space:
mode:
authorKeith Busch <keith.busch@intel.com>2015-04-07 18:57:19 -0400
committerJens Axboe <axboe@fb.com>2015-04-07 21:11:06 -0400
commita67a95134ffddd0ca4527c77e86375c3deb2938f (patch)
tree26981c1df5c40941a9bdcda9dad235cf8a82b4f8 /drivers/block
parent7f749d9c109223e4d1724e674e7d603082e85839 (diff)
NVMe: Meta data handling through submit io ioctl
This adds support for the extended metadata formats through the submit IO ioctl, and simplifies the rest when using a separate metadata format. Signed-off-by: Keith Busch <keith.busch@intel.com> Signed-off-by: Jens Axboe <axboe@fb.com>
Diffstat (limited to 'drivers/block')
-rw-r--r--drivers/block/nvme-core.c123
1 files changed, 49 insertions, 74 deletions
diff --git a/drivers/block/nvme-core.c b/drivers/block/nvme-core.c
index 973c895bd7af..e919de48ff25 100644
--- a/drivers/block/nvme-core.c
+++ b/drivers/block/nvme-core.c
@@ -1745,25 +1745,31 @@ static int nvme_submit_io(struct nvme_ns *ns, struct nvme_user_io __user *uio)
1745 struct nvme_dev *dev = ns->dev; 1745 struct nvme_dev *dev = ns->dev;
1746 struct nvme_user_io io; 1746 struct nvme_user_io io;
1747 struct nvme_command c; 1747 struct nvme_command c;
1748 unsigned length, meta_len; 1748 unsigned length, meta_len, prp_len;
1749 int status, i; 1749 int status, write;
1750 struct nvme_iod *iod, *meta_iod = NULL; 1750 struct nvme_iod *iod;
1751 dma_addr_t meta_dma_addr; 1751 dma_addr_t meta_dma = 0;
1752 void *meta, *uninitialized_var(meta_mem); 1752 void *meta = NULL;
1753 1753
1754 if (copy_from_user(&io, uio, sizeof(io))) 1754 if (copy_from_user(&io, uio, sizeof(io)))
1755 return -EFAULT; 1755 return -EFAULT;
1756 length = (io.nblocks + 1) << ns->lba_shift; 1756 length = (io.nblocks + 1) << ns->lba_shift;
1757 meta_len = (io.nblocks + 1) * ns->ms; 1757 meta_len = (io.nblocks + 1) * ns->ms;
1758 1758
1759 if (meta_len && ((io.metadata & 3) || !io.metadata)) 1759 if (meta_len && ((io.metadata & 3) || !io.metadata) && !ns->ext)
1760 return -EINVAL; 1760 return -EINVAL;
1761 else if (meta_len && ns->ext) {
1762 length += meta_len;
1763 meta_len = 0;
1764 }
1765
1766 write = io.opcode & 1;
1761 1767
1762 switch (io.opcode) { 1768 switch (io.opcode) {
1763 case nvme_cmd_write: 1769 case nvme_cmd_write:
1764 case nvme_cmd_read: 1770 case nvme_cmd_read:
1765 case nvme_cmd_compare: 1771 case nvme_cmd_compare:
1766 iod = nvme_map_user_pages(dev, io.opcode & 1, io.addr, length); 1772 iod = nvme_map_user_pages(dev, write, io.addr, length);
1767 break; 1773 break;
1768 default: 1774 default:
1769 return -EINVAL; 1775 return -EINVAL;
@@ -1772,6 +1778,27 @@ static int nvme_submit_io(struct nvme_ns *ns, struct nvme_user_io __user *uio)
1772 if (IS_ERR(iod)) 1778 if (IS_ERR(iod))
1773 return PTR_ERR(iod); 1779 return PTR_ERR(iod);
1774 1780
1781 prp_len = nvme_setup_prps(dev, iod, length, GFP_KERNEL);
1782 if (length != prp_len) {
1783 status = -ENOMEM;
1784 goto unmap;
1785 }
1786 if (meta_len) {
1787 meta = dma_alloc_coherent(&dev->pci_dev->dev, meta_len,
1788 &meta_dma, GFP_KERNEL);
1789 if (!meta) {
1790 status = -ENOMEM;
1791 goto unmap;
1792 }
1793 if (write) {
1794 if (copy_from_user(meta, (void __user *)io.metadata,
1795 meta_len)) {
1796 status = -EFAULT;
1797 goto unmap;
1798 }
1799 }
1800 }
1801
1775 memset(&c, 0, sizeof(c)); 1802 memset(&c, 0, sizeof(c));
1776 c.rw.opcode = io.opcode; 1803 c.rw.opcode = io.opcode;
1777 c.rw.flags = io.flags; 1804 c.rw.flags = io.flags;
@@ -1783,75 +1810,21 @@ static int nvme_submit_io(struct nvme_ns *ns, struct nvme_user_io __user *uio)
1783 c.rw.reftag = cpu_to_le32(io.reftag); 1810 c.rw.reftag = cpu_to_le32(io.reftag);
1784 c.rw.apptag = cpu_to_le16(io.apptag); 1811 c.rw.apptag = cpu_to_le16(io.apptag);
1785 c.rw.appmask = cpu_to_le16(io.appmask); 1812 c.rw.appmask = cpu_to_le16(io.appmask);
1786
1787 if (meta_len) {
1788 meta_iod = nvme_map_user_pages(dev, io.opcode & 1, io.metadata,
1789 meta_len);
1790 if (IS_ERR(meta_iod)) {
1791 status = PTR_ERR(meta_iod);
1792 meta_iod = NULL;
1793 goto unmap;
1794 }
1795
1796 meta_mem = dma_alloc_coherent(&dev->pci_dev->dev, meta_len,
1797 &meta_dma_addr, GFP_KERNEL);
1798 if (!meta_mem) {
1799 status = -ENOMEM;
1800 goto unmap;
1801 }
1802
1803 if (io.opcode & 1) {
1804 int meta_offset = 0;
1805
1806 for (i = 0; i < meta_iod->nents; i++) {
1807 meta = kmap_atomic(sg_page(&meta_iod->sg[i])) +
1808 meta_iod->sg[i].offset;
1809 memcpy(meta_mem + meta_offset, meta,
1810 meta_iod->sg[i].length);
1811 kunmap_atomic(meta);
1812 meta_offset += meta_iod->sg[i].length;
1813 }
1814 }
1815
1816 c.rw.metadata = cpu_to_le64(meta_dma_addr);
1817 }
1818
1819 length = nvme_setup_prps(dev, iod, length, GFP_KERNEL);
1820 c.rw.prp1 = cpu_to_le64(sg_dma_address(iod->sg)); 1813 c.rw.prp1 = cpu_to_le64(sg_dma_address(iod->sg));
1821 c.rw.prp2 = cpu_to_le64(iod->first_dma); 1814 c.rw.prp2 = cpu_to_le64(iod->first_dma);
1822 1815 c.rw.metadata = cpu_to_le64(meta_dma);
1823 if (length != (io.nblocks + 1) << ns->lba_shift) 1816 status = nvme_submit_io_cmd(dev, ns, &c, NULL);
1824 status = -ENOMEM;
1825 else
1826 status = nvme_submit_io_cmd(dev, ns, &c, NULL);
1827
1828 if (meta_len) {
1829 if (status == NVME_SC_SUCCESS && !(io.opcode & 1)) {
1830 int meta_offset = 0;
1831
1832 for (i = 0; i < meta_iod->nents; i++) {
1833 meta = kmap_atomic(sg_page(&meta_iod->sg[i])) +
1834 meta_iod->sg[i].offset;
1835 memcpy(meta, meta_mem + meta_offset,
1836 meta_iod->sg[i].length);
1837 kunmap_atomic(meta);
1838 meta_offset += meta_iod->sg[i].length;
1839 }
1840 }
1841
1842 dma_free_coherent(&dev->pci_dev->dev, meta_len, meta_mem,
1843 meta_dma_addr);
1844 }
1845
1846 unmap: 1817 unmap:
1847 nvme_unmap_user_pages(dev, io.opcode & 1, iod); 1818 nvme_unmap_user_pages(dev, write, iod);
1848 nvme_free_iod(dev, iod); 1819 nvme_free_iod(dev, iod);
1849 1820 if (meta) {
1850 if (meta_iod) { 1821 if (status == NVME_SC_SUCCESS && !write) {
1851 nvme_unmap_user_pages(dev, io.opcode & 1, meta_iod); 1822 if (copy_to_user((void __user *)io.metadata, meta,
1852 nvme_free_iod(dev, meta_iod); 1823 meta_len))
1824 status = -EFAULT;
1825 }
1826 dma_free_coherent(&dev->pci_dev->dev, meta_len, meta, meta_dma);
1853 } 1827 }
1854
1855 return status; 1828 return status;
1856} 1829}
1857 1830
@@ -2014,7 +1987,8 @@ static int nvme_revalidate_disk(struct gendisk *disk)
2014 struct nvme_dev *dev = ns->dev; 1987 struct nvme_dev *dev = ns->dev;
2015 struct nvme_id_ns *id; 1988 struct nvme_id_ns *id;
2016 dma_addr_t dma_addr; 1989 dma_addr_t dma_addr;
2017 int lbaf, pi_type, old_ms; 1990 u8 lbaf, pi_type;
1991 u16 old_ms;
2018 unsigned short bs; 1992 unsigned short bs;
2019 1993
2020 id = dma_alloc_coherent(&dev->pci_dev->dev, 4096, &dma_addr, 1994 id = dma_alloc_coherent(&dev->pci_dev->dev, 4096, &dma_addr,
@@ -2035,6 +2009,7 @@ static int nvme_revalidate_disk(struct gendisk *disk)
2035 lbaf = id->flbas & NVME_NS_FLBAS_LBA_MASK; 2009 lbaf = id->flbas & NVME_NS_FLBAS_LBA_MASK;
2036 ns->lba_shift = id->lbaf[lbaf].ds; 2010 ns->lba_shift = id->lbaf[lbaf].ds;
2037 ns->ms = le16_to_cpu(id->lbaf[lbaf].ms); 2011 ns->ms = le16_to_cpu(id->lbaf[lbaf].ms);
2012 ns->ext = ns->ms && (id->flbas & NVME_NS_FLBAS_META_EXT);
2038 2013
2039 /* 2014 /*
2040 * If identify namespace failed, use default 512 byte block size so 2015 * If identify namespace failed, use default 512 byte block size so
@@ -2051,14 +2026,14 @@ static int nvme_revalidate_disk(struct gendisk *disk)
2051 if (blk_get_integrity(disk) && (ns->pi_type != pi_type || 2026 if (blk_get_integrity(disk) && (ns->pi_type != pi_type ||
2052 ns->ms != old_ms || 2027 ns->ms != old_ms ||
2053 bs != queue_logical_block_size(disk->queue) || 2028 bs != queue_logical_block_size(disk->queue) ||
2054 (ns->ms && id->flbas & NVME_NS_FLBAS_META_EXT))) 2029 (ns->ms && ns->ext)))
2055 blk_integrity_unregister(disk); 2030 blk_integrity_unregister(disk);
2056 2031
2057 ns->pi_type = pi_type; 2032 ns->pi_type = pi_type;
2058 blk_queue_logical_block_size(ns->queue, bs); 2033 blk_queue_logical_block_size(ns->queue, bs);
2059 2034
2060 if (ns->ms && !blk_get_integrity(disk) && (disk->flags & GENHD_FL_UP) && 2035 if (ns->ms && !blk_get_integrity(disk) && (disk->flags & GENHD_FL_UP) &&
2061 !(id->flbas & NVME_NS_FLBAS_META_EXT)) 2036 !ns->ext)
2062 nvme_init_integrity(ns); 2037 nvme_init_integrity(ns);
2063 2038
2064 if (id->ncap == 0 || (ns->ms && !blk_get_integrity(disk))) 2039 if (id->ncap == 0 || (ns->ms && !blk_get_integrity(disk)))