Skip to content

Commit c0c14e9

Browse files
committed
Merge branch 'nvme-5.1' of git://git.infradead.org/nvme into for-linus
Pull NVMe fixes from Christoph: "Two nvme fixes for 5.1 - fixing the initial CSN for nvme-fc, and handle log page offsets properly in the target." * 'nvme-5.1' of git://git.infradead.org/nvme: nvmet: fix discover log page when offsets are used nvme-fc: correct csn initialization and increments on error
2 parents a3761c3 + d808b7f commit c0c14e9

File tree

5 files changed

+73
-30
lines changed

5 files changed

+73
-30
lines changed

drivers/nvme/host/fc.c

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1845,7 +1845,7 @@ nvme_fc_init_queue(struct nvme_fc_ctrl *ctrl, int idx)
18451845
memset(queue, 0, sizeof(*queue));
18461846
queue->ctrl = ctrl;
18471847
queue->qnum = idx;
1848-
atomic_set(&queue->csn, 1);
1848+
atomic_set(&queue->csn, 0);
18491849
queue->dev = ctrl->dev;
18501850

18511851
if (idx > 0)
@@ -1887,7 +1887,7 @@ nvme_fc_free_queue(struct nvme_fc_queue *queue)
18871887
*/
18881888

18891889
queue->connection_id = 0;
1890-
atomic_set(&queue->csn, 1);
1890+
atomic_set(&queue->csn, 0);
18911891
}
18921892

18931893
static void
@@ -2183,7 +2183,6 @@ nvme_fc_start_fcp_op(struct nvme_fc_ctrl *ctrl, struct nvme_fc_queue *queue,
21832183
{
21842184
struct nvme_fc_cmd_iu *cmdiu = &op->cmd_iu;
21852185
struct nvme_command *sqe = &cmdiu->sqe;
2186-
u32 csn;
21872186
int ret, opstate;
21882187

21892188
/*
@@ -2198,8 +2197,6 @@ nvme_fc_start_fcp_op(struct nvme_fc_ctrl *ctrl, struct nvme_fc_queue *queue,
21982197

21992198
/* format the FC-NVME CMD IU and fcp_req */
22002199
cmdiu->connection_id = cpu_to_be64(queue->connection_id);
2201-
csn = atomic_inc_return(&queue->csn);
2202-
cmdiu->csn = cpu_to_be32(csn);
22032200
cmdiu->data_len = cpu_to_be32(data_len);
22042201
switch (io_dir) {
22052202
case NVMEFC_FCP_WRITE:
@@ -2257,11 +2254,24 @@ nvme_fc_start_fcp_op(struct nvme_fc_ctrl *ctrl, struct nvme_fc_queue *queue,
22572254
if (!(op->flags & FCOP_FLAGS_AEN))
22582255
blk_mq_start_request(op->rq);
22592256

2257+
cmdiu->csn = cpu_to_be32(atomic_inc_return(&queue->csn));
22602258
ret = ctrl->lport->ops->fcp_io(&ctrl->lport->localport,
22612259
&ctrl->rport->remoteport,
22622260
queue->lldd_handle, &op->fcp_req);
22632261

22642262
if (ret) {
2263+
/*
2264+
* If the lld fails to send the command is there an issue with
2265+
* the csn value? If the command that fails is the Connect,
2266+
* no - as the connection won't be live. If it is a command
2267+
* post-connect, it's possible a gap in csn may be created.
2268+
* Does this matter? As Linux initiators don't send fused
2269+
* commands, no. The gap would exist, but as there's nothing
2270+
* that depends on csn order to be delivered on the target
2271+
* side, it shouldn't hurt. It would be difficult for a
2272+
* target to even detect the csn gap as it has no idea when the
2273+
* cmd with the csn was supposed to arrive.
2274+
*/
22652275
opstate = atomic_xchg(&op->state, FCPOP_STATE_COMPLETE);
22662276
__nvme_fc_fcpop_chk_teardowns(ctrl, op, opstate);
22672277

drivers/nvme/target/admin-cmd.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@ u32 nvmet_get_log_page_len(struct nvme_command *cmd)
2424
return len;
2525
}
2626

27+
u64 nvmet_get_log_page_offset(struct nvme_command *cmd)
28+
{
29+
return le64_to_cpu(cmd->get_log_page.lpo);
30+
}
31+
2732
static void nvmet_execute_get_log_page_noop(struct nvmet_req *req)
2833
{
2934
nvmet_req_complete(req, nvmet_zero_sgl(req, 0, req->data_len));

drivers/nvme/target/discovery.c

Lines changed: 45 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -131,54 +131,76 @@ static void nvmet_set_disc_traddr(struct nvmet_req *req, struct nvmet_port *port
131131
memcpy(traddr, port->disc_addr.traddr, NVMF_TRADDR_SIZE);
132132
}
133133

134+
static size_t discovery_log_entries(struct nvmet_req *req)
135+
{
136+
struct nvmet_ctrl *ctrl = req->sq->ctrl;
137+
struct nvmet_subsys_link *p;
138+
struct nvmet_port *r;
139+
size_t entries = 0;
140+
141+
list_for_each_entry(p, &req->port->subsystems, entry) {
142+
if (!nvmet_host_allowed(p->subsys, ctrl->hostnqn))
143+
continue;
144+
entries++;
145+
}
146+
list_for_each_entry(r, &req->port->referrals, entry)
147+
entries++;
148+
return entries;
149+
}
150+
134151
static void nvmet_execute_get_disc_log_page(struct nvmet_req *req)
135152
{
136153
const int entry_size = sizeof(struct nvmf_disc_rsp_page_entry);
137154
struct nvmet_ctrl *ctrl = req->sq->ctrl;
138155
struct nvmf_disc_rsp_page_hdr *hdr;
156+
u64 offset = nvmet_get_log_page_offset(req->cmd);
139157
size_t data_len = nvmet_get_log_page_len(req->cmd);
140-
size_t alloc_len = max(data_len, sizeof(*hdr));
141-
int residual_len = data_len - sizeof(*hdr);
158+
size_t alloc_len;
142159
struct nvmet_subsys_link *p;
143160
struct nvmet_port *r;
144161
u32 numrec = 0;
145162
u16 status = 0;
163+
void *buffer;
164+
165+
/* Spec requires dword aligned offsets */
166+
if (offset & 0x3) {
167+
status = NVME_SC_INVALID_FIELD | NVME_SC_DNR;
168+
goto out;
169+
}
146170

147171
/*
148172
* Make sure we're passing at least a buffer of response header size.
149173
* If host provided data len is less than the header size, only the
150174
* number of bytes requested by host will be sent to host.
151175
*/
152-
hdr = kzalloc(alloc_len, GFP_KERNEL);
153-
if (!hdr) {
176+
down_read(&nvmet_config_sem);
177+
alloc_len = sizeof(*hdr) + entry_size * discovery_log_entries(req);
178+
buffer = kzalloc(alloc_len, GFP_KERNEL);
179+
if (!buffer) {
180+
up_read(&nvmet_config_sem);
154181
status = NVME_SC_INTERNAL;
155182
goto out;
156183
}
157184

158-
down_read(&nvmet_config_sem);
185+
hdr = buffer;
159186
list_for_each_entry(p, &req->port->subsystems, entry) {
187+
char traddr[NVMF_TRADDR_SIZE];
188+
160189
if (!nvmet_host_allowed(p->subsys, ctrl->hostnqn))
161190
continue;
162-
if (residual_len >= entry_size) {
163-
char traddr[NVMF_TRADDR_SIZE];
164-
165-
nvmet_set_disc_traddr(req, req->port, traddr);
166-
nvmet_format_discovery_entry(hdr, req->port,
167-
p->subsys->subsysnqn, traddr,
168-
NVME_NQN_NVME, numrec);
169-
residual_len -= entry_size;
170-
}
191+
192+
nvmet_set_disc_traddr(req, req->port, traddr);
193+
nvmet_format_discovery_entry(hdr, req->port,
194+
p->subsys->subsysnqn, traddr,
195+
NVME_NQN_NVME, numrec);
171196
numrec++;
172197
}
173198

174199
list_for_each_entry(r, &req->port->referrals, entry) {
175-
if (residual_len >= entry_size) {
176-
nvmet_format_discovery_entry(hdr, r,
177-
NVME_DISC_SUBSYS_NAME,
178-
r->disc_addr.traddr,
179-
NVME_NQN_DISC, numrec);
180-
residual_len -= entry_size;
181-
}
200+
nvmet_format_discovery_entry(hdr, r,
201+
NVME_DISC_SUBSYS_NAME,
202+
r->disc_addr.traddr,
203+
NVME_NQN_DISC, numrec);
182204
numrec++;
183205
}
184206

@@ -190,8 +212,8 @@ static void nvmet_execute_get_disc_log_page(struct nvmet_req *req)
190212

191213
up_read(&nvmet_config_sem);
192214

193-
status = nvmet_copy_to_sgl(req, 0, hdr, data_len);
194-
kfree(hdr);
215+
status = nvmet_copy_to_sgl(req, 0, buffer + offset, data_len);
216+
kfree(buffer);
195217
out:
196218
nvmet_req_complete(req, status);
197219
}

drivers/nvme/target/nvmet.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -428,6 +428,7 @@ u16 nvmet_copy_from_sgl(struct nvmet_req *req, off_t off, void *buf,
428428
u16 nvmet_zero_sgl(struct nvmet_req *req, off_t off, size_t len);
429429

430430
u32 nvmet_get_log_page_len(struct nvme_command *cmd);
431+
u64 nvmet_get_log_page_offset(struct nvme_command *cmd);
431432

432433
extern struct list_head *nvmet_ports;
433434
void nvmet_port_disc_changed(struct nvmet_port *port,

include/linux/nvme.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -967,8 +967,13 @@ struct nvme_get_log_page_command {
967967
__le16 numdl;
968968
__le16 numdu;
969969
__u16 rsvd11;
970-
__le32 lpol;
971-
__le32 lpou;
970+
union {
971+
struct {
972+
__le32 lpol;
973+
__le32 lpou;
974+
};
975+
__le64 lpo;
976+
};
972977
__u32 rsvd14[2];
973978
};
974979

0 commit comments

Comments
 (0)