diff options
| author | Stefan Hajnoczi <stefanha@redhat.com> | 2025-12-01 16:43:29 -0500 |
|---|---|---|
| committer | Jens Axboe <axboe@kernel.dk> | 2025-12-04 07:19:26 -0700 |
| commit | 3e2cb9ee76c27f57bfdb7b4753b909594d4fa31a (patch) | |
| tree | 3deb83b6d971b7feab57ddf32b7a856e439ccb95 /block | |
| parent | 22a1ffea5f805dfa21b64d1c7b5fe39c0c78c997 (diff) | |
block: add IOC_PR_READ_RESERVATION ioctl
Add a Persistent Reservations ioctl to read the current reservation.
This calls the pr_ops->read_reservation() function that was previously
added in commit c787f1baa503 ("block: Add PR callouts for read keys and
reservation") but was only used by the in-kernel SCSI target so far.
The IOC_PR_READ_RESERVATION ioctl is necessary so that userspace
applications that rely on Persistent Reservations ioctls have a way of
inspecting the current state. Cluster managers and validation tests need
this functionality.
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'block')
| -rw-r--r-- | block/ioctl.c | 28 |
1 files changed, 28 insertions, 0 deletions
diff --git a/block/ioctl.c b/block/ioctl.c index c0802ebf54a6..61feed686418 100644 --- a/block/ioctl.c +++ b/block/ioctl.c @@ -477,6 +477,32 @@ out: return ret; } +static int blkdev_pr_read_reservation(struct block_device *bdev, + blk_mode_t mode, struct pr_read_reservation __user *arg) +{ + const struct pr_ops *ops = bdev->bd_disk->fops->pr_ops; + struct pr_held_reservation rsv = {}; + struct pr_read_reservation out = {}; + int ret; + + if (!blkdev_pr_allowed(bdev, mode)) + return -EPERM; + if (!ops || !ops->pr_read_reservation) + return -EOPNOTSUPP; + + ret = ops->pr_read_reservation(bdev, &rsv); + if (ret) + return ret; + + out.key = rsv.key; + out.generation = rsv.generation; + out.type = rsv.type; + + if (copy_to_user(arg, &out, sizeof(out))) + return -EFAULT; + return 0; +} + static int blkdev_flushbuf(struct block_device *bdev, unsigned cmd, unsigned long arg) { @@ -701,6 +727,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_RESERVATION: + return blkdev_pr_read_reservation(bdev, mode, argp); default: return blk_get_meta_cap(bdev, cmd, argp); } |
