Skip to content

Commit

Permalink
Merge branch 'nvme-4.18' of git://git.infradead.org/nvme into for-linus
Browse files Browse the repository at this point in the history
Pull NVMe fixes from Christoph:

"Fix various little regressions introduced in this merge window, plus
 a rework of the fibre channel connect and reconnect path to share the
 code instead of having separate sets of bugs. Last but not least a
 trivial trace point addition from Hannes."

* 'nvme-4.18' of git://git.infradead.org/nvme:
  nvme-fabrics: fix and refine state checks in __nvmf_check_ready
  nvme-fabrics: handle the admin-only case properly in nvmf_check_ready
  nvme-fabrics: refactor queue ready check
  blk-mq: remove blk_mq_tagset_iter
  nvme: remove nvme_reinit_tagset
  nvme-fc: fix nulling of queue data on reconnect
  nvme-fc: remove reinit_request routine
  nvme-fc: change controllers first connect to use reconnect path
  nvme: don't rely on the changed namespace list log
  nvmet: free smart-log buffer after use
  nvme-rdma: fix error flow during mapping request data
  nvme: add bio remapping tracepoint
  nvme: fix NULL pointer dereference in nvme_init_subsystem
  • Loading branch information
axboe committed Jun 15, 2018
2 parents da66126 + 35897b9 commit 95c7c09
Show file tree
Hide file tree
Showing 11 changed files with 154 additions and 224 deletions.
29 changes: 0 additions & 29 deletions block/blk-mq-tag.c
Original file line number Diff line number Diff line change
Expand Up @@ -311,35 +311,6 @@ void blk_mq_tagset_busy_iter(struct blk_mq_tag_set *tagset,
}
EXPORT_SYMBOL(blk_mq_tagset_busy_iter);

int blk_mq_tagset_iter(struct blk_mq_tag_set *set, void *data,
int (fn)(void *, struct request *))
{
int i, j, ret = 0;

if (WARN_ON_ONCE(!fn))
goto out;

for (i = 0; i < set->nr_hw_queues; i++) {
struct blk_mq_tags *tags = set->tags[i];

if (!tags)
continue;

for (j = 0; j < tags->nr_tags; j++) {
if (!tags->static_rqs[j])
continue;

ret = fn(data, tags->static_rqs[j]);
if (ret)
goto out;
}
}

out:
return ret;
}
EXPORT_SYMBOL_GPL(blk_mq_tagset_iter);

void blk_mq_queue_tag_busy_iter(struct request_queue *q, busy_iter_fn *fn,
void *priv)
{
Expand Down
48 changes: 12 additions & 36 deletions drivers/nvme/host/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -2208,7 +2208,7 @@ static int nvme_init_subsystem(struct nvme_ctrl *ctrl, struct nvme_id_ctrl *id)
* Verify that the subsystem actually supports multiple
* controllers, else bail out.
*/
if (!ctrl->opts->discovery_nqn &&
if (!(ctrl->opts && ctrl->opts->discovery_nqn) &&
nvme_active_ctrls(found) && !(id->cmic & (1 << 1))) {
dev_err(ctrl->device,
"ignoring ctrl due to duplicate subnqn (%s).\n",
Expand Down Expand Up @@ -3197,40 +3197,28 @@ static void nvme_scan_ns_sequential(struct nvme_ctrl *ctrl, unsigned nn)
nvme_remove_invalid_namespaces(ctrl, nn);
}

static bool nvme_scan_changed_ns_log(struct nvme_ctrl *ctrl)
static void nvme_clear_changed_ns_log(struct nvme_ctrl *ctrl)
{
size_t log_size = NVME_MAX_CHANGED_NAMESPACES * sizeof(__le32);
__le32 *log;
int error, i;
bool ret = false;
int error;

log = kzalloc(log_size, GFP_KERNEL);
if (!log)
return false;
return;

/*
* We need to read the log to clear the AEN, but we don't want to rely
* on it for the changed namespace information as userspace could have
* raced with us in reading the log page, which could cause us to miss
* updates.
*/
error = nvme_get_log(ctrl, NVME_LOG_CHANGED_NS, log, log_size);
if (error) {
if (error)
dev_warn(ctrl->device,
"reading changed ns log failed: %d\n", error);
goto out_free_log;
}

if (log[0] == cpu_to_le32(0xffffffff))
goto out_free_log;

for (i = 0; i < NVME_MAX_CHANGED_NAMESPACES; i++) {
u32 nsid = le32_to_cpu(log[i]);

if (nsid == 0)
break;
dev_info(ctrl->device, "rescanning namespace %d.\n", nsid);
nvme_validate_ns(ctrl, nsid);
}
ret = true;

out_free_log:
kfree(log);
return ret;
}

static void nvme_scan_work(struct work_struct *work)
Expand All @@ -3246,9 +3234,8 @@ static void nvme_scan_work(struct work_struct *work)
WARN_ON_ONCE(!ctrl->tagset);

if (test_and_clear_bit(NVME_AER_NOTICE_NS_CHANGED, &ctrl->events)) {
if (nvme_scan_changed_ns_log(ctrl))
goto out_sort_namespaces;
dev_info(ctrl->device, "rescanning namespaces.\n");
nvme_clear_changed_ns_log(ctrl);
}

if (nvme_identify_ctrl(ctrl, &id))
Expand All @@ -3263,7 +3250,6 @@ static void nvme_scan_work(struct work_struct *work)
nvme_scan_ns_sequential(ctrl, nn);
out_free_id:
kfree(id);
out_sort_namespaces:
down_write(&ctrl->namespaces_rwsem);
list_sort(NULL, &ctrl->namespaces, ns_cmp);
up_write(&ctrl->namespaces_rwsem);
Expand Down Expand Up @@ -3641,16 +3627,6 @@ void nvme_start_queues(struct nvme_ctrl *ctrl)
}
EXPORT_SYMBOL_GPL(nvme_start_queues);

int nvme_reinit_tagset(struct nvme_ctrl *ctrl, struct blk_mq_tag_set *set)
{
if (!ctrl->ops->reinit_request)
return 0;

return blk_mq_tagset_iter(set, set->driver_data,
ctrl->ops->reinit_request);
}
EXPORT_SYMBOL_GPL(nvme_reinit_tagset);

int __init nvme_core_init(void)
{
int result = -ENOMEM;
Expand Down
86 changes: 37 additions & 49 deletions drivers/nvme/host/fabrics.c
Original file line number Diff line number Diff line change
Expand Up @@ -536,67 +536,55 @@ static struct nvmf_transport_ops *nvmf_lookup_transport(
return NULL;
}

blk_status_t nvmf_check_if_ready(struct nvme_ctrl *ctrl, struct request *rq,
bool queue_live, bool is_connected)
/*
* For something we're not in a state to send to the device the default action
* is to busy it and retry it after the controller state is recovered. However,
* anything marked for failfast or nvme multipath is immediately failed.
*
* Note: commands used to initialize the controller will be marked for failfast.
* Note: nvme cli/ioctl commands are marked for failfast.
*/
blk_status_t nvmf_fail_nonready_command(struct request *rq)
{
struct nvme_command *cmd = nvme_req(rq)->cmd;
if (!blk_noretry_request(rq) && !(rq->cmd_flags & REQ_NVME_MPATH))
return BLK_STS_RESOURCE;
nvme_req(rq)->status = NVME_SC_ABORT_REQ;
return BLK_STS_IOERR;
}
EXPORT_SYMBOL_GPL(nvmf_fail_nonready_command);

if (likely(ctrl->state == NVME_CTRL_LIVE && is_connected))
return BLK_STS_OK;
bool __nvmf_check_ready(struct nvme_ctrl *ctrl, struct request *rq,
bool queue_live)
{
struct nvme_request *req = nvme_req(rq);

/*
* If we are in some state of setup or teardown only allow
* internally generated commands.
*/
if (!blk_rq_is_passthrough(rq) || (req->flags & NVME_REQ_USERCMD))
return false;

/*
* Only allow commands on a live queue, except for the connect command,
* which is require to set the queue live in the appropinquate states.
*/
switch (ctrl->state) {
case NVME_CTRL_NEW:
case NVME_CTRL_CONNECTING:
case NVME_CTRL_DELETING:
/*
* This is the case of starting a new or deleting an association
* but connectivity was lost before it was fully created or torn
* down. We need to error the commands used to initialize the
* controller so the reconnect can go into a retry attempt. The
* commands should all be marked REQ_FAILFAST_DRIVER, which will
* hit the reject path below. Anything else will be queued while
* the state settles.
*/
if (!is_connected)
break;

/*
* If queue is live, allow only commands that are internally
* generated pass through. These are commands on the admin
* queue to initialize the controller. This will reject any
* ioctl admin cmds received while initializing.
*/
if (queue_live && !(nvme_req(rq)->flags & NVME_REQ_USERCMD))
return BLK_STS_OK;

/*
* If the queue is not live, allow only a connect command. This
* will reject any ioctl admin cmd as well as initialization
* commands if the controller reverted the queue to non-live.
*/
if (!queue_live && blk_rq_is_passthrough(rq) &&
cmd->common.opcode == nvme_fabrics_command &&
cmd->fabrics.fctype == nvme_fabrics_type_connect)
return BLK_STS_OK;
if (req->cmd->common.opcode == nvme_fabrics_command &&
req->cmd->fabrics.fctype == nvme_fabrics_type_connect)
return true;
break;
default:
break;
case NVME_CTRL_DEAD:
return false;
}

/*
* Any other new io is something we're not in a state to send to the
* device. Default action is to busy it and retry it after the
* controller state is recovered. However, anything marked for failfast
* or nvme multipath is immediately failed. Note: commands used to
* initialize the controller will be marked for failfast.
* Note: nvme cli/ioctl commands are marked for failfast.
*/
if (!blk_noretry_request(rq) && !(rq->cmd_flags & REQ_NVME_MPATH))
return BLK_STS_RESOURCE;
nvme_req(rq)->status = NVME_SC_ABORT_REQ;
return BLK_STS_IOERR;
return queue_live;
}
EXPORT_SYMBOL_GPL(nvmf_check_if_ready);
EXPORT_SYMBOL_GPL(__nvmf_check_ready);

static const match_table_t opt_tokens = {
{ NVMF_OPT_TRANSPORT, "transport=%s" },
Expand Down
14 changes: 12 additions & 2 deletions drivers/nvme/host/fabrics.h
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,17 @@ void nvmf_unregister_transport(struct nvmf_transport_ops *ops);
void nvmf_free_options(struct nvmf_ctrl_options *opts);
int nvmf_get_address(struct nvme_ctrl *ctrl, char *buf, int size);
bool nvmf_should_reconnect(struct nvme_ctrl *ctrl);
blk_status_t nvmf_check_if_ready(struct nvme_ctrl *ctrl,
struct request *rq, bool queue_live, bool is_connected);
blk_status_t nvmf_fail_nonready_command(struct request *rq);
bool __nvmf_check_ready(struct nvme_ctrl *ctrl, struct request *rq,
bool queue_live);

static inline bool nvmf_check_ready(struct nvme_ctrl *ctrl, struct request *rq,
bool queue_live)
{
if (likely(ctrl->state == NVME_CTRL_LIVE ||
ctrl->state == NVME_CTRL_ADMIN_ONLY))
return true;
return __nvmf_check_ready(ctrl, rq, queue_live);
}

#endif /* _NVME_FABRICS_H */
Loading

0 comments on commit 95c7c09

Please sign in to comment.