-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
block: add an API for Persistent Reservations
This commits adds a driver API and ioctls for controlling Persistent Reservations s/genericly/generically/ at the block layer. Persistent Reservations are supported by SCSI and NVMe and allow controlling who gets access to a device in a shared storage setup. Note that we add a pr_ops structure to struct block_device_operations instead of adding the members directly to avoid bloating all instances of devices that will never support Persistent Reservations. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Jens Axboe <axboe@fb.com>
- Loading branch information
Christoph Hellwig
authored and
Jens Axboe
committed
Oct 21, 2015
1 parent
d8e4bb8
commit bbd3e06
Showing
5 changed files
with
290 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
|
||
Block layer support for Persistent Reservations | ||
=============================================== | ||
|
||
The Linux kernel supports a user space interface for simplified | ||
Persistent Reservations which map to block devices that support | ||
these (like SCSI). Persistent Reservations allow restricting | ||
access to block devices to specific initiators in a shared storage | ||
setup. | ||
|
||
This document gives a general overview of the support ioctl commands. | ||
For a more detailed reference please refer the the SCSI Primary | ||
Commands standard, specifically the section on Reservations and the | ||
"PERSISTENT RESERVE IN" and "PERSISTENT RESERVE OUT" commands. | ||
|
||
All implementations are expected to ensure the reservations survive | ||
a power loss and cover all connections in a multi path environment. | ||
These behaviors are optional in SPC but will be automatically applied | ||
by Linux. | ||
|
||
|
||
The following types of reservations are supported: | ||
-------------------------------------------------- | ||
|
||
- PR_WRITE_EXCLUSIVE | ||
|
||
Only the initiator that owns the reservation can write to the | ||
device. Any initiator can read from the device. | ||
|
||
- PR_EXCLUSIVE_ACCESS | ||
|
||
Only the initiator that owns the reservation can access the | ||
device. | ||
|
||
- PR_WRITE_EXCLUSIVE_REG_ONLY | ||
|
||
Only initiators with a registered key can write to the device, | ||
Any initiator can read from the device. | ||
|
||
- PR_EXCLUSIVE_ACCESS_REG_ONLY | ||
|
||
Only initiators with a registered key can access the device. | ||
|
||
- PR_WRITE_EXCLUSIVE_ALL_REGS | ||
|
||
Only initiators with a registered key can write to the device, | ||
Any initiator can read from the device. | ||
All initiators with a registered key are considered reservation | ||
holders. | ||
Please reference the SPC spec on the meaning of a reservation | ||
holder if you want to use this type. | ||
|
||
- PR_EXCLUSIVE_ACCESS_ALL_REGS | ||
|
||
Only initiators with a registered key can access the device. | ||
All initiators with a registered key are considered reservation | ||
holders. | ||
Please reference the SPC spec on the meaning of a reservation | ||
holder if you want to use this type. | ||
|
||
|
||
The following ioctl are supported: | ||
---------------------------------- | ||
|
||
1. IOC_PR_REGISTER | ||
|
||
This ioctl command registers a new reservation if the new_key argument | ||
is non-null. If no existing reservation exists old_key must be zero, | ||
if an existing reservation should be replaced old_key must contain | ||
the old reservation key. | ||
|
||
If the new_key argument is 0 it unregisters the existing reservation passed | ||
in old_key. | ||
|
||
|
||
2. IOC_PR_RESERVE | ||
|
||
This ioctl command reserves the device and thus restricts access for other | ||
devices based on the type argument. The key argument must be the existing | ||
reservation key for the device as acquired by the IOC_PR_REGISTER, | ||
IOC_PR_REGISTER_IGNORE, IOC_PR_PREEMPT or IOC_PR_PREEMPT_ABORT commands. | ||
|
||
|
||
3. IOC_PR_RELEASE | ||
|
||
This ioctl command releases the reservation specified by key and flags | ||
and thus removes any access restriction implied by it. | ||
|
||
|
||
4. IOC_PR_PREEMPT | ||
|
||
This ioctl command releases the existing reservation referred to by | ||
old_key and replaces it with a a new reservation of type for the | ||
reservation key new_key. | ||
|
||
|
||
5. IOC_PR_PREEMPT_ABORT | ||
|
||
This ioctl command works like IOC_PR_PREEMPT except that it also aborts | ||
any outstanding command sent over a connection identified by old_key. | ||
|
||
6. IOC_PR_CLEAR | ||
|
||
This ioctl command unregisters both key and any other reservation key | ||
registered with the device and drops any existing reservation. | ||
|
||
|
||
Flags | ||
----- | ||
|
||
All the ioctls have a flag field. Currently only one flag is supported: | ||
|
||
- PR_FL_IGNORE_KEY | ||
|
||
Ignore the existing reservation key. This is commonly supported for | ||
IOC_PR_REGISTER, and some implementation may support the flag for | ||
IOC_PR_RESERVE. | ||
|
||
For all unknown flags the kernel will return -EOPNOTSUPP. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
#ifndef LINUX_PR_H | ||
#define LINUX_PR_H | ||
|
||
#include <uapi/linux/pr.h> | ||
|
||
struct pr_ops { | ||
int (*pr_register)(struct block_device *bdev, u64 old_key, u64 new_key, | ||
u32 flags); | ||
int (*pr_reserve)(struct block_device *bdev, u64 key, | ||
enum pr_type type, u32 flags); | ||
int (*pr_release)(struct block_device *bdev, u64 key, | ||
enum pr_type type); | ||
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); | ||
}; | ||
|
||
#endif /* LINUX_PR_H */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
#ifndef _UAPI_PR_H | ||
#define _UAPI_PR_H | ||
|
||
enum pr_type { | ||
PR_WRITE_EXCLUSIVE = 1, | ||
PR_EXCLUSIVE_ACCESS = 2, | ||
PR_WRITE_EXCLUSIVE_REG_ONLY = 3, | ||
PR_EXCLUSIVE_ACCESS_REG_ONLY = 4, | ||
PR_WRITE_EXCLUSIVE_ALL_REGS = 5, | ||
PR_EXCLUSIVE_ACCESS_ALL_REGS = 6, | ||
}; | ||
|
||
struct pr_reservation { | ||
__u64 key; | ||
__u32 type; | ||
__u32 flags; | ||
}; | ||
|
||
struct pr_registration { | ||
__u64 old_key; | ||
__u64 new_key; | ||
__u32 flags; | ||
__u32 __pad; | ||
}; | ||
|
||
struct pr_preempt { | ||
__u64 old_key; | ||
__u64 new_key; | ||
__u32 type; | ||
__u32 flags; | ||
}; | ||
|
||
struct pr_clear { | ||
__u64 key; | ||
__u32 flags; | ||
__u32 __pad; | ||
}; | ||
|
||
#define PR_FL_IGNORE_KEY (1 << 0) /* ignore existing key */ | ||
|
||
#define IOC_PR_REGISTER _IOW('p', 200, struct pr_registration) | ||
#define IOC_PR_RESERVE _IOW('p', 201, struct pr_reservation) | ||
#define IOC_PR_RELEASE _IOW('p', 202, struct pr_reservation) | ||
#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) | ||
|
||
#endif /* _UAPI_PR_H */ |