mirror of
https://github.com/torvalds/linux.git
synced 2026-04-18 14:53:58 -04:00
Merge tag 'for-5.8/drivers-2020-06-01' of git://git.kernel.dk/linux-block
Pull block driver updates from Jens Axboe:
"On top of the core changes, here are the block driver changes for this
merge window:
- NVMe changes:
- NVMe over Fibre Channel protocol updates, which also reach
over to drivers/scsi/lpfc (James Smart)
- namespace revalidation support on the target (Anthony
Iliopoulos)
- gcc zero length array fix (Arnd Bergmann)
- nvmet cleanups (Chaitanya Kulkarni)
- misc cleanups and fixes (me, Keith Busch, Sagi Grimberg)
- use a SRQ per completion vector (Max Gurtovoy)
- fix handling of runtime changes to the queue count (Weiping
Zhang)
- t10 protection information support for nvme-rdma and
nvmet-rdma (Israel Rukshin and Max Gurtovoy)
- target side AEN improvements (Chaitanya Kulkarni)
- various fixes and minor improvements all over, icluding the
nvme part of the lpfc driver"
- Floppy code cleanup series (Willy, Denis)
- Floppy contention fix (Jiri)
- Loop CONFIGURE support (Martijn)
- bcache fixes/improvements (Coly, Joe, Colin)
- q->queuedata cleanups (Christoph)
- Get rid of ioctl_by_bdev (Christoph, Stefan)
- md/raid5 allocation fixes (Coly)
- zero length array fixes (Gustavo)
- swim3 task state fix (Xu)"
* tag 'for-5.8/drivers-2020-06-01' of git://git.kernel.dk/linux-block: (166 commits)
bcache: configure the asynchronous registertion to be experimental
bcache: asynchronous devices registration
bcache: fix refcount underflow in bcache_device_free()
bcache: Convert pr_<level> uses to a more typical style
bcache: remove redundant variables i and n
lpfc: Fix return value in __lpfc_nvme_ls_abort
lpfc: fix axchg pointer reference after free and double frees
lpfc: Fix pointer checks and comments in LS receive refactoring
nvme: set dma alignment to qword
nvmet: cleanups the loop in nvmet_async_events_process
nvmet: fix memory leak when removing namespaces and controllers concurrently
nvmet-rdma: add metadata/T10-PI support
nvmet: add metadata support for block devices
nvmet: add metadata/T10-PI support
nvme: add Metadata Capabilities enumerations
nvmet: rename nvmet_check_data_len to nvmet_check_transfer_len
nvmet: rename nvmet_rw_len to nvmet_rw_data_len
nvmet: add metadata characteristics for a namespace
nvme-rdma: add metadata/T10-PI support
nvme-rdma: introduce nvme_rdma_sgl structure
...
This commit is contained in:
@@ -47,6 +47,22 @@ void nvmet_bdev_set_limits(struct block_device *bdev, struct nvme_id_ns *id)
|
||||
id->nows = to0based(ql->io_opt / ql->logical_block_size);
|
||||
}
|
||||
|
||||
static void nvmet_bdev_ns_enable_integrity(struct nvmet_ns *ns)
|
||||
{
|
||||
struct blk_integrity *bi = bdev_get_integrity(ns->bdev);
|
||||
|
||||
if (bi) {
|
||||
ns->metadata_size = bi->tuple_size;
|
||||
if (bi->profile == &t10_pi_type1_crc)
|
||||
ns->pi_type = NVME_NS_DPS_PI_TYPE1;
|
||||
else if (bi->profile == &t10_pi_type3_crc)
|
||||
ns->pi_type = NVME_NS_DPS_PI_TYPE3;
|
||||
else
|
||||
/* Unsupported metadata type */
|
||||
ns->metadata_size = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int nvmet_bdev_ns_enable(struct nvmet_ns *ns)
|
||||
{
|
||||
int ret;
|
||||
@@ -64,6 +80,12 @@ int nvmet_bdev_ns_enable(struct nvmet_ns *ns)
|
||||
}
|
||||
ns->size = i_size_read(ns->bdev->bd_inode);
|
||||
ns->blksize_shift = blksize_bits(bdev_logical_block_size(ns->bdev));
|
||||
|
||||
ns->pi_type = 0;
|
||||
ns->metadata_size = 0;
|
||||
if (IS_ENABLED(CONFIG_BLK_DEV_INTEGRITY_T10))
|
||||
nvmet_bdev_ns_enable_integrity(ns);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -75,6 +97,11 @@ void nvmet_bdev_ns_disable(struct nvmet_ns *ns)
|
||||
}
|
||||
}
|
||||
|
||||
void nvmet_bdev_ns_revalidate(struct nvmet_ns *ns)
|
||||
{
|
||||
ns->size = i_size_read(ns->bdev->bd_inode);
|
||||
}
|
||||
|
||||
static u16 blk_to_nvme_status(struct nvmet_req *req, blk_status_t blk_sts)
|
||||
{
|
||||
u16 status = NVME_SC_SUCCESS;
|
||||
@@ -142,6 +169,61 @@ static void nvmet_bio_done(struct bio *bio)
|
||||
bio_put(bio);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BLK_DEV_INTEGRITY
|
||||
static int nvmet_bdev_alloc_bip(struct nvmet_req *req, struct bio *bio,
|
||||
struct sg_mapping_iter *miter)
|
||||
{
|
||||
struct blk_integrity *bi;
|
||||
struct bio_integrity_payload *bip;
|
||||
struct block_device *bdev = req->ns->bdev;
|
||||
int rc;
|
||||
size_t resid, len;
|
||||
|
||||
bi = bdev_get_integrity(bdev);
|
||||
if (unlikely(!bi)) {
|
||||
pr_err("Unable to locate bio_integrity\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
bip = bio_integrity_alloc(bio, GFP_NOIO,
|
||||
min_t(unsigned int, req->metadata_sg_cnt, BIO_MAX_PAGES));
|
||||
if (IS_ERR(bip)) {
|
||||
pr_err("Unable to allocate bio_integrity_payload\n");
|
||||
return PTR_ERR(bip);
|
||||
}
|
||||
|
||||
bip->bip_iter.bi_size = bio_integrity_bytes(bi, bio_sectors(bio));
|
||||
/* virtual start sector must be in integrity interval units */
|
||||
bip_set_seed(bip, bio->bi_iter.bi_sector >>
|
||||
(bi->interval_exp - SECTOR_SHIFT));
|
||||
|
||||
resid = bip->bip_iter.bi_size;
|
||||
while (resid > 0 && sg_miter_next(miter)) {
|
||||
len = min_t(size_t, miter->length, resid);
|
||||
rc = bio_integrity_add_page(bio, miter->page, len,
|
||||
offset_in_page(miter->addr));
|
||||
if (unlikely(rc != len)) {
|
||||
pr_err("bio_integrity_add_page() failed; %d\n", rc);
|
||||
sg_miter_stop(miter);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
resid -= len;
|
||||
if (len < miter->length)
|
||||
miter->consumed -= miter->length - len;
|
||||
}
|
||||
sg_miter_stop(miter);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
static int nvmet_bdev_alloc_bip(struct nvmet_req *req, struct bio *bio,
|
||||
struct sg_mapping_iter *miter)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
#endif /* CONFIG_BLK_DEV_INTEGRITY */
|
||||
|
||||
static void nvmet_bdev_execute_rw(struct nvmet_req *req)
|
||||
{
|
||||
int sg_cnt = req->sg_cnt;
|
||||
@@ -149,9 +231,12 @@ static void nvmet_bdev_execute_rw(struct nvmet_req *req)
|
||||
struct scatterlist *sg;
|
||||
struct blk_plug plug;
|
||||
sector_t sector;
|
||||
int op, i;
|
||||
int op, i, rc;
|
||||
struct sg_mapping_iter prot_miter;
|
||||
unsigned int iter_flags;
|
||||
unsigned int total_len = nvmet_rw_data_len(req) + req->metadata_len;
|
||||
|
||||
if (!nvmet_check_data_len(req, nvmet_rw_len(req)))
|
||||
if (!nvmet_check_transfer_len(req, total_len))
|
||||
return;
|
||||
|
||||
if (!req->sg_cnt) {
|
||||
@@ -163,8 +248,10 @@ static void nvmet_bdev_execute_rw(struct nvmet_req *req)
|
||||
op = REQ_OP_WRITE | REQ_SYNC | REQ_IDLE;
|
||||
if (req->cmd->rw.control & cpu_to_le16(NVME_RW_FUA))
|
||||
op |= REQ_FUA;
|
||||
iter_flags = SG_MITER_TO_SG;
|
||||
} else {
|
||||
op = REQ_OP_READ;
|
||||
iter_flags = SG_MITER_FROM_SG;
|
||||
}
|
||||
|
||||
if (is_pci_p2pdma_page(sg_page(req->sg)))
|
||||
@@ -186,11 +273,24 @@ static void nvmet_bdev_execute_rw(struct nvmet_req *req)
|
||||
bio->bi_opf = op;
|
||||
|
||||
blk_start_plug(&plug);
|
||||
if (req->metadata_len)
|
||||
sg_miter_start(&prot_miter, req->metadata_sg,
|
||||
req->metadata_sg_cnt, iter_flags);
|
||||
|
||||
for_each_sg(req->sg, sg, req->sg_cnt, i) {
|
||||
while (bio_add_page(bio, sg_page(sg), sg->length, sg->offset)
|
||||
!= sg->length) {
|
||||
struct bio *prev = bio;
|
||||
|
||||
if (req->metadata_len) {
|
||||
rc = nvmet_bdev_alloc_bip(req, bio,
|
||||
&prot_miter);
|
||||
if (unlikely(rc)) {
|
||||
bio_io_error(bio);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
bio = bio_alloc(GFP_KERNEL, min(sg_cnt, BIO_MAX_PAGES));
|
||||
bio_set_dev(bio, req->ns->bdev);
|
||||
bio->bi_iter.bi_sector = sector;
|
||||
@@ -204,6 +304,14 @@ static void nvmet_bdev_execute_rw(struct nvmet_req *req)
|
||||
sg_cnt--;
|
||||
}
|
||||
|
||||
if (req->metadata_len) {
|
||||
rc = nvmet_bdev_alloc_bip(req, bio, &prot_miter);
|
||||
if (unlikely(rc)) {
|
||||
bio_io_error(bio);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
submit_bio(bio);
|
||||
blk_finish_plug(&plug);
|
||||
}
|
||||
@@ -212,7 +320,7 @@ static void nvmet_bdev_execute_flush(struct nvmet_req *req)
|
||||
{
|
||||
struct bio *bio = &req->b.inline_bio;
|
||||
|
||||
if (!nvmet_check_data_len(req, 0))
|
||||
if (!nvmet_check_transfer_len(req, 0))
|
||||
return;
|
||||
|
||||
bio_init(bio, req->inline_bvec, ARRAY_SIZE(req->inline_bvec));
|
||||
@@ -304,7 +412,7 @@ static void nvmet_bdev_execute_write_zeroes(struct nvmet_req *req)
|
||||
sector_t nr_sector;
|
||||
int ret;
|
||||
|
||||
if (!nvmet_check_data_len(req, 0))
|
||||
if (!nvmet_check_transfer_len(req, 0))
|
||||
return;
|
||||
|
||||
sector = le64_to_cpu(write_zeroes->slba) <<
|
||||
@@ -331,6 +439,8 @@ u16 nvmet_bdev_parse_io_cmd(struct nvmet_req *req)
|
||||
case nvme_cmd_read:
|
||||
case nvme_cmd_write:
|
||||
req->execute = nvmet_bdev_execute_rw;
|
||||
if (req->sq->ctrl->pi_support && nvmet_ns_has_pi(req->ns))
|
||||
req->metadata_len = nvmet_rw_metadata_len(req);
|
||||
return 0;
|
||||
case nvme_cmd_flush:
|
||||
req->execute = nvmet_bdev_execute_flush;
|
||||
|
||||
Reference in New Issue
Block a user