]> Git Repo - linux.git/blob - drivers/nvme/host/fabrics.c
arm64: avoid prototype warnings for syscalls
[linux.git] / drivers / nvme / host / fabrics.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * NVMe over Fabrics common host code.
4  * Copyright (c) 2015-2016 HGST, a Western Digital Company.
5  */
6 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
7 #include <linux/init.h>
8 #include <linux/miscdevice.h>
9 #include <linux/module.h>
10 #include <linux/mutex.h>
11 #include <linux/parser.h>
12 #include <linux/seq_file.h>
13 #include "nvme.h"
14 #include "fabrics.h"
15
16 static LIST_HEAD(nvmf_transports);
17 static DECLARE_RWSEM(nvmf_transports_rwsem);
18
19 static LIST_HEAD(nvmf_hosts);
20 static DEFINE_MUTEX(nvmf_hosts_mutex);
21
22 static struct nvmf_host *nvmf_default_host;
23
24 static struct nvmf_host *__nvmf_host_find(const char *hostnqn)
25 {
26         struct nvmf_host *host;
27
28         list_for_each_entry(host, &nvmf_hosts, list) {
29                 if (!strcmp(host->nqn, hostnqn))
30                         return host;
31         }
32
33         return NULL;
34 }
35
36 static struct nvmf_host *nvmf_host_add(const char *hostnqn)
37 {
38         struct nvmf_host *host;
39
40         mutex_lock(&nvmf_hosts_mutex);
41         host = __nvmf_host_find(hostnqn);
42         if (host) {
43                 kref_get(&host->ref);
44                 goto out_unlock;
45         }
46
47         host = kmalloc(sizeof(*host), GFP_KERNEL);
48         if (!host)
49                 goto out_unlock;
50
51         kref_init(&host->ref);
52         strscpy(host->nqn, hostnqn, NVMF_NQN_SIZE);
53
54         list_add_tail(&host->list, &nvmf_hosts);
55 out_unlock:
56         mutex_unlock(&nvmf_hosts_mutex);
57         return host;
58 }
59
60 static struct nvmf_host *nvmf_host_default(void)
61 {
62         struct nvmf_host *host;
63
64         host = kmalloc(sizeof(*host), GFP_KERNEL);
65         if (!host)
66                 return NULL;
67
68         kref_init(&host->ref);
69         uuid_gen(&host->id);
70         snprintf(host->nqn, NVMF_NQN_SIZE,
71                 "nqn.2014-08.org.nvmexpress:uuid:%pUb", &host->id);
72
73         mutex_lock(&nvmf_hosts_mutex);
74         list_add_tail(&host->list, &nvmf_hosts);
75         mutex_unlock(&nvmf_hosts_mutex);
76
77         return host;
78 }
79
80 static void nvmf_host_destroy(struct kref *ref)
81 {
82         struct nvmf_host *host = container_of(ref, struct nvmf_host, ref);
83
84         mutex_lock(&nvmf_hosts_mutex);
85         list_del(&host->list);
86         mutex_unlock(&nvmf_hosts_mutex);
87
88         kfree(host);
89 }
90
91 static void nvmf_host_put(struct nvmf_host *host)
92 {
93         if (host)
94                 kref_put(&host->ref, nvmf_host_destroy);
95 }
96
97 /**
98  * nvmf_get_address() -  Get address/port
99  * @ctrl:       Host NVMe controller instance which we got the address
100  * @buf:        OUTPUT parameter that will contain the address/port
101  * @size:       buffer size
102  */
103 int nvmf_get_address(struct nvme_ctrl *ctrl, char *buf, int size)
104 {
105         int len = 0;
106
107         if (ctrl->opts->mask & NVMF_OPT_TRADDR)
108                 len += scnprintf(buf, size, "traddr=%s", ctrl->opts->traddr);
109         if (ctrl->opts->mask & NVMF_OPT_TRSVCID)
110                 len += scnprintf(buf + len, size - len, "%strsvcid=%s",
111                                 (len) ? "," : "", ctrl->opts->trsvcid);
112         if (ctrl->opts->mask & NVMF_OPT_HOST_TRADDR)
113                 len += scnprintf(buf + len, size - len, "%shost_traddr=%s",
114                                 (len) ? "," : "", ctrl->opts->host_traddr);
115         if (ctrl->opts->mask & NVMF_OPT_HOST_IFACE)
116                 len += scnprintf(buf + len, size - len, "%shost_iface=%s",
117                                 (len) ? "," : "", ctrl->opts->host_iface);
118         len += scnprintf(buf + len, size - len, "\n");
119
120         return len;
121 }
122 EXPORT_SYMBOL_GPL(nvmf_get_address);
123
124 /**
125  * nvmf_reg_read32() -  NVMe Fabrics "Property Get" API function.
126  * @ctrl:       Host NVMe controller instance maintaining the admin
127  *              queue used to submit the property read command to
128  *              the allocated NVMe controller resource on the target system.
129  * @off:        Starting offset value of the targeted property
130  *              register (see the fabrics section of the NVMe standard).
131  * @val:        OUTPUT parameter that will contain the value of
132  *              the property after a successful read.
133  *
134  * Used by the host system to retrieve a 32-bit capsule property value
135  * from an NVMe controller on the target system.
136  *
137  * ("Capsule property" is an "PCIe register concept" applied to the
138  * NVMe fabrics space.)
139  *
140  * Return:
141  *      0: successful read
142  *      > 0: NVMe error status code
143  *      < 0: Linux errno error code
144  */
145 int nvmf_reg_read32(struct nvme_ctrl *ctrl, u32 off, u32 *val)
146 {
147         struct nvme_command cmd = { };
148         union nvme_result res;
149         int ret;
150
151         cmd.prop_get.opcode = nvme_fabrics_command;
152         cmd.prop_get.fctype = nvme_fabrics_type_property_get;
153         cmd.prop_get.offset = cpu_to_le32(off);
154
155         ret = __nvme_submit_sync_cmd(ctrl->fabrics_q, &cmd, &res, NULL, 0,
156                         NVME_QID_ANY, 0, 0);
157
158         if (ret >= 0)
159                 *val = le64_to_cpu(res.u64);
160         if (unlikely(ret != 0))
161                 dev_err(ctrl->device,
162                         "Property Get error: %d, offset %#x\n",
163                         ret > 0 ? ret & ~NVME_SC_DNR : ret, off);
164
165         return ret;
166 }
167 EXPORT_SYMBOL_GPL(nvmf_reg_read32);
168
169 /**
170  * nvmf_reg_read64() -  NVMe Fabrics "Property Get" API function.
171  * @ctrl:       Host NVMe controller instance maintaining the admin
172  *              queue used to submit the property read command to
173  *              the allocated controller resource on the target system.
174  * @off:        Starting offset value of the targeted property
175  *              register (see the fabrics section of the NVMe standard).
176  * @val:        OUTPUT parameter that will contain the value of
177  *              the property after a successful read.
178  *
179  * Used by the host system to retrieve a 64-bit capsule property value
180  * from an NVMe controller on the target system.
181  *
182  * ("Capsule property" is an "PCIe register concept" applied to the
183  * NVMe fabrics space.)
184  *
185  * Return:
186  *      0: successful read
187  *      > 0: NVMe error status code
188  *      < 0: Linux errno error code
189  */
190 int nvmf_reg_read64(struct nvme_ctrl *ctrl, u32 off, u64 *val)
191 {
192         struct nvme_command cmd = { };
193         union nvme_result res;
194         int ret;
195
196         cmd.prop_get.opcode = nvme_fabrics_command;
197         cmd.prop_get.fctype = nvme_fabrics_type_property_get;
198         cmd.prop_get.attrib = 1;
199         cmd.prop_get.offset = cpu_to_le32(off);
200
201         ret = __nvme_submit_sync_cmd(ctrl->fabrics_q, &cmd, &res, NULL, 0,
202                         NVME_QID_ANY, 0, 0);
203
204         if (ret >= 0)
205                 *val = le64_to_cpu(res.u64);
206         if (unlikely(ret != 0))
207                 dev_err(ctrl->device,
208                         "Property Get error: %d, offset %#x\n",
209                         ret > 0 ? ret & ~NVME_SC_DNR : ret, off);
210         return ret;
211 }
212 EXPORT_SYMBOL_GPL(nvmf_reg_read64);
213
214 /**
215  * nvmf_reg_write32() -  NVMe Fabrics "Property Write" API function.
216  * @ctrl:       Host NVMe controller instance maintaining the admin
217  *              queue used to submit the property read command to
218  *              the allocated NVMe controller resource on the target system.
219  * @off:        Starting offset value of the targeted property
220  *              register (see the fabrics section of the NVMe standard).
221  * @val:        Input parameter that contains the value to be
222  *              written to the property.
223  *
224  * Used by the NVMe host system to write a 32-bit capsule property value
225  * to an NVMe controller on the target system.
226  *
227  * ("Capsule property" is an "PCIe register concept" applied to the
228  * NVMe fabrics space.)
229  *
230  * Return:
231  *      0: successful write
232  *      > 0: NVMe error status code
233  *      < 0: Linux errno error code
234  */
235 int nvmf_reg_write32(struct nvme_ctrl *ctrl, u32 off, u32 val)
236 {
237         struct nvme_command cmd = { };
238         int ret;
239
240         cmd.prop_set.opcode = nvme_fabrics_command;
241         cmd.prop_set.fctype = nvme_fabrics_type_property_set;
242         cmd.prop_set.attrib = 0;
243         cmd.prop_set.offset = cpu_to_le32(off);
244         cmd.prop_set.value = cpu_to_le64(val);
245
246         ret = __nvme_submit_sync_cmd(ctrl->fabrics_q, &cmd, NULL, NULL, 0,
247                         NVME_QID_ANY, 0, 0);
248         if (unlikely(ret))
249                 dev_err(ctrl->device,
250                         "Property Set error: %d, offset %#x\n",
251                         ret > 0 ? ret & ~NVME_SC_DNR : ret, off);
252         return ret;
253 }
254 EXPORT_SYMBOL_GPL(nvmf_reg_write32);
255
256 /**
257  * nvmf_log_connect_error() - Error-parsing-diagnostic print out function for
258  *                              connect() errors.
259  * @ctrl:       The specific /dev/nvmeX device that had the error.
260  * @errval:     Error code to be decoded in a more human-friendly
261  *              printout.
262  * @offset:     For use with the NVMe error code
263  *              NVME_SC_CONNECT_INVALID_PARAM.
264  * @cmd:        This is the SQE portion of a submission capsule.
265  * @data:       This is the "Data" portion of a submission capsule.
266  */
267 static void nvmf_log_connect_error(struct nvme_ctrl *ctrl,
268                 int errval, int offset, struct nvme_command *cmd,
269                 struct nvmf_connect_data *data)
270 {
271         int err_sctype = errval & ~NVME_SC_DNR;
272
273         if (errval < 0) {
274                 dev_err(ctrl->device,
275                         "Connect command failed, errno: %d\n", errval);
276                 return;
277         }
278
279         switch (err_sctype) {
280         case NVME_SC_CONNECT_INVALID_PARAM:
281                 if (offset >> 16) {
282                         char *inv_data = "Connect Invalid Data Parameter";
283
284                         switch (offset & 0xffff) {
285                         case (offsetof(struct nvmf_connect_data, cntlid)):
286                                 dev_err(ctrl->device,
287                                         "%s, cntlid: %d\n",
288                                         inv_data, data->cntlid);
289                                 break;
290                         case (offsetof(struct nvmf_connect_data, hostnqn)):
291                                 dev_err(ctrl->device,
292                                         "%s, hostnqn \"%s\"\n",
293                                         inv_data, data->hostnqn);
294                                 break;
295                         case (offsetof(struct nvmf_connect_data, subsysnqn)):
296                                 dev_err(ctrl->device,
297                                         "%s, subsysnqn \"%s\"\n",
298                                         inv_data, data->subsysnqn);
299                                 break;
300                         default:
301                                 dev_err(ctrl->device,
302                                         "%s, starting byte offset: %d\n",
303                                        inv_data, offset & 0xffff);
304                                 break;
305                         }
306                 } else {
307                         char *inv_sqe = "Connect Invalid SQE Parameter";
308
309                         switch (offset) {
310                         case (offsetof(struct nvmf_connect_command, qid)):
311                                 dev_err(ctrl->device,
312                                        "%s, qid %d\n",
313                                         inv_sqe, cmd->connect.qid);
314                                 break;
315                         default:
316                                 dev_err(ctrl->device,
317                                         "%s, starting byte offset: %d\n",
318                                         inv_sqe, offset);
319                         }
320                 }
321                 break;
322         case NVME_SC_CONNECT_INVALID_HOST:
323                 dev_err(ctrl->device,
324                         "Connect for subsystem %s is not allowed, hostnqn: %s\n",
325                         data->subsysnqn, data->hostnqn);
326                 break;
327         case NVME_SC_CONNECT_CTRL_BUSY:
328                 dev_err(ctrl->device,
329                         "Connect command failed: controller is busy or not available\n");
330                 break;
331         case NVME_SC_CONNECT_FORMAT:
332                 dev_err(ctrl->device,
333                         "Connect incompatible format: %d",
334                         cmd->connect.recfmt);
335                 break;
336         case NVME_SC_HOST_PATH_ERROR:
337                 dev_err(ctrl->device,
338                         "Connect command failed: host path error\n");
339                 break;
340         case NVME_SC_AUTH_REQUIRED:
341                 dev_err(ctrl->device,
342                         "Connect command failed: authentication required\n");
343                 break;
344         default:
345                 dev_err(ctrl->device,
346                         "Connect command failed, error wo/DNR bit: %d\n",
347                         err_sctype);
348                 break;
349         }
350 }
351
352 /**
353  * nvmf_connect_admin_queue() - NVMe Fabrics Admin Queue "Connect"
354  *                              API function.
355  * @ctrl:       Host nvme controller instance used to request
356  *              a new NVMe controller allocation on the target
357  *              system and  establish an NVMe Admin connection to
358  *              that controller.
359  *
360  * This function enables an NVMe host device to request a new allocation of
361  * an NVMe controller resource on a target system as well establish a
362  * fabrics-protocol connection of the NVMe Admin queue between the
363  * host system device and the allocated NVMe controller on the
364  * target system via a NVMe Fabrics "Connect" command.
365  *
366  * Return:
367  *      0: success
368  *      > 0: NVMe error status code
369  *      < 0: Linux errno error code
370  *
371  */
372 int nvmf_connect_admin_queue(struct nvme_ctrl *ctrl)
373 {
374         struct nvme_command cmd = { };
375         union nvme_result res;
376         struct nvmf_connect_data *data;
377         int ret;
378         u32 result;
379
380         cmd.connect.opcode = nvme_fabrics_command;
381         cmd.connect.fctype = nvme_fabrics_type_connect;
382         cmd.connect.qid = 0;
383         cmd.connect.sqsize = cpu_to_le16(NVME_AQ_DEPTH - 1);
384
385         /*
386          * Set keep-alive timeout in seconds granularity (ms * 1000)
387          */
388         cmd.connect.kato = cpu_to_le32(ctrl->kato * 1000);
389
390         if (ctrl->opts->disable_sqflow)
391                 cmd.connect.cattr |= NVME_CONNECT_DISABLE_SQFLOW;
392
393         data = kzalloc(sizeof(*data), GFP_KERNEL);
394         if (!data)
395                 return -ENOMEM;
396
397         uuid_copy(&data->hostid, &ctrl->opts->host->id);
398         data->cntlid = cpu_to_le16(0xffff);
399         strncpy(data->subsysnqn, ctrl->opts->subsysnqn, NVMF_NQN_SIZE);
400         strncpy(data->hostnqn, ctrl->opts->host->nqn, NVMF_NQN_SIZE);
401
402         ret = __nvme_submit_sync_cmd(ctrl->fabrics_q, &cmd, &res,
403                         data, sizeof(*data), NVME_QID_ANY, 1,
404                         BLK_MQ_REQ_RESERVED | BLK_MQ_REQ_NOWAIT);
405         if (ret) {
406                 nvmf_log_connect_error(ctrl, ret, le32_to_cpu(res.u32),
407                                        &cmd, data);
408                 goto out_free_data;
409         }
410
411         result = le32_to_cpu(res.u32);
412         ctrl->cntlid = result & 0xFFFF;
413         if (result & (NVME_CONNECT_AUTHREQ_ATR | NVME_CONNECT_AUTHREQ_ASCR)) {
414                 /* Secure concatenation is not implemented */
415                 if (result & NVME_CONNECT_AUTHREQ_ASCR) {
416                         dev_warn(ctrl->device,
417                                  "qid 0: secure concatenation is not supported\n");
418                         ret = NVME_SC_AUTH_REQUIRED;
419                         goto out_free_data;
420                 }
421                 /* Authentication required */
422                 ret = nvme_auth_negotiate(ctrl, 0);
423                 if (ret) {
424                         dev_warn(ctrl->device,
425                                  "qid 0: authentication setup failed\n");
426                         ret = NVME_SC_AUTH_REQUIRED;
427                         goto out_free_data;
428                 }
429                 ret = nvme_auth_wait(ctrl, 0);
430                 if (ret)
431                         dev_warn(ctrl->device,
432                                  "qid 0: authentication failed\n");
433                 else
434                         dev_info(ctrl->device,
435                                  "qid 0: authenticated\n");
436         }
437 out_free_data:
438         kfree(data);
439         return ret;
440 }
441 EXPORT_SYMBOL_GPL(nvmf_connect_admin_queue);
442
443 /**
444  * nvmf_connect_io_queue() - NVMe Fabrics I/O Queue "Connect"
445  *                           API function.
446  * @ctrl:       Host nvme controller instance used to establish an
447  *              NVMe I/O queue connection to the already allocated NVMe
448  *              controller on the target system.
449  * @qid:        NVMe I/O queue number for the new I/O connection between
450  *              host and target (note qid == 0 is illegal as this is
451  *              the Admin queue, per NVMe standard).
452  *
453  * This function issues a fabrics-protocol connection
454  * of a NVMe I/O queue (via NVMe Fabrics "Connect" command)
455  * between the host system device and the allocated NVMe controller
456  * on the target system.
457  *
458  * Return:
459  *      0: success
460  *      > 0: NVMe error status code
461  *      < 0: Linux errno error code
462  */
463 int nvmf_connect_io_queue(struct nvme_ctrl *ctrl, u16 qid)
464 {
465         struct nvme_command cmd = { };
466         struct nvmf_connect_data *data;
467         union nvme_result res;
468         int ret;
469         u32 result;
470
471         cmd.connect.opcode = nvme_fabrics_command;
472         cmd.connect.fctype = nvme_fabrics_type_connect;
473         cmd.connect.qid = cpu_to_le16(qid);
474         cmd.connect.sqsize = cpu_to_le16(ctrl->sqsize);
475
476         if (ctrl->opts->disable_sqflow)
477                 cmd.connect.cattr |= NVME_CONNECT_DISABLE_SQFLOW;
478
479         data = kzalloc(sizeof(*data), GFP_KERNEL);
480         if (!data)
481                 return -ENOMEM;
482
483         uuid_copy(&data->hostid, &ctrl->opts->host->id);
484         data->cntlid = cpu_to_le16(ctrl->cntlid);
485         strncpy(data->subsysnqn, ctrl->opts->subsysnqn, NVMF_NQN_SIZE);
486         strncpy(data->hostnqn, ctrl->opts->host->nqn, NVMF_NQN_SIZE);
487
488         ret = __nvme_submit_sync_cmd(ctrl->connect_q, &cmd, &res,
489                         data, sizeof(*data), qid, 1,
490                         BLK_MQ_REQ_RESERVED | BLK_MQ_REQ_NOWAIT);
491         if (ret) {
492                 nvmf_log_connect_error(ctrl, ret, le32_to_cpu(res.u32),
493                                        &cmd, data);
494         }
495         result = le32_to_cpu(res.u32);
496         if (result & (NVME_CONNECT_AUTHREQ_ATR | NVME_CONNECT_AUTHREQ_ASCR)) {
497                 /* Secure concatenation is not implemented */
498                 if (result & NVME_CONNECT_AUTHREQ_ASCR) {
499                         dev_warn(ctrl->device,
500                                  "qid 0: secure concatenation is not supported\n");
501                         ret = NVME_SC_AUTH_REQUIRED;
502                         goto out_free_data;
503                 }
504                 /* Authentication required */
505                 ret = nvme_auth_negotiate(ctrl, qid);
506                 if (ret) {
507                         dev_warn(ctrl->device,
508                                  "qid %d: authentication setup failed\n", qid);
509                         ret = NVME_SC_AUTH_REQUIRED;
510                 } else {
511                         ret = nvme_auth_wait(ctrl, qid);
512                         if (ret)
513                                 dev_warn(ctrl->device,
514                                          "qid %u: authentication failed\n", qid);
515                 }
516         }
517 out_free_data:
518         kfree(data);
519         return ret;
520 }
521 EXPORT_SYMBOL_GPL(nvmf_connect_io_queue);
522
523 bool nvmf_should_reconnect(struct nvme_ctrl *ctrl)
524 {
525         if (ctrl->opts->max_reconnects == -1 ||
526             ctrl->nr_reconnects < ctrl->opts->max_reconnects)
527                 return true;
528
529         return false;
530 }
531 EXPORT_SYMBOL_GPL(nvmf_should_reconnect);
532
533 /**
534  * nvmf_register_transport() - NVMe Fabrics Library registration function.
535  * @ops:        Transport ops instance to be registered to the
536  *              common fabrics library.
537  *
538  * API function that registers the type of specific transport fabric
539  * being implemented to the common NVMe fabrics library. Part of
540  * the overall init sequence of starting up a fabrics driver.
541  */
542 int nvmf_register_transport(struct nvmf_transport_ops *ops)
543 {
544         if (!ops->create_ctrl)
545                 return -EINVAL;
546
547         down_write(&nvmf_transports_rwsem);
548         list_add_tail(&ops->entry, &nvmf_transports);
549         up_write(&nvmf_transports_rwsem);
550
551         return 0;
552 }
553 EXPORT_SYMBOL_GPL(nvmf_register_transport);
554
555 /**
556  * nvmf_unregister_transport() - NVMe Fabrics Library unregistration function.
557  * @ops:        Transport ops instance to be unregistered from the
558  *              common fabrics library.
559  *
560  * Fabrics API function that unregisters the type of specific transport
561  * fabric being implemented from the common NVMe fabrics library.
562  * Part of the overall exit sequence of unloading the implemented driver.
563  */
564 void nvmf_unregister_transport(struct nvmf_transport_ops *ops)
565 {
566         down_write(&nvmf_transports_rwsem);
567         list_del(&ops->entry);
568         up_write(&nvmf_transports_rwsem);
569 }
570 EXPORT_SYMBOL_GPL(nvmf_unregister_transport);
571
572 static struct nvmf_transport_ops *nvmf_lookup_transport(
573                 struct nvmf_ctrl_options *opts)
574 {
575         struct nvmf_transport_ops *ops;
576
577         lockdep_assert_held(&nvmf_transports_rwsem);
578
579         list_for_each_entry(ops, &nvmf_transports, entry) {
580                 if (strcmp(ops->name, opts->transport) == 0)
581                         return ops;
582         }
583
584         return NULL;
585 }
586
587 static const match_table_t opt_tokens = {
588         { NVMF_OPT_TRANSPORT,           "transport=%s"          },
589         { NVMF_OPT_TRADDR,              "traddr=%s"             },
590         { NVMF_OPT_TRSVCID,             "trsvcid=%s"            },
591         { NVMF_OPT_NQN,                 "nqn=%s"                },
592         { NVMF_OPT_QUEUE_SIZE,          "queue_size=%d"         },
593         { NVMF_OPT_NR_IO_QUEUES,        "nr_io_queues=%d"       },
594         { NVMF_OPT_RECONNECT_DELAY,     "reconnect_delay=%d"    },
595         { NVMF_OPT_CTRL_LOSS_TMO,       "ctrl_loss_tmo=%d"      },
596         { NVMF_OPT_KATO,                "keep_alive_tmo=%d"     },
597         { NVMF_OPT_HOSTNQN,             "hostnqn=%s"            },
598         { NVMF_OPT_HOST_TRADDR,         "host_traddr=%s"        },
599         { NVMF_OPT_HOST_IFACE,          "host_iface=%s"         },
600         { NVMF_OPT_HOST_ID,             "hostid=%s"             },
601         { NVMF_OPT_DUP_CONNECT,         "duplicate_connect"     },
602         { NVMF_OPT_DISABLE_SQFLOW,      "disable_sqflow"        },
603         { NVMF_OPT_HDR_DIGEST,          "hdr_digest"            },
604         { NVMF_OPT_DATA_DIGEST,         "data_digest"           },
605         { NVMF_OPT_NR_WRITE_QUEUES,     "nr_write_queues=%d"    },
606         { NVMF_OPT_NR_POLL_QUEUES,      "nr_poll_queues=%d"     },
607         { NVMF_OPT_TOS,                 "tos=%d"                },
608         { NVMF_OPT_FAIL_FAST_TMO,       "fast_io_fail_tmo=%d"   },
609         { NVMF_OPT_DISCOVERY,           "discovery"             },
610         { NVMF_OPT_DHCHAP_SECRET,       "dhchap_secret=%s"      },
611         { NVMF_OPT_DHCHAP_CTRL_SECRET,  "dhchap_ctrl_secret=%s" },
612         { NVMF_OPT_ERR,                 NULL                    }
613 };
614
615 static int nvmf_parse_options(struct nvmf_ctrl_options *opts,
616                 const char *buf)
617 {
618         substring_t args[MAX_OPT_ARGS];
619         char *options, *o, *p;
620         int token, ret = 0;
621         size_t nqnlen  = 0;
622         int ctrl_loss_tmo = NVMF_DEF_CTRL_LOSS_TMO;
623         uuid_t hostid;
624
625         /* Set defaults */
626         opts->queue_size = NVMF_DEF_QUEUE_SIZE;
627         opts->nr_io_queues = num_online_cpus();
628         opts->reconnect_delay = NVMF_DEF_RECONNECT_DELAY;
629         opts->kato = 0;
630         opts->duplicate_connect = false;
631         opts->fast_io_fail_tmo = NVMF_DEF_FAIL_FAST_TMO;
632         opts->hdr_digest = false;
633         opts->data_digest = false;
634         opts->tos = -1; /* < 0 == use transport default */
635
636         options = o = kstrdup(buf, GFP_KERNEL);
637         if (!options)
638                 return -ENOMEM;
639
640         uuid_gen(&hostid);
641
642         while ((p = strsep(&o, ",\n")) != NULL) {
643                 if (!*p)
644                         continue;
645
646                 token = match_token(p, opt_tokens, args);
647                 opts->mask |= token;
648                 switch (token) {
649                 case NVMF_OPT_TRANSPORT:
650                         p = match_strdup(args);
651                         if (!p) {
652                                 ret = -ENOMEM;
653                                 goto out;
654                         }
655                         kfree(opts->transport);
656                         opts->transport = p;
657                         break;
658                 case NVMF_OPT_NQN:
659                         p = match_strdup(args);
660                         if (!p) {
661                                 ret = -ENOMEM;
662                                 goto out;
663                         }
664                         kfree(opts->subsysnqn);
665                         opts->subsysnqn = p;
666                         nqnlen = strlen(opts->subsysnqn);
667                         if (nqnlen >= NVMF_NQN_SIZE) {
668                                 pr_err("%s needs to be < %d bytes\n",
669                                         opts->subsysnqn, NVMF_NQN_SIZE);
670                                 ret = -EINVAL;
671                                 goto out;
672                         }
673                         opts->discovery_nqn =
674                                 !(strcmp(opts->subsysnqn,
675                                          NVME_DISC_SUBSYS_NAME));
676                         break;
677                 case NVMF_OPT_TRADDR:
678                         p = match_strdup(args);
679                         if (!p) {
680                                 ret = -ENOMEM;
681                                 goto out;
682                         }
683                         kfree(opts->traddr);
684                         opts->traddr = p;
685                         break;
686                 case NVMF_OPT_TRSVCID:
687                         p = match_strdup(args);
688                         if (!p) {
689                                 ret = -ENOMEM;
690                                 goto out;
691                         }
692                         kfree(opts->trsvcid);
693                         opts->trsvcid = p;
694                         break;
695                 case NVMF_OPT_QUEUE_SIZE:
696                         if (match_int(args, &token)) {
697                                 ret = -EINVAL;
698                                 goto out;
699                         }
700                         if (token < NVMF_MIN_QUEUE_SIZE ||
701                             token > NVMF_MAX_QUEUE_SIZE) {
702                                 pr_err("Invalid queue_size %d\n", token);
703                                 ret = -EINVAL;
704                                 goto out;
705                         }
706                         opts->queue_size = token;
707                         break;
708                 case NVMF_OPT_NR_IO_QUEUES:
709                         if (match_int(args, &token)) {
710                                 ret = -EINVAL;
711                                 goto out;
712                         }
713                         if (token <= 0) {
714                                 pr_err("Invalid number of IOQs %d\n", token);
715                                 ret = -EINVAL;
716                                 goto out;
717                         }
718                         if (opts->discovery_nqn) {
719                                 pr_debug("Ignoring nr_io_queues value for discovery controller\n");
720                                 break;
721                         }
722
723                         opts->nr_io_queues = min_t(unsigned int,
724                                         num_online_cpus(), token);
725                         break;
726                 case NVMF_OPT_KATO:
727                         if (match_int(args, &token)) {
728                                 ret = -EINVAL;
729                                 goto out;
730                         }
731
732                         if (token < 0) {
733                                 pr_err("Invalid keep_alive_tmo %d\n", token);
734                                 ret = -EINVAL;
735                                 goto out;
736                         } else if (token == 0 && !opts->discovery_nqn) {
737                                 /* Allowed for debug */
738                                 pr_warn("keep_alive_tmo 0 won't execute keep alives!!!\n");
739                         }
740                         opts->kato = token;
741                         break;
742                 case NVMF_OPT_CTRL_LOSS_TMO:
743                         if (match_int(args, &token)) {
744                                 ret = -EINVAL;
745                                 goto out;
746                         }
747
748                         if (token < 0)
749                                 pr_warn("ctrl_loss_tmo < 0 will reconnect forever\n");
750                         ctrl_loss_tmo = token;
751                         break;
752                 case NVMF_OPT_FAIL_FAST_TMO:
753                         if (match_int(args, &token)) {
754                                 ret = -EINVAL;
755                                 goto out;
756                         }
757
758                         if (token >= 0)
759                                 pr_warn("I/O fail on reconnect controller after %d sec\n",
760                                         token);
761                         else
762                                 token = -1;
763
764                         opts->fast_io_fail_tmo = token;
765                         break;
766                 case NVMF_OPT_HOSTNQN:
767                         if (opts->host) {
768                                 pr_err("hostnqn already user-assigned: %s\n",
769                                        opts->host->nqn);
770                                 ret = -EADDRINUSE;
771                                 goto out;
772                         }
773                         p = match_strdup(args);
774                         if (!p) {
775                                 ret = -ENOMEM;
776                                 goto out;
777                         }
778                         nqnlen = strlen(p);
779                         if (nqnlen >= NVMF_NQN_SIZE) {
780                                 pr_err("%s needs to be < %d bytes\n",
781                                         p, NVMF_NQN_SIZE);
782                                 kfree(p);
783                                 ret = -EINVAL;
784                                 goto out;
785                         }
786                         opts->host = nvmf_host_add(p);
787                         kfree(p);
788                         if (!opts->host) {
789                                 ret = -ENOMEM;
790                                 goto out;
791                         }
792                         break;
793                 case NVMF_OPT_RECONNECT_DELAY:
794                         if (match_int(args, &token)) {
795                                 ret = -EINVAL;
796                                 goto out;
797                         }
798                         if (token <= 0) {
799                                 pr_err("Invalid reconnect_delay %d\n", token);
800                                 ret = -EINVAL;
801                                 goto out;
802                         }
803                         opts->reconnect_delay = token;
804                         break;
805                 case NVMF_OPT_HOST_TRADDR:
806                         p = match_strdup(args);
807                         if (!p) {
808                                 ret = -ENOMEM;
809                                 goto out;
810                         }
811                         kfree(opts->host_traddr);
812                         opts->host_traddr = p;
813                         break;
814                 case NVMF_OPT_HOST_IFACE:
815                         p = match_strdup(args);
816                         if (!p) {
817                                 ret = -ENOMEM;
818                                 goto out;
819                         }
820                         kfree(opts->host_iface);
821                         opts->host_iface = p;
822                         break;
823                 case NVMF_OPT_HOST_ID:
824                         p = match_strdup(args);
825                         if (!p) {
826                                 ret = -ENOMEM;
827                                 goto out;
828                         }
829                         ret = uuid_parse(p, &hostid);
830                         if (ret) {
831                                 pr_err("Invalid hostid %s\n", p);
832                                 ret = -EINVAL;
833                                 kfree(p);
834                                 goto out;
835                         }
836                         kfree(p);
837                         break;
838                 case NVMF_OPT_DUP_CONNECT:
839                         opts->duplicate_connect = true;
840                         break;
841                 case NVMF_OPT_DISABLE_SQFLOW:
842                         opts->disable_sqflow = true;
843                         break;
844                 case NVMF_OPT_HDR_DIGEST:
845                         opts->hdr_digest = true;
846                         break;
847                 case NVMF_OPT_DATA_DIGEST:
848                         opts->data_digest = true;
849                         break;
850                 case NVMF_OPT_NR_WRITE_QUEUES:
851                         if (match_int(args, &token)) {
852                                 ret = -EINVAL;
853                                 goto out;
854                         }
855                         if (token <= 0) {
856                                 pr_err("Invalid nr_write_queues %d\n", token);
857                                 ret = -EINVAL;
858                                 goto out;
859                         }
860                         opts->nr_write_queues = token;
861                         break;
862                 case NVMF_OPT_NR_POLL_QUEUES:
863                         if (match_int(args, &token)) {
864                                 ret = -EINVAL;
865                                 goto out;
866                         }
867                         if (token <= 0) {
868                                 pr_err("Invalid nr_poll_queues %d\n", token);
869                                 ret = -EINVAL;
870                                 goto out;
871                         }
872                         opts->nr_poll_queues = token;
873                         break;
874                 case NVMF_OPT_TOS:
875                         if (match_int(args, &token)) {
876                                 ret = -EINVAL;
877                                 goto out;
878                         }
879                         if (token < 0) {
880                                 pr_err("Invalid type of service %d\n", token);
881                                 ret = -EINVAL;
882                                 goto out;
883                         }
884                         if (token > 255) {
885                                 pr_warn("Clamping type of service to 255\n");
886                                 token = 255;
887                         }
888                         opts->tos = token;
889                         break;
890                 case NVMF_OPT_DISCOVERY:
891                         opts->discovery_nqn = true;
892                         break;
893                 case NVMF_OPT_DHCHAP_SECRET:
894                         p = match_strdup(args);
895                         if (!p) {
896                                 ret = -ENOMEM;
897                                 goto out;
898                         }
899                         if (strlen(p) < 11 || strncmp(p, "DHHC-1:", 7)) {
900                                 pr_err("Invalid DH-CHAP secret %s\n", p);
901                                 ret = -EINVAL;
902                                 goto out;
903                         }
904                         kfree(opts->dhchap_secret);
905                         opts->dhchap_secret = p;
906                         break;
907                 case NVMF_OPT_DHCHAP_CTRL_SECRET:
908                         p = match_strdup(args);
909                         if (!p) {
910                                 ret = -ENOMEM;
911                                 goto out;
912                         }
913                         if (strlen(p) < 11 || strncmp(p, "DHHC-1:", 7)) {
914                                 pr_err("Invalid DH-CHAP secret %s\n", p);
915                                 ret = -EINVAL;
916                                 goto out;
917                         }
918                         kfree(opts->dhchap_ctrl_secret);
919                         opts->dhchap_ctrl_secret = p;
920                         break;
921                 default:
922                         pr_warn("unknown parameter or missing value '%s' in ctrl creation request\n",
923                                 p);
924                         ret = -EINVAL;
925                         goto out;
926                 }
927         }
928
929         if (opts->discovery_nqn) {
930                 opts->nr_io_queues = 0;
931                 opts->nr_write_queues = 0;
932                 opts->nr_poll_queues = 0;
933                 opts->duplicate_connect = true;
934         } else {
935                 if (!opts->kato)
936                         opts->kato = NVME_DEFAULT_KATO;
937         }
938         if (ctrl_loss_tmo < 0) {
939                 opts->max_reconnects = -1;
940         } else {
941                 opts->max_reconnects = DIV_ROUND_UP(ctrl_loss_tmo,
942                                                 opts->reconnect_delay);
943                 if (ctrl_loss_tmo < opts->fast_io_fail_tmo)
944                         pr_warn("failfast tmo (%d) larger than controller loss tmo (%d)\n",
945                                 opts->fast_io_fail_tmo, ctrl_loss_tmo);
946         }
947
948         if (!opts->host) {
949                 kref_get(&nvmf_default_host->ref);
950                 opts->host = nvmf_default_host;
951         }
952
953         uuid_copy(&opts->host->id, &hostid);
954
955 out:
956         kfree(options);
957         return ret;
958 }
959
960 static int nvmf_check_required_opts(struct nvmf_ctrl_options *opts,
961                 unsigned int required_opts)
962 {
963         if ((opts->mask & required_opts) != required_opts) {
964                 unsigned int i;
965
966                 for (i = 0; i < ARRAY_SIZE(opt_tokens); i++) {
967                         if ((opt_tokens[i].token & required_opts) &&
968                             !(opt_tokens[i].token & opts->mask)) {
969                                 pr_warn("missing parameter '%s'\n",
970                                         opt_tokens[i].pattern);
971                         }
972                 }
973
974                 return -EINVAL;
975         }
976
977         return 0;
978 }
979
980 bool nvmf_ip_options_match(struct nvme_ctrl *ctrl,
981                 struct nvmf_ctrl_options *opts)
982 {
983         if (!nvmf_ctlr_matches_baseopts(ctrl, opts) ||
984             strcmp(opts->traddr, ctrl->opts->traddr) ||
985             strcmp(opts->trsvcid, ctrl->opts->trsvcid))
986                 return false;
987
988         /*
989          * Checking the local address or host interfaces is rough.
990          *
991          * In most cases, none is specified and the host port or
992          * host interface is selected by the stack.
993          *
994          * Assume no match if:
995          * -  local address or host interface is specified and address
996          *    or host interface is not the same
997          * -  local address or host interface is not specified but
998          *    remote is, or vice versa (admin using specific
999          *    host_traddr/host_iface when it matters).
1000          */
1001         if ((opts->mask & NVMF_OPT_HOST_TRADDR) &&
1002             (ctrl->opts->mask & NVMF_OPT_HOST_TRADDR)) {
1003                 if (strcmp(opts->host_traddr, ctrl->opts->host_traddr))
1004                         return false;
1005         } else if ((opts->mask & NVMF_OPT_HOST_TRADDR) ||
1006                    (ctrl->opts->mask & NVMF_OPT_HOST_TRADDR)) {
1007                 return false;
1008         }
1009
1010         if ((opts->mask & NVMF_OPT_HOST_IFACE) &&
1011             (ctrl->opts->mask & NVMF_OPT_HOST_IFACE)) {
1012                 if (strcmp(opts->host_iface, ctrl->opts->host_iface))
1013                         return false;
1014         } else if ((opts->mask & NVMF_OPT_HOST_IFACE) ||
1015                    (ctrl->opts->mask & NVMF_OPT_HOST_IFACE)) {
1016                 return false;
1017         }
1018
1019         return true;
1020 }
1021 EXPORT_SYMBOL_GPL(nvmf_ip_options_match);
1022
1023 static int nvmf_check_allowed_opts(struct nvmf_ctrl_options *opts,
1024                 unsigned int allowed_opts)
1025 {
1026         if (opts->mask & ~allowed_opts) {
1027                 unsigned int i;
1028
1029                 for (i = 0; i < ARRAY_SIZE(opt_tokens); i++) {
1030                         if ((opt_tokens[i].token & opts->mask) &&
1031                             (opt_tokens[i].token & ~allowed_opts)) {
1032                                 pr_warn("invalid parameter '%s'\n",
1033                                         opt_tokens[i].pattern);
1034                         }
1035                 }
1036
1037                 return -EINVAL;
1038         }
1039
1040         return 0;
1041 }
1042
1043 void nvmf_free_options(struct nvmf_ctrl_options *opts)
1044 {
1045         nvmf_host_put(opts->host);
1046         kfree(opts->transport);
1047         kfree(opts->traddr);
1048         kfree(opts->trsvcid);
1049         kfree(opts->subsysnqn);
1050         kfree(opts->host_traddr);
1051         kfree(opts->host_iface);
1052         kfree(opts->dhchap_secret);
1053         kfree(opts->dhchap_ctrl_secret);
1054         kfree(opts);
1055 }
1056 EXPORT_SYMBOL_GPL(nvmf_free_options);
1057
1058 #define NVMF_REQUIRED_OPTS      (NVMF_OPT_TRANSPORT | NVMF_OPT_NQN)
1059 #define NVMF_ALLOWED_OPTS       (NVMF_OPT_QUEUE_SIZE | NVMF_OPT_NR_IO_QUEUES | \
1060                                  NVMF_OPT_KATO | NVMF_OPT_HOSTNQN | \
1061                                  NVMF_OPT_HOST_ID | NVMF_OPT_DUP_CONNECT |\
1062                                  NVMF_OPT_DISABLE_SQFLOW | NVMF_OPT_DISCOVERY |\
1063                                  NVMF_OPT_FAIL_FAST_TMO | NVMF_OPT_DHCHAP_SECRET |\
1064                                  NVMF_OPT_DHCHAP_CTRL_SECRET)
1065
1066 static struct nvme_ctrl *
1067 nvmf_create_ctrl(struct device *dev, const char *buf)
1068 {
1069         struct nvmf_ctrl_options *opts;
1070         struct nvmf_transport_ops *ops;
1071         struct nvme_ctrl *ctrl;
1072         int ret;
1073
1074         opts = kzalloc(sizeof(*opts), GFP_KERNEL);
1075         if (!opts)
1076                 return ERR_PTR(-ENOMEM);
1077
1078         ret = nvmf_parse_options(opts, buf);
1079         if (ret)
1080                 goto out_free_opts;
1081
1082
1083         request_module("nvme-%s", opts->transport);
1084
1085         /*
1086          * Check the generic options first as we need a valid transport for
1087          * the lookup below.  Then clear the generic flags so that transport
1088          * drivers don't have to care about them.
1089          */
1090         ret = nvmf_check_required_opts(opts, NVMF_REQUIRED_OPTS);
1091         if (ret)
1092                 goto out_free_opts;
1093         opts->mask &= ~NVMF_REQUIRED_OPTS;
1094
1095         down_read(&nvmf_transports_rwsem);
1096         ops = nvmf_lookup_transport(opts);
1097         if (!ops) {
1098                 pr_info("no handler found for transport %s.\n",
1099                         opts->transport);
1100                 ret = -EINVAL;
1101                 goto out_unlock;
1102         }
1103
1104         if (!try_module_get(ops->module)) {
1105                 ret = -EBUSY;
1106                 goto out_unlock;
1107         }
1108         up_read(&nvmf_transports_rwsem);
1109
1110         ret = nvmf_check_required_opts(opts, ops->required_opts);
1111         if (ret)
1112                 goto out_module_put;
1113         ret = nvmf_check_allowed_opts(opts, NVMF_ALLOWED_OPTS |
1114                                 ops->allowed_opts | ops->required_opts);
1115         if (ret)
1116                 goto out_module_put;
1117
1118         ctrl = ops->create_ctrl(dev, opts);
1119         if (IS_ERR(ctrl)) {
1120                 ret = PTR_ERR(ctrl);
1121                 goto out_module_put;
1122         }
1123
1124         module_put(ops->module);
1125         return ctrl;
1126
1127 out_module_put:
1128         module_put(ops->module);
1129         goto out_free_opts;
1130 out_unlock:
1131         up_read(&nvmf_transports_rwsem);
1132 out_free_opts:
1133         nvmf_free_options(opts);
1134         return ERR_PTR(ret);
1135 }
1136
1137 static struct class *nvmf_class;
1138 static struct device *nvmf_device;
1139 static DEFINE_MUTEX(nvmf_dev_mutex);
1140
1141 static ssize_t nvmf_dev_write(struct file *file, const char __user *ubuf,
1142                 size_t count, loff_t *pos)
1143 {
1144         struct seq_file *seq_file = file->private_data;
1145         struct nvme_ctrl *ctrl;
1146         const char *buf;
1147         int ret = 0;
1148
1149         if (count > PAGE_SIZE)
1150                 return -ENOMEM;
1151
1152         buf = memdup_user_nul(ubuf, count);
1153         if (IS_ERR(buf))
1154                 return PTR_ERR(buf);
1155
1156         mutex_lock(&nvmf_dev_mutex);
1157         if (seq_file->private) {
1158                 ret = -EINVAL;
1159                 goto out_unlock;
1160         }
1161
1162         ctrl = nvmf_create_ctrl(nvmf_device, buf);
1163         if (IS_ERR(ctrl)) {
1164                 ret = PTR_ERR(ctrl);
1165                 goto out_unlock;
1166         }
1167
1168         seq_file->private = ctrl;
1169
1170 out_unlock:
1171         mutex_unlock(&nvmf_dev_mutex);
1172         kfree(buf);
1173         return ret ? ret : count;
1174 }
1175
1176 static void __nvmf_concat_opt_tokens(struct seq_file *seq_file)
1177 {
1178         const struct match_token *tok;
1179         int idx;
1180
1181         /*
1182          * Add dummy entries for instance and cntlid to
1183          * signal an invalid/non-existing controller
1184          */
1185         seq_puts(seq_file, "instance=-1,cntlid=-1");
1186         for (idx = 0; idx < ARRAY_SIZE(opt_tokens); idx++) {
1187                 tok = &opt_tokens[idx];
1188                 if (tok->token == NVMF_OPT_ERR)
1189                         continue;
1190                 seq_puts(seq_file, ",");
1191                 seq_puts(seq_file, tok->pattern);
1192         }
1193         seq_puts(seq_file, "\n");
1194 }
1195
1196 static int nvmf_dev_show(struct seq_file *seq_file, void *private)
1197 {
1198         struct nvme_ctrl *ctrl;
1199
1200         mutex_lock(&nvmf_dev_mutex);
1201         ctrl = seq_file->private;
1202         if (!ctrl) {
1203                 __nvmf_concat_opt_tokens(seq_file);
1204                 goto out_unlock;
1205         }
1206
1207         seq_printf(seq_file, "instance=%d,cntlid=%d\n",
1208                         ctrl->instance, ctrl->cntlid);
1209
1210 out_unlock:
1211         mutex_unlock(&nvmf_dev_mutex);
1212         return 0;
1213 }
1214
1215 static int nvmf_dev_open(struct inode *inode, struct file *file)
1216 {
1217         /*
1218          * The miscdevice code initializes file->private_data, but doesn't
1219          * make use of it later.
1220          */
1221         file->private_data = NULL;
1222         return single_open(file, nvmf_dev_show, NULL);
1223 }
1224
1225 static int nvmf_dev_release(struct inode *inode, struct file *file)
1226 {
1227         struct seq_file *seq_file = file->private_data;
1228         struct nvme_ctrl *ctrl = seq_file->private;
1229
1230         if (ctrl)
1231                 nvme_put_ctrl(ctrl);
1232         return single_release(inode, file);
1233 }
1234
1235 static const struct file_operations nvmf_dev_fops = {
1236         .owner          = THIS_MODULE,
1237         .write          = nvmf_dev_write,
1238         .read           = seq_read,
1239         .open           = nvmf_dev_open,
1240         .release        = nvmf_dev_release,
1241 };
1242
1243 static struct miscdevice nvmf_misc = {
1244         .minor          = MISC_DYNAMIC_MINOR,
1245         .name           = "nvme-fabrics",
1246         .fops           = &nvmf_dev_fops,
1247 };
1248
1249 static int __init nvmf_init(void)
1250 {
1251         int ret;
1252
1253         nvmf_default_host = nvmf_host_default();
1254         if (!nvmf_default_host)
1255                 return -ENOMEM;
1256
1257         nvmf_class = class_create("nvme-fabrics");
1258         if (IS_ERR(nvmf_class)) {
1259                 pr_err("couldn't register class nvme-fabrics\n");
1260                 ret = PTR_ERR(nvmf_class);
1261                 goto out_free_host;
1262         }
1263
1264         nvmf_device =
1265                 device_create(nvmf_class, NULL, MKDEV(0, 0), NULL, "ctl");
1266         if (IS_ERR(nvmf_device)) {
1267                 pr_err("couldn't create nvme-fabrics device!\n");
1268                 ret = PTR_ERR(nvmf_device);
1269                 goto out_destroy_class;
1270         }
1271
1272         ret = misc_register(&nvmf_misc);
1273         if (ret) {
1274                 pr_err("couldn't register misc device: %d\n", ret);
1275                 goto out_destroy_device;
1276         }
1277
1278         return 0;
1279
1280 out_destroy_device:
1281         device_destroy(nvmf_class, MKDEV(0, 0));
1282 out_destroy_class:
1283         class_destroy(nvmf_class);
1284 out_free_host:
1285         nvmf_host_put(nvmf_default_host);
1286         return ret;
1287 }
1288
1289 static void __exit nvmf_exit(void)
1290 {
1291         misc_deregister(&nvmf_misc);
1292         device_destroy(nvmf_class, MKDEV(0, 0));
1293         class_destroy(nvmf_class);
1294         nvmf_host_put(nvmf_default_host);
1295
1296         BUILD_BUG_ON(sizeof(struct nvmf_common_command) != 64);
1297         BUILD_BUG_ON(sizeof(struct nvmf_connect_command) != 64);
1298         BUILD_BUG_ON(sizeof(struct nvmf_property_get_command) != 64);
1299         BUILD_BUG_ON(sizeof(struct nvmf_property_set_command) != 64);
1300         BUILD_BUG_ON(sizeof(struct nvmf_auth_send_command) != 64);
1301         BUILD_BUG_ON(sizeof(struct nvmf_auth_receive_command) != 64);
1302         BUILD_BUG_ON(sizeof(struct nvmf_connect_data) != 1024);
1303         BUILD_BUG_ON(sizeof(struct nvmf_auth_dhchap_negotiate_data) != 8);
1304         BUILD_BUG_ON(sizeof(struct nvmf_auth_dhchap_challenge_data) != 16);
1305         BUILD_BUG_ON(sizeof(struct nvmf_auth_dhchap_reply_data) != 16);
1306         BUILD_BUG_ON(sizeof(struct nvmf_auth_dhchap_success1_data) != 16);
1307         BUILD_BUG_ON(sizeof(struct nvmf_auth_dhchap_success2_data) != 16);
1308 }
1309
1310 MODULE_LICENSE("GPL v2");
1311
1312 module_init(nvmf_init);
1313 module_exit(nvmf_exit);
This page took 0.121355 seconds and 4 git commands to generate.