From: Mike Christie <michael.christie@oracle.com>
To: Christoph Hellwig <hch@lst.de>
Cc: bvanassche@acm.org, martin.petersen@oracle.com,
linux-scsi@vger.kernel.org,
james.bottomley@hansenpartnership.com,
linux-block@vger.kernel.org, dm-devel@redhat.com,
snitzer@kernel.org, axboe@kernel.dk,
linux-nvme@lists.infradead.org, chaitanyak@nvidia.com,
kbusch@kernel.org, target-devel@vger.kernel.org
Subject: Re: [PATCH v3 12/19] block,nvme,scsi,dm: Add blk_status to pr_ops callouts
Date: Sat, 5 Nov 2022 13:36:18 -0500 [thread overview]
Message-ID: <7762a877-9a5f-4dee-6dfc-c2e1fcb8a66a@oracle.com> (raw)
In-Reply-To: <20221101101511.GA13304@lst.de>
On 11/1/22 5:15 AM, Christoph Hellwig wrote:
> On Sun, Oct 30, 2022 at 06:05:35PM -0500, Mike Christie wrote:
>> The problem I hit is that in the ioctl code I then have to do:
>>
>> @@ -269,7 +270,14 @@ static int blkdev_pr_register(struct block_device *bdev,
>>
>> if (reg.flags & ~PR_FL_IGNORE_KEY)
>> return -EOPNOTSUPP;
>> - return ops->pr_register(bdev, reg.old_key, reg.new_key, reg.flags);
>> + ret = ops->pr_register(bdev, reg.old_key, reg.new_key, reg.flags);
>> + if (ret == -EBADE) {
>> + if (bdev_is_nvme(bdev))
>> + ret = NVME_SC_RESERVATION_CONFLICT;
>> + else if (bdev_is_scsi(bdev)
>> + ret = SAM_STAT_RESERVATION_CONFLICT;
>> + }
>> + return ret;
>
> Eww. We should have never leaked protocol specific values out to
> userspace. This is an original bug I introduceѕ, so all blame is on me.
>
> I suspect the right way to fix is is to keep the numeric value of
> SAM_STAT_RESERVATION_CONFLICT and give it a new constant exposed in
> the uapi header, assuming that SCSI is the thing people actually
> used the PR API for, and nvme was just an nice little add-on.
>
Do you mean just doing this:
diff --git a/drivers/nvme/host/pr.c b/drivers/nvme/host/pr.c
index 727123c611e6..6ac70514170d 100644
--- a/drivers/nvme/host/pr.c
+++ b/drivers/nvme/host/pr.c
@@ -72,12 +72,17 @@ static int nvme_send_ns_pr_command(struct nvme_ns *ns, struct nvme_command *c,
static int nvme_send_pr_command(struct block_device *bdev,
struct nvme_command *c, void *data, unsigned int data_len)
{
+ int ret;
+
if (IS_ENABLED(CONFIG_NVME_MULTIPATH) &&
bdev->bd_disk->fops == &nvme_ns_head_ops)
- return nvme_send_ns_head_pr_command(bdev, c, data, data_len);
+ ret = nvme_send_ns_head_pr_command(bdev, c, data, data_len);
else
- return nvme_send_ns_pr_command(bdev->bd_disk->private_data, c,
- data, data_len);
+ ret = nvme_send_ns_pr_command(bdev->bd_disk->private_data, c,
+ data, data_len);
+ if (ret == NVME_SC_RESERVATION_CONFLICT)
+ ret = PR_STS_RESERVATION_CONFLICT;
+ return ret;
}
static int nvme_pr_command(struct block_device *bdev, u32 cdw10,
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index c0a614efcfce..c7621d8ffa51 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -1840,7 +1840,8 @@ static int sd_pr_out_command(struct block_device *bdev, u8 sa,
scsi_sense_valid(&sshdr)) {
sdev_printk(KERN_INFO, sdev, "PR command failed: %d\n", result);
scsi_print_sense_hdr(sdev, NULL, &sshdr);
- }
+ } else if (__get_status_byte(result) == SAM_STAT_RESERVATION_CONFLICT)
+ result = PR_STS_RESERVATION_CONFLICT;
return result;
}
diff --git a/include/uapi/linux/pr.h b/include/uapi/linux/pr.h
index ccc78cbf1221..7a637f9e5b49 100644
--- a/include/uapi/linux/pr.h
+++ b/include/uapi/linux/pr.h
@@ -13,6 +13,15 @@ enum pr_type {
PR_EXCLUSIVE_ACCESS_ALL_REGS = 6,
};
+enum pr_status {
+ PR_STS_SUCCESS = 0x0,
+ /*
+ * The error codes are based on SCSI, because it was the primary user
+ * and had userspace users.
+ */
+ PR_STS_RESERVATION_CONFLICT = 0x18,
+};
+
struct pr_reservation {
__u64 key;
__u32 type;
---------------------------------------------------------------------------
Or we could add a new flag and make it nicer for the user in the future,
but also uglier for the drivers but a little less uglier than adding the
blk_sts field to the calls:
diff --git a/block/ioctl.c b/block/ioctl.c
index 60121e89052b..cae58f57ea13 100644
--- a/block/ioctl.c
+++ b/block/ioctl.c
@@ -269,7 +269,8 @@ static int blkdev_pr_register(struct block_device *bdev,
if (reg.flags & ~PR_FL_IGNORE_KEY)
return -EOPNOTSUPP;
- return ops->pr_register(bdev, reg.old_key, reg.new_key, reg.flags);
+ return ops->pr_register(bdev, reg.old_key, reg.new_key, reg.flags,
+ reg.flags & PR_FL_PR_STAT);
}
static int blkdev_pr_reserve(struct block_device *bdev,
@@ -287,7 +288,8 @@ static int blkdev_pr_reserve(struct block_device *bdev,
if (rsv.flags & ~PR_FL_IGNORE_KEY)
return -EOPNOTSUPP;
- return ops->pr_reserve(bdev, rsv.key, rsv.type, rsv.flags);
+ return ops->pr_reserve(bdev, rsv.key, rsv.type, rsv.flags,
+ rsv.flags & PR_FL_PR_STAT)
}
static int blkdev_pr_release(struct block_device *bdev,
@@ -305,7 +307,8 @@ static int blkdev_pr_release(struct block_device *bdev,
if (rsv.flags)
return -EOPNOTSUPP;
- return ops->pr_release(bdev, rsv.key, rsv.type);
+ return ops->pr_release(bdev, rsv.key, rsv.type,
+ rsv.flags & PR_FL_PR_STAT);
}
static int blkdev_pr_preempt(struct block_device *bdev,
@@ -323,7 +326,8 @@ static int blkdev_pr_preempt(struct block_device *bdev,
if (p.flags)
return -EOPNOTSUPP;
- return ops->pr_preempt(bdev, p.old_key, p.new_key, p.type, abort);
+ return ops->pr_preempt(bdev, p.old_key, p.new_key, p.type, abort,
+ p.flags & PR_FL_PR_STAT)
}
static int blkdev_pr_clear(struct block_device *bdev,
@@ -341,7 +345,7 @@ static int blkdev_pr_clear(struct block_device *bdev,
if (c.flags)
return -EOPNOTSUPP;
- return ops->pr_clear(bdev, c.key);
+ return ops->pr_clear(bdev, c.key, c.flags & PR_FL_PR_STAT);
}
static int blkdev_flushbuf(struct block_device *bdev, fmode_t mode,
diff --git a/drivers/nvme/host/pr.c b/drivers/nvme/host/pr.c
index 727123c611e6..7c317b646cde 100644
--- a/drivers/nvme/host/pr.c
+++ b/drivers/nvme/host/pr.c
@@ -70,18 +70,44 @@ static int nvme_send_ns_pr_command(struct nvme_ns *ns, struct nvme_command *c,
}
static int nvme_send_pr_command(struct block_device *bdev,
- struct nvme_command *c, void *data, unsigned int data_len)
+ struct nvme_command *c, void *data, unsigned int data_len,
+ bool use_pr_sts)
{
+ int ret;
+
if (IS_ENABLED(CONFIG_NVME_MULTIPATH) &&
bdev->bd_disk->fops == &nvme_ns_head_ops)
- return nvme_send_ns_head_pr_command(bdev, c, data, data_len);
+ ret = nvme_send_ns_head_pr_command(bdev, c, data, data_len);
else
- return nvme_send_ns_pr_command(bdev->bd_disk->private_data, c,
- data, data_len);
+ ret = nvme_send_ns_pr_command(bdev->bd_disk->private_data, c,
+ data, data_len);
+ if (!ret || ret < 0 || (ret > 0 && !use_pr_sts))
+ return ret;
+
+ switch (ret) {
+ case NVME_SC_RESERVATION_CONFLICT:
+ ret = PR_STS_RESERVATION_CONFLICT;
+ break;
+ case NVME_SC_HOST_PATH_ERROR:
+ ret = PR_STS_PATH_FAILURE;
+ break
+ case NVME_SC_BAD_ATTRIBUTES:
+ case NVME_SC_ONCS_NOT_SUPPORTED:
+ case NVME_SC_INVALID_OPCODE:
+ case NVME_SC_INVALID_FIELD:
+ case NVME_SC_INVALID_NS:
+ ret = PR_STS_INVALID_OP;
+ break;
+ default:
+ ret = PR_STS_IOERR;
+ break;
+ }
+
+ return ret;
}
static int nvme_pr_command(struct block_device *bdev, u32 cdw10,
- u64 key, u64 sa_key, u8 op)
+ u64 key, u64 sa_key, u8 op, bool use_pr_sts)
{
struct nvme_command c = { };
u8 data[16] = { 0, };
@@ -92,11 +118,11 @@ static int nvme_pr_command(struct block_device *bdev, u32 cdw10,
c.common.opcode = op;
c.common.cdw10 = cpu_to_le32(cdw10);
- return nvme_send_pr_command(bdev, &c, data, sizeof(data));
+ return nvme_send_pr_command(bdev, &c, data, sizeof(data), use_pr_sts);
}
static int nvme_pr_register(struct block_device *bdev, u64 old,
- u64 new, unsigned flags)
+ u64 new, unsigned flags, bool use_pr_sts)
{
u32 cdw10;
@@ -106,11 +132,12 @@ static int nvme_pr_register(struct block_device *bdev, u64 old,
cdw10 = old ? 2 : 0;
cdw10 |= (flags & PR_FL_IGNORE_KEY) ? 1 << 3 : 0;
cdw10 |= (1 << 30) | (1 << 31); /* PTPL=1 */
- return nvme_pr_command(bdev, cdw10, old, new, nvme_cmd_resv_register);
+ return nvme_pr_command(bdev, cdw10, old, new, nvme_cmd_resv_register,
+ use_pr_sts);
}
static int nvme_pr_reserve(struct block_device *bdev, u64 key,
- enum pr_type type, unsigned flags)
+ enum pr_type type, unsigned flags, bool use_pr_sts)
{
u32 cdw10;
@@ -119,29 +146,34 @@ static int nvme_pr_reserve(struct block_device *bdev, u64 key,
cdw10 = nvme_pr_type_from_blk(type) << 8;
cdw10 |= ((flags & PR_FL_IGNORE_KEY) ? 1 << 3 : 0);
- return nvme_pr_command(bdev, cdw10, key, 0, nvme_cmd_resv_acquire);
+ return nvme_pr_command(bdev, cdw10, key, 0, nvme_cmd_resv_acquire,
+ use_pr_sts);
}
static int nvme_pr_preempt(struct block_device *bdev, u64 old, u64 new,
- enum pr_type type, bool abort)
+ enum pr_type type, bool abort, bool use_pr_sts)
{
u32 cdw10 = nvme_pr_type_from_blk(type) << 8 | (abort ? 2 : 1);
- return nvme_pr_command(bdev, cdw10, old, new, nvme_cmd_resv_acquire);
+ return nvme_pr_command(bdev, cdw10, old, new, nvme_cmd_resv_acquire,
+ use_pr_sts);
}
-static int nvme_pr_clear(struct block_device *bdev, u64 key)
+static int nvme_pr_clear(struct block_device *bdev, u64 key, bool use_pr_sts)
{
u32 cdw10 = 1 | (key ? 0 : 1 << 3);
- return nvme_pr_command(bdev, cdw10, key, 0, nvme_cmd_resv_release);
+ return nvme_pr_command(bdev, cdw10, key, 0, nvme_cmd_resv_release,
+ use_pr_sts);
}
-static int nvme_pr_release(struct block_device *bdev, u64 key, enum pr_type type)
+static int nvme_pr_release(struct block_device *bdev, u64 key,
+ enum pr_type type, bool use_pr_sts)
{
u32 cdw10 = nvme_pr_type_from_blk(type) << 8 | (key ? 0 : 1 << 3);
- return nvme_pr_command(bdev, cdw10, key, 0, nvme_cmd_resv_release);
+ return nvme_pr_command(bdev, cdw10, key, 0, nvme_cmd_resv_release,
+ use_pr_sts);
}
static int nvme_pr_resv_report(struct block_device *bdev, void *data,
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index c0a614efcfce..46393bdd7427 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -1797,7 +1797,8 @@ static int sd_pr_read_reservation(struct block_device *bdev,
}
static int sd_pr_out_command(struct block_device *bdev, u8 sa,
- u64 key, u64 sa_key, enum scsi_pr_type type, u8 flags)
+ u64 key, u64 sa_key, enum scsi_pr_type type, u8 flags,
+ bool use_pr_sts)
{
struct scsi_disk *sdkp = scsi_disk(bdev->bd_disk);
struct scsi_device *sdev = sdkp->device;
@@ -1842,44 +1843,74 @@ static int sd_pr_out_command(struct block_device *bdev, u8 sa,
scsi_print_sense_hdr(sdev, NULL, &sshdr);
}
+ if (!result || result < 0 || (result > 0 && !use_pr_sts))
+ return result;
+
+ result = PR_STS_IOERR;
+
+ switch host_byte(result) {
+ case DID_TRANSPORT_FAILFAST:
+ case DID_TRANSPORT_MARGINAL:
+ case DID_TRANSPORT_DISRUPTED:
+ result = PR_STS_PATH_FAILURE;
+ goto done;
+ }
+
+ switch (__get_status_byte(result)) {
+ case SAM_STAT_RESERVATION_CONFLICT:
+ result = PR_STS_RESERVATION_CONFLICT;
+ goto done;
+ case SAM_STAT_CHECK_CONDITION:
+ if (!scsi_sense_valid(&sshdr))
+ goto done;
+
+ if (sshdr.sense_key == ILLEGAL_REQUEST &&
+ (sshdr.asc == 0x26 || sshdr.asc == 0x24)) {
+ result = PR_STS_INVALID_OP;
+ goto done;
+ }
+ }
+
+done:
return result;
}
static int sd_pr_register(struct block_device *bdev, u64 old_key, u64 new_key,
- u32 flags)
+ u32 flags, bool use_pr_sts)
{
if (flags & ~PR_FL_IGNORE_KEY)
return -EOPNOTSUPP;
return sd_pr_out_command(bdev, (flags & PR_FL_IGNORE_KEY) ? 0x06 : 0x00,
- old_key, new_key, 0,
- (1 << 0) /* APTPL */);
+ old_key, new_key, 0, (1 << 0) /* APTPL */,
+ use_pr_sts);
}
static int sd_pr_reserve(struct block_device *bdev, u64 key, enum pr_type type,
- u32 flags)
+ u32 flags, bool use_pr_sts)
{
if (flags)
return -EOPNOTSUPP;
return sd_pr_out_command(bdev, 0x01, key, 0,
- block_pr_type_to_scsi(type), 0);
+ block_pr_type_to_scsi(type), 0, use_pr_sts)
}
-static int sd_pr_release(struct block_device *bdev, u64 key, enum pr_type type)
+static int sd_pr_release(struct block_device *bdev, u64 key, enum pr_type type,
+ bool use_pr_sts)
{
return sd_pr_out_command(bdev, 0x02, key, 0,
- block_pr_type_to_scsi(type), 0);
+ block_pr_type_to_scsi(type), 0, use_pr_sts);
}
static int sd_pr_preempt(struct block_device *bdev, u64 old_key, u64 new_key,
- enum pr_type type, bool abort)
+ enum pr_type type, bool abort, bool use_pr_sts)
{
return sd_pr_out_command(bdev, abort ? 0x05 : 0x04, old_key, new_key,
- block_pr_type_to_scsi(type), 0);
+ block_pr_type_to_scsi(type), 0, use_pr_sts);
}
-static int sd_pr_clear(struct block_device *bdev, u64 key)
+static int sd_pr_clear(struct block_device *bdev, u64 key, bool use_pr_sts)
{
- return sd_pr_out_command(bdev, 0x03, key, 0, 0, 0);
+ return sd_pr_out_command(bdev, 0x03, key, 0, 0, 0, use_pr_sts);
}
static const struct pr_ops sd_pr_ops = {
diff --git a/include/linux/pr.h b/include/linux/pr.h
index 3003daec28a5..51e03e73a87f 100644
--- a/include/linux/pr.h
+++ b/include/linux/pr.h
@@ -18,14 +18,14 @@ struct pr_held_reservation {
struct pr_ops {
int (*pr_register)(struct block_device *bdev, u64 old_key, u64 new_key,
- u32 flags);
+ u32 flags, bool use_pr_sts);
int (*pr_reserve)(struct block_device *bdev, u64 key,
- enum pr_type type, u32 flags);
+ enum pr_type type, u32 flags, bool use_pr_sts);
int (*pr_release)(struct block_device *bdev, u64 key,
- enum pr_type type);
+ enum pr_type type, bool use_pr_sts);
int (*pr_preempt)(struct block_device *bdev, u64 old_key, u64 new_key,
- enum pr_type type, bool abort);
- int (*pr_clear)(struct block_device *bdev, u64 key);
+ enum pr_type type, bool abort, bool use_pr_sts);
+ int (*pr_clear)(struct block_device *bdev, u64 key, bool use_pr_sts);
/*
* pr_read_keys - Read the registered keys and return them in the
* pr_keys->keys array. The keys array will have been allocated at the
diff --git a/include/uapi/linux/pr.h b/include/uapi/linux/pr.h
index ccc78cbf1221..ac8f7fc404ff 100644
--- a/include/uapi/linux/pr.h
+++ b/include/uapi/linux/pr.h
@@ -13,6 +13,14 @@ enum pr_type {
PR_EXCLUSIVE_ACCESS_ALL_REGS = 6,
};
+enum pr_status {
+ PR_STS_SUCCESS,
+ PR_STS_IOERR,
+ PR_STS_RESERVATION_CONFLICT,
+ PR_STS_PATH_FAILURE,
+ PR_STS_INVALID_OP,
+};
+
struct pr_reservation {
__u64 key;
__u32 type;
@@ -40,6 +48,7 @@ struct pr_clear {
};
#define PR_FL_IGNORE_KEY (1 << 0) /* ignore existing key */
+#define PR_FL_PR_STAT (1 << 1) /* Convert device errors to pr_status */
#define IOC_PR_REGISTER _IOW('p', 200, struct pr_registration)
#define IOC_PR_RESERVE _IOW('p', 201, struct pr_reservation)
Bart, if this is what you were suggesting I misunderstood you. I thought you wanted to
only pass the new code in the kernel so that's why I was saying we still have the problem
of converting the error back when passing it back to userspace.
next prev parent reply other threads:[~2022-11-05 18:36 UTC|newest]
Thread overview: 57+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-10-26 23:19 [PATCH v3 00/19] Use block pr_ops in LIO Mike Christie
2022-10-26 23:19 ` [PATCH v3 01/19] block: Add PR callouts for read keys and reservation Mike Christie
2022-11-02 22:50 ` Bart Van Assche
2022-11-03 1:54 ` Mike Christie
2022-11-02 22:53 ` Bart Van Assche
2022-11-03 2:25 ` Mike Christie
2022-10-26 23:19 ` [PATCH v3 02/19] scsi: Rename sd_pr_command Mike Christie
2022-11-01 5:33 ` Chaitanya Kulkarni
2022-10-26 23:19 ` [PATCH v3 03/19] scsi: Move sd_pr_type to header to share Mike Christie
2022-11-01 5:43 ` Chaitanya Kulkarni
2022-11-01 16:43 ` Mike Christie
2022-11-02 22:47 ` Bart Van Assche
2022-11-03 2:13 ` Mike Christie
2022-11-03 18:14 ` Bart Van Assche
2022-10-26 23:19 ` [PATCH v3 04/19] scsi: Add support for block PR read keys/reservation Mike Christie
2022-10-27 6:08 ` kernel test robot
2022-10-27 7:59 ` kernel test robot
2022-10-27 10:41 ` kernel test robot
2022-11-01 5:45 ` Chaitanya Kulkarni
2022-11-02 22:54 ` Bart Van Assche
2022-10-26 23:19 ` [PATCH v3 05/19] dm: " Mike Christie
2022-10-26 23:19 ` [PATCH v3 06/19] nvme: Fix reservation status related structs Mike Christie
2022-10-27 17:04 ` Keith Busch
2022-10-26 23:19 ` [PATCH v3 07/19] nvme: Don't hardcode the data len for pr commands Mike Christie
2022-10-27 17:05 ` Keith Busch
2022-11-01 5:29 ` Chaitanya Kulkarni
2022-10-26 23:19 ` [PATCH v3 08/19] nvme: Move pr code to it's own file Mike Christie
2022-10-27 17:06 ` Keith Busch
2022-10-28 16:06 ` Mike Christie
2022-10-28 16:38 ` Keith Busch
2022-10-30 8:06 ` Christoph Hellwig
2022-11-01 5:25 ` Chaitanya Kulkarni
2022-10-26 23:19 ` [PATCH v3 09/19] nvme: Add pr_ops read_keys support Mike Christie
2022-10-30 8:17 ` Christoph Hellwig
2022-10-30 20:47 ` Mike Christie
2022-10-26 23:19 ` [PATCH v3 10/19] nvme: Move NVMe and Block PR types to an array Mike Christie
2022-10-27 15:18 ` Keith Busch
2022-10-27 17:06 ` Mike Christie
2022-10-27 17:13 ` michael.christie
2022-10-27 17:16 ` Keith Busch
2022-10-28 16:05 ` Mike Christie
2022-10-26 23:19 ` [PATCH v3 11/19] nvme: Add pr_ops read_reservation support Mike Christie
2022-10-30 8:18 ` Christoph Hellwig
2022-10-30 20:54 ` Mike Christie
2022-10-26 23:19 ` [PATCH v3 12/19] block,nvme,scsi,dm: Add blk_status to pr_ops callouts Mike Christie
2022-10-30 8:20 ` Christoph Hellwig
2022-10-30 23:05 ` Mike Christie
2022-11-01 10:15 ` Christoph Hellwig
2022-11-05 18:36 ` Mike Christie [this message]
2022-11-07 9:16 ` Christoph Hellwig
2022-10-26 23:19 ` [PATCH v3 13/19] nvme: Have NVMe pr_ops return a blk_status_t Mike Christie
2022-10-26 23:19 ` [PATCH v3 14/19] scsi: Export scsi_result_to_blk_status Mike Christie
2022-10-26 23:19 ` [PATCH v3 15/19] scsi: Have sd pr_ops return a blk_status_t Mike Christie
2022-10-26 23:19 ` [PATCH v3 16/19] scsi: target: Rename sbc_ops to exec_cmd_ops Mike Christie
2022-10-26 23:19 ` [PATCH v3 17/19] scsi: target: Allow backends to hook into PR handling Mike Christie
2022-10-26 23:19 ` [PATCH v3 18/19] scsi: target: Don't support SCSI-2 RESERVE/RELEASE Mike Christie
2022-10-26 23:19 ` [PATCH v3 19/19] scsi: target: Add block PR support to iblock Mike Christie
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=7762a877-9a5f-4dee-6dfc-c2e1fcb8a66a@oracle.com \
--to=michael.christie@oracle.com \
--cc=axboe@kernel.dk \
--cc=bvanassche@acm.org \
--cc=chaitanyak@nvidia.com \
--cc=dm-devel@redhat.com \
--cc=hch@lst.de \
--cc=james.bottomley@hansenpartnership.com \
--cc=kbusch@kernel.org \
--cc=linux-block@vger.kernel.org \
--cc=linux-nvme@lists.infradead.org \
--cc=linux-scsi@vger.kernel.org \
--cc=martin.petersen@oracle.com \
--cc=snitzer@kernel.org \
--cc=target-devel@vger.kernel.org \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox