> -----Original Message-----
> From: James Bottomley [mailto:james.bottom...@hansenpartnership.com]
> Sent: Friday, March 18, 2016 3:41 PM
> To: KY Srinivasan <k...@microsoft.com>; Martin K. Petersen
> <martin.peter...@oracle.com>
> Cc: Christoph Hellwig <h...@infradead.org>; gre...@linuxfoundation.org;
> linux-ker...@vger.kernel.org; de...@linuxdriverproject.org;
> oher...@suse.com; jbottom...@parallels.com; linux-s...@vger.kernel.org;
> a...@canonical.com; vkuzn...@redhat.com; jasow...@redhat.com;
> h...@suse.de
> Subject: Re: [PATCH 1/1] scsi: storvsc: Support manual scan of FC hosts on
> Hyper-V
> 
> On Thu, 2016-03-17 at 00:01 +0000, KY Srinivasan wrote:
> > The only attributes I would be interested are:
> > 1) node name
> > 2) port name
> >
> > Ideally, if this can show under /sys/class/fc_host/hostx/port_name
> > and node_name,
> > it will be ideal since all user scripts can work.
> 
> OK, like this?
> 
> From 7af7c428e7e04ddcc87fda12d6571e3dff8ae024 Mon Sep 17 00:00:00
> 2001
> From: James Bottomley <james.bottom...@hansenpartnership.com>
> Date: Fri, 18 Mar 2016 15:35:45 -0700
> Subject: scsi_transport_fc: introduce lightweight class for virtualization
>  systems
> 
> The FC transport class is very heavily tilted towards helping things
> which operate a fabric (as it should be).  However, there seems to be
> a need for a lightweight version for use in virtual systems that
> simply want to show pass through FC information without making any use
> of the heavyweight functions.  This is an attempt to give them what
> they want: the lightweight class has no vports or rports and only two
> host attributes.  Essentially, it's designed for the HV storvsc
> driver, but if other virtualizataion systems have similar problems, we
> can add more attributes.
> 
> Signed-off-by: James Bottomley <j...@linux.vnet.ibm.com>
> ---
>  drivers/scsi/scsi_transport_fc.c | 94
> ++++++++++++++++++++++++++++++++++++++++
>  include/scsi/scsi_transport_fc.h |  3 ++
>  2 files changed, 97 insertions(+)
> 
> diff --git a/drivers/scsi/scsi_transport_fc.c 
> b/drivers/scsi/scsi_transport_fc.c
> index 8a88226..a9fcb4d 100644
> --- a/drivers/scsi/scsi_transport_fc.c
> +++ b/drivers/scsi/scsi_transport_fc.c
> @@ -351,6 +351,27 @@ struct fc_internal {
> 
>  #define to_fc_internal(tmpl) container_of(tmpl, struct fc_internal, t)
> 
> +#define FC_LW_HOST_NUM_ATTRS         2
> +struct fc_lw_internal {
> +     struct scsi_transport_template t;
> +     struct fc_function_template *f;
> +
> +     /*
> +      * For attributes : each object has :
> +      *   An array of the actual attributes structures
> +      *   An array of null-terminated pointers to the attribute
> +      *     structures - used for mid-layer interaction.
> +      *
> +      * The attribute containers for the starget and host are are
> +      * part of the midlayer. As the remote port is specific to the
> +      * fc transport, we must provide the attribute container.
> +      */
> +     struct device_attribute
> private_host_attrs[FC_LW_HOST_NUM_ATTRS];
> +     struct device_attribute *host_attrs[FC_LW_HOST_NUM_ATTRS + 1];
> +};
> +
> +#define to_fc_lw_internal(tmpl)      container_of(tmpl, struct
> fc_lw_internal, t)
> +
>  static int fc_target_setup(struct transport_container *tc, struct device 
> *dev,
>                          struct device *cdev)
>  {
> @@ -472,6 +493,12 @@ static int fc_host_remove(struct transport_container
> *tc, struct device *dev,
>       return 0;
>  }
> 
> +static DECLARE_TRANSPORT_CLASS(fc_lw_host_class,
> +                            "fc_host",
> +                            NULL,
> +                            NULL,
> +                            NULL);
> +
>  static DECLARE_TRANSPORT_CLASS(fc_host_class,
>                              "fc_host",
>                              fc_host_setup,
> @@ -1968,6 +1995,25 @@ static int fc_host_match(struct
> attribute_container *cont,
>       return &i->t.host_attrs.ac == cont;
>  }
> 
> +static int fc_lw_host_match(struct attribute_container *cont,
> +                       struct device *dev)
> +{
> +     struct Scsi_Host *shost;
> +     struct fc_lw_internal *i;
> +
> +     if (!scsi_is_host_device(dev))
> +             return 0;
> +
> +     shost = dev_to_shost(dev);
> +     if (!shost->transportt  || shost->transportt->host_attrs.ac.class
> +         != &fc_lw_host_class.class)
> +             return 0;
> +
> +     i = to_fc_lw_internal(shost->transportt);
> +
> +     return &i->t.host_attrs.ac == cont;
> +}
> +
>  static int fc_target_match(struct attribute_container *cont,
>                           struct device *dev)
>  {
> @@ -2171,6 +2217,54 @@ static int fc_it_nexus_response(struct Scsi_Host
> *shost, u64 nexus, int result)
>       return i->f->it_nexus_response(shost, nexus, result);
>  }
> 
> +/**
> + * fc_attach_lw_transport - light weight attach function
> + * @ft:              function template for optional attributes
> + *
> + * This attach function is to be used only for virtual FC emulators
> + * which do not have a physical fabric underneath them and thus only
> + * need a few attributes and no helper functions
> + */
> +struct scsi_transport_template *
> +fc_lw_attach_transport(struct fc_function_template *ft)
> +{
> +     int count;
> +     struct fc_lw_internal *i = kzalloc(sizeof(struct fc_lw_internal),
> +                                        GFP_KERNEL);
> +
> +     if (unlikely(!i))
> +             return NULL;
> +
> +     i->t.host_attrs.ac.attrs = &i->host_attrs[0];
> +     i->t.host_attrs.ac.class = &fc_lw_host_class.class;
> +     i->t.host_attrs.ac.match = fc_lw_host_match;
> +     i->t.host_size = sizeof(struct fc_host_attrs);
> +     transport_container_register(&i->t.host_attrs);
> +
> +     i->f = ft;
> +
> +     count = 0;
> +     SETUP_HOST_ATTRIBUTE_RD(node_name);
> +     SETUP_HOST_ATTRIBUTE_RD(port_name);
> +
> +     BUG_ON(count > FC_HOST_NUM_ATTRS);
> +
> +     i->host_attrs[count] = NULL;
> +
> +     return &i->t;
> +}
> +EXPORT_SYMBOL(fc_lw_attach_transport);
> +
> +void fc_lw_release_transport(struct scsi_transport_template *t)
> +{
> +     struct fc_lw_internal *i = to_fc_lw_internal(t);
> +
> +     transport_container_unregister(&i->t.host_attrs);
> +
> +     kfree(i);
> +}
> +EXPORT_SYMBOL(fc_lw_release_transport);
> +
>  struct scsi_transport_template *
>  fc_attach_transport(struct fc_function_template *ft)
>  {
> diff --git a/include/scsi/scsi_transport_fc.h 
> b/include/scsi/scsi_transport_fc.h
> index 784bc2c..b0a9a64 100644
> --- a/include/scsi/scsi_transport_fc.h
> +++ b/include/scsi/scsi_transport_fc.h
> @@ -835,6 +835,9 @@ fc_vport_set_state(struct fc_vport *vport, enum
> fc_vport_state new_state)
>       vport->vport_state = new_state;
>  }
> 
> +struct scsi_transport_template *fc_lw_attach_transport(
> +                     struct fc_function_template *);
> +void fc_lw_release_transport(struct scsi_transport_template *);
>  struct scsi_transport_template *fc_attach_transport(
>                       struct fc_function_template *);
>  void fc_release_transport(struct scsi_transport_template *);
> --
> 2.6.2

James,

It was great talking to you this afternoon. Is this what you had in mind:

drivers/scsi/scsi_transport_fc.c |  133 ++++++++++++++++++++++++++++++++++++--
 include/scsi/scsi_transport_fc.h |    3 +
 2 files changed, 130 insertions(+), 6 deletions(-)

diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
index 24eaaf6..b8cadd2 100644
--- a/drivers/scsi/scsi_transport_fc.c
+++ b/drivers/scsi/scsi_transport_fc.c
@@ -351,6 +351,27 @@ struct fc_internal {
 
 #define to_fc_internal(tmpl)   container_of(tmpl, struct fc_internal, t)
 
+#define FC_LW_HOST_NUM_ATTRS   2
+struct fc_lw_internal {
+       struct scsi_transport_template t;
+       struct fc_function_template *f;
+
+       /*
+        * For attributes : each object has :
+        *   An array of the actual attributes structures
+        *   An array of null-terminated pointers to the attribute
+        *     structures - used for mid-layer interaction.
+        *
+        * The attribute containers for the starget and host are are
+        * part of the midlayer. As the remote port is specific to the
+        * fc transport, we must provide the attribute container.
+        */
+       struct device_attribute private_host_attrs[FC_LW_HOST_NUM_ATTRS];
+       struct device_attribute *host_attrs[FC_LW_HOST_NUM_ATTRS + 1];
+};
+
+#define to_fc_lw_internal(tmpl)        container_of(tmpl, struct 
fc_lw_internal, t)
+
 static int fc_target_setup(struct transport_container *tc, struct device *dev,
                           struct device *cdev)
 {
@@ -472,6 +493,12 @@ static int fc_host_remove(struct transport_container *tc, 
struct device *dev,
        return 0;
 }
 
+static DECLARE_TRANSPORT_CLASS(fc_lw_host_class,
+                              "fc_host",
+                              NULL,
+                              NULL,
+                              NULL);
+
 static DECLARE_TRANSPORT_CLASS(fc_host_class,
                               "fc_host",
                               fc_host_setup,
@@ -654,11 +681,20 @@ send_vendor_fail:
 EXPORT_SYMBOL(fc_host_post_vendor_event);
 
 
+static bool transport_inited;
+static bool lw_transport_inited;
 
-static __init int fc_transport_init(void)
+static int fc_transport_init(bool lw_transport)
 {
        int error;
+       bool inited = cmpxchg(&transport_inited, transport_inited, true);
 
+       /*
+        * If transport has already been inited, just return.
+        */
+       if (inited)
+               return 0;
+       
        atomic_set(&fc_event_seq, 0);
 
        error = transport_class_register(&fc_host_class);
@@ -670,9 +706,15 @@ static __init int fc_transport_init(void)
        error = transport_class_register(&fc_rport_class);
        if (error)
                goto unreg_vport_class;
-       error = transport_class_register(&fc_transport_class);
+       if (lw_transport)
+               error = transport_class_register(&fc_lw_host_class);
+       else 
+               error = transport_class_register(&fc_transport_class);
        if (error)
                goto unreg_rport_class;
+
+       if (lw_transport)
+                lw_transport_inited = true;
        return 0;
 
 unreg_rport_class:
@@ -686,8 +728,12 @@ unreg_host_class:
 
 static void __exit fc_transport_exit(void)
 {
-       transport_class_unregister(&fc_transport_class);
+       if (lw_transport_inited)
+               transport_class_unregister(&fc_lw_host_class);
+       else
+               transport_class_unregister(&fc_transport_class);
        transport_class_unregister(&fc_rport_class);
+       if (lw_transport_inited)
        transport_class_unregister(&fc_host_class);
        transport_class_unregister(&fc_vport_class);
 }
@@ -1968,6 +2014,25 @@ static int fc_host_match(struct attribute_container 
*cont,
        return &i->t.host_attrs.ac == cont;
 }
 
+static int fc_lw_host_match(struct attribute_container *cont,
+                         struct device *dev)
+{
+       struct Scsi_Host *shost;
+       struct fc_lw_internal *i;
+
+       if (!scsi_is_host_device(dev))
+               return 0;
+
+       shost = dev_to_shost(dev);
+       if (!shost->transportt  || shost->transportt->host_attrs.ac.class
+           != &fc_lw_host_class.class)
+               return 0;
+
+       i = to_fc_lw_internal(shost->transportt);
+
+       return &i->t.host_attrs.ac == cont;
+}
+
 static int fc_target_match(struct attribute_container *cont,
                            struct device *dev)
 {
@@ -2171,13 +2236,70 @@ static int fc_it_nexus_response(struct Scsi_Host 
*shost, u64 nexus, int result)
        return i->f->it_nexus_response(shost, nexus, result);
 }
 
+/**
+ * fc_attach_lw_transport - light weight attach function
+ * @ft:                function template for optional attributes
+ *
+ * This attach function is to be used only for virtual FC emulators
+ * which do not have a physical fabric underneath them and thus only
+ * need a few attributes and no helper functions
+ */
+struct scsi_transport_template *
+fc_lw_attach_transport(struct fc_function_template *ft)
+{
+       int count;
+       struct fc_lw_internal *i;
+
+       if (fc_transport_init(true))
+               return NULL;
+
+       i = kzalloc(sizeof(struct fc_lw_internal),
+                   GFP_KERNEL);
+
+       if (unlikely(!i))
+               return NULL;
+
+       i->t.host_attrs.ac.attrs = &i->host_attrs[0];
+       i->t.host_attrs.ac.class = &fc_lw_host_class.class;
+       i->t.host_attrs.ac.match = fc_lw_host_match;
+       i->t.host_size = sizeof(struct fc_host_attrs);
+       transport_container_register(&i->t.host_attrs);
+
+       i->f = ft;
+
+       count = 0;
+       SETUP_HOST_ATTRIBUTE_RD(node_name);
+       SETUP_HOST_ATTRIBUTE_RD(port_name);
+
+       BUG_ON(count > FC_HOST_NUM_ATTRS);
+
+       i->host_attrs[count] = NULL;
+
+       return &i->t;
+}
+EXPORT_SYMBOL(fc_lw_attach_transport);
+
+void fc_lw_release_transport(struct scsi_transport_template *t)
+{
+       struct fc_lw_internal *i = to_fc_lw_internal(t);
+
+       transport_container_unregister(&i->t.host_attrs);
+
+       kfree(i);
+}
+EXPORT_SYMBOL(fc_lw_release_transport);
+
 struct scsi_transport_template *
 fc_attach_transport(struct fc_function_template *ft)
 {
        int count;
-       struct fc_internal *i = kzalloc(sizeof(struct fc_internal),
-                                       GFP_KERNEL);
+       struct fc_internal *i;
+
+       if (fc_transport_init(false))
+               return NULL;
 
+       i = kzalloc(sizeof(struct fc_internal),
+                          GFP_KERNEL);
        if (unlikely(!i))
                return NULL;
 
@@ -4148,5 +4270,4 @@ MODULE_AUTHOR("James Smart");
 MODULE_DESCRIPTION("FC Transport Attributes");
 MODULE_LICENSE("GPL");
 
-module_init(fc_transport_init);
 module_exit(fc_transport_exit);
diff --git a/include/scsi/scsi_transport_fc.h b/include/scsi/scsi_transport_fc.h
index 784bc2c..b0a9a64 100644
--- a/include/scsi/scsi_transport_fc.h
+++ b/include/scsi/scsi_transport_fc.h
@@ -835,6 +835,9 @@ fc_vport_set_state(struct fc_vport *vport, enum 
fc_vport_state new_state)
        vport->vport_state = new_state;
 }
 
+struct scsi_transport_template *fc_lw_attach_transport(
+                       struct fc_function_template *);
+void fc_lw_release_transport(struct scsi_transport_template *);
 struct scsi_transport_template *fc_attach_transport(
                        struct fc_function_template *);
 void fc_release_transport(struct scsi_transport_template *);
-- 
1.7.4.1

_______________________________________________
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel

Reply via email to