linux-block.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/3] block: expose 'read_keys' and 'read_reservation' PR callbacks
@ 2025-06-03 10:04 Hannes Reinecke
  2025-06-03 10:04 ` [PATCH 1/3] block: add 'read_keys' persistent reservation ioctl Hannes Reinecke
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Hannes Reinecke @ 2025-06-03 10:04 UTC (permalink / raw)
  To: Jens Axboe
  Cc: Christoph Hellwig, Martin K. Petersen, linux-block, linux-scsi,
	James Bottomley, Hannes Reinecke

Hi all,

the generic persistent reservation framework already has callbacks for 'read_keys'
and 'read_reservation', but these callbacks are not exposed via ioctls (unlike
the other callbacks). As we need this information if we want to work with persistent
reservations reliably add two new persistent reservation ioctls 'IOC_PR_READ_KEYS'
and 'IOC_PR_READ_RESV' to expose this information to userspace.

As usual, comments and reviews are welcome.

Hannes Reinecke (3):
  block: add 'read_keys' persistent reservation ioctl
  block: add 'read_reservation' persistent reservation ioctl
  scsi: return PR generation if no reservation is held

 block/ioctl.c           | 61 +++++++++++++++++++++++++++++++++++++++++
 drivers/scsi/sd.c       | 10 +++++--
 include/linux/pr.h      | 12 --------
 include/uapi/linux/pr.h | 14 ++++++++++
 4 files changed, 82 insertions(+), 15 deletions(-)

-- 
2.35.3


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH 1/3] block: add 'read_keys' persistent reservation ioctl
  2025-06-03 10:04 [PATCH 0/3] block: expose 'read_keys' and 'read_reservation' PR callbacks Hannes Reinecke
@ 2025-06-03 10:04 ` Hannes Reinecke
  2025-06-03 10:04 ` [PATCH 2/3] block: add 'read_reservation' " Hannes Reinecke
  2025-06-03 10:04 ` [PATCH 3/3] scsi: return PR generation if no reservation is held Hannes Reinecke
  2 siblings, 0 replies; 4+ messages in thread
From: Hannes Reinecke @ 2025-06-03 10:04 UTC (permalink / raw)
  To: Jens Axboe
  Cc: Christoph Hellwig, Martin K. Petersen, linux-block, linux-scsi,
	James Bottomley, Hannes Reinecke

The persistent reservation operations already have a callback for
'read_keys', but this is not accessible via an ioctl (unlike the
other callbacks). So add a new persistent reservation ioctl 'READ_KEYS'
to allow userspace to use this functionality.

Signed-off-by: Hannes Reinecke <hare@kernel.org>
---
 block/ioctl.c           | 39 +++++++++++++++++++++++++++++++++++++++
 include/linux/pr.h      |  6 ------
 include/uapi/linux/pr.h |  7 +++++++
 3 files changed, 46 insertions(+), 6 deletions(-)

diff --git a/block/ioctl.c b/block/ioctl.c
index e472cc1030c6..71f87974e044 100644
--- a/block/ioctl.c
+++ b/block/ioctl.c
@@ -422,6 +422,43 @@ static int blkdev_pr_clear(struct block_device *bdev, blk_mode_t mode,
 	return ops->pr_clear(bdev, c.key);
 }
 
+static int blkdev_pr_read_keys(struct block_device *bdev, blk_mode_t mode,
+		struct pr_keys __user *arg)
+{
+	const struct pr_ops *ops = bdev->bd_disk->fops->pr_ops;
+	struct pr_keys k_in, *k_out;
+	size_t k_len;
+	int ret, num_keys;
+
+	if (!blkdev_pr_allowed(bdev, mode))
+		return -EPERM;
+	if (!ops || !ops->pr_read_keys)
+		return -EOPNOTSUPP;
+
+	if (copy_from_user(&k_in, arg, sizeof(k_in)))
+		return -EFAULT;
+
+	num_keys = k_in.num_keys;
+	k_out = kzalloc(sizeof(struct pr_keys) + num_keys * sizeof(u64),
+			GFP_KERNEL);
+	if (!k_out)
+		return -ENOMEM;
+
+	k_out->num_keys = num_keys;
+	ret = ops->pr_read_keys(bdev, k_out);
+	if (ret) {
+		kfree(k_out);
+		return ret;
+	}
+
+	k_len = sizeof(k_in) + num_keys * sizeof(u64);
+	if (copy_to_user(arg, k_out, k_len))
+		ret = -EFAULT;
+
+	kfree(k_out);
+	return ret;
+}
+
 static int blkdev_flushbuf(struct block_device *bdev, unsigned cmd,
 		unsigned long arg)
 {
@@ -643,6 +680,8 @@ static int blkdev_common_ioctl(struct block_device *bdev, blk_mode_t mode,
 		return blkdev_pr_preempt(bdev, mode, argp, true);
 	case IOC_PR_CLEAR:
 		return blkdev_pr_clear(bdev, mode, argp);
+	case IOC_PR_READ_KEYS:
+		return blkdev_pr_read_keys(bdev, mode, argp);
 	default:
 		return -ENOIOCTLCMD;
 	}
diff --git a/include/linux/pr.h b/include/linux/pr.h
index 3003daec28a5..6f293c3e27a1 100644
--- a/include/linux/pr.h
+++ b/include/linux/pr.h
@@ -4,12 +4,6 @@
 
 #include <uapi/linux/pr.h>
 
-struct pr_keys {
-	u32	generation;
-	u32	num_keys;
-	u64	keys[];
-};
-
 struct pr_held_reservation {
 	u64		key;
 	u32		generation;
diff --git a/include/uapi/linux/pr.h b/include/uapi/linux/pr.h
index d8126415966f..6e0d91d43c54 100644
--- a/include/uapi/linux/pr.h
+++ b/include/uapi/linux/pr.h
@@ -56,6 +56,12 @@ struct pr_clear {
 	__u32	__pad;
 };
 
+struct pr_keys {
+	__u32	generation;
+	__u32	num_keys;
+	__u64	keys[];
+};
+
 #define PR_FL_IGNORE_KEY	(1 << 0)	/* ignore existing key */
 
 #define IOC_PR_REGISTER		_IOW('p', 200, struct pr_registration)
@@ -64,5 +70,6 @@ struct pr_clear {
 #define IOC_PR_PREEMPT		_IOW('p', 203, struct pr_preempt)
 #define IOC_PR_PREEMPT_ABORT	_IOW('p', 204, struct pr_preempt)
 #define IOC_PR_CLEAR		_IOW('p', 205, struct pr_clear)
+#define IOC_PR_READ_KEYS	_IOWR('p', 206, struct pr_keys)
 
 #endif /* _UAPI_PR_H */
-- 
2.35.3


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH 2/3] block: add 'read_reservation' persistent reservation ioctl
  2025-06-03 10:04 [PATCH 0/3] block: expose 'read_keys' and 'read_reservation' PR callbacks Hannes Reinecke
  2025-06-03 10:04 ` [PATCH 1/3] block: add 'read_keys' persistent reservation ioctl Hannes Reinecke
@ 2025-06-03 10:04 ` Hannes Reinecke
  2025-06-03 10:04 ` [PATCH 3/3] scsi: return PR generation if no reservation is held Hannes Reinecke
  2 siblings, 0 replies; 4+ messages in thread
From: Hannes Reinecke @ 2025-06-03 10:04 UTC (permalink / raw)
  To: Jens Axboe
  Cc: Christoph Hellwig, Martin K. Petersen, linux-block, linux-scsi,
	James Bottomley, Hannes Reinecke

The persistent reservation operations already have a callback for
'read_reservation', but this is not accessible via an ioctl (unlike the
other callbacks). So add a new persistent reservation ioctl 'READ_RESV'
to allow userspace to use this functionality.

Signed-off-by: Hannes Reinecke <hare@kernel.org>
---
 block/ioctl.c           | 22 ++++++++++++++++++++++
 include/linux/pr.h      |  6 ------
 include/uapi/linux/pr.h |  7 +++++++
 3 files changed, 29 insertions(+), 6 deletions(-)

diff --git a/block/ioctl.c b/block/ioctl.c
index 71f87974e044..3612352a1d83 100644
--- a/block/ioctl.c
+++ b/block/ioctl.c
@@ -459,6 +459,26 @@ static int blkdev_pr_read_keys(struct block_device *bdev, blk_mode_t mode,
 	return ret;
 }
 
+static int blkdev_pr_read_reservation(struct block_device *bdev,
+		blk_mode_t mode, struct pr_held_reservation __user *arg)
+{
+	const struct pr_ops *ops = bdev->bd_disk->fops->pr_ops;
+	struct pr_held_reservation r;
+	int ret;
+
+	if (!blkdev_pr_allowed(bdev, mode))
+		return -EPERM;
+	if (!ops || !ops->pr_read_reservation)
+		return -EOPNOTSUPP;
+
+	ret = ops->pr_read_reservation(bdev, &r);
+	if (ret)
+		return ret;
+	if (copy_to_user(arg, &r, sizeof(r)))
+		return -EFAULT;
+	return 0;
+}
+
 static int blkdev_flushbuf(struct block_device *bdev, unsigned cmd,
 		unsigned long arg)
 {
@@ -682,6 +702,8 @@ static int blkdev_common_ioctl(struct block_device *bdev, blk_mode_t mode,
 		return blkdev_pr_clear(bdev, mode, argp);
 	case IOC_PR_READ_KEYS:
 		return blkdev_pr_read_keys(bdev, mode, argp);
+	case IOC_PR_READ_RESV:
+		return blkdev_pr_read_reservation(bdev, mode, argp);
 	default:
 		return -ENOIOCTLCMD;
 	}
diff --git a/include/linux/pr.h b/include/linux/pr.h
index 6f293c3e27a1..e3ccfbd9dfba 100644
--- a/include/linux/pr.h
+++ b/include/linux/pr.h
@@ -4,12 +4,6 @@
 
 #include <uapi/linux/pr.h>
 
-struct pr_held_reservation {
-	u64		key;
-	u32		generation;
-	enum pr_type	type;
-};
-
 struct pr_ops {
 	int (*pr_register)(struct block_device *bdev, u64 old_key, u64 new_key,
 			u32 flags);
diff --git a/include/uapi/linux/pr.h b/include/uapi/linux/pr.h
index 6e0d91d43c54..20198c7e68e8 100644
--- a/include/uapi/linux/pr.h
+++ b/include/uapi/linux/pr.h
@@ -62,6 +62,12 @@ struct pr_keys {
 	__u64	keys[];
 };
 
+struct pr_held_reservation {
+	__u64		key;
+	__u32		generation;
+	__u32		type;
+};
+
 #define PR_FL_IGNORE_KEY	(1 << 0)	/* ignore existing key */
 
 #define IOC_PR_REGISTER		_IOW('p', 200, struct pr_registration)
@@ -71,5 +77,6 @@ struct pr_keys {
 #define IOC_PR_PREEMPT_ABORT	_IOW('p', 204, struct pr_preempt)
 #define IOC_PR_CLEAR		_IOW('p', 205, struct pr_clear)
 #define IOC_PR_READ_KEYS	_IOWR('p', 206, struct pr_keys)
+#define IOC_PR_READ_RESV	_IOWR('p', 207, struct pr_held_reservation)
 
 #endif /* _UAPI_PR_H */
-- 
2.35.3


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH 3/3] scsi: return PR generation if no reservation is held
  2025-06-03 10:04 [PATCH 0/3] block: expose 'read_keys' and 'read_reservation' PR callbacks Hannes Reinecke
  2025-06-03 10:04 ` [PATCH 1/3] block: add 'read_keys' persistent reservation ioctl Hannes Reinecke
  2025-06-03 10:04 ` [PATCH 2/3] block: add 'read_reservation' " Hannes Reinecke
@ 2025-06-03 10:04 ` Hannes Reinecke
  2 siblings, 0 replies; 4+ messages in thread
From: Hannes Reinecke @ 2025-06-03 10:04 UTC (permalink / raw)
  To: Jens Axboe
  Cc: Christoph Hellwig, Martin K. Petersen, linux-block, linux-scsi,
	James Bottomley, Hannes Reinecke

For READ RESERVATION the PRgeneration value is always present, even
if no reservations are held.

Signed-off-by: Hannes Reinecke <hare@kernel.org>
---
 drivers/scsi/sd.c | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 950d8c9fb884..daa61feaf441 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -2008,9 +2008,13 @@ static int sd_pr_read_reservation(struct block_device *bdev,
 	if (result)
 		return result;
 
+	rsv->generation = get_unaligned_be32(&data[0]);
+	rsv->type = 0;
 	len = get_unaligned_be32(&data[4]);
-	if (!len)
+	if (!len) {
+		rsv->key = 0;
 		return 0;
+	}
 
 	/* Make sure we have at least the key and type */
 	if (len < 14) {
@@ -2020,9 +2024,9 @@ static int sd_pr_read_reservation(struct block_device *bdev,
 		return -EINVAL;
 	}
 
-	rsv->generation = get_unaligned_be32(&data[0]);
 	rsv->key = get_unaligned_be64(&data[8]);
-	rsv->type = scsi_pr_type_to_block(data[21] & 0x0f);
+	if (len == 16)
+		rsv->type = scsi_pr_type_to_block(data[21] & 0x0f);
 	return 0;
 }
 
-- 
2.35.3


^ permalink raw reply related	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2025-06-03 10:06 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-06-03 10:04 [PATCH 0/3] block: expose 'read_keys' and 'read_reservation' PR callbacks Hannes Reinecke
2025-06-03 10:04 ` [PATCH 1/3] block: add 'read_keys' persistent reservation ioctl Hannes Reinecke
2025-06-03 10:04 ` [PATCH 2/3] block: add 'read_reservation' " Hannes Reinecke
2025-06-03 10:04 ` [PATCH 3/3] scsi: return PR generation if no reservation is held Hannes Reinecke

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).