All of lore.kernel.org
 help / color / mirror / Atom feed
From: Kirti Wankhede <kwankhede@nvidia.com>
To: Christoph Hellwig <hch@lst.de>,
	Tony Krowiak <akrowiak@linux.ibm.com>,
	Halil Pasic <pasic@linux.ibm.com>,
	Jason Herne <jjherne@linux.ibm.com>,
	Eric Farman <farman@linux.ibm.com>,
	Matthew Rosato <mjrosato@linux.ibm.com>,
	Zhenyu Wang <zhenyuw@linux.intel.com>,
	Zhi Wang <zhi.a.wang@intel.com>,
	Alex Williamson <alex.williamson@redhat.com>
Cc: kvm@vger.kernel.org, linux-s390@vger.kernel.org,
	intel-gvt-dev@lists.freedesktop.org,
	Jason Gunthorpe <jgg@nvidia.com>, Neo Jia <cjia@nvidia.com>,
	Tarun Gupta <targupta@nvidia.com>,
	Dheeraj Nigam <dnigam@nvidia.com>
Subject: Re: [PATCH 09/13] vfio/mdev: consolidate all the device_api sysfs into the core code
Date: Thu, 16 Jun 2022 01:54:22 +0530	[thread overview]
Message-ID: <6599f9b0-c669-d9a0-91f9-e8d967b9ba7d@nvidia.com> (raw)
In-Reply-To: <20220614045428.278494-10-hch@lst.de>



On 6/14/2022 10:24 AM, Christoph Hellwig wrote:
> From: Jason Gunthorpe <jgg@nvidia.com>
> 
> Every driver just emits a static string, simply feed it through the ops
> and provide a standard sysfs show function.
> 
> Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
> Signed-off-by: Christoph Hellwig <hch@lst.de>

Reviewed-by: Kirti Wankhede <kwankhede@nvidia.com>

> ---
>   .../driver-api/vfio-mediated-device.rst       |  2 +-
>   drivers/gpu/drm/i915/gvt/kvmgt.c              |  9 +----
>   drivers/s390/cio/vfio_ccw_ops.c               | 11 ++----
>   drivers/s390/crypto/vfio_ap_ops.c             | 10 +-----
>   drivers/vfio/mdev/mdev_driver.c               |  4 ++-
>   drivers/vfio/mdev/mdev_sysfs.c                | 35 +++++++++++++------
>   include/linux/mdev.h                          |  7 ++--
>   samples/vfio-mdev/mbochs.c                    |  9 +----
>   samples/vfio-mdev/mdpy.c                      |  9 +----
>   samples/vfio-mdev/mtty.c                      | 10 +-----
>   10 files changed, 38 insertions(+), 68 deletions(-)
> 
> diff --git a/Documentation/driver-api/vfio-mediated-device.rst b/Documentation/driver-api/vfio-mediated-device.rst
> index 27247b3bdcb57..e9913bfb4393b 100644
> --- a/Documentation/driver-api/vfio-mediated-device.rst
> +++ b/Documentation/driver-api/vfio-mediated-device.rst
> @@ -204,7 +204,7 @@ Directories and files under the sysfs for Each Physical Device
>   
>   * device_api
>   
> -  This attribute should show which device API is being created, for example,
> +  This attribute shows which device API is being created, for example,
>     "vfio-pci" for a PCI device.
>   
>   * available_instances
> diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c b/drivers/gpu/drm/i915/gvt/kvmgt.c
> index 136f9c0df48b9..44a418d897377 100644
> --- a/drivers/gpu/drm/i915/gvt/kvmgt.c
> +++ b/drivers/gpu/drm/i915/gvt/kvmgt.c
> @@ -123,12 +123,6 @@ static ssize_t available_instances_show(struct mdev_type *mtype,
>   	return sprintf(buf, "%u\n", type->avail_instance);
>   }
>   
> -static ssize_t device_api_show(struct mdev_type *mtype,
> -			       struct mdev_type_attribute *attr, char *buf)
> -{
> -	return sprintf(buf, "%s\n", VFIO_DEVICE_API_PCI_STRING);
> -}
> -
>   static ssize_t description_show(struct mdev_type *mtype,
>   				struct mdev_type_attribute *attr, char *buf)
>   {
> @@ -151,13 +145,11 @@ static ssize_t name_show(struct mdev_type *mtype,
>   }
>   
>   static MDEV_TYPE_ATTR_RO(available_instances);
> -static MDEV_TYPE_ATTR_RO(device_api);
>   static MDEV_TYPE_ATTR_RO(description);
>   static MDEV_TYPE_ATTR_RO(name);
>   
>   static const struct attribute *gvt_type_attrs[] = {
>   	&mdev_type_attr_available_instances.attr,
> -	&mdev_type_attr_device_api.attr,
>   	&mdev_type_attr_description.attr,
>   	&mdev_type_attr_name.attr,
>   	NULL,
> @@ -1587,6 +1579,7 @@ static void intel_vgpu_remove(struct mdev_device *mdev)
>   }
>   
>   static struct mdev_driver intel_vgpu_mdev_driver = {
> +	.device_api	= VFIO_DEVICE_API_PCI_STRING,
>   	.driver = {
>   		.name		= "intel_vgpu_mdev",
>   		.owner		= THIS_MODULE,
> diff --git a/drivers/s390/cio/vfio_ccw_ops.c b/drivers/s390/cio/vfio_ccw_ops.c
> index 43d53736dfe3c..730d87a96a305 100644
> --- a/drivers/s390/cio/vfio_ccw_ops.c
> +++ b/drivers/s390/cio/vfio_ccw_ops.c
> @@ -77,13 +77,6 @@ static ssize_t name_show(struct mdev_type *mtype,
>   }
>   static MDEV_TYPE_ATTR_RO(name);
>   
> -static ssize_t device_api_show(struct mdev_type *mtype,
> -			       struct mdev_type_attribute *attr, char *buf)
> -{
> -	return sprintf(buf, "%s\n", VFIO_DEVICE_API_CCW_STRING);
> -}
> -static MDEV_TYPE_ATTR_RO(device_api);
> -
>   static ssize_t available_instances_show(struct mdev_type *mtype,
>   					struct mdev_type_attribute *attr,
>   					char *buf)
> @@ -96,7 +89,6 @@ static MDEV_TYPE_ATTR_RO(available_instances);
>   
>   static const struct attribute *mdev_types_attrs[] = {
>   	&mdev_type_attr_name.attr,
> -	&mdev_type_attr_device_api.attr,
>   	&mdev_type_attr_available_instances.attr,
>   	NULL,
>   };
> @@ -636,6 +628,7 @@ static const struct vfio_device_ops vfio_ccw_dev_ops = {
>   };
>   
>   struct mdev_driver vfio_ccw_mdev_driver = {
> +	.device_api = VFIO_DEVICE_API_CCW_STRING,
>   	.driver = {
>   		.name = "vfio_ccw_mdev",
>   		.owner = THIS_MODULE,
> @@ -648,7 +641,7 @@ struct mdev_driver vfio_ccw_mdev_driver = {
>   
>   int vfio_ccw_mdev_reg(struct subchannel *sch)
>   {
> -	sprintf(sch->mdev_type.sysfs_name, "io");
> +	strcat(sch->mdev_type.sysfs_name, "io");
>   	sch->mdev_types[0] = &sch->mdev_type;
>   	return mdev_register_parent(&sch->parent, &sch->dev,
>   				    &vfio_ccw_mdev_driver, sch->mdev_types,
> diff --git a/drivers/s390/crypto/vfio_ap_ops.c b/drivers/s390/crypto/vfio_ap_ops.c
> index ff25858b2ebbe..da21fd60877fb 100644
> --- a/drivers/s390/crypto/vfio_ap_ops.c
> +++ b/drivers/s390/crypto/vfio_ap_ops.c
> @@ -529,17 +529,8 @@ static ssize_t available_instances_show(struct mdev_type *mtype,
>   
>   static MDEV_TYPE_ATTR_RO(available_instances);
>   
> -static ssize_t device_api_show(struct mdev_type *mtype,
> -			       struct mdev_type_attribute *attr, char *buf)
> -{
> -	return sprintf(buf, "%s\n", VFIO_DEVICE_API_AP_STRING);
> -}
> -
> -static MDEV_TYPE_ATTR_RO(device_api);
> -
>   static const struct attribute *vfio_ap_mdev_type_attrs[] = {
>   	&mdev_type_attr_name.attr,
> -	&mdev_type_attr_device_api.attr,
>   	&mdev_type_attr_available_instances.attr,
>   	NULL,
>   };
> @@ -1454,6 +1445,7 @@ static const struct vfio_device_ops vfio_ap_matrix_dev_ops = {
>   };
>   
>   static struct mdev_driver vfio_ap_matrix_driver = {
> +	.device_api = VFIO_DEVICE_API_AP_STRING,
>   	.driver = {
>   		.name = "vfio_ap_mdev",
>   		.owner = THIS_MODULE,
> diff --git a/drivers/vfio/mdev/mdev_driver.c b/drivers/vfio/mdev/mdev_driver.c
> index 5b3c94f4fb13d..60e8b9f6474e8 100644
> --- a/drivers/vfio/mdev/mdev_driver.c
> +++ b/drivers/vfio/mdev/mdev_driver.c
> @@ -55,8 +55,10 @@ struct bus_type mdev_bus_type = {
>    **/
>   int mdev_register_driver(struct mdev_driver *drv)
>   {
> -	if (!drv->types_attrs)
> +	if (!drv->types_attrs || !drv->device_api)
>   		return -EINVAL;
> +
> +	/* initialize common driver fields */
>   	drv->driver.bus = &mdev_bus_type;
>   	return driver_register(&drv->driver);
>   }
> diff --git a/drivers/vfio/mdev/mdev_sysfs.c b/drivers/vfio/mdev/mdev_sysfs.c
> index dd81b91afcf7d..20763f1aa9f5a 100644
> --- a/drivers/vfio/mdev/mdev_sysfs.c
> +++ b/drivers/vfio/mdev/mdev_sysfs.c
> @@ -72,9 +72,30 @@ static ssize_t create_store(struct mdev_type *mtype,
>   
>   	return count;
>   }
> -
>   static MDEV_TYPE_ATTR_WO(create);
>   
> +static ssize_t device_api_show(struct mdev_type *mtype,
> +			       struct mdev_type_attribute *attr, char *buf)
> +{
> +	return sysfs_emit(buf, "%s\n", mtype->parent->mdev_driver->device_api);
> +}
> +static MDEV_TYPE_ATTR_RO(device_api);
> +
> +static struct attribute *mdev_types_core_attrs[] = {
> +	&mdev_type_attr_create.attr,
> +	&mdev_type_attr_device_api.attr,
> +	NULL,
> +};
> +
> +static struct attribute_group mdev_type_core_group = {
> +	.attrs = mdev_types_core_attrs,
> +};
> +
> +static const struct attribute_group *mdev_type_groups[] = {
> +	&mdev_type_core_group,
> +	NULL,
> +};
> +
>   static void mdev_type_release(struct kobject *kobj)
>   {
>   	struct mdev_type *type = to_mdev_type(kobj);
> @@ -84,8 +105,9 @@ static void mdev_type_release(struct kobject *kobj)
>   }
>   
>   static struct kobj_type mdev_type_ktype = {
> -	.sysfs_ops = &mdev_type_sysfs_ops,
> -	.release = mdev_type_release,
> +	.sysfs_ops	= &mdev_type_sysfs_ops,
> +	.release	= mdev_type_release,
> +	.default_groups	= mdev_type_groups,
>   };
>   
>   int mdev_type_add(struct mdev_parent *parent, struct mdev_type *type)
> @@ -100,10 +122,6 @@ int mdev_type_add(struct mdev_parent *parent, struct mdev_type *type)
>   	if (ret)
>   		return ret;
>   
> -	ret = sysfs_create_file(&type->kobj, &mdev_type_attr_create.attr);
> -	if (ret)
> -		goto attr_create_failed;
> -
>   	type->devices_kobj = kobject_create_and_add("devices", &type->kobj);
>   	if (!type->devices_kobj) {
>   		ret = -ENOMEM;
> @@ -118,8 +136,6 @@ int mdev_type_add(struct mdev_parent *parent, struct mdev_type *type)
>   attrs_failed:
>   	kobject_put(type->devices_kobj);
>   attr_devices_failed:
> -	sysfs_remove_file(&type->kobj, &mdev_type_attr_create.attr);
> -attr_create_failed:
>   	kobject_del(&type->kobj);
>   	kobject_put(&type->kobj);
>   	return ret;
> @@ -130,7 +146,6 @@ void mdev_type_remove(struct mdev_type *type)
>   	sysfs_remove_files(&type->kobj, type->parent->mdev_driver->types_attrs);
>   
>   	kobject_put(type->devices_kobj);
> -	sysfs_remove_file(&type->kobj, &mdev_type_attr_create.attr);
>   	kobject_del(&type->kobj);
>   	kobject_put(&type->kobj);
>   }
> diff --git a/include/linux/mdev.h b/include/linux/mdev.h
> index ecf964d34f2ca..81e11e18b3e41 100644
> --- a/include/linux/mdev.h
> +++ b/include/linux/mdev.h
> @@ -61,11 +61,6 @@ struct mdev_type_attribute {
>   			 size_t count);
>   };
>   
> -#define MDEV_TYPE_ATTR(_name, _mode, _show, _store)		\
> -struct mdev_type_attribute mdev_type_attr_##_name =		\
> -	__ATTR(_name, _mode, _show, _store)
> -#define MDEV_TYPE_ATTR_RW(_name) \
> -	struct mdev_type_attribute mdev_type_attr_##_name = __ATTR_RW(_name)
>   #define MDEV_TYPE_ATTR_RO(_name) \
>   	struct mdev_type_attribute mdev_type_attr_##_name = __ATTR_RO(_name)
>   #define MDEV_TYPE_ATTR_WO(_name) \
> @@ -73,12 +68,14 @@ struct mdev_type_attribute mdev_type_attr_##_name =		\
>   
>   /**
>    * struct mdev_driver - Mediated device driver
> + * @device_api:	String to return for the device_api sysfs
>    * @probe: called when new device created
>    * @remove: called when device removed
>    * @types_attrs: attributes to the type kobjects.
>    * @driver: device driver structure
>    **/
>   struct mdev_driver {
> +	const char *device_api;
>   	int (*probe)(struct mdev_device *dev);
>   	void (*remove)(struct mdev_device *dev);
>   	const struct attribute * const *types_attrs;
> diff --git a/samples/vfio-mdev/mbochs.c b/samples/vfio-mdev/mbochs.c
> index 1069f561cb012..199846f01de92 100644
> --- a/samples/vfio-mdev/mbochs.c
> +++ b/samples/vfio-mdev/mbochs.c
> @@ -1367,17 +1367,9 @@ static ssize_t available_instances_show(struct mdev_type *mtype,
>   }
>   static MDEV_TYPE_ATTR_RO(available_instances);
>   
> -static ssize_t device_api_show(struct mdev_type *mtype,
> -			       struct mdev_type_attribute *attr, char *buf)
> -{
> -	return sprintf(buf, "%s\n", VFIO_DEVICE_API_PCI_STRING);
> -}
> -static MDEV_TYPE_ATTR_RO(device_api);
> -
>   static const struct attribute *mdev_types_attrs[] = {
>   	&mdev_type_attr_name.attr,
>   	&mdev_type_attr_description.attr,
> -	&mdev_type_attr_device_api.attr,
>   	&mdev_type_attr_available_instances.attr,
>   	NULL,
>   };
> @@ -1391,6 +1383,7 @@ static const struct vfio_device_ops mbochs_dev_ops = {
>   };
>   
>   static struct mdev_driver mbochs_driver = {
> +	.device_api = VFIO_DEVICE_API_PCI_STRING,
>   	.driver = {
>   		.name = "mbochs",
>   		.owner = THIS_MODULE,
> diff --git a/samples/vfio-mdev/mdpy.c b/samples/vfio-mdev/mdpy.c
> index 40b1c8a58157c..401a9a622673c 100644
> --- a/samples/vfio-mdev/mdpy.c
> +++ b/samples/vfio-mdev/mdpy.c
> @@ -678,17 +678,9 @@ static ssize_t available_instances_show(struct mdev_type *mtype,
>   }
>   static MDEV_TYPE_ATTR_RO(available_instances);
>   
> -static ssize_t device_api_show(struct mdev_type *mtype,
> -			       struct mdev_type_attribute *attr, char *buf)
> -{
> -	return sprintf(buf, "%s\n", VFIO_DEVICE_API_PCI_STRING);
> -}
> -static MDEV_TYPE_ATTR_RO(device_api);
> -
>   static const struct attribute *mdev_types_attrs[] = {
>   	&mdev_type_attr_name.attr,
>   	&mdev_type_attr_description.attr,
> -	&mdev_type_attr_device_api.attr,
>   	&mdev_type_attr_available_instances.attr,
>   	NULL,
>   };
> @@ -701,6 +693,7 @@ static const struct vfio_device_ops mdpy_dev_ops = {
>   };
>   
>   static struct mdev_driver mdpy_driver = {
> +	.device_api = VFIO_DEVICE_API_PCI_STRING,
>   	.driver = {
>   		.name = "mdpy",
>   		.owner = THIS_MODULE,
> diff --git a/samples/vfio-mdev/mtty.c b/samples/vfio-mdev/mtty.c
> index 029a19ef8ce7b..2a470424628af 100644
> --- a/samples/vfio-mdev/mtty.c
> +++ b/samples/vfio-mdev/mtty.c
> @@ -1268,17 +1268,8 @@ static ssize_t available_instances_show(struct mdev_type *mtype,
>   
>   static MDEV_TYPE_ATTR_RO(available_instances);
>   
> -static ssize_t device_api_show(struct mdev_type *mtype,
> -			       struct mdev_type_attribute *attr, char *buf)
> -{
> -	return sprintf(buf, "%s\n", VFIO_DEVICE_API_PCI_STRING);
> -}
> -
> -static MDEV_TYPE_ATTR_RO(device_api);
> -
>   static const struct attribute *mdev_types_attrs[] = {
>   	&mdev_type_attr_name.attr,
> -	&mdev_type_attr_device_api.attr,
>   	&mdev_type_attr_available_instances.attr,
>   	NULL,
>   };
> @@ -1291,6 +1282,7 @@ static const struct vfio_device_ops mtty_dev_ops = {
>   };
>   
>   static struct mdev_driver mtty_driver = {
> +	.device_api = VFIO_DEVICE_API_PCI_STRING,
>   	.driver = {
>   		.name = "mtty",
>   		.owner = THIS_MODULE,

  parent reply	other threads:[~2022-06-15 20:24 UTC|newest]

Thread overview: 60+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-06-14  4:54 simplify the mdev interface v2 Christoph Hellwig
2022-06-14  4:54 ` [PATCH 01/13] vfio/mdev: make mdev.h standalone includable Christoph Hellwig
2022-06-14  9:50   ` Tian, Kevin
2022-06-15 19:12   ` Kirti Wankhede
2022-06-23 19:39   ` [PATCH 1/13] " Jason Gunthorpe
2022-06-14  4:54 ` [PATCH 02/13] vfio/mdev: embedd struct mdev_parent in the parent data structure Christoph Hellwig
2022-06-14  9:54   ` Tian, Kevin
2022-06-15 19:29   ` Kirti Wankhede
2022-06-23 20:18     ` Jason Gunthorpe
2022-06-24 12:29       ` Kirti Wankhede
2022-06-24 12:33         ` Jason Gunthorpe
2022-06-24 12:53           ` Kirti Wankhede
2022-06-24 13:05             ` Jason Gunthorpe
2022-06-24 13:14               ` Kirti Wankhede
2022-06-23 20:59   ` [PATCH 2/13] " Jason Gunthorpe
2022-06-14  4:54 ` [PATCH 03/13] vfio/mdev: simplify mdev_type handling Christoph Hellwig
2022-06-14  6:14   ` Yi Liu
2022-06-14 10:06   ` Tian, Kevin
2022-06-15  6:28     ` Christoph Hellwig
2022-06-15  6:11       ` Zhenyu Wang
2022-06-15 19:55   ` Kirti Wankhede
2022-06-19  7:42     ` Christoph Hellwig
2022-06-23 21:27   ` [PATCH 3/13] " Jason Gunthorpe
2022-06-24 12:32     ` Kirti Wankhede
2022-06-14  4:54 ` [PATCH 04/13] vfio/mdev: remove mdev_{create,remove}_sysfs_files Christoph Hellwig
2022-06-15 20:03   ` Kirti Wankhede
2022-06-19  7:37     ` Christoph Hellwig
2022-06-14  4:54 ` [PATCH 05/13] vfio/mdev: remove mdev_from_dev Christoph Hellwig
2022-06-15 20:06   ` Kirti Wankhede
2022-06-14  4:54 ` [PATCH 06/13] vfio/mdev: unexport mdev_bus_type Christoph Hellwig
2022-06-15 20:08   ` Kirti Wankhede
2022-06-14  4:54 ` [PATCH 07/13] vfio/mdev: remove mdev_parent_dev Christoph Hellwig
2022-06-15 20:11   ` Kirti Wankhede
2022-06-14  4:54 ` [PATCH 08/13] vfio/mdev: remove mtype_get_parent_dev Christoph Hellwig
2022-06-15 20:13   ` Kirti Wankhede
2022-06-14  4:54 ` [PATCH 09/13] vfio/mdev: consolidate all the device_api sysfs into the core code Christoph Hellwig
2022-06-14 10:10   ` Tian, Kevin
2022-06-15 20:24   ` Kirti Wankhede [this message]
2022-06-23 21:30   ` [PATCH 9/13] " Jason Gunthorpe
2022-06-14  4:54 ` [PATCH 10/13] vfio/mdev: consolidate all the name " Christoph Hellwig
2022-06-14 10:11   ` Tian, Kevin
2022-06-15 20:31   ` Kirti Wankhede
2022-06-23 21:32   ` Jason Gunthorpe
2022-06-14  4:54 ` [PATCH 11/13] vfio/mdev: consolidate all the available_instance " Christoph Hellwig
2022-06-14 10:14   ` Tian, Kevin
2022-06-14 10:29     ` Tian, Kevin
2022-06-15 20:37   ` Kirti Wankhede
2022-06-23 21:36   ` Jason Gunthorpe
2022-06-14  4:54 ` [PATCH 12/13] vfio/mdev: consolidate all the description " Christoph Hellwig
2022-06-15 20:52   ` Kirti Wankhede
2022-06-23 21:37   ` Jason Gunthorpe
2022-06-14  4:54 ` [PATCH 13/13] vfio/mdev: add mdev available instance checking to the core Christoph Hellwig
2022-06-14 10:32   ` Tian, Kevin
2022-06-15  6:29     ` Christoph Hellwig
2022-06-14  5:03 ` simplify the mdev interface v2 Yi Liu
2022-06-14  5:17   ` Christoph Hellwig
2022-06-14  5:30     ` Yi Liu
2022-06-14  5:44       ` Christoph Hellwig
2022-06-14  5:47         ` Yi Liu
2022-06-28  5:14 simplify the mdev interface v3 Christoph Hellwig
2022-06-28  5:14 ` [PATCH 09/13] vfio/mdev: consolidate all the device_api sysfs into the core code Christoph Hellwig

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=6599f9b0-c669-d9a0-91f9-e8d967b9ba7d@nvidia.com \
    --to=kwankhede@nvidia.com \
    --cc=akrowiak@linux.ibm.com \
    --cc=alex.williamson@redhat.com \
    --cc=cjia@nvidia.com \
    --cc=dnigam@nvidia.com \
    --cc=farman@linux.ibm.com \
    --cc=hch@lst.de \
    --cc=intel-gvt-dev@lists.freedesktop.org \
    --cc=jgg@nvidia.com \
    --cc=jjherne@linux.ibm.com \
    --cc=kvm@vger.kernel.org \
    --cc=linux-s390@vger.kernel.org \
    --cc=mjrosato@linux.ibm.com \
    --cc=pasic@linux.ibm.com \
    --cc=targupta@nvidia.com \
    --cc=zhenyuw@linux.intel.com \
    --cc=zhi.a.wang@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.