From: Stefan Hajnoczi <[email protected]> qemu-pr-helper now supports the vendor-specific PR_HELPER_CLEANUP SCSI command. Add support to the client side.
pr_manager_helper_run() uses scsi_cdb_xfer() to determine the number of bytes to transfer. Extend scsi_cdb_xfer() to know that this vendor-specific command does not transfer any bytes. Signed-off-by: Stefan Hajnoczi <[email protected]> Reviewed-by: Eric Blake <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Paolo Bonzini <[email protected]> --- scsi/pr-manager-helper.c | 20 +++++++++++++++++--- scsi/utils.c | 3 +++ 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/scsi/pr-manager-helper.c b/scsi/pr-manager-helper.c index 26ef3876f0e..e7162e21ff0 100644 --- a/scsi/pr-manager-helper.c +++ b/scsi/pr-manager-helper.c @@ -38,6 +38,8 @@ struct PRManagerHelper { QemuMutex lock; QIOChannel *ioc; + + uint32_t proto_flags; /* flags negotiated with pr-helper */ }; static void pr_manager_send_status_changed_event(PRManagerHelper *pr_mgr) @@ -129,7 +131,9 @@ static int pr_manager_helper_initialize(PRManagerHelper *pr_mgr, goto out_close; } - flags = 0; + pr_mgr->proto_flags = be32_to_cpu(flags) & PR_HELPER_FEATURE_CLEANUP; + + flags = cpu_to_be32(pr_mgr->proto_flags); r = pr_manager_helper_write(pr_mgr, -1, &flags, sizeof(flags), errp); if (r < 0) { goto out_close; @@ -161,9 +165,19 @@ static int pr_manager_helper_run(PRManager *p, } memcpy(cdb, io_hdr->cmdp, io_hdr->cmd_len); - assert(cdb[0] == PERSISTENT_RESERVE_OUT || cdb[0] == PERSISTENT_RESERVE_IN); + assert(cdb[0] == PERSISTENT_RESERVE_OUT || + cdb[0] == PERSISTENT_RESERVE_IN || + cdb[0] == PR_HELPER_CLEANUP); + + /* The command is only available when pr-helper supports it */ + if (cdb[0] == PR_HELPER_CLEANUP && + !(pr_mgr->proto_flags & PR_HELPER_FEATURE_CLEANUP)) { + return -ENOTSUP; + } + expected_dir = - (cdb[0] == PERSISTENT_RESERVE_OUT ? SG_DXFER_TO_DEV : SG_DXFER_FROM_DEV); + (cdb[0] == PERSISTENT_RESERVE_IN ? + SG_DXFER_FROM_DEV : SG_DXFER_TO_DEV); if (io_hdr->dxfer_direction != expected_dir) { return -EINVAL; } diff --git a/scsi/utils.c b/scsi/utils.c index daee90ecf0e..1ee68e68221 100644 --- a/scsi/utils.c +++ b/scsi/utils.c @@ -29,6 +29,9 @@ uint32_t scsi_data_cdb_xfer(uint8_t *buf) uint32_t scsi_cdb_xfer(uint8_t *buf) { + if (buf[0] == PR_HELPER_CLEANUP) { + return 0; + } switch (buf[0] >> 5) { case 0: return buf[4]; -- 2.56.0
