@@ -40,6 +40,7 @@ static void __nvme_free_host(nvme_host_t h);
4040static void __nvme_free_ctrl (nvme_ctrl_t c );
4141static int nvme_subsystem_scan_namespace (nvme_root_t r ,
4242 struct nvme_subsystem * s , char * name );
43+ static int nvme_init_subsystem (nvme_subsystem_t s , const char * name );
4344static int nvme_scan_subsystem (nvme_root_t r , const char * name ,
4445 nvme_scan_filter_t f );
4546static int nvme_ctrl_scan_namespace (nvme_root_t r , struct nvme_ctrl * c ,
@@ -370,26 +371,20 @@ void nvme_free_subsystem(nvme_subsystem_t s)
370371{
371372}
372373
373- struct nvme_subsystem * nvme_lookup_subsystem (struct nvme_host * h ,
374- const char * name ,
375- const char * subsysnqn )
374+ struct nvme_subsystem * nvme_alloc_subsystem (struct nvme_host * h ,
375+ const char * name ,
376+ const char * subsysnqn )
376377{
377378 struct nvme_subsystem * s ;
378379
379- nvme_for_each_subsystem (h , s ) {
380- if (strcmp (s -> subsysnqn , subsysnqn ))
381- continue ;
382- if (name && s -> name &&
383- strcmp (s -> name , name ))
384- continue ;
385- return s ;
386- }
387380 s = calloc (1 , sizeof (* s ));
388381 if (!s )
389382 return NULL ;
390383
391384 s -> h = h ;
392385 s -> subsysnqn = strdup (subsysnqn );
386+ if (name )
387+ nvme_init_subsystem (s , name );
393388 list_head_init (& s -> ctrls );
394389 list_head_init (& s -> namespaces );
395390 list_node_init (& s -> entry );
@@ -398,6 +393,23 @@ struct nvme_subsystem *nvme_lookup_subsystem(struct nvme_host *h,
398393 return s ;
399394}
400395
396+ struct nvme_subsystem * nvme_lookup_subsystem (struct nvme_host * h ,
397+ const char * name ,
398+ const char * subsysnqn )
399+ {
400+ struct nvme_subsystem * s ;
401+
402+ nvme_for_each_subsystem (h , s ) {
403+ if (strcmp (s -> subsysnqn , subsysnqn ))
404+ continue ;
405+ if (name && s -> name &&
406+ strcmp (s -> name , name ))
407+ continue ;
408+ return s ;
409+ }
410+ return nvme_alloc_subsystem (h , name , subsysnqn );
411+ }
412+
401413static void __nvme_free_host (struct nvme_host * h )
402414{
403415 struct nvme_subsystem * s , * _s ;
@@ -504,9 +516,8 @@ static int nvme_init_subsystem(nvme_subsystem_t s, const char *name)
504516static int nvme_scan_subsystem (struct nvme_root * r , const char * name ,
505517 nvme_scan_filter_t f )
506518{
507- struct nvme_subsystem * s ;
519+ struct nvme_subsystem * s = NULL , * _s ;
508520 char * path , * subsysnqn ;
509- char * hostnqn , * hostid = NULL ;
510521 nvme_host_t h = NULL ;
511522 int ret ;
512523
@@ -515,47 +526,49 @@ static int nvme_scan_subsystem(struct nvme_root *r, const char *name,
515526 if (ret < 0 )
516527 return ret ;
517528
518- hostnqn = nvme_get_attr (path , "hostnqn" );
519- if (hostnqn ) {
520- hostid = nvme_get_attr (path , "hostid" );
521- h = nvme_lookup_host (r , hostnqn , hostid );
522- free (hostnqn );
523- if (hostid )
524- free (hostid );
525- if (h ) {
526- if (h -> dhchap_key )
527- free (h -> dhchap_key );
528- h -> dhchap_key = nvme_get_attr (path , "dhchap_secret" );
529- if (h -> dhchap_key && !strcmp (h -> dhchap_key , "none" )) {
530- free (h -> dhchap_key );
531- h -> dhchap_key = NULL ;
532- }
533- }
534- }
535- if (!h )
536- h = nvme_default_host (r );
537- if (!h ) {
538- free (path );
539- errno = ENOMEM ;
540- return -1 ;
541- }
542529 subsysnqn = nvme_get_attr (path , "subsysnqn" );
543530 free (path );
544531 if (!subsysnqn ) {
545532 errno = ENODEV ;
546533 return -1 ;
547534 }
548- s = nvme_lookup_subsystem (h , name , subsysnqn );
549- free (subsysnqn );
535+ nvme_for_each_host (r , h ) {
536+ nvme_for_each_subsystem (h , _s ) {
537+ /*
538+ * We are always called after nvme_scan_ctrl(),
539+ * so any subsystem we're interested at _must_
540+ * have a name.
541+ */
542+ if (!_s -> name )
543+ continue ;
544+ if (strcmp (_s -> name , name ))
545+ continue ;
546+ s = _s ;
547+ }
548+ }
550549 if (!s ) {
551- errno = ENOMEM ;
550+ /*
551+ * Subsystem with non-matching controller. odd.
552+ * Create a subsystem with the default host
553+ * and hope for the best.
554+ */
555+ nvme_msg (r , LOG_DEBUG , "creating detached subsystem '%s'\n" ,
556+ name );
557+ h = nvme_default_host (r );
558+ s = nvme_alloc_subsystem (h , name , subsysnqn );
559+ if (!s ) {
560+ errno = ENOMEM ;
561+ }
562+ } else if (strcmp (s -> subsysnqn , subsysnqn )) {
563+ nvme_msg (r , LOG_WARNING , "NQN mismatch for subsystem '%s'\n" ,
564+ name );
565+ s = NULL ;
566+ errno = EINVAL ;
552567 return -1 ;
553568 }
554- if (!s -> name ) {
555- ret = nvme_init_subsystem (s , name );
556- if (ret < 0 )
557- return -1 ;
558- }
569+ free (subsysnqn );
570+ if (!s )
571+ return -1 ;
559572
560573 nvme_subsystem_scan_namespaces (r , s );
561574
@@ -1199,14 +1212,6 @@ int nvme_init_ctrl(nvme_host_t h, nvme_ctrl_t c, int instance)
11991212 ret = -1 ;
12001213 goto out_free_subsys ;
12011214 }
1202- if (!s -> name ) {
1203- ret = nvme_init_subsystem (s , subsys_name );
1204- if (ret < 0 ) {
1205- nvme_msg (h -> r , LOG_ERR , "Failed to init subsystem %s\n" ,
1206- subsys_name );
1207- goto out_free_subsys ;
1208- }
1209- }
12101215 if (s -> subsystype && !strcmp (s -> subsystype , "discovery" ))
12111216 c -> discovery_ctrl = true;
12121217 c -> s = s ;
@@ -1369,15 +1374,19 @@ nvme_ctrl_t nvme_scan_ctrl(nvme_root_t r, const char *name)
13691374 return NULL ;
13701375 }
13711376 subsysname = nvme_ctrl_lookup_subsystem_name (r , name );
1372- /* subsysname might be NULL here */
1377+ if (!subsysname ) {
1378+ nvme_msg (r , LOG_ERR ,
1379+ "failed to lookup subsystem for controller %s\n" ,
1380+ name );
1381+ free (path );
1382+ errno = ENXIO ;
1383+ return NULL ;
1384+ }
13731385 s = nvme_lookup_subsystem (h , subsysname , subsysnqn );
13741386 free (subsysnqn );
1375-
1376- ret = 0 ;
1377- if (s && !s -> name && subsysname )
1378- ret = nvme_init_subsystem (s , subsysname );
13791387 free (subsysname );
1380- if (!s || ret < 0 ) {
1388+
1389+ if (!s ) {
13811390 free (path );
13821391 errno = ENOMEM ;
13831392 return NULL ;
0 commit comments