Commit 3e2cb9ee authored by Stefan Hajnoczi's avatar Stefan Hajnoczi Committed by Jens Axboe
Browse files

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 c787f1ba ("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: default avatarStefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: default avatarHannes Reinecke <hare@suse.de>
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent 22a1ffea
Loading
Loading
Loading
Loading
+28 −0
Original line number Diff line number Diff line
@@ -477,6 +477,32 @@ 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_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);
	}
+7 −0
Original line number Diff line number Diff line
@@ -62,6 +62,12 @@ struct pr_read_keys {
	__u64	keys_ptr;
};

struct pr_read_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_read_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_read_keys)
#define IOC_PR_READ_RESERVATION	_IOR('p', 207, struct pr_read_reservation)

#endif /* _UAPI_PR_H */