* [PATCH 0/3] blkpr: add read-keys and read-reservations commands
@ 2025-12-11 16:09 Stefan Hajnoczi
2025-12-11 16:09 ` [PATCH 1/3] blkpr: prepare for _IOR() ioctls Stefan Hajnoczi
` (2 more replies)
0 siblings, 3 replies; 6+ messages in thread
From: Stefan Hajnoczi @ 2025-12-11 16:09 UTC (permalink / raw)
To: util-linux; +Cc: pizhenwei, hare, kwolf, Stefan Hajnoczi
New <linux/pr.h> ioctls make it possible to fetch the list of registered keys
and the details of the current reservation from a block device. The relevant
Linux commits are:
3e2cb9ee76c27 block: add IOC_PR_READ_RESERVATION ioctl
22a1ffea5f805 block: add IOC_PR_READ_KEYS ioctl
Add the appropriate commands to blkpr. Users can use these for troubleshooting
and cluster management tools may use them to query the state of persistent
reservations during recovery.
Stefan Hajnoczi (3):
blkpr: prepare for _IOR() ioctls
blkpr: add read-keys command
blkpr: add read-reservation command
meson.build | 6 +++
sys-utils/blkpr.c | 106 ++++++++++++++++++++++++++++++++++++++---
configure.ac | 8 ++++
sys-utils/blkpr.8.adoc | 3 +-
4 files changed, 115 insertions(+), 8 deletions(-)
--
2.52.0
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 1/3] blkpr: prepare for _IOR() ioctls
2025-12-11 16:09 [PATCH 0/3] blkpr: add read-keys and read-reservations commands Stefan Hajnoczi
@ 2025-12-11 16:09 ` Stefan Hajnoczi
2025-12-11 16:09 ` [PATCH 2/3] blkpr: add read-keys command Stefan Hajnoczi
2025-12-11 16:09 ` [PATCH 3/3] blkpr: add read-reservation command Stefan Hajnoczi
2 siblings, 0 replies; 6+ messages in thread
From: Stefan Hajnoczi @ 2025-12-11 16:09 UTC (permalink / raw)
To: util-linux; +Cc: pizhenwei, hare, kwolf, Stefan Hajnoczi
parse_pr_command() returns the ioctl command constant for a given
command or -1 when the command is unknown. Up until now all ioctl
command constants were positive, so the following check worked:
if (command < 0)
err(EXIT_FAILURE, _("unknown command"));
The top two bits of ioctl command constants encode the direction (_IO,
_IOR, _IOW, _IOWR). ioctl commands defined with _IOR have negative ioctl
command constants.
Explicitly check for -1 to differentiate "unknown command" from valid
ioctls commands. Later commits will add ioctl commands that use _IOR.
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
sys-utils/blkpr.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/sys-utils/blkpr.c b/sys-utils/blkpr.c
index 03ca9f7e5..c6b030def 100644
--- a/sys-utils/blkpr.c
+++ b/sys-utils/blkpr.c
@@ -276,7 +276,7 @@ int main(int argc, char **argv)
break;
case 'c':
command = parse_pr_command(optarg);
- if (command < 0)
+ if (command == -1)
err(EXIT_FAILURE, _("unknown command"));
break;
case 't':
--
2.52.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH 2/3] blkpr: add read-keys command
2025-12-11 16:09 [PATCH 0/3] blkpr: add read-keys and read-reservations commands Stefan Hajnoczi
2025-12-11 16:09 ` [PATCH 1/3] blkpr: prepare for _IOR() ioctls Stefan Hajnoczi
@ 2025-12-11 16:09 ` Stefan Hajnoczi
2025-12-11 16:09 ` [PATCH 3/3] blkpr: add read-reservation command Stefan Hajnoczi
2 siblings, 0 replies; 6+ messages in thread
From: Stefan Hajnoczi @ 2025-12-11 16:09 UTC (permalink / raw)
To: util-linux; +Cc: pizhenwei, hare, kwolf, Stefan Hajnoczi
The new IOC_PR_READ_KEYS ioctl lists registered keys on a device. Add a
command so that users can inspect keys. This is useful both for
troubleshooting and for recovery scenarios.
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
meson.build | 3 +++
sys-utils/blkpr.c | 46 ++++++++++++++++++++++++++++++++++++++++++
configure.ac | 4 ++++
sys-utils/blkpr.8.adoc | 3 ++-
4 files changed, 55 insertions(+), 1 deletion(-)
diff --git a/meson.build b/meson.build
index 8b7880e46..47b43c2af 100644
--- a/meson.build
+++ b/meson.build
@@ -765,6 +765,9 @@ conf.set('HAVE_DECL_BLK_ZONE_REP_CAPACITY', have ? 1 : false)
have = cc.has_header_symbol('linux/pr.h', 'PR_REP_CAPACITY')
conf.set('HAVE_DECL_PR_REP_CAPACITY', have ? 1 : false)
+have = cc.has_header_symbol('linux/pr.h', 'IOC_PR_READ_KEYS')
+conf.set('HAVE_DECL_IOC_PR_READ_KEYS', have ? 1 : false)
+
code = '''
#include <time.h>
#if !@0@
diff --git a/sys-utils/blkpr.c b/sys-utils/blkpr.c
index c6b030def..843ef7da1 100644
--- a/sys-utils/blkpr.c
+++ b/sys-utils/blkpr.c
@@ -103,6 +103,12 @@ static const struct type_string pr_command[] = {
{IOC_PR_CLEAR, "clear",
" * clear: This command unregisters both key and any other reservation\n"
" key registered with the device and drops any existing reservation.\n"},
+
+#if HAVE_DECL_IOC_PR_READ_KEYS
+ {IOC_PR_READ_KEYS, "read-keys",
+ " * read-keys: This command lists reservation keys currently registered\n"
+ " with the device.\n"},
+#endif
};
static const struct type_string pr_flag[] = {
@@ -151,6 +157,41 @@ PARSE(pr_type)
PARSE(pr_command)
PARSE(pr_flag)
+#if HAVE_DECL_IOC_PR_READ_KEYS
+static int do_pr_read_keys(int fd)
+{
+ struct pr_read_keys pr_rk;
+ uint32_t num_keys = 8;
+ uint64_t *keys = NULL;
+ int ret;
+
+ /* Loop to grow keys[] until it is large enough */
+ do {
+ num_keys *= 2;
+ keys = xreallocarray(keys, num_keys, sizeof(keys[0]));
+
+ pr_rk.keys_ptr = (uintptr_t)keys;
+ pr_rk.num_keys = num_keys;
+
+ ret = ioctl(fd, IOC_PR_READ_KEYS, &pr_rk);
+ if (ret)
+ goto out;
+ } while (pr_rk.num_keys > num_keys);
+
+ if (pr_rk.num_keys) {
+ for (uint32_t i = 0; i < pr_rk.num_keys; i++) {
+ printf(_("%#" PRIx64 "\n"), (uint64_t)keys[i]);
+ }
+ } else {
+ printf(_("No registered keys\n"));
+ }
+
+out:
+ free(keys);
+ return ret;
+}
+#endif /* HAVE_DECL_IOC_PR_READ_KEYS */
+
static int do_pr(char *path, uint64_t key, uint64_t oldkey, int op, int type, int flag)
{
struct pr_registration pr_reg;
@@ -190,6 +231,11 @@ static int do_pr(char *path, uint64_t key, uint64_t oldkey, int op, int type, in
pr_clr.flags = flag;
ret = ioctl(fd, op, &pr_clr);
break;
+#if HAVE_DECL_IOC_PR_READ_KEYS
+ case IOC_PR_READ_KEYS:
+ ret = do_pr_read_keys(fd);
+ break;
+#endif
default:
errno = EINVAL;
err(EXIT_FAILURE, _("unknown command"));
diff --git a/configure.ac b/configure.ac
index a424e0947..bbd2156d7 100644
--- a/configure.ac
+++ b/configure.ac
@@ -445,6 +445,10 @@ AC_CHECK_DECLS([PR_REP_CAPACITY], [], [], [
#include <linux/pr.h>
])
+AC_CHECK_DECLS([IOC_PR_READ_KEYS], [], [], [
+ #include <linux/pr.h>
+])
+
AC_CHECK_HEADERS([security/openpam.h], [], [], [
#ifdef HAVE_SECURITY_PAM_APPL_H
#include <security/pam_appl.h>
diff --git a/sys-utils/blkpr.8.adoc b/sys-utils/blkpr.8.adoc
index 98983b779..3a157af38 100644
--- a/sys-utils/blkpr.8.adoc
+++ b/sys-utils/blkpr.8.adoc
@@ -25,7 +25,8 @@ The _device_ argument is the pathname of the block device.
*-c*, *--command* _command_::
The command for managing persistent reservations. Supported commands are:
-*register*, *reserve*, *release*, *preempt*, *preempt-abort*, and *clear*.
+*register*, *reserve*, *release*, *preempt*, *preempt-abort*, *clear*, and
+*read-keys*.
*-k*, *--key* _key_::
The key the command should operate on.
--
2.52.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH 3/3] blkpr: add read-reservation command
2025-12-11 16:09 [PATCH 0/3] blkpr: add read-keys and read-reservations commands Stefan Hajnoczi
2025-12-11 16:09 ` [PATCH 1/3] blkpr: prepare for _IOR() ioctls Stefan Hajnoczi
2025-12-11 16:09 ` [PATCH 2/3] blkpr: add read-keys command Stefan Hajnoczi
@ 2025-12-11 16:09 ` Stefan Hajnoczi
2025-12-17 10:53 ` Karel Zak
2 siblings, 1 reply; 6+ messages in thread
From: Stefan Hajnoczi @ 2025-12-11 16:09 UTC (permalink / raw)
To: util-linux; +Cc: pizhenwei, hare, kwolf, Stefan Hajnoczi
The new IOC_PR_READ_RESERVATION ioctl reports the current reservation on
a device. Add a command so that users can inspect the current
reservation. This is useful both for troubleshooting and for recovery
scenarios.
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
meson.build | 3 +++
sys-utils/blkpr.c | 60 +++++++++++++++++++++++++++++++++++++-----
configure.ac | 4 +++
sys-utils/blkpr.8.adoc | 4 +--
4 files changed, 62 insertions(+), 9 deletions(-)
diff --git a/meson.build b/meson.build
index 47b43c2af..b759e992f 100644
--- a/meson.build
+++ b/meson.build
@@ -768,6 +768,9 @@ conf.set('HAVE_DECL_PR_REP_CAPACITY', have ? 1 : false)
have = cc.has_header_symbol('linux/pr.h', 'IOC_PR_READ_KEYS')
conf.set('HAVE_DECL_IOC_PR_READ_KEYS', have ? 1 : false)
+have = cc.has_header_symbol('linux/pr.h', 'IOC_PR_READ_RESERVATION')
+conf.set('HAVE_DECL_IOC_PR_READ_RESERVATION', have ? 1 : false)
+
code = '''
#include <time.h>
#if !@0@
diff --git a/sys-utils/blkpr.c b/sys-utils/blkpr.c
index 843ef7da1..0cb73a3bd 100644
--- a/sys-utils/blkpr.c
+++ b/sys-utils/blkpr.c
@@ -73,7 +73,7 @@ static const struct type_string pr_type[] = {
};
static const struct type_string pr_command[] = {
- {IOC_PR_REGISTER, "register",
+ {IOC_PR_REGISTER, "register",
" * register: This command registers a new reservation if the key argument\n"
" is non-null. If no existing reservation exists oldkey must be zero, if\n"
" an existing reservation should be replaced oldkey must contain the old\n"
@@ -81,34 +81,39 @@ static const struct type_string pr_command[] = {
" reservation passed in oldkey.\n"
},
- {IOC_PR_RESERVE, "reserve",
+ {IOC_PR_RESERVE, "reserve",
" * reserve: This command reserves the device and thus restricts access for\n"
" other devices based on the type argument. The key argument must be\n"
" the existing reservation key for the device as acquired by the register,\n"
" preempt, preempt-abort commands.\n"},
- {IOC_PR_RELEASE, "release",
+ {IOC_PR_RELEASE, "release",
" * release: This command releases the reservation specified by key and flags\n"
" and thus removes any access restriction implied by it.\n"},
- {IOC_PR_PREEMPT, "preempt",
+ {IOC_PR_PREEMPT, "preempt",
" * preempt: This command releases the existing reservation referred to by\n"
" old_key and replaces it with a new reservation of type for the\n"
" reservation key key.\n"},
- {IOC_PR_PREEMPT_ABORT, "preempt-abort",
+ {IOC_PR_PREEMPT_ABORT, "preempt-abort",
" * preempt-abort: This command works like preempt except that it also aborts\n"
" any outstanding command sent over a connection identified by oldkey.\n"},
- {IOC_PR_CLEAR, "clear",
+ {IOC_PR_CLEAR, "clear",
" * clear: This command unregisters both key and any other reservation\n"
" key registered with the device and drops any existing reservation.\n"},
#if HAVE_DECL_IOC_PR_READ_KEYS
- {IOC_PR_READ_KEYS, "read-keys",
+ {IOC_PR_READ_KEYS, "read-keys",
" * read-keys: This command lists reservation keys currently registered\n"
" with the device.\n"},
#endif
+
+#if HAVE_DECL_IOC_PR_READ_RESERVATION
+ {IOC_PR_READ_RESERVATION, "read-reservation",
+ " * read-reservation: This command shows the current reservation.\n"},
+#endif
};
static const struct type_string pr_flag[] = {
@@ -140,6 +145,18 @@ static int parse_type_by_str(const struct type_string *ts, int nmem, char *patte
return -1;
}
+static inline const char *type_to_str(const struct type_string *ts, int nmem,
+ int type)
+{
+ int i;
+
+ for (i = 0; i < nmem; i++) {
+ if (ts[i].type == type)
+ return ts[i].str;
+ }
+ return "unknown type";
+}
+
#define PRINT_SUPPORTED(XX) \
static void print_##XX(FILE *out) \
@@ -192,6 +209,30 @@ out:
}
#endif /* HAVE_DECL_IOC_PR_READ_KEYS */
+#if HAVE_DECL_IOC_PR_READ_RESERVATION
+static int do_pr_read_reservation(int fd)
+{
+ struct pr_read_reservation pr_rr;
+ const char *type_str;
+ int ret;
+
+ ret = ioctl(fd, IOC_PR_READ_RESERVATION, &pr_rr);
+ if (ret)
+ return ret;
+
+ type_str = type_to_str(pr_type, ARRAY_SIZE(pr_type), pr_rr.type);
+
+ if (pr_rr.key) {
+ printf(_("Key: %#" PRIx64 "\n"), (uint64_t)pr_rr.key);
+ printf(_("Generation: %#x\n"), pr_rr.generation);
+ printf(_("Type: %s\n"), type_str);
+ } else {
+ printf(_("No reservation\n"));
+ }
+ return 0;
+}
+#endif /* HAVE_DECL_IOC_PR_READ_RESERVATION */
+
static int do_pr(char *path, uint64_t key, uint64_t oldkey, int op, int type, int flag)
{
struct pr_registration pr_reg;
@@ -235,6 +276,11 @@ static int do_pr(char *path, uint64_t key, uint64_t oldkey, int op, int type, in
case IOC_PR_READ_KEYS:
ret = do_pr_read_keys(fd);
break;
+#endif
+#if HAVE_DECL_IOC_PR_READ_RESERVATION
+ case IOC_PR_READ_RESERVATION:
+ ret = do_pr_read_reservation(fd);
+ break;
#endif
default:
errno = EINVAL;
diff --git a/configure.ac b/configure.ac
index bbd2156d7..9dfb12a7a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -449,6 +449,10 @@ AC_CHECK_DECLS([IOC_PR_READ_KEYS], [], [], [
#include <linux/pr.h>
])
+AC_CHECK_DECLS([IOC_PR_READ_RESERVATION], [], [], [
+ #include <linux/pr.h>
+])
+
AC_CHECK_HEADERS([security/openpam.h], [], [], [
#ifdef HAVE_SECURITY_PAM_APPL_H
#include <security/pam_appl.h>
diff --git a/sys-utils/blkpr.8.adoc b/sys-utils/blkpr.8.adoc
index 3a157af38..630bafb92 100644
--- a/sys-utils/blkpr.8.adoc
+++ b/sys-utils/blkpr.8.adoc
@@ -25,8 +25,8 @@ The _device_ argument is the pathname of the block device.
*-c*, *--command* _command_::
The command for managing persistent reservations. Supported commands are:
-*register*, *reserve*, *release*, *preempt*, *preempt-abort*, *clear*, and
-*read-keys*.
+*register*, *reserve*, *release*, *preempt*, *preempt-abort*, *clear*,
+*read-keys*, and *read-reservation*.
*-k*, *--key* _key_::
The key the command should operate on.
--
2.52.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH 3/3] blkpr: add read-reservation command
2025-12-11 16:09 ` [PATCH 3/3] blkpr: add read-reservation command Stefan Hajnoczi
@ 2025-12-17 10:53 ` Karel Zak
2025-12-17 18:26 ` Stefan Hajnoczi
0 siblings, 1 reply; 6+ messages in thread
From: Karel Zak @ 2025-12-17 10:53 UTC (permalink / raw)
To: Stefan Hajnoczi; +Cc: util-linux
On Thu, Dec 11, 2025 at 11:09:56AM -0500, Stefan Hajnoczi wrote:
>
> diff --git a/meson.build b/meson.build
> index 47b43c2af..b759e992f 100644
> --- a/meson.build
> +++ b/meson.build
> @@ -768,6 +768,9 @@ conf.set('HAVE_DECL_PR_REP_CAPACITY', have ? 1 : false)
> have = cc.has_header_symbol('linux/pr.h', 'IOC_PR_READ_KEYS')
> conf.set('HAVE_DECL_IOC_PR_READ_KEYS', have ? 1 : false)
>
> +have = cc.has_header_symbol('linux/pr.h', 'IOC_PR_READ_RESERVATION')
> +conf.set('HAVE_DECL_IOC_PR_READ_RESERVATION', have ? 1 : false)
It seems you do not need to define HAVE_DECL_IOC_PR_READ_RESERVATION
and care about this in meson.build or configure.ac.
> +#if HAVE_DECL_IOC_PR_READ_RESERVATION
> + {IOC_PR_READ_RESERVATION, "read-reservation",
> + " * read-reservation: This command shows the current reservation.\n"},
> +#endif
I think you can use directly
#ifdef IOC_PR_READ_RESERVATION
#endif
as IOC_PR_READ_RESERVATION is macro in linux/pr.h
Karel
--
Karel Zak <kzak@redhat.com>
http://karelzak.blogspot.com
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 3/3] blkpr: add read-reservation command
2025-12-17 10:53 ` Karel Zak
@ 2025-12-17 18:26 ` Stefan Hajnoczi
0 siblings, 0 replies; 6+ messages in thread
From: Stefan Hajnoczi @ 2025-12-17 18:26 UTC (permalink / raw)
To: Karel Zak; +Cc: util-linux
[-- Attachment #1: Type: text/plain, Size: 1141 bytes --]
On Wed, Dec 17, 2025 at 11:53:46AM +0100, Karel Zak wrote:
> On Thu, Dec 11, 2025 at 11:09:56AM -0500, Stefan Hajnoczi wrote:
> >
> > diff --git a/meson.build b/meson.build
> > index 47b43c2af..b759e992f 100644
> > --- a/meson.build
> > +++ b/meson.build
> > @@ -768,6 +768,9 @@ conf.set('HAVE_DECL_PR_REP_CAPACITY', have ? 1 : false)
> > have = cc.has_header_symbol('linux/pr.h', 'IOC_PR_READ_KEYS')
> > conf.set('HAVE_DECL_IOC_PR_READ_KEYS', have ? 1 : false)
> >
> > +have = cc.has_header_symbol('linux/pr.h', 'IOC_PR_READ_RESERVATION')
> > +conf.set('HAVE_DECL_IOC_PR_READ_RESERVATION', have ? 1 : false)
>
> It seems you do not need to define HAVE_DECL_IOC_PR_READ_RESERVATION
> and care about this in meson.build or configure.ac.
>
> > +#if HAVE_DECL_IOC_PR_READ_RESERVATION
> > + {IOC_PR_READ_RESERVATION, "read-reservation",
> > + " * read-reservation: This command shows the current reservation.\n"},
> > +#endif
>
> I think you can use directly
>
> #ifdef IOC_PR_READ_RESERVATION
>
> #endif
>
> as IOC_PR_READ_RESERVATION is macro in linux/pr.h
Will fix in v2.
Stefan
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2025-12-17 18:26 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-12-11 16:09 [PATCH 0/3] blkpr: add read-keys and read-reservations commands Stefan Hajnoczi
2025-12-11 16:09 ` [PATCH 1/3] blkpr: prepare for _IOR() ioctls Stefan Hajnoczi
2025-12-11 16:09 ` [PATCH 2/3] blkpr: add read-keys command Stefan Hajnoczi
2025-12-11 16:09 ` [PATCH 3/3] blkpr: add read-reservation command Stefan Hajnoczi
2025-12-17 10:53 ` Karel Zak
2025-12-17 18:26 ` Stefan Hajnoczi
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox