Commit 19240e6b authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://git.kernel.dk/linux-block

Pull block fixes from Jens Axboe:

 - Two sets of NVMe pull requests from Christoph:
      - Fixes for the Fibre Channel host/target to fix spec compliance
      - Allow a zero keep alive timeout
      - Make the debug printk for broken SGLs work better
      - Fix queue zeroing during initialization
      - Set of RDMA and FC fixes
      - Target div-by-zero fix

 - bsg double-free fix.

 - ndb unknown ioctl fix from Josef.

 - Buffered vs O_DIRECT page cache inconsistency fix. Has been floating
   around for a long time, well reviewed. From Lukas.

 - brd overflow fix from Mikulas.

 - Fix for a loop regression in this merge window, where using a union
   for two members of the loop_cmd turned out to be a really bad idea.
   From Omar.

 - Fix for an iostat regression fix in this series, using the wrong API
   to get at the block queue. From Shaohua.

 - Fix for a potential blktrace delection deadlock. From Waiman.

* 'for-linus' of git://git.kernel.dk/linux-block: (30 commits)
  nvme-fcloop: fix port deletes and callbacks
  nvmet-fc: sync header templates with comments
  nvmet-fc: ensure target queue id within range.
  nvmet-fc: on port remove call put outside lock
  nvme-rdma: don't fully stop the controller in error recovery
  nvme-rdma: give up reconnect if state change fails
  nvme-core: Use nvme_wq to queue async events and fw activation
  nvme: fix sqhd reference when admin queue connect fails
  block: fix a crash caused by wrong API
  fs: Fix page cache inconsistency when mixing buffered and AIO DIO
  nvmet: implement valid sqhd values in completions
  nvme-fabrics: Allow 0 as KATO value
  nvme: allow timed-out ios to retry
  nvme: stop aer posting if controller state not live
  nvme-pci: Print invalid SGL only once
  nvme-pci: initialize queue memory before interrupts
  nvmet-fc: fix failing max io queue connections
  nvme-fc: use transport-specific sgl format
  nvme: add transport SGL definitions
  nvme.h: remove FC transport-specific error values
  ...
parents 17763641 fddc9923
...@@ -854,6 +854,9 @@ struct request_queue *blk_alloc_queue_node(gfp_t gfp_mask, int node_id) ...@@ -854,6 +854,9 @@ struct request_queue *blk_alloc_queue_node(gfp_t gfp_mask, int node_id)
kobject_init(&q->kobj, &blk_queue_ktype); kobject_init(&q->kobj, &blk_queue_ktype);
#ifdef CONFIG_BLK_DEV_IO_TRACE
mutex_init(&q->blk_trace_mutex);
#endif
mutex_init(&q->sysfs_lock); mutex_init(&q->sysfs_lock);
spin_lock_init(&q->__queue_lock); spin_lock_init(&q->__queue_lock);
......
...@@ -154,7 +154,6 @@ static int bsg_prepare_job(struct device *dev, struct request *req) ...@@ -154,7 +154,6 @@ static int bsg_prepare_job(struct device *dev, struct request *req)
failjob_rls_rqst_payload: failjob_rls_rqst_payload:
kfree(job->request_payload.sg_list); kfree(job->request_payload.sg_list);
failjob_rls_job: failjob_rls_job:
kfree(job);
return -ENOMEM; return -ENOMEM;
} }
......
...@@ -112,7 +112,7 @@ ssize_t part_stat_show(struct device *dev, ...@@ -112,7 +112,7 @@ ssize_t part_stat_show(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct hd_struct *p = dev_to_part(dev); struct hd_struct *p = dev_to_part(dev);
struct request_queue *q = dev_to_disk(dev)->queue; struct request_queue *q = part_to_disk(p)->queue;
unsigned int inflight[2]; unsigned int inflight[2];
int cpu; int cpu;
......
...@@ -342,7 +342,7 @@ static long __brd_direct_access(struct brd_device *brd, pgoff_t pgoff, ...@@ -342,7 +342,7 @@ static long __brd_direct_access(struct brd_device *brd, pgoff_t pgoff,
if (!brd) if (!brd)
return -ENODEV; return -ENODEV;
page = brd_insert_page(brd, PFN_PHYS(pgoff) / 512); page = brd_insert_page(brd, (sector_t)pgoff << PAGE_SECTORS_SHIFT);
if (!page) if (!page)
return -ENOSPC; return -ENOSPC;
*kaddr = page_address(page); *kaddr = page_address(page);
......
...@@ -67,10 +67,8 @@ struct loop_device { ...@@ -67,10 +67,8 @@ struct loop_device {
struct loop_cmd { struct loop_cmd {
struct kthread_work work; struct kthread_work work;
struct request *rq; struct request *rq;
union { bool use_aio; /* use AIO interface to handle I/O */
bool use_aio; /* use AIO interface to handle I/O */ atomic_t ref; /* only for aio */
atomic_t ref; /* only for aio */
};
long ret; long ret;
struct kiocb iocb; struct kiocb iocb;
struct bio_vec *bvec; struct bio_vec *bvec;
......
...@@ -1194,6 +1194,12 @@ static int nbd_ioctl(struct block_device *bdev, fmode_t mode, ...@@ -1194,6 +1194,12 @@ static int nbd_ioctl(struct block_device *bdev, fmode_t mode,
if (!capable(CAP_SYS_ADMIN)) if (!capable(CAP_SYS_ADMIN))
return -EPERM; return -EPERM;
/* The block layer will pass back some non-nbd ioctls in case we have
* special handling for them, but we don't so just return an error.
*/
if (_IOC_TYPE(cmd) != 0xab)
return -EINVAL;
mutex_lock(&nbd->config_lock); mutex_lock(&nbd->config_lock);
/* Don't allow ioctl operations on a nbd device that was created with /* Don't allow ioctl operations on a nbd device that was created with
......
...@@ -134,8 +134,6 @@ static inline bool nvme_req_needs_retry(struct request *req) ...@@ -134,8 +134,6 @@ static inline bool nvme_req_needs_retry(struct request *req)
return false; return false;
if (nvme_req(req)->status & NVME_SC_DNR) if (nvme_req(req)->status & NVME_SC_DNR)
return false; return false;
if (jiffies - req->start_time >= req->timeout)
return false;
if (nvme_req(req)->retries >= nvme_max_retries) if (nvme_req(req)->retries >= nvme_max_retries)
return false; return false;
return true; return true;
...@@ -2590,7 +2588,7 @@ static void nvme_async_event_work(struct work_struct *work) ...@@ -2590,7 +2588,7 @@ static void nvme_async_event_work(struct work_struct *work)
container_of(work, struct nvme_ctrl, async_event_work); container_of(work, struct nvme_ctrl, async_event_work);
spin_lock_irq(&ctrl->lock); spin_lock_irq(&ctrl->lock);
while (ctrl->event_limit > 0) { while (ctrl->state == NVME_CTRL_LIVE && ctrl->event_limit > 0) {
int aer_idx = --ctrl->event_limit; int aer_idx = --ctrl->event_limit;
spin_unlock_irq(&ctrl->lock); spin_unlock_irq(&ctrl->lock);
...@@ -2677,7 +2675,8 @@ void nvme_complete_async_event(struct nvme_ctrl *ctrl, __le16 status, ...@@ -2677,7 +2675,8 @@ void nvme_complete_async_event(struct nvme_ctrl *ctrl, __le16 status,
/*FALLTHRU*/ /*FALLTHRU*/
case NVME_SC_ABORT_REQ: case NVME_SC_ABORT_REQ:
++ctrl->event_limit; ++ctrl->event_limit;
queue_work(nvme_wq, &ctrl->async_event_work); if (ctrl->state == NVME_CTRL_LIVE)
queue_work(nvme_wq, &ctrl->async_event_work);
break; break;
default: default:
break; break;
...@@ -2692,7 +2691,7 @@ void nvme_complete_async_event(struct nvme_ctrl *ctrl, __le16 status, ...@@ -2692,7 +2691,7 @@ void nvme_complete_async_event(struct nvme_ctrl *ctrl, __le16 status,
nvme_queue_scan(ctrl); nvme_queue_scan(ctrl);
break; break;
case NVME_AER_NOTICE_FW_ACT_STARTING: case NVME_AER_NOTICE_FW_ACT_STARTING:
schedule_work(&ctrl->fw_act_work); queue_work(nvme_wq, &ctrl->fw_act_work);
break; break;
default: default:
dev_warn(ctrl->device, "async event result %08x\n", result); dev_warn(ctrl->device, "async event result %08x\n", result);
......
...@@ -565,6 +565,7 @@ static int nvmf_parse_options(struct nvmf_ctrl_options *opts, ...@@ -565,6 +565,7 @@ static int nvmf_parse_options(struct nvmf_ctrl_options *opts,
opts->queue_size = NVMF_DEF_QUEUE_SIZE; opts->queue_size = NVMF_DEF_QUEUE_SIZE;
opts->nr_io_queues = num_online_cpus(); opts->nr_io_queues = num_online_cpus();
opts->reconnect_delay = NVMF_DEF_RECONNECT_DELAY; opts->reconnect_delay = NVMF_DEF_RECONNECT_DELAY;
opts->kato = NVME_DEFAULT_KATO;
options = o = kstrdup(buf, GFP_KERNEL); options = o = kstrdup(buf, GFP_KERNEL);
if (!options) if (!options)
...@@ -655,21 +656,22 @@ static int nvmf_parse_options(struct nvmf_ctrl_options *opts, ...@@ -655,21 +656,22 @@ static int nvmf_parse_options(struct nvmf_ctrl_options *opts,
goto out; goto out;
} }
if (opts->discovery_nqn) {
pr_err("Discovery controllers cannot accept keep_alive_tmo != 0\n");
ret = -EINVAL;
goto out;
}
if (token < 0) { if (token < 0) {
pr_err("Invalid keep_alive_tmo %d\n", token); pr_err("Invalid keep_alive_tmo %d\n", token);
ret = -EINVAL; ret = -EINVAL;
goto out; goto out;
} else if (token == 0) { } else if (token == 0 && !opts->discovery_nqn) {
/* Allowed for debug */ /* Allowed for debug */
pr_warn("keep_alive_tmo 0 won't execute keep alives!!!\n"); pr_warn("keep_alive_tmo 0 won't execute keep alives!!!\n");
} }
opts->kato = token; opts->kato = token;
if (opts->discovery_nqn && opts->kato) {
pr_err("Discovery controllers cannot accept KATO != 0\n");
ret = -EINVAL;
goto out;
}
break; break;
case NVMF_OPT_CTRL_LOSS_TMO: case NVMF_OPT_CTRL_LOSS_TMO:
if (match_int(args, &token)) { if (match_int(args, &token)) {
...@@ -762,8 +764,6 @@ static int nvmf_parse_options(struct nvmf_ctrl_options *opts, ...@@ -762,8 +764,6 @@ static int nvmf_parse_options(struct nvmf_ctrl_options *opts,
uuid_copy(&opts->host->id, &hostid); uuid_copy(&opts->host->id, &hostid);
out: out:
if (!opts->discovery_nqn && !opts->kato)
opts->kato = NVME_DEFAULT_KATO;
kfree(options); kfree(options);
return ret; return ret;
} }
......
...@@ -1376,7 +1376,7 @@ nvme_fc_fcpio_done(struct nvmefc_fcp_req *req) ...@@ -1376,7 +1376,7 @@ nvme_fc_fcpio_done(struct nvmefc_fcp_req *req)
if (atomic_read(&op->state) == FCPOP_STATE_ABORTED) if (atomic_read(&op->state) == FCPOP_STATE_ABORTED)
status = cpu_to_le16((NVME_SC_ABORT_REQ | NVME_SC_DNR) << 1); status = cpu_to_le16((NVME_SC_ABORT_REQ | NVME_SC_DNR) << 1);
else if (freq->status) else if (freq->status)
status = cpu_to_le16(NVME_SC_FC_TRANSPORT_ERROR << 1); status = cpu_to_le16(NVME_SC_INTERNAL << 1);
/* /*
* For the linux implementation, if we have an unsuccesful * For the linux implementation, if we have an unsuccesful
...@@ -1404,7 +1404,7 @@ nvme_fc_fcpio_done(struct nvmefc_fcp_req *req) ...@@ -1404,7 +1404,7 @@ nvme_fc_fcpio_done(struct nvmefc_fcp_req *req)
*/ */
if (freq->transferred_length != if (freq->transferred_length !=
be32_to_cpu(op->cmd_iu.data_len)) { be32_to_cpu(op->cmd_iu.data_len)) {
status = cpu_to_le16(NVME_SC_FC_TRANSPORT_ERROR << 1); status = cpu_to_le16(NVME_SC_INTERNAL << 1);
goto done; goto done;
} }
result.u64 = 0; result.u64 = 0;
...@@ -1421,7 +1421,7 @@ nvme_fc_fcpio_done(struct nvmefc_fcp_req *req) ...@@ -1421,7 +1421,7 @@ nvme_fc_fcpio_done(struct nvmefc_fcp_req *req)
freq->transferred_length || freq->transferred_length ||
op->rsp_iu.status_code || op->rsp_iu.status_code ||
sqe->common.command_id != cqe->command_id)) { sqe->common.command_id != cqe->command_id)) {
status = cpu_to_le16(NVME_SC_FC_TRANSPORT_ERROR << 1); status = cpu_to_le16(NVME_SC_INTERNAL << 1);
goto done; goto done;
} }
result = cqe->result; result = cqe->result;
...@@ -1429,7 +1429,7 @@ nvme_fc_fcpio_done(struct nvmefc_fcp_req *req) ...@@ -1429,7 +1429,7 @@ nvme_fc_fcpio_done(struct nvmefc_fcp_req *req)
break; break;
default: default:
status = cpu_to_le16(NVME_SC_FC_TRANSPORT_ERROR << 1); status = cpu_to_le16(NVME_SC_INTERNAL << 1);
goto done; goto done;
} }
...@@ -1989,16 +1989,17 @@ nvme_fc_start_fcp_op(struct nvme_fc_ctrl *ctrl, struct nvme_fc_queue *queue, ...@@ -1989,16 +1989,17 @@ nvme_fc_start_fcp_op(struct nvme_fc_ctrl *ctrl, struct nvme_fc_queue *queue,
* as well as those by FC-NVME spec. * as well as those by FC-NVME spec.
*/ */
WARN_ON_ONCE(sqe->common.metadata); WARN_ON_ONCE(sqe->common.metadata);
WARN_ON_ONCE(sqe->common.dptr.prp1);
WARN_ON_ONCE(sqe->common.dptr.prp2);
sqe->common.flags |= NVME_CMD_SGL_METABUF; sqe->common.flags |= NVME_CMD_SGL_METABUF;
/* /*
* format SQE DPTR field per FC-NVME rules * format SQE DPTR field per FC-NVME rules:
* type=data block descr; subtype=offset; * type=0x5 Transport SGL Data Block Descriptor
* offset is currently 0. * subtype=0xA Transport-specific value
* address=0
* length=length of the data series
*/ */
sqe->rw.dptr.sgl.type = NVME_SGL_FMT_OFFSET; sqe->rw.dptr.sgl.type = (NVME_TRANSPORT_SGL_DATA_DESC << 4) |
NVME_SGL_FMT_TRANSPORT_A;
sqe->rw.dptr.sgl.length = cpu_to_le32(data_len); sqe->rw.dptr.sgl.length = cpu_to_le32(data_len);
sqe->rw.dptr.sgl.addr = 0; sqe->rw.dptr.sgl.addr = 0;
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/once.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/poison.h> #include <linux/poison.h>
#include <linux/t10-pi.h> #include <linux/t10-pi.h>
...@@ -540,6 +541,20 @@ static void nvme_dif_complete(u32 p, u32 v, struct t10_pi_tuple *pi) ...@@ -540,6 +541,20 @@ static void nvme_dif_complete(u32 p, u32 v, struct t10_pi_tuple *pi)
} }
#endif #endif
static void nvme_print_sgl(struct scatterlist *sgl, int nents)
{
int i;
struct scatterlist *sg;
for_each_sg(sgl, sg, nents, i) {
dma_addr_t phys = sg_phys(sg);
pr_warn("sg[%d] phys_addr:%pad offset:%d length:%d "
"dma_address:%pad dma_length:%d\n",
i, &phys, sg->offset, sg->length, &sg_dma_address(sg),
sg_dma_len(sg));
}
}
static blk_status_t nvme_setup_prps(struct nvme_dev *dev, struct request *req) static blk_status_t nvme_setup_prps(struct nvme_dev *dev, struct request *req)
{ {
struct nvme_iod *iod = blk_mq_rq_to_pdu(req); struct nvme_iod *iod = blk_mq_rq_to_pdu(req);
...@@ -622,19 +637,10 @@ static blk_status_t nvme_setup_prps(struct nvme_dev *dev, struct request *req) ...@@ -622,19 +637,10 @@ static blk_status_t nvme_setup_prps(struct nvme_dev *dev, struct request *req)
return BLK_STS_OK; return BLK_STS_OK;
bad_sgl: bad_sgl:
if (WARN_ONCE(1, "Invalid SGL for payload:%d nents:%d\n", WARN(DO_ONCE(nvme_print_sgl, iod->sg, iod->nents),
blk_rq_payload_bytes(req), iod->nents)) { "Invalid SGL for payload:%d nents:%d\n",
for_each_sg(iod->sg, sg, iod->nents, i) { blk_rq_payload_bytes(req), iod->nents);
dma_addr_t phys = sg_phys(sg);
pr_warn("sg[%d] phys_addr:%pad offset:%d length:%d "
"dma_address:%pad dma_length:%d\n", i, &phys,
sg->offset, sg->length,
&sg_dma_address(sg),
sg_dma_len(sg));
}
}
return BLK_STS_IOERR; return BLK_STS_IOERR;
} }
static blk_status_t nvme_map_data(struct nvme_dev *dev, struct request *req, static blk_status_t nvme_map_data(struct nvme_dev *dev, struct request *req,
...@@ -1313,11 +1319,11 @@ static int nvme_create_queue(struct nvme_queue *nvmeq, int qid) ...@@ -1313,11 +1319,11 @@ static int nvme_create_queue(struct nvme_queue *nvmeq, int qid)
if (result < 0) if (result < 0)
goto release_cq; goto release_cq;
nvme_init_queue(nvmeq, qid);
result = queue_request_irq(nvmeq); result = queue_request_irq(nvmeq);
if (result < 0) if (result < 0)
goto release_sq; goto release_sq;
nvme_init_queue(nvmeq, qid);
return result; return result;
release_sq: release_sq:
...@@ -1464,6 +1470,7 @@ static int nvme_pci_configure_admin_queue(struct nvme_dev *dev) ...@@ -1464,6 +1470,7 @@ static int nvme_pci_configure_admin_queue(struct nvme_dev *dev)
return result; return result;
nvmeq->cq_vector = 0; nvmeq->cq_vector = 0;
nvme_init_queue(nvmeq, 0);
result = queue_request_irq(nvmeq); result = queue_request_irq(nvmeq);
if (result) { if (result) {
nvmeq->cq_vector = -1; nvmeq->cq_vector = -1;
...@@ -2156,7 +2163,6 @@ static void nvme_reset_work(struct work_struct *work) ...@@ -2156,7 +2163,6 @@ static void nvme_reset_work(struct work_struct *work)
if (result) if (result)
goto out; goto out;
nvme_init_queue(dev->queues[0], 0);
result = nvme_alloc_admin_tags(dev); result = nvme_alloc_admin_tags(dev);
if (result) if (result)
goto out; goto out;
......
...@@ -942,7 +942,12 @@ static void nvme_rdma_reconnect_ctrl_work(struct work_struct *work) ...@@ -942,7 +942,12 @@ static void nvme_rdma_reconnect_ctrl_work(struct work_struct *work)
} }
changed = nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_LIVE); changed = nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_LIVE);
WARN_ON_ONCE(!changed); if (!changed) {
/* state change failure is ok if we're in DELETING state */
WARN_ON_ONCE(ctrl->ctrl.state != NVME_CTRL_DELETING);
return;
}
ctrl->ctrl.nr_reconnects = 0; ctrl->ctrl.nr_reconnects = 0;
nvme_start_ctrl(&ctrl->ctrl); nvme_start_ctrl(&ctrl->ctrl);
...@@ -962,7 +967,7 @@ static void nvme_rdma_error_recovery_work(struct work_struct *work) ...@@ -962,7 +967,7 @@ static void nvme_rdma_error_recovery_work(struct work_struct *work)
struct nvme_rdma_ctrl *ctrl = container_of(work, struct nvme_rdma_ctrl *ctrl = container_of(work,
struct nvme_rdma_ctrl, err_work); struct nvme_rdma_ctrl, err_work);
nvme_stop_ctrl(&ctrl->ctrl); nvme_stop_keep_alive(&ctrl->ctrl);
if (ctrl->ctrl.queue_count > 1) { if (ctrl->ctrl.queue_count > 1) {
nvme_stop_queues(&ctrl->ctrl); nvme_stop_queues(&ctrl->ctrl);
......
...@@ -390,10 +390,10 @@ static void __nvmet_req_complete(struct nvmet_req *req, u16 status) ...@@ -390,10 +390,10 @@ static void __nvmet_req_complete(struct nvmet_req *req, u16 status)
if (status) if (status)
nvmet_set_status(req, status); nvmet_set_status(req, status);
/* XXX: need to fill in something useful for sq_head */ if (req->sq->size)
req->rsp->sq_head = 0; req->sq->sqhd = (req->sq->sqhd + 1) % req->sq->size;
if (likely(req->sq)) /* may happen during early failure */ req->rsp->sq_head = cpu_to_le16(req->sq->sqhd);
req->rsp->sq_id = cpu_to_le16(req->sq->qid); req->rsp->sq_id = cpu_to_le16(req->sq->qid);
req->rsp->command_id = req->cmd->common.command_id; req->rsp->command_id = req->cmd->common.command_id;
if (req->ns) if (req->ns)
...@@ -420,6 +420,7 @@ void nvmet_cq_setup(struct nvmet_ctrl *ctrl, struct nvmet_cq *cq, ...@@ -420,6 +420,7 @@ void nvmet_cq_setup(struct nvmet_ctrl *ctrl, struct nvmet_cq *cq,
void nvmet_sq_setup(struct nvmet_ctrl *ctrl, struct nvmet_sq *sq, void nvmet_sq_setup(struct nvmet_ctrl *ctrl, struct nvmet_sq *sq,
u16 qid, u16 size) u16 qid, u16 size)
{ {
sq->sqhd = 0;
sq->qid = qid; sq->qid = qid;
sq->size = size; sq->size = size;
......
...@@ -109,9 +109,14 @@ static u16 nvmet_install_queue(struct nvmet_ctrl *ctrl, struct nvmet_req *req) ...@@ -109,9 +109,14 @@ static u16 nvmet_install_queue(struct nvmet_ctrl *ctrl, struct nvmet_req *req)
pr_warn("queue already connected!\n"); pr_warn("queue already connected!\n");
return NVME_SC_CONNECT_CTRL_BUSY | NVME_SC_DNR; return NVME_SC_CONNECT_CTRL_BUSY | NVME_SC_DNR;
} }
if (!sqsize) {
pr_warn("queue size zero!\n");
return NVME_SC_CONNECT_INVALID_PARAM | NVME_SC_DNR;
}
nvmet_cq_setup(ctrl, req->cq, qid, sqsize); /* note: convert queue size from 0's-based value to 1's-based value */
nvmet_sq_setup(ctrl, req->sq, qid, sqsize); nvmet_cq_setup(ctrl, req->cq, qid, sqsize + 1);
nvmet_sq_setup(ctrl, req->sq, qid, sqsize + 1);
return 0; return 0;
} }
......
...@@ -148,7 +148,7 @@ struct nvmet_fc_tgt_assoc { ...@@ -148,7 +148,7 @@ struct nvmet_fc_tgt_assoc {
u32 a_id; u32 a_id;
struct nvmet_fc_tgtport *tgtport; struct nvmet_fc_tgtport *tgtport;
struct list_head a_list; struct list_head a_list;
struct nvmet_fc_tgt_queue *queues[NVMET_NR_QUEUES]; struct nvmet_fc_tgt_queue *queues[NVMET_NR_QUEUES + 1];
struct kref ref; struct kref ref;
}; };
...@@ -608,7 +608,7 @@ nvmet_fc_alloc_target_queue(struct nvmet_fc_tgt_assoc *assoc, ...@@ -608,7 +608,7 @@ nvmet_fc_alloc_target_queue(struct nvmet_fc_tgt_assoc *assoc,
unsigned long flags; unsigned long flags;
int ret; int ret;
if (qid >= NVMET_NR_QUEUES) if (qid > NVMET_NR_QUEUES)
return NULL; return NULL;
queue = kzalloc((sizeof(*queue) + queue = kzalloc((sizeof(*queue) +
...@@ -783,6 +783,9 @@ nvmet_fc_find_target_queue(struct nvmet_fc_tgtport *tgtport, ...@@ -783,6 +783,9 @@ nvmet_fc_find_target_queue(struct nvmet_fc_tgtport *tgtport,
u16 qid = nvmet_fc_getqueueid(connection_id); u16 qid = nvmet_fc_getqueueid(connection_id);
unsigned long flags; unsigned long flags;
if (qid > NVMET_NR_QUEUES)
return NULL;
spin_lock_irqsave(&tgtport->lock, flags); spin_lock_irqsave(&tgtport->lock, flags);
list_for_each_entry(assoc, &tgtport->assoc_list, a_list) { list_for_each_entry(assoc, &tgtport->assoc_list, a_list) {
if (association_id == assoc->association_id) { if (association_id == assoc->association_id) {
...@@ -888,7 +891,7 @@ nvmet_fc_delete_target_assoc(struct nvmet_fc_tgt_assoc *assoc) ...@@ -888,7 +891,7 @@ nvmet_fc_delete_target_assoc(struct nvmet_fc_tgt_assoc *assoc)
int i; int i;
spin_lock_irqsave(&tgtport->lock, flags); spin_lock_irqsave(&tgtport->lock, flags);
for (i = NVMET_NR_QUEUES - 1; i >= 0; i--) { for (i = NVMET_NR_QUEUES; i >= 0; i--) {
queue = assoc->queues[i]; queue = assoc->queues[i];
if (queue) { if (queue) {
if (!nvmet_fc_tgt_q_get(queue)) if (!nvmet_fc_tgt_q_get(queue))
...@@ -1910,8 +1913,7 @@ nvmet_fc_transfer_fcp_data(struct nvmet_fc_tgtport *tgtport, ...@@ -1910,8 +1913,7 @@ nvmet_fc_transfer_fcp_data(struct nvmet_fc_tgtport *tgtport,
spin_lock_irqsave(&fod->flock, flags); spin_lock_irqsave(&fod->flock, flags);
fod->writedataactive = false; fod->writedataactive = false;
spin_unlock_irqrestore(&fod->flock, flags); spin_unlock_irqrestore(&fod->flock, flags);
nvmet_req_complete(&fod->req, nvmet_req_complete(&fod->req, NVME_SC_INTERNAL);
NVME_SC_FC_TRANSPORT_ERROR);
} else /* NVMET_FCOP_READDATA or NVMET_FCOP_READDATA_RSP */ { } else /* NVMET_FCOP_READDATA or NVMET_FCOP_READDATA_RSP */ {
fcpreq->fcp_error = ret; fcpreq->fcp_error = ret;
fcpreq->transferred_length = 0; fcpreq->transferred_length = 0;
...@@ -1929,8 +1931,7 @@ __nvmet_fc_fod_op_abort(struct nvmet_fc_fcp_iod *fod, bool abort) ...@@ -1929,8 +1931,7 @@ __nvmet_fc_fod_op_abort(struct nvmet_fc_fcp_iod *fod, bool abort)
/* if in the middle of an io and we need to tear down */ /* if in the middle of an io and we need to tear down */
if (abort) { if (abort) {
if (fcpreq->op == NVMET_FCOP_WRITEDATA) { if (fcpreq->op == NVMET_FCOP_WRITEDATA) {
nvmet_req_complete(&fod->req, nvmet_req_complete(&fod->req, NVME_SC_INTERNAL);
NVME_SC_FC_TRANSPORT_ERROR);
return true; return true;
} }
...@@ -1968,8 +1969,7 @@ nvmet_fc_fod_op_done(struct nvmet_fc_fcp_iod *fod) ...@@ -1968,8 +1969,7 @@ nvmet_fc_fod_op_done(struct nvmet_fc_fcp_iod *fod)
fod->abort = true; fod->abort = true;
spin_unlock(&fod->flock); spin_unlock(&fod->flock);
nvmet_req_complete(&fod->req, nvmet_req_complete(&fod->req, NVME_SC_INTERNAL);
NVME_SC_FC_TRANSPORT_ERROR);
return; return;
} }
...@@ -2533,13 +2533,17 @@ nvmet_fc_remove_port(struct nvmet_port *port) ...@@ -2533,13 +2533,17 @@ nvmet_fc_remove_port(struct nvmet_port *port)
{ {
struct nvmet_fc_tgtport *tgtport = port->priv; struct nvmet_fc_tgtport *tgtport = port->priv;
unsigned long flags; unsigned long flags;
bool matched = false;
spin_lock_irqsave(&nvmet_fc_tgtlock, flags); spin_lock_irqsave(&nvmet_fc_tgtlock, flags);
if (tgtport->port == port) { if (tgtport->port == port) {
nvmet_fc_tgtport_put(tgtport); matched = true;
tgtport->port = NULL; tgtport->port = NULL;
} }
spin_unlock_irqrestore(&nvmet_fc_tgtlock, flags); spin_unlock_irqrestore(&nvmet_fc_tgtlock, flags);
if (matched)
nvmet_fc_tgtport_put(tgtport);
} }
static struct nvmet_fabrics_ops nvmet_fc_tgt_fcp_ops = { static struct nvmet_fabrics_ops nvmet_fc_tgt_fcp_ops = {
......
...@@ -224,8 +224,6 @@ struct fcloop_nport { ...@@ -224,8 +224,6 @@ struct fcloop_nport {
struct fcloop_lport *lport; struct fcloop_lport *lport;
struct list_head nport_list; struct list_head nport_list;
struct kref ref; struct kref ref;
struct completion rport_unreg_done;
struct completion tport_unreg_done;
u64 node_name; u64 node_name;
u64 port_name; u64 port_name;
u32 port_role; u32 port_role;
...@@ -576,7 +574,7 @@ fcloop_tgt_fcp_abort(struct nvmet_fc_target_port *tgtport, ...@@ -576,7 +574,7 @@ fcloop_tgt_fcp_abort(struct nvmet_fc_target_port *tgtport,
tfcp_req->aborted = true; tfcp_req->aborted = true;
spin_unlock(&tfcp_req->reqlock); spin_unlock(&tfcp_req->reqlock);
tfcp_req->status = NVME_SC_FC_TRANSPORT_ABORTED; tfcp_req->status = NVME_SC_INTERNAL;
/* /*
* nothing more to do. If io wasn't active, the transport should * nothing more to do. If io wasn't active, the transport should
...@@ -630,6 +628,32 @@ fcloop_fcp_abort(struct nvme_fc_local_port *localport, ...@@ -630,6 +628,32 @@ fcloop_fcp_abort(struct nvme_fc_local_port *localport,
schedule_work(&inireq->iniwork); schedule_work(&inireq->iniwork);
} }
static void
fcloop_nport_free(struct kref *ref)
{
struct fcloop_nport *nport =
container_of(ref, struct fcloop_nport, ref);
unsigned long flags;
spin_lock_irqsave(&fcloop_lock, flags);
list_del(&nport->nport_list);
spin_unlock_irqrestore(&fcloop_lock, flags);
kfree(nport);
}
static void
fcloop_nport_put(struct fcloop_nport *nport)
{
kref_put(&nport->ref, fcloop_nport_free);
}
static int
fcloop_nport_get(struct fcloop_nport *nport)
{
return kref_get_unless_zero(&nport->ref);
}
static void static void
fcloop_localport_delete(struct nvme_fc_local_port *localport) fcloop_localport_delete(struct nvme_fc_local_port *localport)
{ {
...@@ -644,8 +668,7 @@ fcloop_remoteport_delete(struct nvme_fc_remote_port *remoteport) ...@@ -644,8 +668,7 @@ fcloop_remoteport_delete(struct nvme_fc_remote_port *remoteport)
{ {
struct fcloop_rport *rport = remoteport->private; struct fcloop_rport *rport = remoteport->private;
/* release any threads waiting for the unreg to complete */ fcloop_nport_put(rport->nport);
complete(&rport->nport->rport_unreg_done);
} }
static void static void
...@@ -653,8 +676,7 @@ fcloop_targetport_delete(struct nvmet_fc_target_port *targetport) ...@@ -653,8 +676,7 @@ fcloop_targetport_delete(struct nvmet_fc_target_port *targetport)
{ {
struct fcloop_tport *tport = targetport->private; struct fcloop_tport *tport = targetport->private;
/* release any threads waiting for the unreg to complete */ fcloop_nport_put(tport->nport);
complete(&tport->nport->tport_unreg_done);
} }
#define FCLOOP_HW_QUEUES 4 #define FCLOOP_HW_QUEUES 4
...@@ -722,6 +744,7 @@ fcloop_create_local_port(struct device *dev, struct device_attribute *attr, ...@@ -722,6 +744,7 @@ fcloop_create_local_port(struct device *dev, struct device_attribute *attr,
goto out_free_opts; goto out_free_opts;
} }
memset(&pinfo, 0, sizeof(pinfo));
pinfo.node_name = opts->wwnn; pinfo.node_name = opts->wwnn;
pinfo.port_name = opts->wwpn; pinfo.port_name = opts->wwpn;
pinfo.port_role = opts->roles; pinfo.port_role = opts->roles;
...@@ -804,32 +827,6 @@ fcloop_delete_local_port(struct device *dev, struct device_attribute *attr, ...@@ -804,32 +827,6 @@ fcloop_delete_local_port(struct device *dev, struct device_attribute *attr,
return ret ? ret : count; return ret ? ret : count;
} }
static void
fcloop_nport_free(struct kref *ref)
{
struct fcloop_nport *nport =
container_of(ref, struct fcloop_nport, ref);
unsigned long flags;
spin_lock_irqsave(&fcloop_lock, flags);
list_del(&nport->nport_list);
spin_unlock_irqrestore(&fcloop_lock, flags);
kfree(nport);
}
static void
fcloop_nport_put(struct fcloop_nport *nport)
{
kref_put(&nport->ref, fcloop_nport_free);
}
static int
fcloop_nport_get(struct fcloop_nport *nport)
{
return kref_get_unless_zero(&nport->ref);
}
static struct fcloop_nport * static struct fcloop_nport *
fcloop_alloc_nport(const char *buf, size_t count, bool remoteport) fcloop_alloc_nport(const char *buf, size_t count, bool remoteport)
{ {
...@@ -938,6 +935,7 @@ fcloop_create_remote_port(struct device *dev, struct device_attribute *attr, ...@@ -938,6 +935,7 @@ fcloop_create_remote_port(struct device *dev, struct device_attribute *attr,
if (!nport) if (!nport)
return -EIO; return -EIO;
memset(&pinfo, 0, sizeof(pinfo));
pinfo.node_name = nport->node_name; pinfo.node_name = nport->node_name;
pinfo.port_name = nport->port_name; pinfo.port_name = nport->port_name;
pinfo.port_role = nport->port_role; pinfo.port_role = nport->port_role;
...@@ -979,24 +977,12 @@ __unlink_remote_port(struct fcloop_nport *nport) ...@@ -979,24 +977,12 @@ __unlink_remote_port(struct fcloop_nport *nport)
} }
static int static int
__wait_remoteport_unreg(struct fcloop_nport *nport, struct fcloop_rport *rport) __remoteport_unreg(struct fcloop_nport *nport, struct fcloop_rport *rport)
{ {
int ret;
if (!rport) if (!rport)
return -EALREADY; return -EALREADY;
init_completion(&nport->rport_unreg_done); return nvme_fc_unregister_remoteport(rport->remoteport);
ret = nvme_fc_unregister_remoteport(rport->remoteport);
if (ret)
return ret;
wait_for_completion(&nport->rport_unreg_done);
fcloop_nport_put(nport);
return ret;
} }
static ssize_t static ssize_t
...@@ -1029,7 +1015,7 @@ fcloop_delete_remote_port(struct device *dev, struct device_attribute *attr, ...@@ -1029,7 +1015,7 @@ fcloop_delete_remote_port(struct device *dev, struct device_attribute *attr,
if (!nport) if (!nport)
return -ENOENT; return -ENOENT;
ret = __wait_remoteport_unreg(nport, rport); ret = __remoteport_unreg(nport, rport);
return ret ? ret : count; return ret ? ret : count;
} }
...@@ -1086,24 +1072,12 @@ __unlink_target_port(struct fcloop_nport *nport) ...@@ -1086,24 +1072,12 @@ __unlink_target_port(struct fcloop_nport *nport)
} }
static int static int
__wait_targetport_unreg(struct fcloop_nport *nport, struct fcloop_tport *tport) __targetport_unreg(struct fcloop_nport *nport, struct fcloop_tport *tport)
{ {
int ret;
if (!tport) if (!tport)
return -EALREADY; return -EALREADY;
init_completion(&nport->tport_unreg_done); return nvmet_fc_unregister_targetport(tport->targetport);
ret = nvmet_fc_unregister_targetport(tport->targetport);
if (ret)
return ret;
wait_for_completion(&nport->tport_unreg_done);
fcloop_nport_put(nport);
return ret;
} }
static ssize_t static ssize_t
...@@ -1136,7 +1110,7 @@ fcloop_delete_target_port(struct device *dev, struct device_attribute *attr, ...@@ -1136,7 +1110,7 @@ fcloop_delete_target_port(struct device *dev, struct device_attribute *attr,
if (!nport) if (!nport)
return -ENOENT; return -ENOENT;
ret = __wait_targetport_unreg(nport, tport); ret = __targetport_unreg(nport, tport);
return ret ? ret : count; return ret ? ret : count;
} }
...@@ -1223,11 +1197,11 @@ static void __exit fcloop_exit(void) ...@@ -1223,11 +1197,11 @@ static void __exit fcloop_exit(void)
spin_unlock_irqrestore(&fcloop_lock, flags); spin_unlock_irqrestore(&fcloop_lock, flags);
ret = __wait_targetport_unreg(nport, tport); ret = __targetport_unreg(nport, tport);
if (ret) if (ret)
pr_warn("%s: Failed deleting target port\n", __func__); pr_warn("%s: Failed deleting target port\n", __func__);
ret = __wait_remoteport_unreg(nport, rport); ret = __remoteport_unreg(nport, rport);
if (ret) if (ret)
pr_warn("%s: Failed deleting remote port\n", __func__); pr_warn("%s: Failed deleting remote port\n", __func__);
......
...@@ -74,6 +74,7 @@ struct nvmet_sq { ...@@ -74,6 +74,7 @@ struct nvmet_sq {
struct percpu_ref ref; struct percpu_ref ref;
u16 qid; u16 qid;
u16 size; u16 size;
u16 sqhd;
struct completion free_done; struct completion free_done;
struct completion confirm_done; struct completion confirm_done;
}; };
......
...@@ -884,7 +884,7 @@ lpfc_nvme_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn, ...@@ -884,7 +884,7 @@ lpfc_nvme_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn,
wcqe->total_data_placed); wcqe->total_data_placed);
nCmd->transferred_length = 0; nCmd->transferred_length = 0;
nCmd->rcv_rsplen = 0; nCmd->rcv_rsplen = 0;
nCmd->status = NVME_SC_FC_TRANSPORT_ERROR; nCmd->status = NVME_SC_INTERNAL;
} }
} }
......
...@@ -180,7 +180,7 @@ static void qla_nvme_sp_done(void *ptr, int res) ...@@ -180,7 +180,7 @@ static void qla_nvme_sp_done(void *ptr, int res)
goto rel; goto rel;
if (unlikely(res == QLA_FUNCTION_FAILED)) if (unlikely(res == QLA_FUNCTION_FAILED))
fd->status = NVME_SC_FC_TRANSPORT_ERROR; fd->status = NVME_SC_INTERNAL;
else else
fd->status = 0; fd->status = 0;
......
...@@ -229,6 +229,7 @@ static ssize_t dio_complete(struct dio *dio, ssize_t ret, bool is_async) ...@@ -229,6 +229,7 @@ static ssize_t dio_complete(struct dio *dio, ssize_t ret, bool is_async)
{ {
loff_t offset = dio->iocb->ki_pos; loff_t offset = dio->iocb->ki_pos;
ssize_t transferred = 0; ssize_t transferred = 0;
int err;
/* /*
* AIO submission can race with bio completion to get here while * AIO submission can race with bio completion to get here while
...@@ -258,8 +259,22 @@ static ssize_t dio_complete(struct dio *dio, ssize_t ret, bool is_async) ...@@ -258,8 +259,22 @@ static ssize_t dio_complete(struct dio *dio, ssize_t ret, bool is_async)
if (ret == 0) if (ret == 0)
ret = transferred; ret = transferred;
/*
* Try again to invalidate clean pages which might have been cached by
* non-direct readahead, or faulted in by get_user_pages() if the source
* of the write was an mmap'ed region of the file we're writing. Either
* one is a pretty crazy thing to do, so we don't support it 100%. If
* this invalidation fails, tough, the write still worked...
*/
if (ret > 0 && dio->op == REQ_OP_WRITE &&
dio->inode->i_mapping->nrpages) {
err = invalidate_inode_pages2_range(dio->inode->i_mapping,
offset >> PAGE_SHIFT,
(offset + ret - 1) >> PAGE_SHIFT);
WARN_ON_ONCE(err);
}
if (dio->end_io) { if (dio->end_io) {
int err;
// XXX: ki_pos?? // XXX: ki_pos??
err = dio->end_io(dio->iocb, offset, ret, dio->private); err = dio->end_io(dio->iocb, offset, ret, dio->private);
...@@ -304,6 +319,7 @@ static void dio_bio_end_aio(struct bio *bio) ...@@ -304,6 +319,7 @@ static void dio_bio_end_aio(struct bio *bio)
struct dio *dio = bio->bi_private; struct dio *dio = bio->bi_private;
unsigned long remaining; unsigned long remaining;
unsigned long flags; unsigned long flags;
bool defer_completion = false;
/* cleanup the bio */ /* cleanup the bio */
dio_bio_complete(dio, bio); dio_bio_complete(dio, bio);
...@@ -315,7 +331,19 @@ static void dio_bio_end_aio(struct bio *bio) ...@@ -315,7 +331,19 @@ static void dio_bio_end_aio(struct bio *bio)
spin_unlock_irqrestore(&dio->bio_lock, flags); spin_unlock_irqrestore(&dio->bio_lock, flags);
if (remaining == 0) { if (remaining == 0) {
if (dio->result && dio->defer_completion) { /*
* Defer completion when defer_completion is set or
* when the inode has pages mapped and this is AIO write.
* We need to invalidate those pages because there is a
* chance they contain stale data in the case buffered IO
* went in between AIO submission and completion into the
* same region.
*/
if (dio->result)
defer_completion = dio->defer_completion ||
(dio->op == REQ_OP_WRITE &&
dio->inode->i_mapping->nrpages);
if (defer_completion) {
INIT_WORK(&dio->complete_work, dio_aio_complete_work); INIT_WORK(&dio->complete_work, dio_aio_complete_work);
queue_work(dio->inode->i_sb->s_dio_done_wq, queue_work(dio->inode->i_sb->s_dio_done_wq,
&dio->complete_work); &dio->complete_work);
...@@ -1210,10 +1238,19 @@ do_blockdev_direct_IO(struct kiocb *iocb, struct inode *inode, ...@@ -1210,10 +1238,19 @@ do_blockdev_direct_IO(struct kiocb *iocb, struct inode *inode,
* For AIO O_(D)SYNC writes we need to defer completions to a workqueue * For AIO O_(D)SYNC writes we need to defer completions to a workqueue
* so that we can call ->fsync. * so that we can call ->fsync.
*/ */
if (dio->is_async && iov_iter_rw(iter) == WRITE && if (dio->is_async && iov_iter_rw(iter) == WRITE) {
((iocb->ki_filp->f_flags & O_DSYNC) || retval = 0;
IS_SYNC(iocb->ki_filp->f_mapping->host))) { if ((iocb->ki_filp->f_flags & O_DSYNC) ||
retval = dio_set_defer_completion(dio); IS_SYNC(iocb->ki_filp->f_mapping->host))
retval = dio_set_defer_completion(dio);
else if (!dio->inode->i_sb->s_dio_done_wq) {
/*
* In case of AIO write racing with buffered read we
* need to defer completion. We can't decide this now,
* however the workqueue needs to be initialized here.
*/
retval = sb_init_dio_done_wq(dio->inode->i_sb);
}
if (retval) { if (retval) {
/* /*
* We grab i_mutex only for reads so we don't have * We grab i_mutex only for reads so we don't have
......
...@@ -713,8 +713,24 @@ struct iomap_dio { ...@@ -713,8 +713,24 @@ struct iomap_dio {
static ssize_t iomap_dio_complete(struct iomap_dio *dio) static ssize_t iomap_dio_complete(struct iomap_dio *dio)
{ {
struct kiocb *iocb = dio->iocb; struct kiocb *iocb = dio->iocb;
struct inode *inode = file_inode(iocb->ki_filp);
ssize_t ret; ssize_t ret;
/*
* Try again to invalidate clean pages which might have been cached by
* non-direct readahead, or faulted in by get_user_pages() if the source
* of the write was an mmap'ed region of the file we're writing. Either
* one is a pretty crazy thing to do, so we don't support it 100%. If
* this invalidation fails, tough, the write still worked...
*/
if (!dio->error &&
(dio->flags & IOMAP_DIO_WRITE) && inode->i_mapping->nrpages) {
ret = invalidate_inode_pages2_range(inode->i_mapping,
iocb->ki_pos >> PAGE_SHIFT,
(iocb->ki_pos + dio->size - 1) >> PAGE_SHIFT);
WARN_ON_ONCE(ret);
}
if (dio->end_io) { if (dio->end_io) {
ret = dio->end_io(iocb, ret = dio->end_io(iocb,
dio->error ? dio->error : dio->size, dio->error ? dio->error : dio->size,
...@@ -1042,19 +1058,6 @@ iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter, ...@@ -1042,19 +1058,6 @@ iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter,
ret = iomap_dio_complete(dio); ret = iomap_dio_complete(dio);
/*
* Try again to invalidate clean pages which might have been cached by
* non-direct readahead, or faulted in by get_user_pages() if the source
* of the write was an mmap'ed region of the file we're writing. Either
* one is a pretty crazy thing to do, so we don't support it 100%. If
* this invalidation fails, tough, the write still worked...
*/
if (iov_iter_rw(iter) == WRITE) {
int err = invalidate_inode_pages2_range(mapping,
start >> PAGE_SHIFT, end >> PAGE_SHIFT);
WARN_ON_ONCE(err);
}
return ret; return ret;
out_free_dio: out_free_dio:
......
...@@ -551,6 +551,7 @@ struct request_queue { ...@@ -551,6 +551,7 @@ struct request_queue {
int node; int node;
#ifdef CONFIG_BLK_DEV_IO_TRACE #ifdef CONFIG_BLK_DEV_IO_TRACE
struct blk_trace *blk_trace; struct blk_trace *blk_trace;
struct mutex blk_trace_mutex;
#endif #endif
/* /*
* for flush operations * for flush operations
......
...@@ -346,11 +346,6 @@ struct nvme_fc_remote_port { ...@@ -346,11 +346,6 @@ struct nvme_fc_remote_port {
* indicating an FC transport Aborted status. * indicating an FC transport Aborted status.
* Entrypoint is Mandatory. * Entrypoint is Mandatory.
* *
* @defer_rcv: Called by the transport to signal the LLLD that it has
* begun processing of a previously received NVME CMD IU. The LLDD
* is now free to re-use the rcv buffer associated with the
* nvmefc_tgt_fcp_req.
*
* @max_hw_queues: indicates the maximum number of hw queues the LLDD * @max_hw_queues: indicates the maximum number of hw queues the LLDD
* supports for cpu affinitization. * supports for cpu affinitization.
* Value is Mandatory. Must be at least 1. * Value is Mandatory. Must be at least 1.
...@@ -806,11 +801,19 @@ struct nvmet_fc_target_port { ...@@ -806,11 +801,19 @@ struct nvmet_fc_target_port {
* outstanding operation (if there was one) to complete, then will * outstanding operation (if there was one) to complete, then will
* call the fcp_req_release() callback to return the command's * call the fcp_req_release() callback to return the command's
* exchange context back to the LLDD. * exchange context back to the LLDD.
* Entrypoint is Mandatory.
* *
* @fcp_req_release: Called by the transport to return a nvmefc_tgt_fcp_req * @fcp_req_release: Called by the transport to return a nvmefc_tgt_fcp_req
* to the LLDD after all operations on the fcp operation are complete. * to the LLDD after all operations on the fcp operation are complete.
* This may be due to the command completing or upon completion of * This may be due to the command completing or upon completion of
* abort cleanup. * abort cleanup.
* Entrypoint is Mandatory.
*
* @defer_rcv: Called by the transport to signal the LLLD that it has
* begun processing of a previously received NVME CMD IU. The LLDD
* is now free to re-use the rcv buffer associated with the
* nvmefc_tgt_fcp_req.
* Entrypoint is Optional.
* *
* @max_hw_queues: indicates the maximum number of hw queues the LLDD * @max_hw_queues: indicates the maximum number of hw queues the LLDD
* supports for cpu affinitization. * supports for cpu affinitization.
......
...@@ -471,12 +471,14 @@ enum nvme_opcode { ...@@ -471,12 +471,14 @@ enum nvme_opcode {
* *
* @NVME_SGL_FMT_ADDRESS: absolute address of the data block * @NVME_SGL_FMT_ADDRESS: absolute address of the data block
* @NVME_SGL_FMT_OFFSET: relative offset of the in-capsule data block * @NVME_SGL_FMT_OFFSET: relative offset of the in-capsule data block
* @NVME_SGL_FMT_TRANSPORT_A: transport defined format, value 0xA
* @NVME_SGL_FMT_INVALIDATE: RDMA transport specific remote invalidation * @NVME_SGL_FMT_INVALIDATE: RDMA transport specific remote invalidation
* request subtype * request subtype
*/ */
enum { enum {
NVME_SGL_FMT_ADDRESS = 0x00, NVME_SGL_FMT_ADDRESS = 0x00,
NVME_SGL_FMT_OFFSET = 0x01, NVME_SGL_FMT_OFFSET = 0x01,
NVME_SGL_FMT_TRANSPORT_A = 0x0A,
NVME_SGL_FMT_INVALIDATE = 0x0f, NVME_SGL_FMT_INVALIDATE = 0x0f,
}; };
...@@ -490,12 +492,16 @@ enum { ...@@ -490,12 +492,16 @@ enum {
* *
* For struct nvme_keyed_sgl_desc: * For struct nvme_keyed_sgl_desc:
* @NVME_KEY_SGL_FMT_DATA_DESC: keyed data block descriptor * @NVME_KEY_SGL_FMT_DATA_DESC: keyed data block descriptor
*
* Transport-specific SGL types:
* @NVME_TRANSPORT_SGL_DATA_DESC: Transport SGL data dlock descriptor
*/ */
enum { enum {
NVME_SGL_FMT_DATA_DESC = 0x00, NVME_SGL_FMT_DATA_DESC = 0x00,
NVME_SGL_FMT_SEG_DESC = 0x02, NVME_SGL_FMT_SEG_DESC = 0x02,
NVME_SGL_FMT_LAST_SEG_DESC = 0x03, NVME_SGL_FMT_LAST_SEG_DESC = 0x03,
NVME_KEY_SGL_FMT_DATA_DESC = 0x04, NVME_KEY_SGL_FMT_DATA_DESC = 0x04,
NVME_TRANSPORT_SGL_DATA_DESC = 0x05,
}; };
struct nvme_sgl_desc { struct nvme_sgl_desc {
...@@ -1127,19 +1133,6 @@ enum { ...@@ -1127,19 +1133,6 @@ enum {
NVME_SC_UNWRITTEN_BLOCK = 0x287, NVME_SC_UNWRITTEN_BLOCK = 0x287,
NVME_SC_DNR = 0x4000, NVME_SC_DNR = 0x4000,
/*
* FC Transport-specific error status values for NVME commands
*
* Transport-specific status code values must be in the range 0xB0..0xBF
*/
/* Generic FC failure - catchall */
NVME_SC_FC_TRANSPORT_ERROR = 0x00B0,
/* I/O failure due to FC ABTS'd */
NVME_SC_FC_TRANSPORT_ABORTED = 0x00B1,
}; };
struct nvme_completion { struct nvme_completion {
......
...@@ -648,6 +648,12 @@ int blk_trace_startstop(struct request_queue *q, int start) ...@@ -648,6 +648,12 @@ int blk_trace_startstop(struct request_queue *q, int start)
} }
EXPORT_SYMBOL_GPL(blk_trace_startstop); EXPORT_SYMBOL_GPL(blk_trace_startstop);
/*
* When reading or writing the blktrace sysfs files, the references to the
* opened sysfs or device files should prevent the underlying block device
* from being removed. So no further delete protection is really needed.
*/
/** /**
* blk_trace_ioctl: - handle the ioctls associated with tracing * blk_trace_ioctl: - handle the ioctls associated with tracing
* @bdev: the block device * @bdev: the block device
...@@ -665,7 +671,7 @@ int blk_trace_ioctl(struct block_device *bdev, unsigned cmd, char __user *arg) ...@@ -665,7 +671,7 @@ int blk_trace_ioctl(struct block_device *bdev, unsigned cmd, char __user *arg)
if (!q) if (!q)
return -ENXIO; return -ENXIO;
mutex_lock(&bdev->bd_mutex); mutex_lock(&q->blk_trace_mutex);
switch (cmd) { switch (cmd) {
case BLKTRACESETUP: case BLKTRACESETUP:
...@@ -691,7 +697,7 @@ int blk_trace_ioctl(struct block_device *bdev, unsigned cmd, char __user *arg) ...@@ -691,7 +697,7 @@ int blk_trace_ioctl(struct block_device *bdev, unsigned cmd, char __user *arg)
break; break;
} }
mutex_unlock(&bdev->bd_mutex); mutex_unlock(&q->blk_trace_mutex);
return ret; return ret;
} }
...@@ -1727,7 +1733,7 @@ static ssize_t sysfs_blk_trace_attr_show(struct device *dev, ...@@ -1727,7 +1733,7 @@ static ssize_t sysfs_blk_trace_attr_show(struct device *dev,
if (q == NULL) if (q == NULL)
goto out_bdput; goto out_bdput;
mutex_lock(&bdev->bd_mutex); mutex_lock(&q->blk_trace_mutex);
if (attr == &dev_attr_enable) { if (attr == &dev_attr_enable) {
ret = sprintf(buf, "%u\n", !!q->blk_trace); ret = sprintf(buf, "%u\n", !!q->blk_trace);
...@@ -1746,7 +1752,7 @@ static ssize_t sysfs_blk_trace_attr_show(struct device *dev, ...@@ -1746,7 +1752,7 @@ static ssize_t sysfs_blk_trace_attr_show(struct device *dev,
ret = sprintf(buf, "%llu\n", q->blk_trace->end_lba); ret = sprintf(buf, "%llu\n", q->blk_trace->end_lba);
out_unlock_bdev: out_unlock_bdev:
mutex_unlock(&bdev->bd_mutex); mutex_unlock(&q->blk_trace_mutex);
out_bdput: out_bdput:
bdput(bdev); bdput(bdev);
out: out:
...@@ -1788,7 +1794,7 @@ static ssize_t sysfs_blk_trace_attr_store(struct device *dev, ...@@ -1788,7 +1794,7 @@ static ssize_t sysfs_blk_trace_attr_store(struct device *dev,
if (q == NULL) if (q == NULL)
goto out_bdput; goto out_bdput;
mutex_lock(&bdev->bd_mutex); mutex_lock(&q->blk_trace_mutex);
if (attr == &dev_attr_enable) { if (attr == &dev_attr_enable) {
if (value) if (value)
...@@ -1814,7 +1820,7 @@ static ssize_t sysfs_blk_trace_attr_store(struct device *dev, ...@@ -1814,7 +1820,7 @@ static ssize_t sysfs_blk_trace_attr_store(struct device *dev,
} }
out_unlock_bdev: out_unlock_bdev:
mutex_unlock(&bdev->bd_mutex); mutex_unlock(&q->blk_trace_mutex);
out_bdput: out_bdput:
bdput(bdev); bdput(bdev);
out: out:
......
...@@ -2926,9 +2926,15 @@ generic_file_direct_write(struct kiocb *iocb, struct iov_iter *from) ...@@ -2926,9 +2926,15 @@ generic_file_direct_write(struct kiocb *iocb, struct iov_iter *from)
* we're writing. Either one is a pretty crazy thing to do, * we're writing. Either one is a pretty crazy thing to do,
* so we don't support it 100%. If this invalidation * so we don't support it 100%. If this invalidation
* fails, tough, the write still worked... * fails, tough, the write still worked...
*
* Most of the time we do not need this since dio_complete() will do
* the invalidation for us. However there are some file systems that
* do not end up with dio_complete() being called, so let's not break
* them by removing it completely
*/ */
invalidate_inode_pages2_range(mapping, if (mapping->nrpages)
pos >> PAGE_SHIFT, end); invalidate_inode_pages2_range(mapping,
pos >> PAGE_SHIFT, end);
if (written > 0) { if (written > 0) {
pos += written; pos += written;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment