1
2
3
4
5
6
7
8
9
10
11
12
13
14#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
15#include <linux/init.h>
16#include <linux/miscdevice.h>
17#include <linux/module.h>
18#include <linux/mutex.h>
19#include <linux/parser.h>
20#include <linux/seq_file.h>
21#include "nvme.h"
22#include "fabrics.h"
23
24static LIST_HEAD(nvmf_transports);
25static DEFINE_MUTEX(nvmf_transports_mutex);
26
27static LIST_HEAD(nvmf_hosts);
28static DEFINE_MUTEX(nvmf_hosts_mutex);
29
30static struct nvmf_host *nvmf_default_host;
31
32static struct nvmf_host *__nvmf_host_find(const char *hostnqn)
33{
34 struct nvmf_host *host;
35
36 list_for_each_entry(host, &nvmf_hosts, list) {
37 if (!strcmp(host->nqn, hostnqn))
38 return host;
39 }
40
41 return NULL;
42}
43
44static struct nvmf_host *nvmf_host_add(const char *hostnqn)
45{
46 struct nvmf_host *host;
47
48 mutex_lock(&nvmf_hosts_mutex);
49 host = __nvmf_host_find(hostnqn);
50 if (host) {
51 kref_get(&host->ref);
52 goto out_unlock;
53 }
54
55 host = kmalloc(sizeof(*host), GFP_KERNEL);
56 if (!host)
57 goto out_unlock;
58
59 kref_init(&host->ref);
60 memcpy(host->nqn, hostnqn, NVMF_NQN_SIZE);
61 uuid_be_gen(&host->id);
62
63 list_add_tail(&host->list, &nvmf_hosts);
64out_unlock:
65 mutex_unlock(&nvmf_hosts_mutex);
66 return host;
67}
68
69static struct nvmf_host *nvmf_host_default(void)
70{
71 struct nvmf_host *host;
72
73 host = kmalloc(sizeof(*host), GFP_KERNEL);
74 if (!host)
75 return NULL;
76
77 kref_init(&host->ref);
78 uuid_be_gen(&host->id);
79 snprintf(host->nqn, NVMF_NQN_SIZE,
80 "nqn.2014-08.org.nvmexpress:NVMf:uuid:%pUb", &host->id);
81
82 mutex_lock(&nvmf_hosts_mutex);
83 list_add_tail(&host->list, &nvmf_hosts);
84 mutex_unlock(&nvmf_hosts_mutex);
85
86 return host;
87}
88
89static void nvmf_host_destroy(struct kref *ref)
90{
91 struct nvmf_host *host = container_of(ref, struct nvmf_host, ref);
92
93 mutex_lock(&nvmf_hosts_mutex);
94 list_del(&host->list);
95 mutex_unlock(&nvmf_hosts_mutex);
96
97 kfree(host);
98}
99
100static void nvmf_host_put(struct nvmf_host *host)
101{
102 if (host)
103 kref_put(&host->ref, nvmf_host_destroy);
104}
105
106
107
108
109
110
111
112int nvmf_get_address(struct nvme_ctrl *ctrl, char *buf, int size)
113{
114 int len = 0;
115
116 if (ctrl->opts->mask & NVMF_OPT_TRADDR)
117 len += snprintf(buf, size, "traddr=%s", ctrl->opts->traddr);
118 if (ctrl->opts->mask & NVMF_OPT_TRSVCID)
119 len += snprintf(buf + len, size - len, "%strsvcid=%s",
120 (len) ? "," : "", ctrl->opts->trsvcid);
121 if (ctrl->opts->mask & NVMF_OPT_HOST_TRADDR)
122 len += snprintf(buf + len, size - len, "%shost_traddr=%s",
123 (len) ? "," : "", ctrl->opts->host_traddr);
124 len += snprintf(buf + len, size - len, "\n");
125
126 return len;
127}
128EXPORT_SYMBOL_GPL(nvmf_get_address);
129
130
131
132
133
134const char *nvmf_get_subsysnqn(struct nvme_ctrl *ctrl)
135{
136 return ctrl->opts->subsysnqn;
137}
138EXPORT_SYMBOL_GPL(nvmf_get_subsysnqn);
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161int nvmf_reg_read32(struct nvme_ctrl *ctrl, u32 off, u32 *val)
162{
163 struct nvme_command cmd;
164 union nvme_result res;
165 int ret;
166
167 memset(&cmd, 0, sizeof(cmd));
168 cmd.prop_get.opcode = nvme_fabrics_command;
169 cmd.prop_get.fctype = nvme_fabrics_type_property_get;
170 cmd.prop_get.offset = cpu_to_le32(off);
171
172 ret = __nvme_submit_sync_cmd(ctrl->admin_q, &cmd, &res, NULL, 0, 0,
173 NVME_QID_ANY, 0, 0);
174
175 if (ret >= 0)
176 *val = le64_to_cpu(res.u64);
177 if (unlikely(ret != 0))
178 dev_err(ctrl->device,
179 "Property Get error: %d, offset %#x\n",
180 ret > 0 ? ret & ~NVME_SC_DNR : ret, off);
181
182 return ret;
183}
184EXPORT_SYMBOL_GPL(nvmf_reg_read32);
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207int nvmf_reg_read64(struct nvme_ctrl *ctrl, u32 off, u64 *val)
208{
209 struct nvme_command cmd;
210 union nvme_result res;
211 int ret;
212
213 memset(&cmd, 0, sizeof(cmd));
214 cmd.prop_get.opcode = nvme_fabrics_command;
215 cmd.prop_get.fctype = nvme_fabrics_type_property_get;
216 cmd.prop_get.attrib = 1;
217 cmd.prop_get.offset = cpu_to_le32(off);
218
219 ret = __nvme_submit_sync_cmd(ctrl->admin_q, &cmd, &res, NULL, 0, 0,
220 NVME_QID_ANY, 0, 0);
221
222 if (ret >= 0)
223 *val = le64_to_cpu(res.u64);
224 if (unlikely(ret != 0))
225 dev_err(ctrl->device,
226 "Property Get error: %d, offset %#x\n",
227 ret > 0 ? ret & ~NVME_SC_DNR : ret, off);
228 return ret;
229}
230EXPORT_SYMBOL_GPL(nvmf_reg_read64);
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253int nvmf_reg_write32(struct nvme_ctrl *ctrl, u32 off, u32 val)
254{
255 struct nvme_command cmd;
256 int ret;
257
258 memset(&cmd, 0, sizeof(cmd));
259 cmd.prop_set.opcode = nvme_fabrics_command;
260 cmd.prop_set.fctype = nvme_fabrics_type_property_set;
261 cmd.prop_set.attrib = 0;
262 cmd.prop_set.offset = cpu_to_le32(off);
263 cmd.prop_set.value = cpu_to_le64(val);
264
265 ret = __nvme_submit_sync_cmd(ctrl->admin_q, &cmd, NULL, NULL, 0, 0,
266 NVME_QID_ANY, 0, 0);
267 if (unlikely(ret))
268 dev_err(ctrl->device,
269 "Property Set error: %d, offset %#x\n",
270 ret > 0 ? ret & ~NVME_SC_DNR : ret, off);
271 return ret;
272}
273EXPORT_SYMBOL_GPL(nvmf_reg_write32);
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290static void nvmf_log_connect_error(struct nvme_ctrl *ctrl,
291 int errval, int offset, struct nvme_command *cmd,
292 struct nvmf_connect_data *data)
293{
294 int err_sctype = errval & (~NVME_SC_DNR);
295
296 switch (err_sctype) {
297
298 case (NVME_SC_CONNECT_INVALID_PARAM):
299 if (offset >> 16) {
300 char *inv_data = "Connect Invalid Data Parameter";
301
302 switch (offset & 0xffff) {
303 case (offsetof(struct nvmf_connect_data, cntlid)):
304 dev_err(ctrl->device,
305 "%s, cntlid: %d\n",
306 inv_data, data->cntlid);
307 break;
308 case (offsetof(struct nvmf_connect_data, hostnqn)):
309 dev_err(ctrl->device,
310 "%s, hostnqn \"%s\"\n",
311 inv_data, data->hostnqn);
312 break;
313 case (offsetof(struct nvmf_connect_data, subsysnqn)):
314 dev_err(ctrl->device,
315 "%s, subsysnqn \"%s\"\n",
316 inv_data, data->subsysnqn);
317 break;
318 default:
319 dev_err(ctrl->device,
320 "%s, starting byte offset: %d\n",
321 inv_data, offset & 0xffff);
322 break;
323 }
324 } else {
325 char *inv_sqe = "Connect Invalid SQE Parameter";
326
327 switch (offset) {
328 case (offsetof(struct nvmf_connect_command, qid)):
329 dev_err(ctrl->device,
330 "%s, qid %d\n",
331 inv_sqe, cmd->connect.qid);
332 break;
333 default:
334 dev_err(ctrl->device,
335 "%s, starting byte offset: %d\n",
336 inv_sqe, offset);
337 }
338 }
339 break;
340 default:
341 dev_err(ctrl->device,
342 "Connect command failed, error wo/DNR bit: %d\n",
343 err_sctype);
344 break;
345 }
346}
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368int nvmf_connect_admin_queue(struct nvme_ctrl *ctrl)
369{
370 struct nvme_command cmd;
371 union nvme_result res;
372 struct nvmf_connect_data *data;
373 int ret;
374
375 memset(&cmd, 0, sizeof(cmd));
376 cmd.connect.opcode = nvme_fabrics_command;
377 cmd.connect.fctype = nvme_fabrics_type_connect;
378 cmd.connect.qid = 0;
379
380
381
382
383
384
385 cmd.connect.sqsize = cpu_to_le16(NVMF_AQ_DEPTH - 1);
386
387
388
389
390
391 cmd.connect.kato = ctrl->opts->discovery_nqn ? 0 :
392 cpu_to_le32((ctrl->kato + NVME_KATO_GRACE) * 1000);
393
394 data = kzalloc(sizeof(*data), GFP_KERNEL);
395 if (!data)
396 return -ENOMEM;
397
398 memcpy(&data->hostid, &ctrl->opts->host->id, sizeof(uuid_be));
399 data->cntlid = cpu_to_le16(0xffff);
400 strncpy(data->subsysnqn, ctrl->opts->subsysnqn, NVMF_NQN_SIZE);
401 strncpy(data->hostnqn, ctrl->opts->host->nqn, NVMF_NQN_SIZE);
402
403 ret = __nvme_submit_sync_cmd(ctrl->admin_q, &cmd, &res,
404 data, sizeof(*data), 0, NVME_QID_ANY, 1,
405 BLK_MQ_REQ_RESERVED | BLK_MQ_REQ_NOWAIT);
406 if (ret) {
407 nvmf_log_connect_error(ctrl, ret, le32_to_cpu(res.u32),
408 &cmd, data);
409 goto out_free_data;
410 }
411
412 ctrl->cntlid = le16_to_cpu(res.u16);
413
414out_free_data:
415 kfree(data);
416 return ret;
417}
418EXPORT_SYMBOL_GPL(nvmf_connect_admin_queue);
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440int nvmf_connect_io_queue(struct nvme_ctrl *ctrl, u16 qid)
441{
442 struct nvme_command cmd;
443 struct nvmf_connect_data *data;
444 union nvme_result res;
445 int ret;
446
447 memset(&cmd, 0, sizeof(cmd));
448 cmd.connect.opcode = nvme_fabrics_command;
449 cmd.connect.fctype = nvme_fabrics_type_connect;
450 cmd.connect.qid = cpu_to_le16(qid);
451 cmd.connect.sqsize = cpu_to_le16(ctrl->sqsize);
452
453 data = kzalloc(sizeof(*data), GFP_KERNEL);
454 if (!data)
455 return -ENOMEM;
456
457 memcpy(&data->hostid, &ctrl->opts->host->id, sizeof(uuid_be));
458 data->cntlid = cpu_to_le16(ctrl->cntlid);
459 strncpy(data->subsysnqn, ctrl->opts->subsysnqn, NVMF_NQN_SIZE);
460 strncpy(data->hostnqn, ctrl->opts->host->nqn, NVMF_NQN_SIZE);
461
462 ret = __nvme_submit_sync_cmd(ctrl->connect_q, &cmd, &res,
463 data, sizeof(*data), 0, qid, 1,
464 BLK_MQ_REQ_RESERVED | BLK_MQ_REQ_NOWAIT);
465 if (ret) {
466 nvmf_log_connect_error(ctrl, ret, le32_to_cpu(res.u32),
467 &cmd, data);
468 }
469 kfree(data);
470 return ret;
471}
472EXPORT_SYMBOL_GPL(nvmf_connect_io_queue);
473
474
475
476
477
478
479
480
481
482
483int nvmf_register_transport(struct nvmf_transport_ops *ops)
484{
485 if (!ops->create_ctrl)
486 return -EINVAL;
487
488 mutex_lock(&nvmf_transports_mutex);
489 list_add_tail(&ops->entry, &nvmf_transports);
490 mutex_unlock(&nvmf_transports_mutex);
491
492 return 0;
493}
494EXPORT_SYMBOL_GPL(nvmf_register_transport);
495
496
497
498
499
500
501
502
503
504
505void nvmf_unregister_transport(struct nvmf_transport_ops *ops)
506{
507 mutex_lock(&nvmf_transports_mutex);
508 list_del(&ops->entry);
509 mutex_unlock(&nvmf_transports_mutex);
510}
511EXPORT_SYMBOL_GPL(nvmf_unregister_transport);
512
513static struct nvmf_transport_ops *nvmf_lookup_transport(
514 struct nvmf_ctrl_options *opts)
515{
516 struct nvmf_transport_ops *ops;
517
518 lockdep_assert_held(&nvmf_transports_mutex);
519
520 list_for_each_entry(ops, &nvmf_transports, entry) {
521 if (strcmp(ops->name, opts->transport) == 0)
522 return ops;
523 }
524
525 return NULL;
526}
527
528static const match_table_t opt_tokens = {
529 { NVMF_OPT_TRANSPORT, "transport=%s" },
530 { NVMF_OPT_TRADDR, "traddr=%s" },
531 { NVMF_OPT_TRSVCID, "trsvcid=%s" },
532 { NVMF_OPT_NQN, "nqn=%s" },
533 { NVMF_OPT_QUEUE_SIZE, "queue_size=%d" },
534 { NVMF_OPT_NR_IO_QUEUES, "nr_io_queues=%d" },
535 { NVMF_OPT_RECONNECT_DELAY, "reconnect_delay=%d" },
536 { NVMF_OPT_KATO, "keep_alive_tmo=%d" },
537 { NVMF_OPT_HOSTNQN, "hostnqn=%s" },
538 { NVMF_OPT_HOST_TRADDR, "host_traddr=%s" },
539 { NVMF_OPT_ERR, NULL }
540};
541
542static int nvmf_parse_options(struct nvmf_ctrl_options *opts,
543 const char *buf)
544{
545 substring_t args[MAX_OPT_ARGS];
546 char *options, *o, *p;
547 int token, ret = 0;
548 size_t nqnlen = 0;
549
550
551 opts->queue_size = NVMF_DEF_QUEUE_SIZE;
552 opts->nr_io_queues = num_online_cpus();
553 opts->reconnect_delay = NVMF_DEF_RECONNECT_DELAY;
554
555 options = o = kstrdup(buf, GFP_KERNEL);
556 if (!options)
557 return -ENOMEM;
558
559 while ((p = strsep(&o, ",\n")) != NULL) {
560 if (!*p)
561 continue;
562
563 token = match_token(p, opt_tokens, args);
564 opts->mask |= token;
565 switch (token) {
566 case NVMF_OPT_TRANSPORT:
567 p = match_strdup(args);
568 if (!p) {
569 ret = -ENOMEM;
570 goto out;
571 }
572 opts->transport = p;
573 break;
574 case NVMF_OPT_NQN:
575 p = match_strdup(args);
576 if (!p) {
577 ret = -ENOMEM;
578 goto out;
579 }
580 opts->subsysnqn = p;
581 nqnlen = strlen(opts->subsysnqn);
582 if (nqnlen >= NVMF_NQN_SIZE) {
583 pr_err("%s needs to be < %d bytes\n",
584 opts->subsysnqn, NVMF_NQN_SIZE);
585 ret = -EINVAL;
586 goto out;
587 }
588 opts->discovery_nqn =
589 !(strcmp(opts->subsysnqn,
590 NVME_DISC_SUBSYS_NAME));
591 if (opts->discovery_nqn)
592 opts->nr_io_queues = 0;
593 break;
594 case NVMF_OPT_TRADDR:
595 p = match_strdup(args);
596 if (!p) {
597 ret = -ENOMEM;
598 goto out;
599 }
600 opts->traddr = p;
601 break;
602 case NVMF_OPT_TRSVCID:
603 p = match_strdup(args);
604 if (!p) {
605 ret = -ENOMEM;
606 goto out;
607 }
608 opts->trsvcid = p;
609 break;
610 case NVMF_OPT_QUEUE_SIZE:
611 if (match_int(args, &token)) {
612 ret = -EINVAL;
613 goto out;
614 }
615 if (token < NVMF_MIN_QUEUE_SIZE ||
616 token > NVMF_MAX_QUEUE_SIZE) {
617 pr_err("Invalid queue_size %d\n", token);
618 ret = -EINVAL;
619 goto out;
620 }
621 opts->queue_size = token;
622 break;
623 case NVMF_OPT_NR_IO_QUEUES:
624 if (match_int(args, &token)) {
625 ret = -EINVAL;
626 goto out;
627 }
628 if (token <= 0) {
629 pr_err("Invalid number of IOQs %d\n", token);
630 ret = -EINVAL;
631 goto out;
632 }
633 opts->nr_io_queues = min_t(unsigned int,
634 num_online_cpus(), token);
635 break;
636 case NVMF_OPT_KATO:
637 if (match_int(args, &token)) {
638 ret = -EINVAL;
639 goto out;
640 }
641
642 if (opts->discovery_nqn) {
643 pr_err("Discovery controllers cannot accept keep_alive_tmo != 0\n");
644 ret = -EINVAL;
645 goto out;
646 }
647
648 if (token < 0) {
649 pr_err("Invalid keep_alive_tmo %d\n", token);
650 ret = -EINVAL;
651 goto out;
652 } else if (token == 0) {
653
654 pr_warn("keep_alive_tmo 0 won't execute keep alives!!!\n");
655 }
656 opts->kato = token;
657 break;
658 case NVMF_OPT_HOSTNQN:
659 if (opts->host) {
660 pr_err("hostnqn already user-assigned: %s\n",
661 opts->host->nqn);
662 ret = -EADDRINUSE;
663 goto out;
664 }
665 p = match_strdup(args);
666 if (!p) {
667 ret = -ENOMEM;
668 goto out;
669 }
670 nqnlen = strlen(p);
671 if (nqnlen >= NVMF_NQN_SIZE) {
672 pr_err("%s needs to be < %d bytes\n",
673 p, NVMF_NQN_SIZE);
674 kfree(p);
675 ret = -EINVAL;
676 goto out;
677 }
678 opts->host = nvmf_host_add(p);
679 kfree(p);
680 if (!opts->host) {
681 ret = -ENOMEM;
682 goto out;
683 }
684 break;
685 case NVMF_OPT_RECONNECT_DELAY:
686 if (match_int(args, &token)) {
687 ret = -EINVAL;
688 goto out;
689 }
690 if (token <= 0) {
691 pr_err("Invalid reconnect_delay %d\n", token);
692 ret = -EINVAL;
693 goto out;
694 }
695 opts->reconnect_delay = token;
696 break;
697 case NVMF_OPT_HOST_TRADDR:
698 p = match_strdup(args);
699 if (!p) {
700 ret = -ENOMEM;
701 goto out;
702 }
703 opts->host_traddr = p;
704 break;
705 default:
706 pr_warn("unknown parameter or missing value '%s' in ctrl creation request\n",
707 p);
708 ret = -EINVAL;
709 goto out;
710 }
711 }
712
713 if (!opts->host) {
714 kref_get(&nvmf_default_host->ref);
715 opts->host = nvmf_default_host;
716 }
717
718out:
719 if (!opts->discovery_nqn && !opts->kato)
720 opts->kato = NVME_DEFAULT_KATO;
721 kfree(options);
722 return ret;
723}
724
725static int nvmf_check_required_opts(struct nvmf_ctrl_options *opts,
726 unsigned int required_opts)
727{
728 if ((opts->mask & required_opts) != required_opts) {
729 int i;
730
731 for (i = 0; i < ARRAY_SIZE(opt_tokens); i++) {
732 if ((opt_tokens[i].token & required_opts) &&
733 !(opt_tokens[i].token & opts->mask)) {
734 pr_warn("missing parameter '%s'\n",
735 opt_tokens[i].pattern);
736 }
737 }
738
739 return -EINVAL;
740 }
741
742 return 0;
743}
744
745static int nvmf_check_allowed_opts(struct nvmf_ctrl_options *opts,
746 unsigned int allowed_opts)
747{
748 if (opts->mask & ~allowed_opts) {
749 int i;
750
751 for (i = 0; i < ARRAY_SIZE(opt_tokens); i++) {
752 if (opt_tokens[i].token & ~allowed_opts) {
753 pr_warn("invalid parameter '%s'\n",
754 opt_tokens[i].pattern);
755 }
756 }
757
758 return -EINVAL;
759 }
760
761 return 0;
762}
763
764void nvmf_free_options(struct nvmf_ctrl_options *opts)
765{
766 nvmf_host_put(opts->host);
767 kfree(opts->transport);
768 kfree(opts->traddr);
769 kfree(opts->trsvcid);
770 kfree(opts->subsysnqn);
771 kfree(opts->host_traddr);
772 kfree(opts);
773}
774EXPORT_SYMBOL_GPL(nvmf_free_options);
775
776#define NVMF_REQUIRED_OPTS (NVMF_OPT_TRANSPORT | NVMF_OPT_NQN)
777#define NVMF_ALLOWED_OPTS (NVMF_OPT_QUEUE_SIZE | NVMF_OPT_NR_IO_QUEUES | \
778 NVMF_OPT_KATO | NVMF_OPT_HOSTNQN)
779
780static struct nvme_ctrl *
781nvmf_create_ctrl(struct device *dev, const char *buf, size_t count)
782{
783 struct nvmf_ctrl_options *opts;
784 struct nvmf_transport_ops *ops;
785 struct nvme_ctrl *ctrl;
786 int ret;
787
788 opts = kzalloc(sizeof(*opts), GFP_KERNEL);
789 if (!opts)
790 return ERR_PTR(-ENOMEM);
791
792 ret = nvmf_parse_options(opts, buf);
793 if (ret)
794 goto out_free_opts;
795
796
797
798
799
800
801 ret = nvmf_check_required_opts(opts, NVMF_REQUIRED_OPTS);
802 if (ret)
803 goto out_free_opts;
804 opts->mask &= ~NVMF_REQUIRED_OPTS;
805
806 mutex_lock(&nvmf_transports_mutex);
807 ops = nvmf_lookup_transport(opts);
808 if (!ops) {
809 pr_info("no handler found for transport %s.\n",
810 opts->transport);
811 ret = -EINVAL;
812 goto out_unlock;
813 }
814
815 ret = nvmf_check_required_opts(opts, ops->required_opts);
816 if (ret)
817 goto out_unlock;
818 ret = nvmf_check_allowed_opts(opts, NVMF_ALLOWED_OPTS |
819 ops->allowed_opts | ops->required_opts);
820 if (ret)
821 goto out_unlock;
822
823 ctrl = ops->create_ctrl(dev, opts);
824 if (IS_ERR(ctrl)) {
825 ret = PTR_ERR(ctrl);
826 goto out_unlock;
827 }
828
829 mutex_unlock(&nvmf_transports_mutex);
830 return ctrl;
831
832out_unlock:
833 mutex_unlock(&nvmf_transports_mutex);
834out_free_opts:
835 nvmf_free_options(opts);
836 return ERR_PTR(ret);
837}
838
839static struct class *nvmf_class;
840static struct device *nvmf_device;
841static DEFINE_MUTEX(nvmf_dev_mutex);
842
843static ssize_t nvmf_dev_write(struct file *file, const char __user *ubuf,
844 size_t count, loff_t *pos)
845{
846 struct seq_file *seq_file = file->private_data;
847 struct nvme_ctrl *ctrl;
848 const char *buf;
849 int ret = 0;
850
851 if (count > PAGE_SIZE)
852 return -ENOMEM;
853
854 buf = memdup_user_nul(ubuf, count);
855 if (IS_ERR(buf))
856 return PTR_ERR(buf);
857
858 mutex_lock(&nvmf_dev_mutex);
859 if (seq_file->private) {
860 ret = -EINVAL;
861 goto out_unlock;
862 }
863
864 ctrl = nvmf_create_ctrl(nvmf_device, buf, count);
865 if (IS_ERR(ctrl)) {
866 ret = PTR_ERR(ctrl);
867 goto out_unlock;
868 }
869
870 seq_file->private = ctrl;
871
872out_unlock:
873 mutex_unlock(&nvmf_dev_mutex);
874 kfree(buf);
875 return ret ? ret : count;
876}
877
878static int nvmf_dev_show(struct seq_file *seq_file, void *private)
879{
880 struct nvme_ctrl *ctrl;
881 int ret = 0;
882
883 mutex_lock(&nvmf_dev_mutex);
884 ctrl = seq_file->private;
885 if (!ctrl) {
886 ret = -EINVAL;
887 goto out_unlock;
888 }
889
890 seq_printf(seq_file, "instance=%d,cntlid=%d\n",
891 ctrl->instance, ctrl->cntlid);
892
893out_unlock:
894 mutex_unlock(&nvmf_dev_mutex);
895 return ret;
896}
897
898static int nvmf_dev_open(struct inode *inode, struct file *file)
899{
900
901
902
903
904 file->private_data = NULL;
905 return single_open(file, nvmf_dev_show, NULL);
906}
907
908static int nvmf_dev_release(struct inode *inode, struct file *file)
909{
910 struct seq_file *seq_file = file->private_data;
911 struct nvme_ctrl *ctrl = seq_file->private;
912
913 if (ctrl)
914 nvme_put_ctrl(ctrl);
915 return single_release(inode, file);
916}
917
918static const struct file_operations nvmf_dev_fops = {
919 .owner = THIS_MODULE,
920 .write = nvmf_dev_write,
921 .read = seq_read,
922 .open = nvmf_dev_open,
923 .release = nvmf_dev_release,
924};
925
926static struct miscdevice nvmf_misc = {
927 .minor = MISC_DYNAMIC_MINOR,
928 .name = "nvme-fabrics",
929 .fops = &nvmf_dev_fops,
930};
931
932static int __init nvmf_init(void)
933{
934 int ret;
935
936 nvmf_default_host = nvmf_host_default();
937 if (!nvmf_default_host)
938 return -ENOMEM;
939
940 nvmf_class = class_create(THIS_MODULE, "nvme-fabrics");
941 if (IS_ERR(nvmf_class)) {
942 pr_err("couldn't register class nvme-fabrics\n");
943 ret = PTR_ERR(nvmf_class);
944 goto out_free_host;
945 }
946
947 nvmf_device =
948 device_create(nvmf_class, NULL, MKDEV(0, 0), NULL, "ctl");
949 if (IS_ERR(nvmf_device)) {
950 pr_err("couldn't create nvme-fabris device!\n");
951 ret = PTR_ERR(nvmf_device);
952 goto out_destroy_class;
953 }
954
955 ret = misc_register(&nvmf_misc);
956 if (ret) {
957 pr_err("couldn't register misc device: %d\n", ret);
958 goto out_destroy_device;
959 }
960
961 return 0;
962
963out_destroy_device:
964 device_destroy(nvmf_class, MKDEV(0, 0));
965out_destroy_class:
966 class_destroy(nvmf_class);
967out_free_host:
968 nvmf_host_put(nvmf_default_host);
969 return ret;
970}
971
972static void __exit nvmf_exit(void)
973{
974 misc_deregister(&nvmf_misc);
975 device_destroy(nvmf_class, MKDEV(0, 0));
976 class_destroy(nvmf_class);
977 nvmf_host_put(nvmf_default_host);
978
979 BUILD_BUG_ON(sizeof(struct nvmf_connect_command) != 64);
980 BUILD_BUG_ON(sizeof(struct nvmf_property_get_command) != 64);
981 BUILD_BUG_ON(sizeof(struct nvmf_property_set_command) != 64);
982 BUILD_BUG_ON(sizeof(struct nvmf_connect_data) != 1024);
983}
984
985MODULE_LICENSE("GPL v2");
986
987module_init(nvmf_init);
988module_exit(nvmf_exit);
989