From patchwork Fri Jul 5 10:56:05 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Changqi Lu X-Patchwork-Id: 1957284 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=bytedance.com header.i=@bytedance.com header.a=rsa-sha256 header.s=google header.b=Y6D7QpcR; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=patchwork.ozlabs.org) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4WFr8f1gMkz1xr0 for ; Fri, 5 Jul 2024 20:58:10 +1000 (AEST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1sPgcE-0002Bc-Cs; Fri, 05 Jul 2024 06:56:34 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1sPgcC-0002Ak-BA for qemu-devel@nongnu.org; Fri, 05 Jul 2024 06:56:32 -0400 Received: from mail-pg1-x533.google.com ([2607:f8b0:4864:20::533]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1sPgc8-0006aK-Gh for qemu-devel@nongnu.org; Fri, 05 Jul 2024 06:56:32 -0400 Received: by mail-pg1-x533.google.com with SMTP id 41be03b00d2f7-765590154b4so426436a12.0 for ; Fri, 05 Jul 2024 03:56:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bytedance.com; s=google; t=1720176987; x=1720781787; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=kjAdu6ZTaJ2H/T12j7/Y4iOTA7PHN1pPSyvKcs9msGY=; b=Y6D7QpcRver8lGOQMsmXAr4Fp41A31t0+sxJpwitHA3hlj9CbwYbz6wuzDQWcftzFh wvhVqq4I+30GbqgARw8uuHuCb3LU2g3w10TFiI8Qa7rXvS9q3YQnrGdkFkpEJ8wfhXkY /BIM5eRoUBFp6Mlf+vOs/EXZr7YBUDoaL+Jm52F2w7E0y5LQ00OJGFPLArKEsgpx1VKP gbhw9PGea9Cwibfio7NGL+YJ7Iv9eq86URlglIxavICQwrFF/sK/OxlFoAeop2VTrmPM f0Wjh1VmY9iKgKP/CeHo5+FBbSz5480k8fgqo+O9tIscyjhf3itaLKjI3qLhFHr+1vdS JuNA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1720176987; x=1720781787; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=kjAdu6ZTaJ2H/T12j7/Y4iOTA7PHN1pPSyvKcs9msGY=; b=rKnveFFZib9b5cXjr3k0uUkZPZHT2Oksv620MuK69siQwbTxDU2Q65rZiDIC7XzLnq PzbLjx5iMbkdL7tVtSf5dgc2CsjCn5mULtxNeiawO8qN+G2VxstEo70LVLm8kMFTS+R3 tnQqx2Eci2vC6j3HpgKeAyr7K4Y04Kk4GoL1sa1BUFOM9TBzjNmQCcjssT9Cd8xlDPQP TAV4Fp9tQThszaypMeu97iqJTN/A4TdL2tbvpEXfShXxOJh7S1TAe9f3ai/vPj1XbPEU O8QzwhruF259J9XURmkStds2vw/h1i1uX07UmQVeX51QmSSbLALwKjmXtfx7fY3lhghF 0NrQ== X-Forwarded-Encrypted: i=1; AJvYcCXrLaXEVQ2rr/3wIAhQRKt9fC9s3dIhDYeL7XXE9MKIPNnmtzohPYEL2MR2KCnbNZzaxMh2yDn1y+fHddTuG+fExgZNETA= X-Gm-Message-State: AOJu0YxTT8v4jibGuPtns/coFvXGNFxMqNKcBWT8yNoWRiDOKiz9KTC1 5dHy9i/htwNXPJpRh2rMAF7jzrOnCSLtPvE6RIYDH7Tjpg86i8ZwfG/mBY7rmls= X-Google-Smtp-Source: AGHT+IENjrAgJ1M86o/e91Lo1S2UyzvjApqGMAcGm95qzKBKyFhLzqmD/cUnTN/0B252fy6F/SyggA== X-Received: by 2002:a05:6a20:7488:b0:1be:e1f9:a33 with SMTP id adf61e73a8af0-1c0cc74d734mr4334404637.32.1720176986855; Fri, 05 Jul 2024 03:56:26 -0700 (PDT) Received: from n37-006-243.byted.org ([180.184.84.173]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-1fac0ba60a2sm141292125ad.0.2024.07.05.03.56.23 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 05 Jul 2024 03:56:26 -0700 (PDT) From: Changqi Lu To: qemu-block@nongnu.org, qemu-devel@nongnu.org Cc: kwolf@redhat.com, hreitz@redhat.com, stefanha@redhat.com, fam@euphon.net, ronniesahlberg@gmail.com, pbonzini@redhat.com, pl@dlhnet.de, kbusch@kernel.org, its@irrelevant.dk, foss@defmacro.it, philmd@linaro.org, pizhenwei@bytedance.com, Changqi Lu Subject: [PATCH v7 01/10] block: add persistent reservation in/out api Date: Fri, 5 Jul 2024 18:56:05 +0800 Message-Id: <20240705105614.3377694-2-luchangqi.123@bytedance.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20240705105614.3377694-1-luchangqi.123@bytedance.com> References: <20240705105614.3377694-1-luchangqi.123@bytedance.com> MIME-Version: 1.0 Received-SPF: pass client-ip=2607:f8b0:4864:20::533; envelope-from=luchangqi.123@bytedance.com; helo=mail-pg1-x533.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=unavailable autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Add persistent reservation in/out operations at the block level. The following operations are included: - read_keys: retrieves the list of registered keys. - read_reservation: retrieves the current reservation status. - register: registers a new reservation key. - reserve: initiates a reservation for a specific key. - release: releases a reservation for a specific key. - clear: clears all existing reservations. - preempt: preempts a reservation held by another key. Signed-off-by: Changqi Lu Signed-off-by: zhenwei pi Reviewed-by: Stefan Hajnoczi --- block/block-backend.c | 403 ++++++++++++++++++++++++++++++ block/io.c | 164 ++++++++++++ include/block/block-common.h | 40 +++ include/block/block-io.h | 20 ++ include/block/block_int-common.h | 84 +++++++ include/sysemu/block-backend-io.h | 24 ++ 6 files changed, 735 insertions(+) diff --git a/block/block-backend.c b/block/block-backend.c index db6f9b92a3..b74aaba23f 100644 --- a/block/block-backend.c +++ b/block/block-backend.c @@ -1770,6 +1770,409 @@ BlockAIOCB *blk_aio_ioctl(BlockBackend *blk, unsigned long int req, void *buf, return blk_aio_prwv(blk, req, 0, buf, blk_aio_ioctl_entry, 0, cb, opaque); } +typedef struct BlkPrInCo { + BlockBackend *blk; + uint32_t *generation; + uint32_t num_keys; + BlockPrType *type; + uint64_t *keys; + int ret; +} BlkPrInCo; + +typedef struct BlkPrInCB { + BlockAIOCB common; + BlkPrInCo prco; + bool has_returned; +} BlkPrInCB; + +static const AIOCBInfo blk_pr_in_aiocb_info = { + .aiocb_size = sizeof(BlkPrInCB), +}; + +static void blk_pr_in_complete(BlkPrInCB *acb) +{ + if (acb->has_returned) { + acb->common.cb(acb->common.opaque, acb->prco.ret); + + /* This is paired with blk_inc_in_flight() in blk_aio_pr_in(). */ + blk_dec_in_flight(acb->prco.blk); + qemu_aio_unref(acb); + } +} + +static void blk_pr_in_complete_bh(void *opaque) +{ + BlkPrInCB *acb = opaque; + assert(acb->has_returned); + blk_pr_in_complete(acb); +} + +static BlockAIOCB *blk_aio_pr_in(BlockBackend *blk, uint32_t *generation, + uint32_t num_keys, BlockPrType *type, + uint64_t *keys, CoroutineEntry co_entry, + BlockCompletionFunc *cb, void *opaque) +{ + BlkPrInCB *acb; + Coroutine *co; + + /* This is paired with blk_dec_in_flight() in blk_pr_in_complete(). */ + blk_inc_in_flight(blk); + acb = blk_aio_get(&blk_pr_in_aiocb_info, blk, cb, opaque); + acb->prco = (BlkPrInCo) { + .blk = blk, + .generation = generation, + .num_keys = num_keys, + .type = type, + .ret = NOT_DONE, + .keys = keys, + }; + acb->has_returned = false; + + co = qemu_coroutine_create(co_entry, acb); + aio_co_enter(qemu_get_current_aio_context(), co); + + acb->has_returned = true; + if (acb->prco.ret != NOT_DONE) { + replay_bh_schedule_oneshot_event(qemu_get_current_aio_context(), + blk_pr_in_complete_bh, acb); + } + + return &acb->common; +} + +/* To be called between exactly one pair of blk_inc/dec_in_flight() */ +static int coroutine_fn +blk_aio_pr_do_read_keys(BlockBackend *blk, uint32_t *generation, + uint32_t num_keys, uint64_t *keys) +{ + IO_CODE(); + + blk_wait_while_drained(blk); + GRAPH_RDLOCK_GUARD(); + + if (!blk_co_is_available(blk)) { + return -ENOMEDIUM; + } + + return bdrv_co_pr_read_keys(blk_bs(blk), generation, num_keys, keys); +} + +static void coroutine_fn blk_aio_pr_read_keys_entry(void *opaque) +{ + BlkPrInCB *acb = opaque; + BlkPrInCo *prco = &acb->prco; + + prco->ret = blk_aio_pr_do_read_keys(prco->blk, prco->generation, + prco->num_keys, prco->keys); + blk_pr_in_complete(acb); +} + +BlockAIOCB *blk_aio_pr_read_keys(BlockBackend *blk, uint32_t *generation, + uint32_t num_keys, uint64_t *keys, + BlockCompletionFunc *cb, void *opaque) +{ + IO_CODE(); + return blk_aio_pr_in(blk, generation, num_keys, NULL, keys, + blk_aio_pr_read_keys_entry, cb, opaque); +} + +/* To be called between exactly one pair of blk_inc/dec_in_flight() */ +static int coroutine_fn +blk_aio_pr_do_read_reservation(BlockBackend *blk, uint32_t *generation, + uint64_t *key, BlockPrType *type) +{ + IO_CODE(); + + blk_wait_while_drained(blk); + GRAPH_RDLOCK_GUARD(); + + if (!blk_co_is_available(blk)) { + return -ENOMEDIUM; + } + + return bdrv_co_pr_read_reservation(blk_bs(blk), generation, key, type); +} + +static void coroutine_fn blk_aio_pr_read_reservation_entry(void *opaque) +{ + BlkPrInCB *acb = opaque; + BlkPrInCo *prco = &acb->prco; + + prco->ret = blk_aio_pr_do_read_reservation(prco->blk, prco->generation, + prco->keys, prco->type); + blk_pr_in_complete(acb); +} + +BlockAIOCB *blk_aio_pr_read_reservation(BlockBackend *blk, uint32_t *generation, + uint64_t *key, BlockPrType *type, + BlockCompletionFunc *cb, void *opaque) +{ + IO_CODE(); + return blk_aio_pr_in(blk, generation, 0, type, key, + blk_aio_pr_read_reservation_entry, cb, opaque); +} + +typedef struct BlkPrOutCo { + BlockBackend *blk; + uint64_t old_key; + uint64_t new_key; + bool ptpl; + BlockPrType type; + bool ignore_key; + bool abort; + int ret; +} BlkPrOutCo; + +typedef struct BlkPrOutCB { + BlockAIOCB common; + BlkPrOutCo prco; + bool has_returned; +} BlkPrOutCB; + +static const AIOCBInfo blk_pr_out_aiocb_info = { + .aiocb_size = sizeof(BlkPrOutCB), +}; + +static void blk_pr_out_complete(BlkPrOutCB *acb) +{ + if (acb->has_returned) { + acb->common.cb(acb->common.opaque, acb->prco.ret); + + /* This is paired with blk_inc_in_flight() in blk_aio_pr_out(). */ + blk_dec_in_flight(acb->prco.blk); + qemu_aio_unref(acb); + } +} + +static void blk_pr_out_complete_bh(void *opaque) +{ + BlkPrOutCB *acb = opaque; + assert(acb->has_returned); + blk_pr_out_complete(acb); +} + +static BlockAIOCB *blk_aio_pr_out(BlockBackend *blk, uint64_t old_key, + uint64_t new_key, bool ptpl, + BlockPrType type, bool ignore_key, + bool abort, CoroutineEntry co_entry, + BlockCompletionFunc *cb, void *opaque) +{ + BlkPrOutCB *acb; + Coroutine *co; + + /* This is paired with blk_dec_in_flight() in blk_pr_out_complete(). */ + blk_inc_in_flight(blk); + acb = blk_aio_get(&blk_pr_out_aiocb_info, blk, cb, opaque); + acb->prco = (BlkPrOutCo) { + .blk = blk, + .old_key = old_key, + .new_key = new_key, + .ptpl = ptpl, + .type = type, + .ignore_key = ignore_key, + .abort = abort, + .ret = NOT_DONE, + }; + acb->has_returned = false; + + co = qemu_coroutine_create(co_entry, acb); + aio_co_enter(qemu_get_current_aio_context(), co); + + acb->has_returned = true; + if (acb->prco.ret != NOT_DONE) { + replay_bh_schedule_oneshot_event(qemu_get_current_aio_context(), + blk_pr_out_complete_bh, acb); + } + + return &acb->common; +} + +/* To be called between exactly one pair of blk_inc/dec_in_flight() */ +static int coroutine_fn +blk_aio_pr_do_register(BlockBackend *blk, uint64_t old_key, + uint64_t new_key, BlockPrType type, + bool ptpl, bool ignore_key) +{ + IO_CODE(); + + blk_wait_while_drained(blk); + GRAPH_RDLOCK_GUARD(); + + if (!blk_co_is_available(blk)) { + return -ENOMEDIUM; + } + + return bdrv_co_pr_register(blk_bs(blk), old_key, new_key, type, + ptpl, ignore_key); +} + +static void coroutine_fn blk_aio_pr_register_entry(void *opaque) +{ + BlkPrOutCB *acb = opaque; + BlkPrOutCo *prco = &acb->prco; + + prco->ret = blk_aio_pr_do_register(prco->blk, prco->old_key, prco->new_key, + prco->type, prco->ptpl, + prco->ignore_key); + blk_pr_out_complete(acb); +} + +BlockAIOCB *blk_aio_pr_register(BlockBackend *blk, uint64_t old_key, + uint64_t new_key, BlockPrType type, + bool ptpl, bool ignore_key, + BlockCompletionFunc *cb, + void *opaque) +{ + IO_CODE(); + return blk_aio_pr_out(blk, old_key, new_key, ptpl, type, ignore_key, false, + blk_aio_pr_register_entry, cb, opaque); +} + +/* To be called between exactly one pair of blk_inc/dec_in_flight() */ +static int coroutine_fn +blk_aio_pr_do_reserve(BlockBackend *blk, uint64_t key, BlockPrType type) +{ + IO_CODE(); + + blk_wait_while_drained(blk); + GRAPH_RDLOCK_GUARD(); + + if (!blk_co_is_available(blk)) { + return -ENOMEDIUM; + } + + return bdrv_co_pr_reserve(blk_bs(blk), key, type); +} + +static void coroutine_fn blk_aio_pr_reserve_entry(void *opaque) +{ + BlkPrOutCB *acb = opaque; + BlkPrOutCo *prco = &acb->prco; + + prco->ret = blk_aio_pr_do_reserve(prco->blk, prco->old_key, + prco->type); + blk_pr_out_complete(acb); +} + + +BlockAIOCB *blk_aio_pr_reserve(BlockBackend *blk, uint64_t key, + BlockPrType type, + BlockCompletionFunc *cb, + void *opaque) +{ + IO_CODE(); + return blk_aio_pr_out(blk, key, 0, false, type, false, false, + blk_aio_pr_reserve_entry, cb, opaque); +} + +/* To be called between exactly one pair of blk_inc/dec_in_flight() */ +static int coroutine_fn +blk_aio_pr_do_release(BlockBackend *blk, uint64_t key, BlockPrType type) +{ + IO_CODE(); + + blk_wait_while_drained(blk); + GRAPH_RDLOCK_GUARD(); + + if (!blk_co_is_available(blk)) { + return -ENOMEDIUM; + } + + return bdrv_co_pr_release(blk_bs(blk), key, type); +} + +static void coroutine_fn blk_aio_pr_release_entry(void *opaque) +{ + BlkPrOutCB *acb = opaque; + BlkPrOutCo *prco = &acb->prco; + + prco->ret = blk_aio_pr_do_release(prco->blk, prco->old_key, prco->type); + blk_pr_out_complete(acb); +} + + +BlockAIOCB *blk_aio_pr_release(BlockBackend *blk, uint64_t key, + BlockPrType type, BlockCompletionFunc *cb, + void *opaque) +{ + IO_CODE(); + return blk_aio_pr_out(blk, key, 0, false, type, false, false, + blk_aio_pr_release_entry, cb, opaque); +} + +/* To be called between exactly one pair of blk_inc/dec_in_flight() */ +static int coroutine_fn +blk_aio_pr_do_clear(BlockBackend *blk, uint64_t key) +{ + IO_CODE(); + + blk_wait_while_drained(blk); + GRAPH_RDLOCK_GUARD(); + + if (!blk_co_is_available(blk)) { + return -ENOMEDIUM; + } + + return bdrv_co_pr_clear(blk_bs(blk), key); +} + +static void coroutine_fn blk_aio_pr_clear_entry(void *opaque) +{ + BlkPrOutCB *acb = opaque; + BlkPrOutCo *prco = &acb->prco; + + prco->ret = blk_aio_pr_do_clear(prco->blk, prco->old_key); + blk_pr_out_complete(acb); +} + + +BlockAIOCB *blk_aio_pr_clear(BlockBackend *blk, uint64_t key, + BlockCompletionFunc *cb, void *opaque) +{ + IO_CODE(); + return blk_aio_pr_out(blk, key, 0, false, 0, false, false, + blk_aio_pr_clear_entry, cb, opaque); +} + +/* To be called between exactly one pair of blk_inc/dec_in_flight() */ +static int coroutine_fn +blk_aio_pr_do_preempt(BlockBackend *blk, uint64_t cr_key, + uint64_t pr_key, BlockPrType type, bool abort) +{ + IO_CODE(); + + blk_wait_while_drained(blk); + GRAPH_RDLOCK_GUARD(); + + if (!blk_co_is_available(blk)) { + return -ENOMEDIUM; + } + + return bdrv_co_pr_preempt(blk_bs(blk), cr_key, pr_key, type, abort); +} + +static void coroutine_fn blk_aio_pr_preempt_entry(void *opaque) +{ + BlkPrOutCB *acb = opaque; + BlkPrOutCo *prco = &acb->prco; + + prco->ret = blk_aio_pr_do_preempt(prco->blk, prco->old_key, + prco->new_key, prco->type, + prco->abort); + blk_pr_out_complete(acb); +} + + +BlockAIOCB *blk_aio_pr_preempt(BlockBackend *blk, uint64_t cr_key, + uint64_t pr_key, BlockPrType type, + bool abort, BlockCompletionFunc *cb, + void *opaque) +{ + IO_CODE(); + return blk_aio_pr_out(blk, cr_key, pr_key, false, type, false, abort, + blk_aio_pr_preempt_entry, cb, opaque); +} + /* To be called between exactly one pair of blk_inc/dec_in_flight() */ static int coroutine_fn blk_co_do_pdiscard(BlockBackend *blk, int64_t offset, int64_t bytes) diff --git a/block/io.c b/block/io.c index 7217cf811b..105161930e 100644 --- a/block/io.c +++ b/block/io.c @@ -146,6 +146,7 @@ static void bdrv_merge_limits(BlockLimits *dst, const BlockLimits *src) src->min_mem_alignment); dst->max_iov = MIN_NON_ZERO(dst->max_iov, src->max_iov); dst->max_hw_iov = MIN_NON_ZERO(dst->max_hw_iov, src->max_hw_iov); + dst->pr_cap |= src->pr_cap; } typedef struct BdrvRefreshLimitsState { @@ -3220,6 +3221,169 @@ out: return co.ret; } +int coroutine_fn bdrv_co_pr_read_keys(BlockDriverState *bs, + uint32_t *generation, uint32_t num_keys, + uint64_t *keys) +{ + BlockDriver *drv = bs->drv; + CoroutineIOCompletion co = { + .coroutine = qemu_coroutine_self(), + }; + + IO_CODE(); + assert_bdrv_graph_readable(); + + bdrv_inc_in_flight(bs); + if (!drv || !drv->bdrv_co_pr_read_keys) { + co.ret = -ENOTSUP; + goto out; + } + + co.ret = drv->bdrv_co_pr_read_keys(bs, generation, num_keys, keys); +out: + bdrv_dec_in_flight(bs); + return co.ret; +} + +int coroutine_fn bdrv_co_pr_read_reservation(BlockDriverState *bs, + uint32_t *generation, uint64_t *key, BlockPrType *type) +{ + BlockDriver *drv = bs->drv; + CoroutineIOCompletion co = { + .coroutine = qemu_coroutine_self(), + }; + + IO_CODE(); + assert_bdrv_graph_readable(); + + bdrv_inc_in_flight(bs); + if (!drv || !drv->bdrv_co_pr_read_reservation) { + co.ret = -ENOTSUP; + goto out; + } + + co.ret = drv->bdrv_co_pr_read_reservation(bs, generation, key, type); +out: + bdrv_dec_in_flight(bs); + return co.ret; +} + +int coroutine_fn bdrv_co_pr_register(BlockDriverState *bs, uint64_t old_key, + uint64_t new_key, BlockPrType type, bool ptpl, + bool ignore_key) +{ + BlockDriver *drv = bs->drv; + CoroutineIOCompletion co = { + .coroutine = qemu_coroutine_self(), + }; + + IO_CODE(); + assert_bdrv_graph_readable(); + + bdrv_inc_in_flight(bs); + if (!drv || !drv->bdrv_co_pr_register) { + co.ret = -ENOTSUP; + goto out; + } + + co.ret = drv->bdrv_co_pr_register(bs, old_key, new_key, type, + ptpl, ignore_key); +out: + bdrv_dec_in_flight(bs); + return co.ret; +} + +int coroutine_fn bdrv_co_pr_reserve(BlockDriverState *bs, uint64_t key, + BlockPrType type) +{ + BlockDriver *drv = bs->drv; + CoroutineIOCompletion co = { + .coroutine = qemu_coroutine_self(), + }; + + IO_CODE(); + assert_bdrv_graph_readable(); + + bdrv_inc_in_flight(bs); + if (!drv || !drv->bdrv_co_pr_reserve) { + co.ret = -ENOTSUP; + goto out; + } + + co.ret = drv->bdrv_co_pr_reserve(bs, key, type); +out: + bdrv_dec_in_flight(bs); + return co.ret; +} + +int coroutine_fn bdrv_co_pr_release(BlockDriverState *bs, uint64_t key, + BlockPrType type) +{ + BlockDriver *drv = bs->drv; + CoroutineIOCompletion co = { + .coroutine = qemu_coroutine_self(), + }; + + IO_CODE(); + assert_bdrv_graph_readable(); + + bdrv_inc_in_flight(bs); + if (!drv || !drv->bdrv_co_pr_release) { + co.ret = -ENOTSUP; + goto out; + } + + co.ret = drv->bdrv_co_pr_release(bs, key, type); +out: + bdrv_dec_in_flight(bs); + return co.ret; +} + +int coroutine_fn bdrv_co_pr_clear(BlockDriverState *bs, uint64_t key) +{ + BlockDriver *drv = bs->drv; + CoroutineIOCompletion co = { + .coroutine = qemu_coroutine_self(), + }; + + IO_CODE(); + assert_bdrv_graph_readable(); + + bdrv_inc_in_flight(bs); + if (!drv || !drv->bdrv_co_pr_clear) { + co.ret = -ENOTSUP; + goto out; + } + + co.ret = drv->bdrv_co_pr_clear(bs, key); +out: + bdrv_dec_in_flight(bs); + return co.ret; +} + +int coroutine_fn bdrv_co_pr_preempt(BlockDriverState *bs, uint64_t cr_key, + uint64_t pr_key, BlockPrType type, bool abort) +{ + BlockDriver *drv = bs->drv; + CoroutineIOCompletion co = { + .coroutine = qemu_coroutine_self(), + }; + + IO_CODE(); + assert_bdrv_graph_readable(); + + bdrv_inc_in_flight(bs); + if (!drv || !drv->bdrv_co_pr_preempt) { + co.ret = -ENOTSUP; + goto out; + } + + co.ret = drv->bdrv_co_pr_preempt(bs, cr_key, pr_key, type, abort); +out: + bdrv_dec_in_flight(bs); + return co.ret; +} + int coroutine_fn bdrv_co_zone_report(BlockDriverState *bs, int64_t offset, unsigned int *nr_zones, BlockZoneDescriptor *zones) diff --git a/include/block/block-common.h b/include/block/block-common.h index a846023a09..7ca4e2328f 100644 --- a/include/block/block-common.h +++ b/include/block/block-common.h @@ -524,6 +524,46 @@ typedef enum { BDRV_FIX_ERRORS = 2, } BdrvCheckMode; +/** + * According SCSI protocol(chapter 5.9 of SCSI Primary Commands - 4) + * and NVMe protocol(chapter 7.2 of NVMe Base Specification 2.0), + * the persistent reservation types and persistent capabilities of + * the public layer block are abstracted. + */ +typedef enum { + BLK_PR_WRITE_EXCLUSIVE = 0x1, + BLK_PR_EXCLUSIVE_ACCESS = 0x2, + BLK_PR_WRITE_EXCLUSIVE_REGS_ONLY = 0x3, + BLK_PR_EXCLUSIVE_ACCESS_REGS_ONLY = 0x4, + BLK_PR_WRITE_EXCLUSIVE_ALL_REGS = 0x5, + BLK_PR_EXCLUSIVE_ACCESS_ALL_REGS = 0x6, +} BlockPrType; + +typedef enum BLKPrCap { + /* Persist Through Power Loss */ + BLK_PR_CAP_PTPL = 1 << 0, + /* Write Exclusive reservation type */ + BLK_PR_CAP_WR_EX = 1 << 1, + /* Exclusive Access reservation type */ + BLK_PR_CAP_EX_AC = 1 << 2, + /* Write Exclusive Registrants Only reservation type */ + BLK_PR_CAP_WR_EX_RO = 1 << 3, + /* Exclusive Access Registrants Only reservation type */ + BLK_PR_CAP_EX_AC_RO = 1 << 4, + /* Write Exclusive All Registrants reservation type */ + BLK_PR_CAP_WR_EX_AR = 1 << 5, + /* Exclusive Access All Registrants reservation type */ + BLK_PR_CAP_EX_AC_AR = 1 << 6, + + BLK_PR_CAP_ALL = (BLK_PR_CAP_PTPL | + BLK_PR_CAP_WR_EX | + BLK_PR_CAP_EX_AC | + BLK_PR_CAP_WR_EX_RO | + BLK_PR_CAP_EX_AC_RO | + BLK_PR_CAP_WR_EX_AR | + BLK_PR_CAP_EX_AC_AR), +} BLKPrCap; + typedef struct BlockSizes { uint32_t phys; uint32_t log; diff --git a/include/block/block-io.h b/include/block/block-io.h index b49e0537dd..908361862b 100644 --- a/include/block/block-io.h +++ b/include/block/block-io.h @@ -106,6 +106,26 @@ void bdrv_aio_cancel_async(BlockAIOCB *acb); int coroutine_fn GRAPH_RDLOCK bdrv_co_ioctl(BlockDriverState *bs, int req, void *buf); +int coroutine_fn GRAPH_RDLOCK +bdrv_co_pr_read_keys(BlockDriverState *bs, uint32_t *generation, + uint32_t num_keys, uint64_t *keys); +int coroutine_fn GRAPH_RDLOCK +bdrv_co_pr_read_reservation(BlockDriverState *bs, uint32_t *generation, + uint64_t *key, BlockPrType *type); +int coroutine_fn GRAPH_RDLOCK +bdrv_co_pr_register(BlockDriverState *bs, uint64_t old_key, + uint64_t new_key, BlockPrType type, + bool ptpl, bool ignore_key); +int coroutine_fn GRAPH_RDLOCK +bdrv_co_pr_reserve(BlockDriverState *bs, uint64_t key, BlockPrType type); +int coroutine_fn GRAPH_RDLOCK +bdrv_co_pr_release(BlockDriverState *bs, uint64_t key, BlockPrType type); +int coroutine_fn GRAPH_RDLOCK +bdrv_co_pr_clear(BlockDriverState *bs, uint64_t key); +int coroutine_fn GRAPH_RDLOCK +bdrv_co_pr_preempt(BlockDriverState *bs, uint64_t cr_key, uint64_t pr_key, + BlockPrType type, bool abort); + /* Ensure contents are flushed to disk. */ int coroutine_fn GRAPH_RDLOCK bdrv_co_flush(BlockDriverState *bs); diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h index 761276127e..6e628069e9 100644 --- a/include/block/block_int-common.h +++ b/include/block/block_int-common.h @@ -766,6 +766,87 @@ struct BlockDriver { int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_ioctl)( BlockDriverState *bs, unsigned long int req, void *buf); + /* + * Persistent reservation series api. + * Please refer to chapter 5.9 of SCSI Primary Commands - 4 or + * chapter 7 of NVMe Base Specification 2.0. + * + * The block layer driver should implement all the following APIs + * or none at all, including: bdrv_co_pr_read_keys, + * bdrv_co_pr_read_reservation, bdrv_co_pr_register, + * bdrv_co_pr_reserve, bdrv_co_pr_release, + * bdrv_co_pr_clear and bdrv_co_pr_preempt. + * + * Read the registered keys and return them in the @keys. + * @generation: The generation of the reservation key. + * @num_keys: The maximum number of keys that can be transmitted. + * @keys: Registered keys array. + * + * On success, store generation in @generation and store keys @keys + * and return the number of @keys. + * On failure return -errno. + */ + int coroutine_fn GRAPH_RDLOCK_PTR(*bdrv_co_pr_read_keys)( + BlockDriverState *bs, uint32_t *generation, + uint32_t num_keys, uint64_t *keys); + /* + * Read the reservation key and store it in the @key. + * @generation: The generation of the reservation key. + * @key: The reservation key. + * @type: Type of the reservation key. + * + * On success, store generation in @generation, store the + * reservation key in @key and return the number of @key + * which used to determine whether the reservation key exists. + * On failure return -errno. + */ + int coroutine_fn GRAPH_RDLOCK_PTR(*bdrv_co_pr_read_reservation)( + BlockDriverState *bs, uint32_t *generation, + uint64_t *key, BlockPrType *type); + /* + * Register, unregister, or replace a reservation key. + * @old_key: The current reservation key associated with the host. + * @new_key: The new reservation Key. + * @type: Type of the reservation key. + * @ignore_key: Ignore or not @old_key. + * @ptpl: Whether to support Persist Through Power Loss(PTPL). + */ + int coroutine_fn GRAPH_RDLOCK_PTR(*bdrv_co_pr_register)( + BlockDriverState *bs, uint64_t old_key, + uint64_t new_key, BlockPrType type, + bool ptpl, bool ignore_key); + /* + * Acquire a reservation on a host. + * @key: The current reservation key associated with the host. + * @type: Type of the reservation key. + */ + int coroutine_fn GRAPH_RDLOCK_PTR(*bdrv_co_pr_reserve)( + BlockDriverState *bs, uint64_t key, BlockPrType type); + /* + * Release a reservation on a host. + * @key: The current reservation key associated with the host. + * @type: Type of the reservation key. + */ + int coroutine_fn GRAPH_RDLOCK_PTR(*bdrv_co_pr_release)( + BlockDriverState *bs, uint64_t key, BlockPrType type); + /** + * Clear reservations on a host. + * @key: The current reservation key associated with the host. + */ + int coroutine_fn GRAPH_RDLOCK_PTR(*bdrv_co_pr_clear)( + BlockDriverState *bs, uint64_t key); + /* + * Preempt a reservation held on a host. + * @cr_key: The current reservation key associated with the host. + * @pr_key: The preempt reservation Key which to be + * unregistered from the namespace. + * @type: Type of the reservation key. + * @abort: Whether to abort a reservation held on a host. + */ + int coroutine_fn GRAPH_RDLOCK_PTR(*bdrv_co_pr_preempt)( + BlockDriverState *bs, uint64_t cr_key, + uint64_t pr_key, BlockPrType type, bool abort); + /* * Returns 0 for completed check, -errno for internal errors. * The check results are stored in result. @@ -899,6 +980,9 @@ typedef struct BlockLimits { uint32_t max_active_zones; uint32_t write_granularity; + + /* Persistent reservation capacities. */ + uint8_t pr_cap; } BlockLimits; typedef struct BdrvOpBlocker BdrvOpBlocker; diff --git a/include/sysemu/block-backend-io.h b/include/sysemu/block-backend-io.h index d174275a5c..b3d49a3c6f 100644 --- a/include/sysemu/block-backend-io.h +++ b/include/sysemu/block-backend-io.h @@ -62,6 +62,30 @@ void blk_aio_cancel_async(BlockAIOCB *acb); BlockAIOCB *blk_aio_ioctl(BlockBackend *blk, unsigned long int req, void *buf, BlockCompletionFunc *cb, void *opaque); +BlockAIOCB *blk_aio_pr_read_keys(BlockBackend *blk, uint32_t *generation, + uint32_t num_keys, uint64_t *keys, + BlockCompletionFunc *cb, void *opaque); +BlockAIOCB *blk_aio_pr_read_reservation(BlockBackend *blk, uint32_t *generation, + uint64_t *key, BlockPrType *type, + BlockCompletionFunc *cb, void *opaque); +BlockAIOCB *blk_aio_pr_register(BlockBackend *blk, uint64_t old_key, + uint64_t new_key, BlockPrType type, + bool ptpl, bool ignore_key, + BlockCompletionFunc *cb, + void *opaque); +BlockAIOCB *blk_aio_pr_reserve(BlockBackend *blk, uint64_t key, + BlockPrType type, + BlockCompletionFunc *cb, + void *opaque); +BlockAIOCB *blk_aio_pr_release(BlockBackend *blk, uint64_t key, + BlockPrType type, BlockCompletionFunc *cb, + void *opaque); +BlockAIOCB *blk_aio_pr_clear(BlockBackend *blk, uint64_t key, + BlockCompletionFunc *cb, void *opaque); +BlockAIOCB *blk_aio_pr_preempt(BlockBackend *blk, uint64_t cr_key, + uint64_t pr_key, BlockPrType type, bool abort, + BlockCompletionFunc *cb, void *opaque); + void blk_inc_in_flight(BlockBackend *blk); void blk_dec_in_flight(BlockBackend *blk); From patchwork Fri Jul 5 10:56:06 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Changqi Lu X-Patchwork-Id: 1957277 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=bytedance.com header.i=@bytedance.com header.a=rsa-sha256 header.s=google header.b=Kx44+b9T; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=patchwork.ozlabs.org) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4WFr8B4WBdz1xqb for ; Fri, 5 Jul 2024 20:57:46 +1000 (AEST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1sPgcF-0002C7-4J; Fri, 05 Jul 2024 06:56:35 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1sPgcD-0002B6-QZ for qemu-devel@nongnu.org; Fri, 05 Jul 2024 06:56:33 -0400 Received: from mail-pl1-x633.google.com ([2607:f8b0:4864:20::633]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1sPgcC-0006ar-5L for qemu-devel@nongnu.org; Fri, 05 Jul 2024 06:56:33 -0400 Received: by mail-pl1-x633.google.com with SMTP id d9443c01a7336-1fb05ac6b77so8891755ad.0 for ; Fri, 05 Jul 2024 03:56:31 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bytedance.com; s=google; t=1720176991; x=1720781791; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=ROim7xG4VeV7okIeoWk1lldyf4YzP1rLfO+fx4YPjhw=; b=Kx44+b9T5AMVtDhiM25kkEDuPNwTzfoj94yX5Ahdx3PuIZ6JIIx0LNRtkZHHA8TBH0 hiqu0LxhMkBwA7yKkmon/sS90TaKGFYBtBjkUPesaQMEuWd5CV5gXwpHSYSibXV/E8vd nlgyWzSnSAVIT7XzukXQYh+KmVUhZgozHs40l/xc+nGJSR3PWxG825BuhMRwQfzQ3e4C 2J71bVl9adZ2sQ3jhIaES73wCFNE7RWDntkprpkpQ4/DWc1JHPFDJLWs5chaERkxtkb/ c0n69TxyjXtxsLLNG5uufgekI6lwNJ2Hm/S/7nlBBNstSUP0sEnfdDUD03eMBTO2JD+b Prig== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1720176991; x=1720781791; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=ROim7xG4VeV7okIeoWk1lldyf4YzP1rLfO+fx4YPjhw=; b=B45Py4fNIB05Ep7MUFx5sk5bIKQJR/bqOpjKWUQt5E+OwFwRqbaSOicfD2sLEpNB2G eUcSnMdAlousF8rNEAlQXJyIjV4gYpF3KRwCJocJJ/9Cc6Cr+4EJcFomWJAL8b/tUuIu qFVhLwAnU2GjmRD7l81oSvdkvgKXSY4Kpj16XCtNrz6YdvHTVOpm4BIPW4Huoz9WcytC CmkOs3ITz7DvYzQJghnbpCKbWxDdrpdbimDcCqBtsPcMlCn9SyryPf4fDIxlY9yC6Wm3 ebIpRSEnq02UCTybdHhWfjUeC12/1JhXcM57UrgkuSnT5T0lZRBNHG1tRLvWssIOLXAD gdyw== X-Forwarded-Encrypted: i=1; AJvYcCW5eLa49ahYI9x8aDQ6QYSP4oApGfugv3488utbbqFs5JYFji02LgFEgOI2qa/Z0pr0cjdvvWMSzRLxfedQoVg8WpUqlnY= X-Gm-Message-State: AOJu0YywMEuJJjA3AIb9dSks4Zlans1+N0cdeAj2XYxmtI9tNC1NQOFm iJFWQJhVyFNVm8CAgkiW+WTasUHgjCxbffHyFOOPO6oFgB1uM9URVM6yFoUJOgI= X-Google-Smtp-Source: AGHT+IHdqvZQqbQvouqUnBwhoqH2w60e9fQTBpR4toW0S7MN9G22FzrDAqF6N7Rh/67KMZjsGmVQFg== X-Received: by 2002:a17:903:2307:b0:1fb:34ef:444b with SMTP id d9443c01a7336-1fb34ef4d00mr37181055ad.54.1720176990704; Fri, 05 Jul 2024 03:56:30 -0700 (PDT) Received: from n37-006-243.byted.org ([180.184.84.173]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-1fac0ba60a2sm141292125ad.0.2024.07.05.03.56.27 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 05 Jul 2024 03:56:30 -0700 (PDT) From: Changqi Lu To: qemu-block@nongnu.org, qemu-devel@nongnu.org Cc: kwolf@redhat.com, hreitz@redhat.com, stefanha@redhat.com, fam@euphon.net, ronniesahlberg@gmail.com, pbonzini@redhat.com, pl@dlhnet.de, kbusch@kernel.org, its@irrelevant.dk, foss@defmacro.it, philmd@linaro.org, pizhenwei@bytedance.com, Changqi Lu Subject: [PATCH v7 02/10] block/raw: add persistent reservation in/out driver Date: Fri, 5 Jul 2024 18:56:06 +0800 Message-Id: <20240705105614.3377694-3-luchangqi.123@bytedance.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20240705105614.3377694-1-luchangqi.123@bytedance.com> References: <20240705105614.3377694-1-luchangqi.123@bytedance.com> MIME-Version: 1.0 Received-SPF: pass client-ip=2607:f8b0:4864:20::633; envelope-from=luchangqi.123@bytedance.com; helo=mail-pl1-x633.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Add persistent reservation in/out operations for raw driver. The following methods are implemented: bdrv_co_pr_read_keys, bdrv_co_pr_read_reservation, bdrv_co_pr_register, bdrv_co_pr_reserve, bdrv_co_pr_release, bdrv_co_pr_clear and bdrv_co_pr_preempt. Signed-off-by: Changqi Lu Signed-off-by: zhenwei pi Reviewed-by: Stefan Hajnoczi --- block/raw-format.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/block/raw-format.c b/block/raw-format.c index ac7e8495f6..3746bc1bd3 100644 --- a/block/raw-format.c +++ b/block/raw-format.c @@ -454,6 +454,55 @@ raw_co_ioctl(BlockDriverState *bs, unsigned long int req, void *buf) return bdrv_co_ioctl(bs->file->bs, req, buf); } +static int coroutine_fn GRAPH_RDLOCK +raw_co_pr_read_keys(BlockDriverState *bs, uint32_t *generation, + uint32_t num_keys, uint64_t *keys) +{ + + return bdrv_co_pr_read_keys(bs->file->bs, generation, num_keys, keys); +} + +static int coroutine_fn GRAPH_RDLOCK +raw_co_pr_read_reservation(BlockDriverState *bs, uint32_t *generation, + uint64_t *key, BlockPrType *type) +{ + return bdrv_co_pr_read_reservation(bs->file->bs, generation, key, type); +} + +static int coroutine_fn GRAPH_RDLOCK +raw_co_pr_register(BlockDriverState *bs, uint64_t old_key, + uint64_t new_key, BlockPrType type, + bool ptpl, bool ignore_key) +{ + return bdrv_co_pr_register(bs->file->bs, old_key, new_key, + type, ptpl, ignore_key); +} + +static int coroutine_fn GRAPH_RDLOCK +raw_co_pr_reserve(BlockDriverState *bs, uint64_t key, BlockPrType type) +{ + return bdrv_co_pr_reserve(bs->file->bs, key, type); +} + +static int coroutine_fn GRAPH_RDLOCK +raw_co_pr_release(BlockDriverState *bs, uint64_t key, BlockPrType type) +{ + return bdrv_co_pr_release(bs->file->bs, key, type); +} + +static int coroutine_fn GRAPH_RDLOCK +raw_co_pr_clear(BlockDriverState *bs, uint64_t key) +{ + return bdrv_co_pr_clear(bs->file->bs, key); +} + +static int coroutine_fn GRAPH_RDLOCK +raw_co_pr_preempt(BlockDriverState *bs, uint64_t old_key, + uint64_t new_key, BlockPrType type, bool abort) +{ + return bdrv_co_pr_preempt(bs->file->bs, old_key, new_key, type, abort); +} + static int GRAPH_RDLOCK raw_has_zero_init(BlockDriverState *bs) { return bdrv_has_zero_init(bs->file->bs); @@ -672,6 +721,13 @@ BlockDriver bdrv_raw = { .strong_runtime_opts = raw_strong_runtime_opts, .mutable_opts = mutable_opts, .bdrv_cancel_in_flight = raw_cancel_in_flight, + .bdrv_co_pr_read_keys = raw_co_pr_read_keys, + .bdrv_co_pr_read_reservation = raw_co_pr_read_reservation, + .bdrv_co_pr_register = raw_co_pr_register, + .bdrv_co_pr_reserve = raw_co_pr_reserve, + .bdrv_co_pr_release = raw_co_pr_release, + .bdrv_co_pr_clear = raw_co_pr_clear, + .bdrv_co_pr_preempt = raw_co_pr_preempt, }; static void bdrv_raw_init(void) From patchwork Fri Jul 5 10:56:07 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Changqi Lu X-Patchwork-Id: 1957278 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=bytedance.com header.i=@bytedance.com header.a=rsa-sha256 header.s=google header.b=IZ/6ZVsT; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=patchwork.ozlabs.org) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4WFr8B5403z1xr0 for ; Fri, 5 Jul 2024 20:57:46 +1000 (AEST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1sPgcJ-0002Gl-I8; Fri, 05 Jul 2024 06:56:39 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1sPgcH-0002Fn-N3 for qemu-devel@nongnu.org; Fri, 05 Jul 2024 06:56:37 -0400 Received: from mail-pl1-x62b.google.com ([2607:f8b0:4864:20::62b]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1sPgcG-0006bm-0J for qemu-devel@nongnu.org; Fri, 05 Jul 2024 06:56:37 -0400 Received: by mail-pl1-x62b.google.com with SMTP id d9443c01a7336-1fb457b53c8so5287025ad.0 for ; Fri, 05 Jul 2024 03:56:35 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bytedance.com; s=google; t=1720176994; x=1720781794; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=USEpHR6NMIBW3vxaZJ60aZgKZIewwnVEOQkR5GTNazo=; b=IZ/6ZVsT2Tumj7UiVzmQxyTOCDNg7cwFo7Gyx3aEVGzLBCorWwaC1lrPiUo49XtG9N GPOhqc7Lhd0RwaDgYFRseUl50oF6SYlp4noa72Rf+i+XpsbxmWOYQSCjWPsyze6a3VlH HZGWA06ugLbK6/jwaZI5YzWYXS+DVOJRGnxdMoKRjrdrPhMZDGJr9zcDUYbtWGS2Li1j rQnNs2YpPMNg2/achXEMxs8CLinKPr5k9/hZ5FRQsLfMo/WLwKDm1iiB+mkrIBXSQYO3 kKGV7Qn1Xkx8Nh7hTgmgyoLacmhKbJiyKTE6nzm10WaNOo3AyXTUXOpMBkuD8J6IdY6D 44ew== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1720176994; x=1720781794; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=USEpHR6NMIBW3vxaZJ60aZgKZIewwnVEOQkR5GTNazo=; b=n1vXjMT2fabvOUUWIcVumxqTOdfZZfoJzGCAYYV+VNMPZPuwDezqxYoY+ll3lduKXL RCVy2XwIs9pFsJRnQDl7VM9epP4b+gwyN4mervjmh3f/Vr+FwN2qCIxThhHrwvV84DHo VWf/tbQPAbvlfR4UE4aMOxRwMKMVK1n9wVI6HgTvVERAm1M/hWT+eluQUpdA5+5a/7xD +pFS9SS3PblWD4GC6fZxnuUS01AmEgJtg0kMpIaFI5uDKZcXKdPavYpifrD3N96wmtMp PYDjBAHQ5vv5XhQpnnvQgrRPY3g1raLVFjN0jSWnZlxabEle0is6N8mXhUp74JkWF/ny MdzA== X-Forwarded-Encrypted: i=1; AJvYcCXgNHqrN0RHtjT70hrlT267siqErqEEqylOR65NOSty1jRJc39KE6/liPaa0Qjxp8ZMFxyP42+ksdhyJ6P3/aO4dgvSbpw= X-Gm-Message-State: AOJu0YyzVHOJTgFbmjOtt8RGDkodjZrAAc9Lzki1rtjZSHjwXe2dw7dI Xaf1sFk2teA357N3oYkI1ZR8mkigXYp9ASkklkRRHO2GFOsDJIJMrn0om/LlEac= X-Google-Smtp-Source: AGHT+IF+dxVDv4wrKIWIG5XxZutv50Q+Qa8aerhd+XVJ+Kef1fVmU5i2tGpXeUS5Wtd0ASn5c5f9NA== X-Received: by 2002:a17:902:ea02:b0:1fb:59e6:b0e1 with SMTP id d9443c01a7336-1fb59e6b383mr1406375ad.32.1720176994512; Fri, 05 Jul 2024 03:56:34 -0700 (PDT) Received: from n37-006-243.byted.org ([180.184.84.173]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-1fac0ba60a2sm141292125ad.0.2024.07.05.03.56.31 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 05 Jul 2024 03:56:34 -0700 (PDT) From: Changqi Lu To: qemu-block@nongnu.org, qemu-devel@nongnu.org Cc: kwolf@redhat.com, hreitz@redhat.com, stefanha@redhat.com, fam@euphon.net, ronniesahlberg@gmail.com, pbonzini@redhat.com, pl@dlhnet.de, kbusch@kernel.org, its@irrelevant.dk, foss@defmacro.it, philmd@linaro.org, pizhenwei@bytedance.com, Changqi Lu Subject: [PATCH v7 03/10] scsi/constant: add persistent reservation in/out protocol constants Date: Fri, 5 Jul 2024 18:56:07 +0800 Message-Id: <20240705105614.3377694-4-luchangqi.123@bytedance.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20240705105614.3377694-1-luchangqi.123@bytedance.com> References: <20240705105614.3377694-1-luchangqi.123@bytedance.com> MIME-Version: 1.0 Received-SPF: pass client-ip=2607:f8b0:4864:20::62b; envelope-from=luchangqi.123@bytedance.com; helo=mail-pl1-x62b.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Add constants for the persistent reservation in/out protocol in the scsi/constant module. The constants include the persistent reservation command, type, and scope values defined in sections 6.13 and 6.14 of the SCSI Primary Commands-4 (SPC-4) specification. Signed-off-by: Changqi Lu Signed-off-by: zhenwei pi Reviewed-by: Stefan Hajnoczi --- include/scsi/constants.h | 52 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/include/scsi/constants.h b/include/scsi/constants.h index 9b98451912..922a314535 100644 --- a/include/scsi/constants.h +++ b/include/scsi/constants.h @@ -319,4 +319,56 @@ #define IDENT_DESCR_TGT_DESCR_SIZE 32 #define XCOPY_BLK2BLK_SEG_DESC_SIZE 28 +typedef enum { + SCSI_PR_WRITE_EXCLUSIVE = 0x01, + SCSI_PR_EXCLUSIVE_ACCESS = 0x03, + SCSI_PR_WRITE_EXCLUSIVE_REGS_ONLY = 0x05, + SCSI_PR_EXCLUSIVE_ACCESS_REGS_ONLY = 0x06, + SCSI_PR_WRITE_EXCLUSIVE_ALL_REGS = 0x07, + SCSI_PR_EXCLUSIVE_ACCESS_ALL_REGS = 0x08, +} SCSIPrType; + +typedef enum { + SCSI_PR_LU_SCOPE = 0x00, +} SCSIPrScope; + +typedef enum { + SCSI_PR_OUT_REGISTER = 0x0, + SCSI_PR_OUT_RESERVE = 0x1, + SCSI_PR_OUT_RELEASE = 0x2, + SCSI_PR_OUT_CLEAR = 0x3, + SCSI_PR_OUT_PREEMPT = 0x4, + SCSI_PR_OUT_PREEMPT_AND_ABORT = 0x5, + SCSI_PR_OUT_REG_AND_IGNORE_KEY = 0x6, + SCSI_PR_OUT_REG_AND_MOVE = 0x7, +} SCSIPrOutAction; + +typedef enum { + SCSI_PR_IN_READ_KEYS = 0x0, + SCSI_PR_IN_READ_RESERVATION = 0x1, + SCSI_PR_IN_REPORT_CAPABILITIES = 0x2, +} SCSIPrInAction; + +typedef enum { + /* Exclusive Access All Registrants reservation type */ + SCSI_PR_CAP_EX_AC_AR = 1 << 0, + /* Write Exclusive reservation type */ + SCSI_PR_CAP_WR_EX = 1 << 9, + /* Exclusive Access reservation type */ + SCSI_PR_CAP_EX_AC = 1 << 11, + /* Write Exclusive Registrants Only reservation type */ + SCSI_PR_CAP_WR_EX_RO = 1 << 13, + /* Exclusive Access Registrants Only reservation type */ + SCSI_PR_CAP_EX_AC_RO = 1 << 14, + /* Write Exclusive All Registrants reservation type */ + SCSI_PR_CAP_WR_EX_AR = 1 << 15, + + SCSI_PR_CAP_ALL = (SCSI_PR_CAP_EX_AC_AR | + SCSI_PR_CAP_WR_EX | + SCSI_PR_CAP_EX_AC | + SCSI_PR_CAP_WR_EX_RO | + SCSI_PR_CAP_EX_AC_RO | + SCSI_PR_CAP_WR_EX_AR), +} SCSIPrCap; + #endif From patchwork Fri Jul 5 10:56:08 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Changqi Lu X-Patchwork-Id: 1957286 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=bytedance.com header.i=@bytedance.com header.a=rsa-sha256 header.s=google header.b=XmatrLwF; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=patchwork.ozlabs.org) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4WFr8f6ThPz1xqb for ; Fri, 5 Jul 2024 20:58:10 +1000 (AEST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1sPgcM-0002Kz-AB; Fri, 05 Jul 2024 06:56:42 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1sPgcL-0002Jg-74 for qemu-devel@nongnu.org; Fri, 05 Jul 2024 06:56:41 -0400 Received: from mail-pg1-x533.google.com ([2607:f8b0:4864:20::533]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1sPgcJ-0006cJ-IV for qemu-devel@nongnu.org; Fri, 05 Jul 2024 06:56:40 -0400 Received: by mail-pg1-x533.google.com with SMTP id 41be03b00d2f7-75a6c290528so867365a12.1 for ; Fri, 05 Jul 2024 03:56:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bytedance.com; s=google; t=1720176998; x=1720781798; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=CUQGygF7ax3lHkGrG99vLN6/xen2jiCuqCocfv+MI40=; b=XmatrLwFasqeMSXeOZBdUv5DefKEScXJlZjAbRubKccYZeGw5BRddSKA04/IF9v/Rx cAeZqCLXvZkBMlt3+AqoSE2672W03ORGYCkOS44EjmB+7Ok2k/RvoUnJ0eb2gArPJV/M Rt8MrThkjrXmIsYqmOW72l82/cDw56RALWchfMQ4KRbBz2JdZu6+8iU8pwt+9umR4VOo wfw9aAWHRfIyMCs2A6BQOBW6HTUxZ64UlBVz/ajZrMpBj4ZdiZD+nlii5Gkq1dXXJw80 O3HOXLk4n80VmSd9nE+wmrXkpGZemWzYxQRdOf08dMArMdHGBOGqKVikVJ3Uzf1wwwXr cUFA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1720176998; x=1720781798; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=CUQGygF7ax3lHkGrG99vLN6/xen2jiCuqCocfv+MI40=; b=c22d9KxEu3UVqMHDtqpjOUy8vDBB05ZWVZU3mTi2oxYy1y5Uo5uxzvcsYgOenNILdI Mb5wyzD7+yP5KtWf0Pq8zQ2AGffnzaj/whE4GEwkMuedgnwpIXFdzfDPvYfH1ng4J7jp 92zhvMSP0/BqyUQq41L0Y44143OikctEa9TYMvptT8bmE+rsHZ3mtGrZ5xWKS2xvd/So J11ViqiAOcwMvQS8NsjG0FQgNA3MHVlNpGRChejVdx9MB7bd2WDwLoy6sDcxyKS9JB6w EsmTN4QvnZ+jL31RCNKc1MF3oBcHOUb7zYst8nGv1y+geSPYS2Yms1VLz+LwXAbxJb1I F2pQ== X-Forwarded-Encrypted: i=1; AJvYcCXRky6xyR6RBTm/wKgO4n2Da6AtPR3LiEYhZW/fltju62nSZdb8y+KkNEEgSxVAkGeNeWu9n05ZBgBuzgD8HmualHk4ylU= X-Gm-Message-State: AOJu0Yxu9AK6cFv/OCH16NWErfTW1F7KRWrxem12TmgOAeqjKxoAkZ22 iCqPMRAvZYSR4eLmk06YXeWQF1N9FAZ/KmLRp+ptgAnsCN0HdUSC35si552Wpm4= X-Google-Smtp-Source: AGHT+IH0T3GOqJ3iklD/KYVe5Y58Icg44Es8SEyuOSlgPB2S86a+J56+x0vedXt2fmo8+Acn7ksgtQ== X-Received: by 2002:a05:6a20:258a:b0:1bd:2562:6a06 with SMTP id adf61e73a8af0-1c0cc75c779mr4229117637.32.1720176998275; Fri, 05 Jul 2024 03:56:38 -0700 (PDT) Received: from n37-006-243.byted.org ([180.184.84.173]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-1fac0ba60a2sm141292125ad.0.2024.07.05.03.56.34 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 05 Jul 2024 03:56:37 -0700 (PDT) From: Changqi Lu To: qemu-block@nongnu.org, qemu-devel@nongnu.org Cc: kwolf@redhat.com, hreitz@redhat.com, stefanha@redhat.com, fam@euphon.net, ronniesahlberg@gmail.com, pbonzini@redhat.com, pl@dlhnet.de, kbusch@kernel.org, its@irrelevant.dk, foss@defmacro.it, philmd@linaro.org, pizhenwei@bytedance.com, Changqi Lu Subject: [PATCH v7 04/10] scsi/util: add helper functions for persistent reservation types conversion Date: Fri, 5 Jul 2024 18:56:08 +0800 Message-Id: <20240705105614.3377694-5-luchangqi.123@bytedance.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20240705105614.3377694-1-luchangqi.123@bytedance.com> References: <20240705105614.3377694-1-luchangqi.123@bytedance.com> MIME-Version: 1.0 Received-SPF: pass client-ip=2607:f8b0:4864:20::533; envelope-from=luchangqi.123@bytedance.com; helo=mail-pg1-x533.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org This commit introduces two helper functions that facilitate the conversion between the persistent reservation types used in the SCSI protocol and those used in the block layer. Signed-off-by: Changqi Lu Signed-off-by: zhenwei pi Reviewed-by: Stefan Hajnoczi --- include/scsi/utils.h | 8 +++++ scsi/utils.c | 81 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 89 insertions(+) diff --git a/include/scsi/utils.h b/include/scsi/utils.h index d5c8efa16e..89a0b082fb 100644 --- a/include/scsi/utils.h +++ b/include/scsi/utils.h @@ -1,6 +1,8 @@ #ifndef SCSI_UTILS_H #define SCSI_UTILS_H +#include "block/block-common.h" +#include "scsi/constants.h" #ifdef CONFIG_LINUX #include #endif @@ -135,6 +137,12 @@ uint32_t scsi_data_cdb_xfer(uint8_t *buf); uint32_t scsi_cdb_xfer(uint8_t *buf); int scsi_cdb_length(uint8_t *buf); +BlockPrType scsi_pr_type_to_block(SCSIPrType type); +SCSIPrType block_pr_type_to_scsi(BlockPrType type); + +uint8_t scsi_pr_cap_to_block(uint16_t scsi_pr_cap); +uint16_t block_pr_cap_to_scsi(uint8_t block_pr_cap); + /* Linux SG_IO interface. */ #ifdef CONFIG_LINUX #define SG_ERR_DRIVER_TIMEOUT 0x06 diff --git a/scsi/utils.c b/scsi/utils.c index 357b036671..0dfdeb499d 100644 --- a/scsi/utils.c +++ b/scsi/utils.c @@ -658,3 +658,84 @@ int scsi_sense_from_host_status(uint8_t host_status, } return GOOD; } + +BlockPrType scsi_pr_type_to_block(SCSIPrType type) +{ + switch (type) { + case SCSI_PR_WRITE_EXCLUSIVE: + return BLK_PR_WRITE_EXCLUSIVE; + case SCSI_PR_EXCLUSIVE_ACCESS: + return BLK_PR_EXCLUSIVE_ACCESS; + case SCSI_PR_WRITE_EXCLUSIVE_REGS_ONLY: + return BLK_PR_WRITE_EXCLUSIVE_REGS_ONLY; + case SCSI_PR_EXCLUSIVE_ACCESS_REGS_ONLY: + return BLK_PR_EXCLUSIVE_ACCESS_REGS_ONLY; + case SCSI_PR_WRITE_EXCLUSIVE_ALL_REGS: + return BLK_PR_WRITE_EXCLUSIVE_ALL_REGS; + case SCSI_PR_EXCLUSIVE_ACCESS_ALL_REGS: + return BLK_PR_EXCLUSIVE_ACCESS_ALL_REGS; + } + + return 0; +} + +SCSIPrType block_pr_type_to_scsi(BlockPrType type) +{ + switch (type) { + case BLK_PR_WRITE_EXCLUSIVE: + return SCSI_PR_WRITE_EXCLUSIVE; + case BLK_PR_EXCLUSIVE_ACCESS: + return SCSI_PR_EXCLUSIVE_ACCESS; + case BLK_PR_WRITE_EXCLUSIVE_REGS_ONLY: + return SCSI_PR_WRITE_EXCLUSIVE_REGS_ONLY; + case BLK_PR_EXCLUSIVE_ACCESS_REGS_ONLY: + return SCSI_PR_EXCLUSIVE_ACCESS_REGS_ONLY; + case BLK_PR_WRITE_EXCLUSIVE_ALL_REGS: + return SCSI_PR_WRITE_EXCLUSIVE_ALL_REGS; + case BLK_PR_EXCLUSIVE_ACCESS_ALL_REGS: + return SCSI_PR_EXCLUSIVE_ACCESS_ALL_REGS; + } + + return 0; +} + + +uint8_t scsi_pr_cap_to_block(uint16_t scsi_pr_cap) +{ + uint8_t res = 0; + + res |= (scsi_pr_cap & SCSI_PR_CAP_WR_EX) ? + BLK_PR_CAP_WR_EX : 0; + res |= (scsi_pr_cap & SCSI_PR_CAP_EX_AC) ? + BLK_PR_CAP_EX_AC : 0; + res |= (scsi_pr_cap & SCSI_PR_CAP_WR_EX_RO) ? + BLK_PR_CAP_WR_EX_RO : 0; + res |= (scsi_pr_cap & SCSI_PR_CAP_EX_AC_RO) ? + BLK_PR_CAP_EX_AC_RO : 0; + res |= (scsi_pr_cap & SCSI_PR_CAP_WR_EX_AR) ? + BLK_PR_CAP_WR_EX_AR : 0; + res |= (scsi_pr_cap & SCSI_PR_CAP_EX_AC_AR) ? + BLK_PR_CAP_EX_AC_AR : 0; + + return res; +} + +uint16_t block_pr_cap_to_scsi(uint8_t block_pr_cap) +{ + uint16_t res = 0; + + res |= (block_pr_cap & BLK_PR_CAP_WR_EX) ? + SCSI_PR_CAP_WR_EX : 0; + res |= (block_pr_cap & BLK_PR_CAP_EX_AC) ? + SCSI_PR_CAP_EX_AC : 0; + res |= (block_pr_cap & BLK_PR_CAP_WR_EX_RO) ? + SCSI_PR_CAP_WR_EX_RO : 0; + res |= (block_pr_cap & BLK_PR_CAP_EX_AC_RO) ? + SCSI_PR_CAP_EX_AC_RO : 0; + res |= (block_pr_cap & BLK_PR_CAP_WR_EX_AR) ? + SCSI_PR_CAP_WR_EX_AR : 0; + res |= (block_pr_cap & BLK_PR_CAP_EX_AC_AR) ? + SCSI_PR_CAP_EX_AC_AR : 0; + + return res; +} From patchwork Fri Jul 5 10:56:09 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Changqi Lu X-Patchwork-Id: 1957281 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=bytedance.com header.i=@bytedance.com header.a=rsa-sha256 header.s=google header.b=dv3w4zeP; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=patchwork.ozlabs.org) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4WFr8V1rCwz1xqb for ; Fri, 5 Jul 2024 20:58:02 +1000 (AEST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1sPgcR-0002Ma-6R; Fri, 05 Jul 2024 06:56:47 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1sPgcP-0002M8-Lh for qemu-devel@nongnu.org; Fri, 05 Jul 2024 06:56:45 -0400 Received: from mail-pl1-x62f.google.com ([2607:f8b0:4864:20::62f]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1sPgcN-0006ch-Fk for qemu-devel@nongnu.org; Fri, 05 Jul 2024 06:56:45 -0400 Received: by mail-pl1-x62f.google.com with SMTP id d9443c01a7336-1fb0d88fdc8so7232645ad.2 for ; Fri, 05 Jul 2024 03:56:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bytedance.com; s=google; t=1720177002; x=1720781802; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=7mQHIH+tXsVU5BpOvi2zApOoLf+I//9f1DuCkDkrR+I=; b=dv3w4zePakUrWdmnlcgFO+hOjlGXp9BrTyDdsfsCDeqkv+xVZbEGtPhKqfmC2x24TY xDdA3iCO/5b71h+BY6luH3wPos19DBINBlSSkz4TZooS+f6w/eJyT4/uAqHd1kVaU8sX 91/IWioTOH0n/fW0xCuHOmfJbZDWmWBedN2YSTzAelIW58CmmytZjmoLzgyyVXYbmRjZ uBYV8DlLBq5/l07+XhBqmIZ04uPrH+ayY3N8iO2FJ9GgNrKoBE4CNmBzaWUfh/sFcldl R+DTfzxN57a5gNKXoy9koAIf4eGHiDpqcxKaV4TT/q4DVWWnnXKQ2vyx3w3HTHX/8DaS Ggbg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1720177002; x=1720781802; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=7mQHIH+tXsVU5BpOvi2zApOoLf+I//9f1DuCkDkrR+I=; b=AS92xQCC05rWmQG2s+OdYSeK2RcjaqfPe83uXmdaaZgi+Xmt6k2nMAbY9X6l/7BkJo zBcSvaKbPMhzUX3kpzKUC6TiR5rwELGilRUAR6HObu7jF2Bszq+TOv+rlMxFqNUtNQwj bdtlj8cSsAmGB9DOTh28J8aduwQOfBUsBJl+WOwvGOsD9gMeic415RfF6f45lhGcbkET KzZ3XkUVHZrbXyoXLlgnfwfeEOtKkz7wOOI68+n06Et+qirjDFju1IOY51mcLruVhO4S ckZLnvHrkWHZiYoT8Q+Yro2oEtBluW3TXOMxwWviCXmP8GzvDYWYbp+qzalVj2R/MAwP 1iKA== X-Forwarded-Encrypted: i=1; AJvYcCXV6nqtmDNiRsAylcKniVgT77GgEoS100/cg5j5TtyiLexYGb2sZvwz9peZ7xBS6r4osQMnnYUhZ4DbNqULIAMYP5UXLMs= X-Gm-Message-State: AOJu0YytI4ZJyKuvC/sPjT3jpi36lqT3EYryz2ckdk02cASn82dt3XOO U8RMjqIg24SUTXg97HEMY0wGaSF8Cm1UQHbn4ByARh2LI056e1oSesymJ2VyEKo= X-Google-Smtp-Source: AGHT+IHxq7fNmQEzKju8aCMRxXWMgQAyzBuK5qQ+bZJcboSI7cH9JM6EJwRJlmO5uTZi85qpplUCTw== X-Received: by 2002:a17:903:2349:b0:1fa:fbe1:284e with SMTP id d9443c01a7336-1fb33cbb7e4mr34308885ad.0.1720177002118; Fri, 05 Jul 2024 03:56:42 -0700 (PDT) Received: from n37-006-243.byted.org ([180.184.84.173]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-1fac0ba60a2sm141292125ad.0.2024.07.05.03.56.38 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 05 Jul 2024 03:56:41 -0700 (PDT) From: Changqi Lu To: qemu-block@nongnu.org, qemu-devel@nongnu.org Cc: kwolf@redhat.com, hreitz@redhat.com, stefanha@redhat.com, fam@euphon.net, ronniesahlberg@gmail.com, pbonzini@redhat.com, pl@dlhnet.de, kbusch@kernel.org, its@irrelevant.dk, foss@defmacro.it, philmd@linaro.org, pizhenwei@bytedance.com, Changqi Lu Subject: [PATCH v7 05/10] hw/scsi: add persistent reservation in/out api for scsi device Date: Fri, 5 Jul 2024 18:56:09 +0800 Message-Id: <20240705105614.3377694-6-luchangqi.123@bytedance.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20240705105614.3377694-1-luchangqi.123@bytedance.com> References: <20240705105614.3377694-1-luchangqi.123@bytedance.com> MIME-Version: 1.0 Received-SPF: pass client-ip=2607:f8b0:4864:20::62f; envelope-from=luchangqi.123@bytedance.com; helo=mail-pl1-x62f.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Add persistent reservation in/out operations in the SCSI device layer. By introducing the persistent reservation in/out api, this enables the SCSI device to perform reservation-related tasks, including querying keys, querying reservation status, registering reservation keys, initiating and releasing reservations, as well as clearing and preempting reservations held by other keys. These operations are crucial for management and control of shared storage resources in a persistent manner. Signed-off-by: Changqi Lu Signed-off-by: zhenwei pi --- hw/scsi/scsi-disk.c | 368 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 368 insertions(+) diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c index 4bd7af9d0c..f0c3ce774f 100644 --- a/hw/scsi/scsi-disk.c +++ b/hw/scsi/scsi-disk.c @@ -32,6 +32,7 @@ #include "migration/vmstate.h" #include "hw/scsi/emulation.h" #include "scsi/constants.h" +#include "scsi/utils.h" #include "sysemu/block-backend.h" #include "sysemu/blockdev.h" #include "hw/block/block.h" @@ -42,6 +43,7 @@ #include "qemu/cutils.h" #include "trace.h" #include "qom/object.h" +#include "block/block_int.h" #ifdef __linux #include @@ -1474,6 +1476,362 @@ static void scsi_disk_emulate_read_data(SCSIRequest *req) scsi_req_complete(&r->req, GOOD); } +typedef struct SCSIPrReadKeys { + uint32_t generation; + uint32_t num_keys; + uint64_t *keys; + SCSIDiskReq *req; +} SCSIPrReadKeys; + +typedef struct SCSIPrReadReservation { + uint32_t generation; + uint64_t key; + BlockPrType type; + SCSIDiskReq *req; +} SCSIPrReadReservation; + +static void scsi_pr_read_keys_complete(void *opaque, int ret) +{ + int num_keys; + uint8_t *buf; + SCSIPrReadKeys *blk_keys = (SCSIPrReadKeys *)opaque; + SCSIDiskReq *r = blk_keys->req; + SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev); + + assert(blk_get_aio_context(s->qdev.conf.blk) == + qemu_get_current_aio_context()); + + assert(r->req.aiocb != NULL); + r->req.aiocb = NULL; + + if (scsi_disk_req_check_error(r, ret, true)) { + goto done; + } + + buf = scsi_req_get_buf(&r->req); + num_keys = MIN(blk_keys->num_keys, ret); + blk_keys->generation = cpu_to_be32(blk_keys->generation); + memcpy(&buf[0], &blk_keys->generation, 4); + for (int i = 0; i < num_keys; i++) { + blk_keys->keys[i] = cpu_to_be64(blk_keys->keys[i]); + memcpy(&buf[8 + i * 8], &blk_keys->keys[i], 8); + } + num_keys = cpu_to_be32(num_keys * 8); + memcpy(&buf[4], &num_keys, 4); + + scsi_req_data(&r->req, r->buflen); +done: + scsi_req_unref(&r->req); + g_free(blk_keys->keys); + g_free(blk_keys); +} + +static void scsi_disk_emulate_pr_read_keys(SCSIRequest *req) +{ + SCSIPrReadKeys *blk_keys; + SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req); + SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev); + int buflen = MIN(r->req.cmd.xfer, r->buflen); + int num_keys = (buflen - sizeof(uint32_t) * 2) / sizeof(uint64_t); + + if (num_keys <= 0) { + scsi_check_condition(r, SENSE_CODE(INVALID_PARAM_LEN)); + return; + } + + blk_keys = g_new0(SCSIPrReadKeys, 1); + blk_keys->generation = 0; + /* num_keys is the maximum number of keys that can be transmitted */ + blk_keys->num_keys = num_keys; + blk_keys->keys = g_malloc(sizeof(uint64_t) * num_keys); + blk_keys->req = r; + + /* The request is used as the AIO opaque value, so add a ref. */ + scsi_req_ref(&r->req); + r->req.aiocb = blk_aio_pr_read_keys(s->qdev.conf.blk, &blk_keys->generation, + blk_keys->num_keys, blk_keys->keys, + scsi_pr_read_keys_complete, blk_keys); + return; +} + +static void scsi_pr_read_reservation_complete(void *opaque, int ret) +{ + uint8_t *buf; + uint32_t additional_len = 0; + SCSIPrReadReservation *blk_rsv = (SCSIPrReadReservation *)opaque; + SCSIDiskReq *r = blk_rsv->req; + SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev); + + assert(blk_get_aio_context(s->qdev.conf.blk) == + qemu_get_current_aio_context()); + + assert(r->req.aiocb != NULL); + r->req.aiocb = NULL; + + if (scsi_disk_req_check_error(r, ret, true)) { + goto done; + } + + buf = scsi_req_get_buf(&r->req); + blk_rsv->generation = cpu_to_be32(blk_rsv->generation); + memcpy(&buf[0], &blk_rsv->generation, 4); + if (ret) { + additional_len = cpu_to_be32(16); + blk_rsv->key = cpu_to_be64(blk_rsv->key); + memcpy(&buf[8], &blk_rsv->key, 8); + buf[21] = block_pr_type_to_scsi(blk_rsv->type) & 0xf; + } else { + additional_len = cpu_to_be32(0); + } + + memcpy(&buf[4], &additional_len, 4); + scsi_req_data(&r->req, r->buflen); + +done: + scsi_req_unref(&r->req); + g_free(blk_rsv); +} + +static void scsi_disk_emulate_pr_read_reservation(SCSIRequest *req) +{ + SCSIPrReadReservation *blk_rsv; + SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req); + SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev); + int buflen = MIN(r->req.cmd.xfer, r->buflen); + int count = sizeof(uint32_t) * 2 + sizeof(uint64_t) + + sizeof(uint32_t) + sizeof(uint8_t) * 2; + + if (buflen < count) { + scsi_check_condition(r, SENSE_CODE(INVALID_PARAM_LEN)); + return; + } + + blk_rsv = g_malloc(sizeof(*blk_rsv)); + blk_rsv->generation = 0; + blk_rsv->key = 0; + blk_rsv->type = 0; + blk_rsv->req = r; + + /* The request is used as the AIO opaque value, so add a ref. */ + scsi_req_ref(&r->req); + r->req.aiocb = blk_aio_pr_read_reservation(s->qdev.conf.blk, + &blk_rsv->generation, &blk_rsv->key, &blk_rsv->type, + scsi_pr_read_reservation_complete, blk_rsv); + return; +} + +static void scsi_disk_emulate_pr_report_capabilities(SCSIRequest *req) +{ + SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req); + SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev); + BlockDriverState *bs = blk_bs(s->qdev.conf.blk); + uint8_t blk_pr_cap = bs->bl.pr_cap; + uint8_t *buf = scsi_req_get_buf(req); + uint16_t pr_cap; + /* + * according to response of report_capabilities + * command of chapter 6.13 of spc4 + */ + int len = sizeof(uint16_t) * 2 + sizeof(uint8_t) * 4; + + if (len > r->buflen) { + scsi_check_condition(r, SENSE_CODE(INVALID_PARAM_LEN)); + return; + } + + len = cpu_to_be16(len); + memcpy(&buf[0], &len, 2); + /* enable PTPL_C */ + buf[2] = 1; + buf[3] = (blk_pr_cap & BLK_PR_CAP_PTPL) ? 1 : 0; + /* enable TMV */ + buf[3] |= 1 << 7; + + /* enable persistent reservation type */ + pr_cap = block_pr_cap_to_scsi(blk_pr_cap); + buf[4] = pr_cap >> 8 & 0xff; + buf[5] = pr_cap & 0xff; + + scsi_req_data(&r->req, len); + return; +} + +static void scsi_aio_pr_complete(void *opaque, int ret) +{ + SCSIDiskReq *r = (SCSIDiskReq *)opaque; + SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev); + + /* The request must only run in the BlockBackend's AioContext */ + assert(blk_get_aio_context(s->qdev.conf.blk) == + qemu_get_current_aio_context()); + + assert(r->req.aiocb != NULL); + r->req.aiocb = NULL; + + if (scsi_disk_req_check_error(r, ret, true)) { + goto done; + } + + scsi_req_complete(&r->req, GOOD); + +done: + scsi_req_unref(&r->req); +} + +static void scsi_disk_emulate_pr_register(SCSIDiskReq *r, uint64_t r_key, + uint64_t sa_key, SCSIPrType type, + uint8_t aptpl, bool ignore_key) +{ + SCSIRequest *req = &r->req; + SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev); + + /* The request is used as the AIO opaque value, so add a ref. */ + scsi_req_ref(&r->req); + r->req.aiocb = blk_aio_pr_register(s->qdev.conf.blk, r_key, sa_key, + scsi_pr_type_to_block(type), + aptpl ? true : false, + ignore_key, scsi_aio_pr_complete, r); + + return; +} + +static void scsi_disk_emulate_pr_reserve(SCSIDiskReq *r, uint64_t r_key, + SCSIPrType type) +{ + SCSIRequest *req = &r->req; + SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev); + + /* The request is used as the AIO opaque value, so add a ref. */ + scsi_req_ref(&r->req); + r->req.aiocb = blk_aio_pr_reserve(s->qdev.conf.blk, r_key, + scsi_pr_type_to_block(type), + scsi_aio_pr_complete, r); + + return; +} + +static void scsi_disk_emulate_pr_release(SCSIDiskReq *r, uint64_t r_key, + SCSIPrType type) +{ + SCSIRequest *req = &r->req; + SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev); + + /* The request is used as the AIO opaque value, so add a ref. */ + scsi_req_ref(&r->req); + r->req.aiocb = blk_aio_pr_release(s->qdev.conf.blk, r_key, + scsi_pr_type_to_block(type), + scsi_aio_pr_complete, r); + + return; +} + +static void scsi_disk_emulate_pr_clear(SCSIDiskReq *r, uint64_t r_key) +{ + SCSIRequest *req = &r->req; + SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev); + + /* The request is used as the AIO opaque value, so add a ref. */ + scsi_req_ref(&r->req); + r->req.aiocb = blk_aio_pr_clear(s->qdev.conf.blk, r_key, + scsi_aio_pr_complete, r); + + return; +} + +static void scsi_disk_emulate_pr_preempt(SCSIDiskReq *r, uint64_t r_key, + uint64_t sa_key, SCSIPrType type, + bool abort) +{ + SCSIRequest *req = &r->req; + SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev); + + /* The request is used as the AIO opaque value, so add a ref. */ + scsi_req_ref(&r->req); + r->req.aiocb = blk_aio_pr_preempt(s->qdev.conf.blk, r_key, sa_key, + scsi_pr_type_to_block(type), abort, + scsi_aio_pr_complete, r); + + return; +} + +static void scsi_disk_emulate_pr_in(SCSIRequest *req) +{ + SCSIPrInAction action = req->cmd.buf[1] & 0x1f; + SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req); + + switch (action) { + case SCSI_PR_IN_READ_KEYS: + scsi_disk_emulate_pr_read_keys(req); + break; + case SCSI_PR_IN_READ_RESERVATION: + scsi_disk_emulate_pr_read_reservation(req); + break; + case SCSI_PR_IN_REPORT_CAPABILITIES: + scsi_disk_emulate_pr_report_capabilities(req); + break; + default: + scsi_check_condition(r, SENSE_CODE(INVALID_OPCODE)); + return; + } + + return; +} + +static void scsi_disk_emulate_pr_out(SCSIDiskReq *r, uint8_t *inbuf) +{ + uint8_t aptpl; + uint64_t r_key, sa_key; + SCSIPrOutAction action; + SCSIPrScope scope; + SCSIPrType type; + SCSIRequest *req = &r->req; + + memcpy(&r_key, &inbuf[0], 8); + r_key = be64_to_cpu(r_key); + memcpy(&sa_key, &inbuf[8], 8); + sa_key = be64_to_cpu(sa_key); + memcpy(&aptpl, &inbuf[20], 1); + aptpl = aptpl & 0x01; + action = req->cmd.buf[1] & 0x1f; + scope = (req->cmd.buf[2] >> 4) & 0x0f; + type = req->cmd.buf[2] & 0x0f; + + if (scope != SCSI_PR_LU_SCOPE) { + scsi_req_complete(&r->req, TASK_ABORTED); + return; + } + + switch (action) { + case SCSI_PR_OUT_REGISTER: + scsi_disk_emulate_pr_register(r, r_key, sa_key, type, + aptpl, false); + break; + case SCSI_PR_OUT_REG_AND_IGNORE_KEY: + scsi_disk_emulate_pr_register(r, r_key, sa_key, type, aptpl, true); + break; + case SCSI_PR_OUT_RESERVE: + scsi_disk_emulate_pr_reserve(r, r_key, type); + break; + case SCSI_PR_OUT_RELEASE: + scsi_disk_emulate_pr_release(r, r_key, type); + break; + case SCSI_PR_OUT_CLEAR: + scsi_disk_emulate_pr_clear(r, r_key); + break; + case SCSI_PR_OUT_PREEMPT: + scsi_disk_emulate_pr_preempt(r, r_key, sa_key, type, false); + break; + case SCSI_PR_OUT_PREEMPT_AND_ABORT: + scsi_disk_emulate_pr_preempt(r, r_key, sa_key, type, true); + break; + default: + scsi_check_condition(r, SENSE_CODE(INVALID_OPCODE)); + return; + } + + return; +} + static int scsi_disk_check_mode_select(SCSIDiskState *s, int page, uint8_t *inbuf, int inlen) { @@ -1957,6 +2315,9 @@ static void scsi_disk_emulate_write_data(SCSIRequest *req) scsi_req_complete(&r->req, GOOD); break; + case PERSISTENT_RESERVE_OUT: + scsi_disk_emulate_pr_out(r, r->iov.iov_base); + break; default: abort(); } @@ -2213,6 +2574,11 @@ static int32_t scsi_disk_emulate_command(SCSIRequest *req, uint8_t *buf) case FORMAT_UNIT: trace_scsi_disk_emulate_command_FORMAT_UNIT(r->req.cmd.xfer); break; + case PERSISTENT_RESERVE_OUT: + break; + case PERSISTENT_RESERVE_IN: + scsi_disk_emulate_pr_in(req); + return 0; default: trace_scsi_disk_emulate_command_UNKNOWN(buf[0], scsi_command_name(buf[0])); @@ -2632,6 +2998,8 @@ static const SCSIReqOps *const scsi_disk_reqops_dispatch[256] = { [VERIFY_12] = &scsi_disk_emulate_reqops, [VERIFY_16] = &scsi_disk_emulate_reqops, [FORMAT_UNIT] = &scsi_disk_emulate_reqops, + [PERSISTENT_RESERVE_IN] = &scsi_disk_emulate_reqops, + [PERSISTENT_RESERVE_OUT] = &scsi_disk_emulate_reqops, [READ_6] = &scsi_disk_dma_reqops, [READ_10] = &scsi_disk_dma_reqops, From patchwork Fri Jul 5 10:56:10 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Changqi Lu X-Patchwork-Id: 1957282 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=bytedance.com header.i=@bytedance.com header.a=rsa-sha256 header.s=google header.b=NuloFEx7; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=patchwork.ozlabs.org) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4WFr8W2WKbz1xqb for ; Fri, 5 Jul 2024 20:58:03 +1000 (AEST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1sPgcV-0002Os-5S; Fri, 05 Jul 2024 06:56:51 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1sPgcS-0002NO-UJ for qemu-devel@nongnu.org; Fri, 05 Jul 2024 06:56:48 -0400 Received: from mail-pg1-x52c.google.com ([2607:f8b0:4864:20::52c]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1sPgcR-0006d2-BQ for qemu-devel@nongnu.org; Fri, 05 Jul 2024 06:56:48 -0400 Received: by mail-pg1-x52c.google.com with SMTP id 41be03b00d2f7-75c3acf90f0so889860a12.2 for ; Fri, 05 Jul 2024 03:56:46 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bytedance.com; s=google; t=1720177006; x=1720781806; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=alm7vM+qKN2FyJ/IuJ+5ag0uczfU/rBggLkQnuq48Wg=; b=NuloFEx7Ed0A+giYZ5wGEIIC/+PyElXOpM4GauqDMytzdQqdvgAnSa2PkiQ9hGeDog gUpsZe6CpcQOQm5mlUH58oSDh4d6aYjccVOUjL6pEyGJQmyUsJ3lMqIRomT25KYl0oTk DQNBuq7YoZe1b9EbXFiteddLk02Dr73EwEaV4DDWJpW2wLTCkctT2uF14Dv5MRLeAYVq 15QrD8I+v6GqCHCfBmOmd+dof52OSOatW/rjHQSXEoYm+V/0AUbqS+5CUzSsAieT/llw SOj2rNF/qRlAZ6y6iLYVVXbghd0IWwcpq4kReGPNM7iyvXC8BvQF7wKVtg3BoNdoGwO0 lSWg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1720177006; x=1720781806; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=alm7vM+qKN2FyJ/IuJ+5ag0uczfU/rBggLkQnuq48Wg=; b=da50ozUDCb8cu01HTwHMPwZMELi8n59u8288Ia6bCMTfvdWURO3SFscZ0Ix9bGbU7i qr2OW8QwS6B8oQH0vz2t6zC+WBXvpvjCpHrUx2BbObTnJZIpH31PyHb90rX8MFc//Nwp QIbB+qkK91MhyGHrAt6L3+A3Kk/zLYgTz1lSP5vcVvxDUlZpTeo4se+QgEotmC5NAojQ CTyhvCVxKxF2zwmNgA6Ufbjw4uPCp+bLICr4xH4tnuGPQ+1o1zDs3OxB4Jn3E/0w73zf x/rKbYYy74SNfOFw311Lk6crSzqvMClRFCm01HLD9zpaASYhQ+iBmGWvbMQ+gd33qCFX h7HA== X-Forwarded-Encrypted: i=1; AJvYcCWj9cVW5V6qrgYAi/RCyIJoambdd2lWKJk7ycgCj80E3aKxRhopDYtSSFz8SynnWIUgeqovlJt1zSYw7fe8FKOXwvi+JgI= X-Gm-Message-State: AOJu0YwyliOnLZ+Lqdr1XnESAwysZKNaknZKt9aynKEFm/hP8zX2Btbc 2KmMhnPqDkPoJKyB4vAd8erNLzKpB3p8yYKeh9CkuyqfK/n7hnkitHFU8w6tKhY= X-Google-Smtp-Source: AGHT+IHZHU2D67aVq86uxb9tl4LyYd8FTnSYGNxQj7GstHopxRvXn9+7IB4jUJ6nFkBgTt8v4ueinA== X-Received: by 2002:a05:6a20:840b:b0:1bd:1e06:9dba with SMTP id adf61e73a8af0-1c0cc75b3a6mr4361105637.27.1720177005942; Fri, 05 Jul 2024 03:56:45 -0700 (PDT) Received: from n37-006-243.byted.org ([180.184.84.173]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-1fac0ba60a2sm141292125ad.0.2024.07.05.03.56.42 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 05 Jul 2024 03:56:45 -0700 (PDT) From: Changqi Lu To: qemu-block@nongnu.org, qemu-devel@nongnu.org Cc: kwolf@redhat.com, hreitz@redhat.com, stefanha@redhat.com, fam@euphon.net, ronniesahlberg@gmail.com, pbonzini@redhat.com, pl@dlhnet.de, kbusch@kernel.org, its@irrelevant.dk, foss@defmacro.it, philmd@linaro.org, pizhenwei@bytedance.com, Changqi Lu Subject: [PATCH v7 06/10] block/nvme: add reservation command protocol constants Date: Fri, 5 Jul 2024 18:56:10 +0800 Message-Id: <20240705105614.3377694-7-luchangqi.123@bytedance.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20240705105614.3377694-1-luchangqi.123@bytedance.com> References: <20240705105614.3377694-1-luchangqi.123@bytedance.com> MIME-Version: 1.0 Received-SPF: pass client-ip=2607:f8b0:4864:20::52c; envelope-from=luchangqi.123@bytedance.com; helo=mail-pg1-x52c.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Add constants for the NVMe persistent command protocol. The constants include the reservation command opcode and reservation type values defined in section 7 of the NVMe 2.0 specification. Signed-off-by: Changqi Lu Signed-off-by: zhenwei pi Reviewed-by: Stefan Hajnoczi --- include/block/nvme.h | 61 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/include/block/nvme.h b/include/block/nvme.h index bb231d0b9a..8b125f7769 100644 --- a/include/block/nvme.h +++ b/include/block/nvme.h @@ -633,7 +633,11 @@ enum NvmeIoCommands { NVME_CMD_WRITE_ZEROES = 0x08, NVME_CMD_DSM = 0x09, NVME_CMD_VERIFY = 0x0c, + NVME_CMD_RESV_REGISTER = 0x0d, + NVME_CMD_RESV_REPORT = 0x0e, + NVME_CMD_RESV_ACQUIRE = 0x11, NVME_CMD_IO_MGMT_RECV = 0x12, + NVME_CMD_RESV_RELEASE = 0x15, NVME_CMD_COPY = 0x19, NVME_CMD_IO_MGMT_SEND = 0x1d, NVME_CMD_ZONE_MGMT_SEND = 0x79, @@ -641,6 +645,63 @@ enum NvmeIoCommands { NVME_CMD_ZONE_APPEND = 0x7d, }; +typedef enum { + NVME_RESV_REGISTER_ACTION_REGISTER = 0x00, + NVME_RESV_REGISTER_ACTION_UNREGISTER = 0x01, + NVME_RESV_REGISTER_ACTION_REPLACE = 0x02, +} NvmeReservationRegisterAction; + +typedef enum { + NVME_RESV_RELEASE_ACTION_RELEASE = 0x00, + NVME_RESV_RELEASE_ACTION_CLEAR = 0x01, +} NvmeReservationReleaseAction; + +typedef enum { + NVME_RESV_ACQUIRE_ACTION_ACQUIRE = 0x00, + NVME_RESV_ACQUIRE_ACTION_PREEMPT = 0x01, + NVME_RESV_ACQUIRE_ACTION_PREEMPT_AND_ABORT = 0x02, +} NvmeReservationAcquireAction; + +typedef enum { + NVME_RESV_WRITE_EXCLUSIVE = 0x01, + NVME_RESV_EXCLUSIVE_ACCESS = 0x02, + NVME_RESV_WRITE_EXCLUSIVE_REGS_ONLY = 0x03, + NVME_RESV_EXCLUSIVE_ACCESS_REGS_ONLY = 0x04, + NVME_RESV_WRITE_EXCLUSIVE_ALL_REGS = 0x05, + NVME_RESV_EXCLUSIVE_ACCESS_ALL_REGS = 0x06, +} NvmeResvType; + +typedef enum { + NVME_RESV_PTPL_NO_CHANGE = 0x00, + NVME_RESV_PTPL_DISABLE = 0x02, + NVME_RESV_PTPL_ENABLE = 0x03, +} NvmeResvPTPL; + +typedef enum NVMEPrCap { + /* Persist Through Power Loss */ + NVME_PR_CAP_PTPL = 1 << 0, + /* Write Exclusive reservation type */ + NVME_PR_CAP_WR_EX = 1 << 1, + /* Exclusive Access reservation type */ + NVME_PR_CAP_EX_AC = 1 << 2, + /* Write Exclusive Registrants Only reservation type */ + NVME_PR_CAP_WR_EX_RO = 1 << 3, + /* Exclusive Access Registrants Only reservation type */ + NVME_PR_CAP_EX_AC_RO = 1 << 4, + /* Write Exclusive All Registrants reservation type */ + NVME_PR_CAP_WR_EX_AR = 1 << 5, + /* Exclusive Access All Registrants reservation type */ + NVME_PR_CAP_EX_AC_AR = 1 << 6, + + NVME_PR_CAP_ALL = (NVME_PR_CAP_PTPL | + NVME_PR_CAP_WR_EX | + NVME_PR_CAP_EX_AC | + NVME_PR_CAP_WR_EX_RO | + NVME_PR_CAP_EX_AC_RO | + NVME_PR_CAP_WR_EX_AR | + NVME_PR_CAP_EX_AC_AR), +} NvmePrCap; + typedef struct QEMU_PACKED NvmeDeleteQ { uint8_t opcode; uint8_t flags; From patchwork Fri Jul 5 10:56:11 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Changqi Lu X-Patchwork-Id: 1957283 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=bytedance.com header.i=@bytedance.com header.a=rsa-sha256 header.s=google header.b=T5NyQC/r; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=patchwork.ozlabs.org) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4WFr8d6dSdz1xqb for ; Fri, 5 Jul 2024 20:58:09 +1000 (AEST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1sPgci-0002S4-PL; Fri, 05 Jul 2024 06:57:05 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1sPgcY-0002PN-1o for qemu-devel@nongnu.org; Fri, 05 Jul 2024 06:56:55 -0400 Received: from mail-pl1-x62a.google.com ([2607:f8b0:4864:20::62a]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1sPgcW-0006e1-Dd for qemu-devel@nongnu.org; Fri, 05 Jul 2024 06:56:53 -0400 Received: by mail-pl1-x62a.google.com with SMTP id d9443c01a7336-1fafc9e07f8so9767805ad.0 for ; Fri, 05 Jul 2024 03:56:52 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bytedance.com; s=google; t=1720177011; x=1720781811; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=t0xxob6zB1P7gFRfbCBxVpf1NpVXQswWX1uR6CV85Ls=; b=T5NyQC/rAXa+ie0O48aaVKFUMdLI0Urw/O4QHWOxmdo8R3VzTGk9JcNPiSHbzFWUmv lZYH646NDkP9BOAxjFCsf/PsfKXfhnNf074fxf+lY1Z9s1qPhkpfUYYO2MXN18wyJ9d/ HBY+sCCm3jwPQPJUT0PMl3hW5NxR7hOPM4SW1tpmTaBiWgZrV7R8aJ2o67pY7hug6vmp RaOjfMla2kzoqENfSE9AVCLi9LJ2S+aKjcJv7rDahLb02cqQeX8GIaNxcNPuDEs9QNnV F1PzD6DfjlQO2OwMqa+N+Ir6AwcJ1Isluu/J+mV6krj1RjGZaSZ4fw/3ZFiAONYhz/Z6 4TtA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1720177011; x=1720781811; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=t0xxob6zB1P7gFRfbCBxVpf1NpVXQswWX1uR6CV85Ls=; b=Q+KKCMWL+OPIw9QLLAJgmzbDiJcscHqyUAGVjtOgR+93U6xnKznXnxvYYguCPNV1ax 7KD5v8ZMqyF5Hec+dfiMpgLbYCsqYVvZce2osmj6hKJiff9EJMG2MU+ksHhKopu6aT3m emlP+l1nCzzeoTtJ8Nq6icMkH8j8snfKG8VLSAccfi2ry2/zD5d/huZpeEOeFHJ+Zibq 6I+hKneZBkUuxBPk/fZR2HDjepa2R/uHcSuFdV8XuQxjyawFqdS9gU8Vt8MjXFh+n78a 4UStYpyX5erp/BUGp/6s0uQZnu8oWsl4SZvylPpa+eDCauNQaFFnIok6SCRW00DPYi28 jfvg== X-Forwarded-Encrypted: i=1; AJvYcCX+ba1ADgR8nh33TbzqrVqK0Nwgh3kqrtoDABlj0/PZm5tFyRXqmTAPOK3hHtLjyVjLr0pbObpF8qsOi8jdhbN8mPVc10s= X-Gm-Message-State: AOJu0YyQqwdVn5jQNcdq1gKMos1ieXT4TLPEcpAN7WKAWqIVQtee9kpt zOSaDo0OS0wSpajEVyg/OPHmTDr1EC1z5rLzBGg0z0jcSWPe2xcLfeNumT0dSr8= X-Google-Smtp-Source: AGHT+IHBRneACYSjBAHCWH46b3ZwQQ2ChM8s2T24Vgd2U4Jej8JOGJo7L8IRjkl5AtyKjhBhOp7K9A== X-Received: by 2002:a17:902:f543:b0:1fb:3718:ca0b with SMTP id d9443c01a7336-1fb3718ced8mr36201345ad.26.1720177009761; Fri, 05 Jul 2024 03:56:49 -0700 (PDT) Received: from n37-006-243.byted.org ([180.184.84.173]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-1fac0ba60a2sm141292125ad.0.2024.07.05.03.56.46 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 05 Jul 2024 03:56:49 -0700 (PDT) From: Changqi Lu To: qemu-block@nongnu.org, qemu-devel@nongnu.org Cc: kwolf@redhat.com, hreitz@redhat.com, stefanha@redhat.com, fam@euphon.net, ronniesahlberg@gmail.com, pbonzini@redhat.com, pl@dlhnet.de, kbusch@kernel.org, its@irrelevant.dk, foss@defmacro.it, philmd@linaro.org, pizhenwei@bytedance.com, Changqi Lu Subject: [PATCH v7 07/10] hw/nvme: add helper functions for converting reservation types Date: Fri, 5 Jul 2024 18:56:11 +0800 Message-Id: <20240705105614.3377694-8-luchangqi.123@bytedance.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20240705105614.3377694-1-luchangqi.123@bytedance.com> References: <20240705105614.3377694-1-luchangqi.123@bytedance.com> MIME-Version: 1.0 Received-SPF: pass client-ip=2607:f8b0:4864:20::62a; envelope-from=luchangqi.123@bytedance.com; helo=mail-pl1-x62a.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org This commit introduces two helper functions that facilitate the conversion between the reservation types used in the NVME protocol and those used in the block layer. Reviewed-by: Stefan Hajnoczi Signed-off-by: Changqi Lu Signed-off-by: zhenwei pi Reviewed-by: Klaus Jensen --- hw/nvme/nvme.h | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) diff --git a/hw/nvme/nvme.h b/hw/nvme/nvme.h index bed8191bd5..6d0e456348 100644 --- a/hw/nvme/nvme.h +++ b/hw/nvme/nvme.h @@ -474,6 +474,90 @@ static inline const char *nvme_io_opc_str(uint8_t opc) } } +static inline NvmeResvType block_pr_type_to_nvme(BlockPrType type) +{ + switch (type) { + case BLK_PR_WRITE_EXCLUSIVE: + return NVME_RESV_WRITE_EXCLUSIVE; + case BLK_PR_EXCLUSIVE_ACCESS: + return NVME_RESV_EXCLUSIVE_ACCESS; + case BLK_PR_WRITE_EXCLUSIVE_REGS_ONLY: + return NVME_RESV_WRITE_EXCLUSIVE_REGS_ONLY; + case BLK_PR_EXCLUSIVE_ACCESS_REGS_ONLY: + return NVME_RESV_EXCLUSIVE_ACCESS_REGS_ONLY; + case BLK_PR_WRITE_EXCLUSIVE_ALL_REGS: + return NVME_RESV_WRITE_EXCLUSIVE_ALL_REGS; + case BLK_PR_EXCLUSIVE_ACCESS_ALL_REGS: + return NVME_RESV_EXCLUSIVE_ACCESS_ALL_REGS; + } + + return 0; +} + +static inline BlockPrType nvme_pr_type_to_block(NvmeResvType type) +{ + switch (type) { + case NVME_RESV_WRITE_EXCLUSIVE: + return BLK_PR_WRITE_EXCLUSIVE; + case NVME_RESV_EXCLUSIVE_ACCESS: + return BLK_PR_EXCLUSIVE_ACCESS; + case NVME_RESV_WRITE_EXCLUSIVE_REGS_ONLY: + return BLK_PR_WRITE_EXCLUSIVE_REGS_ONLY; + case NVME_RESV_EXCLUSIVE_ACCESS_REGS_ONLY: + return BLK_PR_EXCLUSIVE_ACCESS_REGS_ONLY; + case NVME_RESV_WRITE_EXCLUSIVE_ALL_REGS: + return BLK_PR_WRITE_EXCLUSIVE_ALL_REGS; + case NVME_RESV_EXCLUSIVE_ACCESS_ALL_REGS: + return BLK_PR_EXCLUSIVE_ACCESS_ALL_REGS; + } + + return 0; +} + +static inline uint8_t nvme_pr_cap_to_block(uint16_t nvme_pr_cap) +{ + uint8_t res = 0; + + res |= (nvme_pr_cap & NVME_PR_CAP_PTPL) ? + NVME_PR_CAP_PTPL : 0; + res |= (nvme_pr_cap & NVME_PR_CAP_WR_EX) ? + BLK_PR_CAP_WR_EX : 0; + res |= (nvme_pr_cap & NVME_PR_CAP_EX_AC) ? + BLK_PR_CAP_EX_AC : 0; + res |= (nvme_pr_cap & NVME_PR_CAP_WR_EX_RO) ? + BLK_PR_CAP_WR_EX_RO : 0; + res |= (nvme_pr_cap & NVME_PR_CAP_EX_AC_RO) ? + BLK_PR_CAP_EX_AC_RO : 0; + res |= (nvme_pr_cap & NVME_PR_CAP_WR_EX_AR) ? + BLK_PR_CAP_WR_EX_AR : 0; + res |= (nvme_pr_cap & NVME_PR_CAP_EX_AC_AR) ? + BLK_PR_CAP_EX_AC_AR : 0; + + return res; +} + +static inline uint8_t block_pr_cap_to_nvme(uint8_t block_pr_cap) +{ + uint16_t res = 0; + + res |= (block_pr_cap & BLK_PR_CAP_PTPL) ? + NVME_PR_CAP_PTPL : 0; + res |= (block_pr_cap & BLK_PR_CAP_WR_EX) ? + NVME_PR_CAP_WR_EX : 0; + res |= (block_pr_cap & BLK_PR_CAP_EX_AC) ? + NVME_PR_CAP_EX_AC : 0; + res |= (block_pr_cap & BLK_PR_CAP_WR_EX_RO) ? + NVME_PR_CAP_WR_EX_RO : 0; + res |= (block_pr_cap & BLK_PR_CAP_EX_AC_RO) ? + NVME_PR_CAP_EX_AC_RO : 0; + res |= (block_pr_cap & BLK_PR_CAP_WR_EX_AR) ? + NVME_PR_CAP_WR_EX_AR : 0; + res |= (block_pr_cap & BLK_PR_CAP_EX_AC_AR) ? + NVME_PR_CAP_EX_AC_AR : 0; + + return res; +} + typedef struct NvmeSQueue { struct NvmeCtrl *ctrl; uint16_t sqid; From patchwork Fri Jul 5 10:56:12 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Changqi Lu X-Patchwork-Id: 1957287 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=bytedance.com header.i=@bytedance.com header.a=rsa-sha256 header.s=google header.b=D7U/E9mw; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=patchwork.ozlabs.org) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4WFr8h6znFz1xqb for ; Fri, 5 Jul 2024 20:58:12 +1000 (AEST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1sPgcq-0002uC-FB; Fri, 05 Jul 2024 06:57:12 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1sPgcn-0002c5-9D for qemu-devel@nongnu.org; Fri, 05 Jul 2024 06:57:09 -0400 Received: from mail-pl1-x62d.google.com ([2607:f8b0:4864:20::62d]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1sPgca-0006ee-6w for qemu-devel@nongnu.org; Fri, 05 Jul 2024 06:57:09 -0400 Received: by mail-pl1-x62d.google.com with SMTP id d9443c01a7336-1fafc9e07f8so9768085ad.0 for ; Fri, 05 Jul 2024 03:56:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bytedance.com; s=google; t=1720177015; x=1720781815; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=IyZGNDRE1BJIuJp5qNhxmIBvAAaNOJEW0axHYABlNto=; b=D7U/E9mwaFdMfDKq6BJ90p6/eaRpS9Dz0Jkdv6XJnmxpm/euwqsJ1Czx3Ci5ZlPniE ockPr/OP5v5E0HvWJ7fS8mpxahlUZaIgwPxsewuw8ra7A0i0Jd6ESP6vJmct6xajtOWx CBscNe481QqoG8An3CQ5oI+ebynVx3Txsi9koRCQ5avzx4sSK4sxktHX/BzV7ewph6o+ m1AEmLCyMnuSMnSs54g5wXjKzumwIXj+Hts28UZYEGUVogyONt8yc8Hasb/NaGIb0/l7 lv3fNHMEsx1IqzXAUz/cbrX8Xt6R1rgXUCKcLvW2afPPmclPtUbfNYVheApmrWb7iHMp 5b8A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1720177015; x=1720781815; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=IyZGNDRE1BJIuJp5qNhxmIBvAAaNOJEW0axHYABlNto=; b=ltqZNkVLMeqquL7I4EdUeNFUSUpxZ/ThvroXLTIuNPRYUBM6QnL6t2RT6qokUDe1pa niRlXWmF+q8Zh1w9g7GSUfcAGnDVJTMbl4BGRBZqMv+ZVLAigF2D/4cQTLFz303dh7lb 5iS7Cr1fDo+Kte4LVcWe0Gb8D/qNm4ZGo4GMlNwSUYOfXWSmGTzvl4B3ntYxRadx63DW WbB6z4fEHaXvmHqXwsy+MRPlEt1leZaMgnW3aZpc41qYqn9fs22cU5dPAJWnjkVNLEEZ xZ4jglaPCj9njdE6z/QF4rnXJITolsWYqTvvvRW3T7r9N5SV4s+crR7zDHttDdBLWaR+ svhg== X-Forwarded-Encrypted: i=1; AJvYcCUcpIVwL5z1B1yN1Vx20srCBuRDLuDsGT3lvPFoHKX/Ufq7OYDnENJLjJOwb51jPlcvaIe7WtpFeb+03KcUnp9ru0C+B0s= X-Gm-Message-State: AOJu0YzuDO4ozidhdpWKQOcfaOCKMgC4q2Qo8NkQ1vxccokRf+MqSEIN 2i1vHqN8CiKpdw3YzbYPiXRcovyyciXbrg/Q89yFs3U4jOqnnbHmSl1qk2CGVFA= X-Google-Smtp-Source: AGHT+IFAE7z0vLJyaPWMeky2CLlou97DodjnmmZ+zlY/lsANWYMrbYkNLLMlw2JGEvLe6Qi+yrDsTA== X-Received: by 2002:a17:902:d4c7:b0:1fb:4b87:6e8e with SMTP id d9443c01a7336-1fb4b877196mr11405555ad.42.1720177014874; Fri, 05 Jul 2024 03:56:54 -0700 (PDT) Received: from n37-006-243.byted.org ([180.184.84.173]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-1fac0ba60a2sm141292125ad.0.2024.07.05.03.56.51 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 05 Jul 2024 03:56:54 -0700 (PDT) From: Changqi Lu To: qemu-block@nongnu.org, qemu-devel@nongnu.org Cc: kwolf@redhat.com, hreitz@redhat.com, stefanha@redhat.com, fam@euphon.net, ronniesahlberg@gmail.com, pbonzini@redhat.com, pl@dlhnet.de, kbusch@kernel.org, its@irrelevant.dk, foss@defmacro.it, philmd@linaro.org, pizhenwei@bytedance.com, Changqi Lu Subject: [PATCH v7 08/10] hw/nvme: enable ONCS and rescap function Date: Fri, 5 Jul 2024 18:56:12 +0800 Message-Id: <20240705105614.3377694-9-luchangqi.123@bytedance.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20240705105614.3377694-1-luchangqi.123@bytedance.com> References: <20240705105614.3377694-1-luchangqi.123@bytedance.com> MIME-Version: 1.0 Received-SPF: pass client-ip=2607:f8b0:4864:20::62d; envelope-from=luchangqi.123@bytedance.com; helo=mail-pl1-x62d.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=unavailable autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org This commit enables ONCS to support the reservation function at the controller level. Also enables rescap function in the namespace by detecting the supported reservation function in the backend driver. Signed-off-by: Changqi Lu Signed-off-by: zhenwei pi Reviewed-by: Stefan Hajnoczi Reviewed-by: Klaus Jensen --- hw/nvme/ctrl.c | 3 ++- hw/nvme/ns.c | 5 +++++ include/block/nvme.h | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/hw/nvme/ctrl.c b/hw/nvme/ctrl.c index 127c3d2383..ad212de723 100644 --- a/hw/nvme/ctrl.c +++ b/hw/nvme/ctrl.c @@ -8248,7 +8248,8 @@ static void nvme_init_ctrl(NvmeCtrl *n, PCIDevice *pci_dev) id->nn = cpu_to_le32(NVME_MAX_NAMESPACES); id->oncs = cpu_to_le16(NVME_ONCS_WRITE_ZEROES | NVME_ONCS_TIMESTAMP | NVME_ONCS_FEATURES | NVME_ONCS_DSM | - NVME_ONCS_COMPARE | NVME_ONCS_COPY); + NVME_ONCS_COMPARE | NVME_ONCS_COPY | + NVME_ONCS_RESERVATIONS); /* * NOTE: If this device ever supports a command set that does NOT use 0x0 diff --git a/hw/nvme/ns.c b/hw/nvme/ns.c index ea8db175db..a5c903d727 100644 --- a/hw/nvme/ns.c +++ b/hw/nvme/ns.c @@ -20,6 +20,7 @@ #include "qemu/bitops.h" #include "sysemu/sysemu.h" #include "sysemu/block-backend.h" +#include "block/block_int.h" #include "nvme.h" #include "trace.h" @@ -33,6 +34,7 @@ void nvme_ns_init_format(NvmeNamespace *ns) BlockDriverInfo bdi; int npdg, ret; int64_t nlbas; + uint8_t blk_pr_cap; ns->lbaf = id_ns->lbaf[NVME_ID_NS_FLBAS_INDEX(id_ns->flbas)]; ns->lbasz = 1 << ns->lbaf.ds; @@ -55,6 +57,9 @@ void nvme_ns_init_format(NvmeNamespace *ns) } id_ns->npda = id_ns->npdg = npdg - 1; + + blk_pr_cap = blk_bs(ns->blkconf.blk)->bl.pr_cap; + id_ns->rescap = block_pr_cap_to_nvme(blk_pr_cap); } static int nvme_ns_init(NvmeNamespace *ns, Error **errp) diff --git a/include/block/nvme.h b/include/block/nvme.h index 8b125f7769..9b9eaeb3a7 100644 --- a/include/block/nvme.h +++ b/include/block/nvme.h @@ -1251,7 +1251,7 @@ enum NvmeIdCtrlOncs { NVME_ONCS_DSM = 1 << 2, NVME_ONCS_WRITE_ZEROES = 1 << 3, NVME_ONCS_FEATURES = 1 << 4, - NVME_ONCS_RESRVATIONS = 1 << 5, + NVME_ONCS_RESERVATIONS = 1 << 5, NVME_ONCS_TIMESTAMP = 1 << 6, NVME_ONCS_VERIFY = 1 << 7, NVME_ONCS_COPY = 1 << 8, From patchwork Fri Jul 5 10:56:13 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Changqi Lu X-Patchwork-Id: 1957285 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=bytedance.com header.i=@bytedance.com header.a=rsa-sha256 header.s=google header.b=C/GAvGZV; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=patchwork.ozlabs.org) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4WFr8f3DP8z1xr1 for ; Fri, 5 Jul 2024 20:58:10 +1000 (AEST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1sPgcn-0002XS-0D; Fri, 05 Jul 2024 06:57:09 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1sPgck-0002Sx-1n for qemu-devel@nongnu.org; Fri, 05 Jul 2024 06:57:06 -0400 Received: from mail-pf1-x42f.google.com ([2607:f8b0:4864:20::42f]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1sPgce-0006ew-9q for qemu-devel@nongnu.org; Fri, 05 Jul 2024 06:57:05 -0400 Received: by mail-pf1-x42f.google.com with SMTP id d2e1a72fcca58-70af22a9c19so1062417b3a.2 for ; Fri, 05 Jul 2024 03:56:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bytedance.com; s=google; t=1720177019; x=1720781819; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=vnnlaAsHMDMy1W0jqBEpl+WRDzxCFDRuHFC4XpL5tjY=; b=C/GAvGZVKOhdLm9M1Q77I76xgG060b3SMUPsC3mnbAnifZJwNmmoF+VJ5p0aS6CHTg ooLXQKXy/L2V3SzZ9zvzbGTVOLi3jbKcICjJzpNUQNkV/wa0Iu7B1h1Y7bw6JNRPyVYs ZuB4o7rpjPCYzxLlQd9fNmCFjXiF0MwWZuOfrLmYbPv4aGlPBptLaIu3MVdn4Ai5UOjj n7BapS8XkrX7EDueawLskRFKI0rmpHcrULzwOM1biWeFBiBAws74SNFyPqBG3sRgJIjT jI6G7xdYpB+Vk4kDklKVFy+KMtEJK7LE+wHHxBpcAjDJ58DhyuqkfXPSFkhLR01eCcID Stmg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1720177019; x=1720781819; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=vnnlaAsHMDMy1W0jqBEpl+WRDzxCFDRuHFC4XpL5tjY=; b=Z3We18m5HPsRRML+102RbcM0KD175VLSCyx+VOdBT8XpkYB/cqXu+9vOLOwIXrun+V 6YAsTHP5nFKiPWnHn53RA/UDZFGpdyvneROHbOU1bUdU9r1V898DTLLw2cUZA+wsu7i2 jUgWJaoZHp6tlToOC7cC9XWXt5zNKlF30jdBSEQlSg8o+KvWHAiG5aBMj1IyyKbKHlVz 6L0lbv8yd+4rChrkt27MKA0lkJslYk1O5eARa2dEgkpjmeOVLLRbFe6UAS6vL13wtaDL 35PFs6tHjCQi7ZTs8f9Ryhw5Z3MypfRxm87dUjhSTHqoHWHBHK33Q5XC2sVE89e26a3D tzGg== X-Forwarded-Encrypted: i=1; AJvYcCU3ivnrz5gt2wXaB+a1vUq/9Ssra0jYhFC1zVeylbBsMgkkRw5hdHu9eJw+FemeMcT9jALAkle6kUv/0R1cQvE7baef+wk= X-Gm-Message-State: AOJu0YyOAPf3CiUIm7A02JVAE38v7ShLmUZt5v+UYYYdYxU3tjhjSgdc ZRoq9fPuH0JsIXz6WOfVar904no/DDDpPb6pAYXHaWDi6WNjEdq8TMVhht4l6Gc= X-Google-Smtp-Source: AGHT+IEzPBnUv22JiHc+NpW7hEF7mwdFoUuzgd/H5ZQ82I91Z8wP4L7jtbTfdlYJN+cJ+gwey6RXcw== X-Received: by 2002:a05:6a21:329a:b0:1c0:dc29:8dbe with SMTP id adf61e73a8af0-1c0dc298ea7mr1071748637.62.1720177018853; Fri, 05 Jul 2024 03:56:58 -0700 (PDT) Received: from n37-006-243.byted.org ([180.184.84.173]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-1fac0ba60a2sm141292125ad.0.2024.07.05.03.56.55 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 05 Jul 2024 03:56:58 -0700 (PDT) From: Changqi Lu To: qemu-block@nongnu.org, qemu-devel@nongnu.org Cc: kwolf@redhat.com, hreitz@redhat.com, stefanha@redhat.com, fam@euphon.net, ronniesahlberg@gmail.com, pbonzini@redhat.com, pl@dlhnet.de, kbusch@kernel.org, its@irrelevant.dk, foss@defmacro.it, philmd@linaro.org, pizhenwei@bytedance.com, Changqi Lu , Klaus Jensen Subject: [PATCH v7 09/10] hw/nvme: add reservation protocal command Date: Fri, 5 Jul 2024 18:56:13 +0800 Message-Id: <20240705105614.3377694-10-luchangqi.123@bytedance.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20240705105614.3377694-1-luchangqi.123@bytedance.com> References: <20240705105614.3377694-1-luchangqi.123@bytedance.com> MIME-Version: 1.0 Received-SPF: pass client-ip=2607:f8b0:4864:20::42f; envelope-from=luchangqi.123@bytedance.com; helo=mail-pf1-x42f.google.com X-Spam_score_int: -16 X-Spam_score: -1.7 X-Spam_bar: - X-Spam_report: (-1.7 / 5.0 requ) BAYES_00=-1.9, DKIM_INVALID=0.1, DKIM_SIGNED=0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Add reservation acquire, reservation register, reservation release and reservation report commands in the nvme device layer. By introducing these commands, this enables the nvme device to perform reservation-related tasks, including querying keys, querying reservation status, registering reservation keys, initiating and releasing reservations, as well as clearing and preempting reservations held by other keys. These commands are crucial for management and control of shared storage resources in a persistent manner. Signed-off-by: Changqi Lu Signed-off-by: zhenwei pi Acked-by: Klaus Jensen --- hw/nvme/ctrl.c | 323 ++++++++++++++++++++++++++++++++++++++++++- hw/nvme/nvme.h | 4 + include/block/nvme.h | 37 +++++ 3 files changed, 363 insertions(+), 1 deletion(-) diff --git a/hw/nvme/ctrl.c b/hw/nvme/ctrl.c index ad212de723..a69a499078 100644 --- a/hw/nvme/ctrl.c +++ b/hw/nvme/ctrl.c @@ -294,6 +294,10 @@ static const uint32_t nvme_cse_iocs_nvm[256] = { [NVME_CMD_COMPARE] = NVME_CMD_EFF_CSUPP, [NVME_CMD_IO_MGMT_RECV] = NVME_CMD_EFF_CSUPP, [NVME_CMD_IO_MGMT_SEND] = NVME_CMD_EFF_CSUPP | NVME_CMD_EFF_LBCC, + [NVME_CMD_RESV_REGISTER] = NVME_CMD_EFF_CSUPP, + [NVME_CMD_RESV_REPORT] = NVME_CMD_EFF_CSUPP, + [NVME_CMD_RESV_ACQUIRE] = NVME_CMD_EFF_CSUPP, + [NVME_CMD_RESV_RELEASE] = NVME_CMD_EFF_CSUPP, }; static const uint32_t nvme_cse_iocs_zoned[256] = { @@ -308,6 +312,10 @@ static const uint32_t nvme_cse_iocs_zoned[256] = { [NVME_CMD_ZONE_APPEND] = NVME_CMD_EFF_CSUPP | NVME_CMD_EFF_LBCC, [NVME_CMD_ZONE_MGMT_SEND] = NVME_CMD_EFF_CSUPP | NVME_CMD_EFF_LBCC, [NVME_CMD_ZONE_MGMT_RECV] = NVME_CMD_EFF_CSUPP, + [NVME_CMD_RESV_REGISTER] = NVME_CMD_EFF_CSUPP, + [NVME_CMD_RESV_REPORT] = NVME_CMD_EFF_CSUPP, + [NVME_CMD_RESV_ACQUIRE] = NVME_CMD_EFF_CSUPP, + [NVME_CMD_RESV_RELEASE] = NVME_CMD_EFF_CSUPP, }; static void nvme_process_sq(void *opaque); @@ -1745,6 +1753,7 @@ static void nvme_aio_err(NvmeRequest *req, int ret) switch (req->cmd.opcode) { case NVME_CMD_READ: + case NVME_CMD_RESV_REPORT: status = NVME_UNRECOVERED_READ; break; case NVME_CMD_FLUSH: @@ -1752,6 +1761,9 @@ static void nvme_aio_err(NvmeRequest *req, int ret) case NVME_CMD_WRITE_ZEROES: case NVME_CMD_ZONE_APPEND: case NVME_CMD_COPY: + case NVME_CMD_RESV_REGISTER: + case NVME_CMD_RESV_ACQUIRE: + case NVME_CMD_RESV_RELEASE: status = NVME_WRITE_FAULT; break; default: @@ -2127,7 +2139,10 @@ static inline bool nvme_is_write(NvmeRequest *req) return rw->opcode == NVME_CMD_WRITE || rw->opcode == NVME_CMD_ZONE_APPEND || - rw->opcode == NVME_CMD_WRITE_ZEROES; + rw->opcode == NVME_CMD_WRITE_ZEROES || + rw->opcode == NVME_CMD_RESV_REGISTER || + rw->opcode == NVME_CMD_RESV_ACQUIRE || + rw->opcode == NVME_CMD_RESV_RELEASE; } static void nvme_misc_cb(void *opaque, int ret) @@ -2692,6 +2707,304 @@ static uint16_t nvme_verify(NvmeCtrl *n, NvmeRequest *req) return NVME_NO_COMPLETE; } +typedef struct NvmeKeyInfo { + uint64_t cr_key; + uint64_t nr_key; +} NvmeKeyInfo; + +static uint16_t nvme_resv_register(NvmeCtrl *n, NvmeRequest *req) +{ + int ret; + NvmeKeyInfo key_info; + NvmeNamespace *ns = req->ns; + uint32_t cdw10 = le32_to_cpu(req->cmd.cdw10); + bool ignore_key = cdw10 >> 3 & 0x1; + uint8_t action = cdw10 & 0x7; + uint8_t ptpl = cdw10 >> 30 & 0x3; + bool aptpl; + + switch (ptpl) { + case NVME_RESV_PTPL_NO_CHANGE: + aptpl = (ns->id_ns.rescap & NVME_PR_CAP_PTPL) ? true : false; + break; + case NVME_RESV_PTPL_DISABLE: + aptpl = false; + break; + case NVME_RESV_PTPL_ENABLE: + aptpl = true; + break; + default: + return NVME_INVALID_FIELD; + } + + ret = nvme_h2c(n, (uint8_t *)&key_info, sizeof(NvmeKeyInfo), req); + if (ret) { + return ret; + } + + switch (action) { + case NVME_RESV_REGISTER_ACTION_REGISTER: + req->aiocb = blk_aio_pr_register(ns->blkconf.blk, 0, + key_info.nr_key, 0, aptpl, + ignore_key, nvme_misc_cb, + req); + break; + case NVME_RESV_REGISTER_ACTION_UNREGISTER: + req->aiocb = blk_aio_pr_register(ns->blkconf.blk, key_info.cr_key, 0, + 0, aptpl, ignore_key, + nvme_misc_cb, req); + break; + case NVME_RESV_REGISTER_ACTION_REPLACE: + req->aiocb = blk_aio_pr_register(ns->blkconf.blk, key_info.cr_key, + key_info.nr_key, 0, aptpl, ignore_key, + nvme_misc_cb, req); + break; + default: + return NVME_INVALID_FIELD; + } + + return NVME_NO_COMPLETE; +} + +static uint16_t nvme_resv_release(NvmeCtrl *n, NvmeRequest *req) +{ + int ret; + uint64_t cr_key; + NvmeNamespace *ns = req->ns; + uint32_t cdw10 = le32_to_cpu(req->cmd.cdw10); + uint8_t action = cdw10 & 0x7; + NvmeResvType type = cdw10 >> 8 & 0xff; + + ret = nvme_h2c(n, (uint8_t *)&cr_key, sizeof(cr_key), req); + if (ret) { + return ret; + } + + switch (action) { + case NVME_RESV_RELEASE_ACTION_RELEASE: + req->aiocb = blk_aio_pr_release(ns->blkconf.blk, cr_key, + nvme_pr_type_to_block(type), + nvme_misc_cb, req); + break; + case NVME_RESV_RELEASE_ACTION_CLEAR: + req->aiocb = blk_aio_pr_clear(ns->blkconf.blk, cr_key, + nvme_misc_cb, req); + break; + default: + return NVME_INVALID_FIELD; + } + + return NVME_NO_COMPLETE; +} + +static uint16_t nvme_resv_acquire(NvmeCtrl *n, NvmeRequest *req) +{ + int ret; + NvmeKeyInfo key_info; + NvmeNamespace *ns = req->ns; + uint32_t cdw10 = le32_to_cpu(req->cmd.cdw10); + uint8_t action = cdw10 & 0x7; + NvmeResvType type = cdw10 >> 8 & 0xff; + + ret = nvme_h2c(n, (uint8_t *)&key_info, sizeof(NvmeKeyInfo), req); + if (ret) { + return ret; + } + + switch (action) { + case NVME_RESV_ACQUIRE_ACTION_ACQUIRE: + req->aiocb = blk_aio_pr_reserve(ns->blkconf.blk, key_info.cr_key, + nvme_pr_type_to_block(type), + nvme_misc_cb, req); + break; + case NVME_RESV_ACQUIRE_ACTION_PREEMPT: + req->aiocb = blk_aio_pr_preempt(ns->blkconf.blk, + key_info.cr_key, key_info.nr_key, + nvme_pr_type_to_block(type), + false, nvme_misc_cb, req); + break; + case NVME_RESV_ACQUIRE_ACTION_PREEMPT_AND_ABORT: + req->aiocb = blk_aio_pr_preempt(ns->blkconf.blk, key_info.cr_key, + key_info.nr_key, type, true, + nvme_misc_cb, req); + break; + default: + return NVME_INVALID_FIELD; + } + + return NVME_NO_COMPLETE; +} + +typedef struct NvmeResvKeys { + uint32_t generation; + uint32_t num_keys; + uint64_t *keys; + NvmeRequest *req; +} NvmeResvKeys; + +typedef struct NvmeReadReservation { + uint32_t generation; + uint64_t key; + BlockPrType type; + NvmeRequest *req; + NvmeResvKeys *keys_info; +} NvmeReadReservation; + +static int nvme_read_reservation_cb(NvmeReadReservation *reservation) +{ + int rc; + NvmeReservationStatus *nvme_status; + NvmeRequest *req = reservation->req; + NvmeCtrl *n = req->sq->ctrl; + NvmeResvKeys *keys_info = reservation->keys_info; + int len = sizeof(NvmeReservationStatusHeader) + + sizeof(NvmeRegisteredCtrl) * keys_info->num_keys; + + nvme_status = g_malloc(len); + nvme_status->header.gen = reservation->generation; + nvme_status->header.rtype = block_pr_type_to_nvme(reservation->type); + nvme_status->header.regctl = keys_info->num_keys; + for (int i = 0; i < keys_info->num_keys; i++) { + nvme_status->regctl_ds[i].cntlid = nvme_ctrl(req)->cntlid; + nvme_status->regctl_ds[i].rkey = keys_info->keys[i]; + nvme_status->regctl_ds[i].rcsts = keys_info->keys[i] == + reservation->key ? 1 : 0; + /* hostid is not supported currently */ + memset(&nvme_status->regctl_ds[i].hostid, 0, 8); + } + + rc = nvme_c2h(n, (uint8_t *)nvme_status, len, req); + g_free(nvme_status); + return rc; +} + +static int nvme_read_reservation_ext_cb(NvmeReadReservation *reservation) +{ + int rc; + NvmeReservationStatusExt *nvme_status_ext; + NvmeRequest *req = reservation->req; + NvmeCtrl *n = req->sq->ctrl; + NvmeResvKeys *keys_info = reservation->keys_info; + int len = sizeof(NvmeReservationStatusHeader) + + sizeof(uint8_t) * 40 + + sizeof(NvmeRegisteredCtrlExt) * keys_info->num_keys; + + nvme_status_ext = g_malloc(len); + nvme_status_ext->header.gen = cpu_to_be32(reservation->generation); + nvme_status_ext->header.rtype = block_pr_type_to_nvme(reservation->type); + nvme_status_ext->header.regctl = cpu_to_be16(keys_info->num_keys); + + for (int i = 0; i < keys_info->num_keys; i++) { + uint16_t ctnlid = nvme_ctrl(req)->cntlid; + nvme_status_ext->regctl_eds[i].cntlid = cpu_to_be16(ctnlid); + nvme_status_ext->regctl_eds[i].rkey = cpu_to_be64(keys_info->keys[i]); + nvme_status_ext->regctl_eds[i].rcsts = keys_info->keys[i] == + reservation->key ? 1 : 0; + /* hostid is not supported currently */ + memset(&nvme_status_ext->regctl_eds[i].hostid, 0, 16); + } + + rc = nvme_c2h(n, (uint8_t *)nvme_status_ext, len, req); + g_free(nvme_status_ext); + return rc; +} + +static void nvme_resv_read_reservation_cb(void *opaque, int ret) +{ + NvmeReadReservation *reservation = opaque; + NvmeRequest *req = reservation->req; + bool eds = req->cmd.cdw11 & 0x1; + NvmeResvKeys *keys_info = reservation->keys_info; + + if (ret < 0) { + goto out; + } + + if (eds) { + ret = nvme_read_reservation_ext_cb(reservation); + } else { + ret = nvme_read_reservation_cb(reservation); + } + +out: + g_free(keys_info->keys); + g_free(keys_info); + g_free(reservation); + nvme_misc_cb(req, ret); +} + +static void nvme_resv_read_keys_cb(void *opaque, int ret) +{ + NvmeResvKeys *keys_info = opaque; + NvmeRequest *req = keys_info->req; + NvmeNamespace *ns = req->ns; + NvmeReadReservation *reservation; + + if (ret < 0) { + goto out; + } + + keys_info->num_keys = MIN(ret, keys_info->num_keys); + reservation = g_new0(NvmeReadReservation, 1); + memset(reservation, 0, sizeof(*reservation)); + reservation->req = req; + reservation->keys_info = keys_info; + + req->aiocb = blk_aio_pr_read_reservation(ns->blkconf.blk, + &reservation->generation, &reservation->key, + &reservation->type, nvme_resv_read_reservation_cb, + reservation); + return; + +out: + g_free(keys_info->keys); + g_free(keys_info); + nvme_misc_cb(req, ret); +} + + +static uint16_t nvme_resv_report(NvmeCtrl *n, NvmeRequest *req) +{ + int num_keys; + uint32_t cdw10 = req->cmd.cdw10; + uint32_t cdw11 = req->cmd.cdw11; + int buflen = (cdw10 + 1) * sizeof(uint32_t); + bool eds = cdw11 & 0x1; + NvmeNamespace *ns = req->ns; + NvmeResvKeys *keys_info; + + if (eds) { + if (buflen < sizeof(NvmeReservationStatusHeader) + + sizeof(uint8_t) * 40) { + return NVME_INVALID_FIELD; + } + + num_keys = (buflen - sizeof(NvmeReservationStatusHeader) - + sizeof(uint8_t) * 40) / + sizeof(struct NvmeRegisteredCtrlExt); + } else { + if (buflen < sizeof(NvmeReservationStatusHeader)) { + return NVME_INVALID_FIELD; + } + + num_keys = (buflen - sizeof(NvmeReservationStatusHeader)) / + sizeof(struct NvmeRegisteredCtrl); + } + + keys_info = g_new0(NvmeResvKeys, 1); + keys_info->generation = 0; + /* num_keys is the maximum number of keys that can be transmitted */ + keys_info->num_keys = num_keys; + keys_info->keys = g_malloc(sizeof(uint64_t) * num_keys); + keys_info->req = req; + + req->aiocb = blk_aio_pr_read_keys(ns->blkconf.blk, &keys_info->generation, + keys_info->num_keys, keys_info->keys, + nvme_resv_read_keys_cb, keys_info); + + return NVME_NO_COMPLETE; +} + typedef struct NvmeCopyAIOCB { BlockAIOCB common; BlockAIOCB *aiocb; @@ -4469,6 +4782,14 @@ static uint16_t nvme_io_cmd(NvmeCtrl *n, NvmeRequest *req) return nvme_dsm(n, req); case NVME_CMD_VERIFY: return nvme_verify(n, req); + case NVME_CMD_RESV_REGISTER: + return nvme_resv_register(n, req); + case NVME_CMD_RESV_REPORT: + return nvme_resv_report(n, req); + case NVME_CMD_RESV_ACQUIRE: + return nvme_resv_acquire(n, req); + case NVME_CMD_RESV_RELEASE: + return nvme_resv_release(n, req); case NVME_CMD_COPY: return nvme_copy(n, req); case NVME_CMD_ZONE_MGMT_SEND: diff --git a/hw/nvme/nvme.h b/hw/nvme/nvme.h index 6d0e456348..fdd919c2b1 100644 --- a/hw/nvme/nvme.h +++ b/hw/nvme/nvme.h @@ -470,6 +470,10 @@ static inline const char *nvme_io_opc_str(uint8_t opc) case NVME_CMD_ZONE_MGMT_SEND: return "NVME_ZONED_CMD_MGMT_SEND"; case NVME_CMD_ZONE_MGMT_RECV: return "NVME_ZONED_CMD_MGMT_RECV"; case NVME_CMD_ZONE_APPEND: return "NVME_ZONED_CMD_ZONE_APPEND"; + case NVME_CMD_RESV_REGISTER: return "NVME_CMD_RESV_REGISTER"; + case NVME_CMD_RESV_REPORT: return "NVME_CMD_RESV_REPORT"; + case NVME_CMD_RESV_ACQUIRE: return "NVME_CMD_RESV_ACQUIRE"; + case NVME_CMD_RESV_RELEASE: return "NVME_CMD_RESV_RELEASE"; default: return "NVME_NVM_CMD_UNKNOWN"; } } diff --git a/include/block/nvme.h b/include/block/nvme.h index 9b9eaeb3a7..2f24570d4a 100644 --- a/include/block/nvme.h +++ b/include/block/nvme.h @@ -702,6 +702,43 @@ typedef enum NVMEPrCap { NVME_PR_CAP_EX_AC_AR), } NvmePrCap; +typedef struct QEMU_PACKED NvmeRegisteredCtrl { + uint16_t cntlid; + uint8_t rcsts; + uint8_t rsvd3[5]; + uint8_t hostid[8]; + uint64_t rkey; +} NvmeRegisteredCtrl; + +typedef struct QEMU_PACKED NvmeRegisteredCtrlExt { + uint16_t cntlid; + uint8_t rcsts; + uint8_t rsvd3[5]; + uint64_t rkey; + uint8_t hostid[16]; + uint8_t rsvd32[32]; +} NvmeRegisteredCtrlExt; + +typedef struct QEMU_PACKED NvmeReservationStatusHeader { + uint32_t gen; + uint8_t rtype; + uint16_t regctl; + uint16_t resv5; + uint8_t ptpls; + uint8_t resv10[14]; +} NvmeReservationStatusHeader; + +typedef struct QEMU_PACKED NvmeReservationStatus { + struct NvmeReservationStatusHeader header; + struct NvmeRegisteredCtrl regctl_ds[]; +} NvmeReservationStatus; + +typedef struct QEMU_PACKED NvmeReservationStatusExt { + struct NvmeReservationStatusHeader header; + uint8_t rsvd24[40]; + struct NvmeRegisteredCtrlExt regctl_eds[]; +} NvmeReservationStatusExt; + typedef struct QEMU_PACKED NvmeDeleteQ { uint8_t opcode; uint8_t flags; From patchwork Fri Jul 5 10:56:14 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Changqi Lu X-Patchwork-Id: 1957280 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=bytedance.com header.i=@bytedance.com header.a=rsa-sha256 header.s=google header.b=DNMsu+mb; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org (client-ip=209.51.188.17; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=patchwork.ozlabs.org) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4WFr8Q2vlgz1xqb for ; Fri, 5 Jul 2024 20:57:58 +1000 (AEST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1sPgcp-0002p7-6h; Fri, 05 Jul 2024 06:57:11 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1sPgcl-0002WJ-JZ for qemu-devel@nongnu.org; Fri, 05 Jul 2024 06:57:07 -0400 Received: from mail-pl1-x62c.google.com ([2607:f8b0:4864:20::62c]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1sPgch-0006fE-VW for qemu-devel@nongnu.org; Fri, 05 Jul 2024 06:57:07 -0400 Received: by mail-pl1-x62c.google.com with SMTP id d9443c01a7336-1fb457b53c8so5289665ad.0 for ; Fri, 05 Jul 2024 03:57:03 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bytedance.com; s=google; t=1720177023; x=1720781823; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=mbIPWoYULyohj2jKH6OYS7ol47G1ROScPcCok227d7I=; b=DNMsu+mbKDyQkvoPFkNZP5KkQr7KjT0BWhbvFoQtYf3dmd8tkB4tJ/RrjK1zMrFtN/ yRpV5GqE1jCSqEdhTkI34nrJHP8YTD6b7aNgVHwacZRKSCa3PAHaXhsNB5LmgZmEouaU p2hYDH+dERHZkvnJu3E00HjIQNSmCyBjzgatBlnbpOpN2VZg50S3ogyE6qEJGTqkxGF2 74hdhWsJK0t1rN7Hjm4XXeIrZHQiTlaRDMYjqyKJ79+T32/sA9bJtfq2701EYL6vlqEH IohD9RgrGUU7aP1hU9cBrx8DgGIRChO+eUfUjJw2UoWk8Dfbr6nEXi6YXroyNClxsKMe WxuQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1720177023; x=1720781823; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=mbIPWoYULyohj2jKH6OYS7ol47G1ROScPcCok227d7I=; b=Nec0rLa8AB1tBmX/WBtY1ie6f93L+xbPzcgmJWNbaWFARxIUWHeyLGskuLrH0jeU4Q Otla6juVv5ChPeEtjYopTTJnMsjYM7JutKUgjGA+bKnzrHp8di69s2iLFBx0DuV8StRy RZnM3jNkLNMhKEc68xXotsF6jTQB9h+eXyft/ZG0gWwJQwMM+6Cad94tYpeRcroQAxfY WmdJfj3xyp3rFxl84LGPD2Qiw0bEXchZqoZwZwTPE5pxEpGVJMdnEhKtgav/RNLLVIyz 9nETX5BypYUTYoitzXCmyy8scCYuLpIV08+OJSveG4qzBnqxt8oeH7V7P0t3Ws+shbGP mAVg== X-Forwarded-Encrypted: i=1; AJvYcCVdL3YxyIbd/nRZLiE8mbgUitZp6GLIhMdA7emE/prDUdE6yYi9swUhL+Udjwt355rMuoZeC6FpCGqF9cDvXw4HOYFJbKM= X-Gm-Message-State: AOJu0YyC3Iv9ZwwYT4jTm1b796lJhVs+oZfaio++FkU8tdYH3KZfriE4 PnxeP8NgN02/c5lLjdcjAsyuu1uyyYQ1HuptAA4DKUy9QM2pTDeGTHNv9v613+LD+hu63K/tD02 + X-Google-Smtp-Source: AGHT+IEsrBB7VVqkSc6HrITsLyg5o4WNs0C0SNkSWqG7v7FpudOvjZTUOq1YfyjxAjXAo/3iLWQIxg== X-Received: by 2002:a17:903:249:b0:1f4:b43f:9c01 with SMTP id d9443c01a7336-1fb33f41be8mr34547595ad.64.1720177022660; Fri, 05 Jul 2024 03:57:02 -0700 (PDT) Received: from n37-006-243.byted.org ([180.184.84.173]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-1fac0ba60a2sm141292125ad.0.2024.07.05.03.56.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 05 Jul 2024 03:57:02 -0700 (PDT) From: Changqi Lu To: qemu-block@nongnu.org, qemu-devel@nongnu.org Cc: kwolf@redhat.com, hreitz@redhat.com, stefanha@redhat.com, fam@euphon.net, ronniesahlberg@gmail.com, pbonzini@redhat.com, pl@dlhnet.de, kbusch@kernel.org, its@irrelevant.dk, foss@defmacro.it, philmd@linaro.org, pizhenwei@bytedance.com, Changqi Lu Subject: [PATCH v7 10/10] block/iscsi: add persistent reservation in/out driver Date: Fri, 5 Jul 2024 18:56:14 +0800 Message-Id: <20240705105614.3377694-11-luchangqi.123@bytedance.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20240705105614.3377694-1-luchangqi.123@bytedance.com> References: <20240705105614.3377694-1-luchangqi.123@bytedance.com> MIME-Version: 1.0 Received-SPF: pass client-ip=2607:f8b0:4864:20::62c; envelope-from=luchangqi.123@bytedance.com; helo=mail-pl1-x62c.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Add persistent reservation in/out operations for iscsi driver. The following methods are implemented: bdrv_co_pr_read_keys, bdrv_co_pr_read_reservation, bdrv_co_pr_register, bdrv_co_pr_reserve, bdrv_co_pr_release, bdrv_co_pr_clear and bdrv_co_pr_preempt. Signed-off-by: Changqi Lu Signed-off-by: zhenwei pi --- block/iscsi.c | 431 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 431 insertions(+) diff --git a/block/iscsi.c b/block/iscsi.c index 2ff14b7472..9a546f48de 100644 --- a/block/iscsi.c +++ b/block/iscsi.c @@ -96,6 +96,7 @@ typedef struct IscsiLun { unsigned long *allocmap_valid; long allocmap_size; int cluster_size; + uint8_t pr_cap; bool use_16_for_rw; bool write_protected; bool lbpme; @@ -280,6 +281,10 @@ iscsi_co_generic_cb(struct iscsi_context *iscsi, int status, iTask->err_code = -error; iTask->err_str = g_strdup(iscsi_get_error(iscsi)); } + } else if (status == SCSI_STATUS_RESERVATION_CONFLICT) { + iTask->err_code = -EBADE; + error_report("iSCSI Persistent Reservation Conflict: %s", + iscsi_get_error(iscsi)); } } } @@ -1792,6 +1797,52 @@ static void iscsi_save_designator(IscsiLun *lun, } } +static void iscsi_get_pr_cap_sync(IscsiLun *iscsilun, Error **errp) +{ + struct scsi_task *task = NULL; + struct scsi_persistent_reserve_in_report_capabilities *rc = NULL; + int retries = ISCSI_CMD_RETRIES; + int xferlen = sizeof(struct scsi_persistent_reserve_in_report_capabilities); + + do { + if (task != NULL) { + scsi_free_scsi_task(task); + task = NULL; + } + + task = iscsi_persistent_reserve_in_sync(iscsilun->iscsi, + iscsilun->lun, SCSI_PR_IN_REPORT_CAPABILITIES, xferlen); + if (task != NULL && task->status == SCSI_STATUS_GOOD) { + rc = scsi_datain_unmarshall(task); + if (rc == NULL) { + error_setg(errp, + "iSCSI: Failed to unmarshall report capabilities data."); + } else { + iscsilun->pr_cap = + scsi_pr_cap_to_block(rc->persistent_reservation_type_mask); + iscsilun->pr_cap |= (rc->ptpl_a) ? BLK_PR_CAP_PTPL : 0; + } + break; + } + + if (task != NULL && task->status == SCSI_STATUS_CHECK_CONDITION + && task->sense.key == SCSI_SENSE_UNIT_ATTENTION) { + break; + } + + } while (task != NULL && task->status == SCSI_STATUS_CHECK_CONDITION + && task->sense.key == SCSI_SENSE_UNIT_ATTENTION + && retries-- > 0); + + if (task == NULL || task->status != SCSI_STATUS_GOOD) { + error_setg(errp, "iSCSI: failed to send report capabilities command"); + } + + if (task) { + scsi_free_scsi_task(task); + } +} + static int iscsi_open(BlockDriverState *bs, QDict *options, int flags, Error **errp) { @@ -2024,6 +2075,11 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags, bs->supported_zero_flags = BDRV_REQ_MAY_UNMAP; } + iscsi_get_pr_cap_sync(iscsilun, &local_err); + if (local_err != NULL) { + error_propagate(errp, local_err); + ret = -EINVAL; + } out: qemu_opts_del(opts); g_free(initiator_name); @@ -2110,6 +2166,8 @@ static void iscsi_refresh_limits(BlockDriverState *bs, Error **errp) bs->bl.opt_transfer = pow2floor(iscsilun->bl.opt_xfer_len * iscsilun->block_size); } + + bs->bl.pr_cap = iscsilun->pr_cap; } /* Note that this will not re-establish a connection with an iSCSI target - it @@ -2408,6 +2466,371 @@ out_unlock: return r; } +static int coroutine_fn +iscsi_co_pr_read_keys(BlockDriverState *bs, uint32_t *generation, + uint32_t num_keys, uint64_t *keys) +{ + IscsiLun *iscsilun = bs->opaque; + QEMUIOVector qiov; + struct IscsiTask iTask; + int xferlen = sizeof(struct scsi_persistent_reserve_in_read_keys) + + sizeof(uint64_t) * num_keys; + uint8_t *buf = g_malloc0(xferlen); + int32_t num_collect_keys = 0; + int r = 0; + + qemu_iovec_init_buf(&qiov, buf, xferlen); + iscsi_co_init_iscsitask(iscsilun, &iTask); + qemu_mutex_lock(&iscsilun->mutex); +retry: + iTask.task = iscsi_persistent_reserve_in_task(iscsilun->iscsi, + iscsilun->lun, SCSI_PR_IN_READ_KEYS, xferlen, + iscsi_co_generic_cb, &iTask); + + if (iTask.task == NULL) { + qemu_mutex_unlock(&iscsilun->mutex); + return -ENOMEM; + } + + scsi_task_set_iov_in(iTask.task, (struct scsi_iovec *)qiov.iov, qiov.niov); + iscsi_co_wait_for_task(&iTask, iscsilun); + + if (iTask.task != NULL) { + scsi_free_scsi_task(iTask.task); + iTask.task = NULL; + } + + if (iTask.do_retry) { + iTask.complete = 0; + goto retry; + } + + if (iTask.status != SCSI_STATUS_GOOD) { + error_report("iSCSI PERSISTENT_RESERVE_IN failed: %s", iTask.err_str); + r = iTask.err_code; + goto out; + } + + memcpy(generation, &buf[0], 4); + *generation = be32_to_cpu(*generation); + memcpy(&num_collect_keys, &buf[4], 4); + num_collect_keys = be32_to_cpu(num_collect_keys) / sizeof(uint64_t); + if (num_collect_keys > num_keys) { + r = -EINVAL; + goto out; + } + + for (int i = 0; i < num_collect_keys; i++) { + memcpy(&keys[i], &buf[8 + i * 8], 8); + keys[i] = be64_to_cpu(keys[i]); + } + r = num_collect_keys; + +out: + qemu_mutex_unlock(&iscsilun->mutex); + g_free(iTask.err_str); + g_free(buf); + return r; +} + +static int coroutine_fn +iscsi_co_pr_read_reservation(BlockDriverState *bs, uint32_t *generation, + uint64_t *key, BlockPrType *type) +{ + IscsiLun *iscsilun = bs->opaque; + QEMUIOVector qiov; + struct IscsiTask iTask; + int xferlen = sizeof(struct scsi_persistent_reserve_in_read_reservation); + uint8_t *buf = g_malloc0(xferlen); + uint8_t scope_type = 0; + int32_t num_collect_keys = 0; + int r = 0; + + qemu_iovec_init_buf(&qiov, buf, xferlen); + iscsi_co_init_iscsitask(iscsilun, &iTask); + qemu_mutex_lock(&iscsilun->mutex); +retry: + iTask.task = iscsi_persistent_reserve_in_task(iscsilun->iscsi, + iscsilun->lun, SCSI_PR_IN_READ_RESERVATION, + xferlen, iscsi_co_generic_cb, &iTask); + + if (iTask.task == NULL) { + qemu_mutex_unlock(&iscsilun->mutex); + return -ENOMEM; + } + + scsi_task_set_iov_in(iTask.task, (struct scsi_iovec *)qiov.iov, qiov.niov); + iscsi_co_wait_for_task(&iTask, iscsilun); + + if (iTask.task != NULL) { + scsi_free_scsi_task(iTask.task); + iTask.task = NULL; + } + + if (iTask.do_retry) { + iTask.complete = 0; + goto retry; + } + + if (iTask.status != SCSI_STATUS_GOOD) { + error_report("iSCSI PERSISTENT_RESERVE_IN failed: %s", iTask.err_str); + r = iTask.err_code; + goto out; + } + + memcpy(generation, &buf[0], 4); + *generation = be32_to_cpu(*generation); + memcpy(key, &buf[8], 8); + *key = be64_to_cpu(*key); + memcpy(&scope_type, &buf[21], 1); + *type = scsi_pr_type_to_block(scope_type & 0xf); + memcpy(&num_collect_keys, &buf[4], 4); + r = be32_to_cpu(num_collect_keys) / sizeof(uint64_t); +out: + qemu_mutex_unlock(&iscsilun->mutex); + g_free(iTask.err_str); + g_free(buf); + return r; +} + +static int coroutine_fn +iscsi_co_pr_register(BlockDriverState *bs, uint64_t old_key, + uint64_t new_key, BlockPrType type, + bool ptpl, bool ignore_key) +{ + IscsiLun *iscsilun = bs->opaque; + struct IscsiTask iTask; + struct scsi_persistent_reserve_out_basic basic; + SCSIPrOutAction action = ignore_key ? SCSI_PR_OUT_REG_AND_IGNORE_KEY : + SCSI_PR_OUT_REGISTER; + int r = 0; + + basic.reservation_key = old_key; + basic.service_action_reservation_key = new_key; + basic.aptpl = ptpl ? 1 : 0; + + iscsi_co_init_iscsitask(iscsilun, &iTask); + qemu_mutex_lock(&iscsilun->mutex); +retry: + iTask.task = iscsi_persistent_reserve_out_task(iscsilun->iscsi, + iscsilun->lun, action, 0, block_pr_type_to_scsi(type), + &basic, iscsi_co_generic_cb, &iTask); + + if (iTask.task == NULL) { + qemu_mutex_unlock(&iscsilun->mutex); + return -ENOMEM; + } + + iscsi_co_wait_for_task(&iTask, iscsilun); + + if (iTask.task != NULL) { + scsi_free_scsi_task(iTask.task); + iTask.task = NULL; + } + + if (iTask.do_retry) { + iTask.complete = 0; + goto retry; + } + + if (iTask.status != SCSI_STATUS_GOOD) { + error_report("iSCSI PERSISTENT_RESERVE_OUT failed: %s", iTask.err_str); + r = iTask.err_code; + } + + qemu_mutex_unlock(&iscsilun->mutex); + + g_free(iTask.err_str); + return r; +} + +static int coroutine_fn +iscsi_co_pr_reserve(BlockDriverState *bs, uint64_t key, BlockPrType type) +{ + IscsiLun *iscsilun = bs->opaque; + struct IscsiTask iTask; + struct scsi_persistent_reserve_out_basic basic; + int r = 0; + + basic.reservation_key = key; + iscsi_co_init_iscsitask(iscsilun, &iTask); + qemu_mutex_lock(&iscsilun->mutex); +retry: + iTask.task = iscsi_persistent_reserve_out_task(iscsilun->iscsi, + iscsilun->lun, SCSI_PR_OUT_RESERVE, 0, + block_pr_type_to_scsi(type), &basic, + iscsi_co_generic_cb, &iTask); + + if (iTask.task == NULL) { + qemu_mutex_unlock(&iscsilun->mutex); + return -ENOMEM; + } + + + iscsi_co_wait_for_task(&iTask, iscsilun); + + if (iTask.task != NULL) { + scsi_free_scsi_task(iTask.task); + iTask.task = NULL; + } + + if (iTask.do_retry) { + iTask.complete = 0; + goto retry; + } + + if (iTask.status != SCSI_STATUS_GOOD) { + error_report("iSCSI PERSISTENT_RESERVE_OUT failed: %s", iTask.err_str); + r = iTask.err_code; + } + + qemu_mutex_unlock(&iscsilun->mutex); + + g_free(iTask.err_str); + return r; +} + +static int coroutine_fn +iscsi_co_pr_release(BlockDriverState *bs, uint64_t key, BlockPrType type) +{ + IscsiLun *iscsilun = bs->opaque; + struct IscsiTask iTask; + struct scsi_persistent_reserve_out_basic basic; + int r = 0; + + basic.reservation_key = key; + iscsi_co_init_iscsitask(iscsilun, &iTask); + qemu_mutex_lock(&iscsilun->mutex); +retry: + iTask.task = iscsi_persistent_reserve_out_task(iscsilun->iscsi, + iscsilun->lun, SCSI_PR_OUT_RELEASE, 0, + block_pr_type_to_scsi(type), &basic, + iscsi_co_generic_cb, &iTask); + + if (iTask.task == NULL) { + qemu_mutex_unlock(&iscsilun->mutex); + return -ENOMEM; + } + + + iscsi_co_wait_for_task(&iTask, iscsilun); + + if (iTask.task != NULL) { + scsi_free_scsi_task(iTask.task); + iTask.task = NULL; + } + + if (iTask.do_retry) { + iTask.complete = 0; + goto retry; + } + + if (iTask.status != SCSI_STATUS_GOOD) { + error_report("iSCSI PERSISTENT_RESERVE_OUT failed: %s", iTask.err_str); + r = iTask.err_code; + } + + qemu_mutex_unlock(&iscsilun->mutex); + + g_free(iTask.err_str); + return r; +} + +static int coroutine_fn +iscsi_co_pr_clear(BlockDriverState *bs, uint64_t key) +{ + IscsiLun *iscsilun = bs->opaque; + struct IscsiTask iTask; + struct scsi_persistent_reserve_out_basic basic; + int r = 0; + + basic.reservation_key = key; + iscsi_co_init_iscsitask(iscsilun, &iTask); + qemu_mutex_lock(&iscsilun->mutex); +retry: + iTask.task = iscsi_persistent_reserve_out_task(iscsilun->iscsi, + iscsilun->lun, SCSI_PR_OUT_CLEAR, 0, 0, &basic, + iscsi_co_generic_cb, &iTask); + + if (iTask.task == NULL) { + qemu_mutex_unlock(&iscsilun->mutex); + return -ENOMEM; + } + + + iscsi_co_wait_for_task(&iTask, iscsilun); + + if (iTask.task != NULL) { + scsi_free_scsi_task(iTask.task); + iTask.task = NULL; + } + + if (iTask.do_retry) { + iTask.complete = 0; + goto retry; + } + + if (iTask.status != SCSI_STATUS_GOOD) { + error_report("iSCSI PERSISTENT_RESERVE_OUT failed: %s", iTask.err_str); + r = iTask.err_code; + } + + qemu_mutex_unlock(&iscsilun->mutex); + + g_free(iTask.err_str); + return r; +} + +static int coroutine_fn +iscsi_co_pr_preempt(BlockDriverState *bs, uint64_t old_key, + uint64_t new_key, BlockPrType type, bool abort) +{ + IscsiLun *iscsilun = bs->opaque; + struct IscsiTask iTask; + struct scsi_persistent_reserve_out_basic basic; + SCSIPrOutAction action = abort ? SCSI_PR_OUT_PREEMPT_AND_ABORT : + SCSI_PR_OUT_PREEMPT; + int r = 0; + + basic.reservation_key = old_key; + basic.service_action_reservation_key = new_key; + + iscsi_co_init_iscsitask(iscsilun, &iTask); + qemu_mutex_lock(&iscsilun->mutex); +retry: + iTask.task = iscsi_persistent_reserve_out_task(iscsilun->iscsi, + iscsilun->lun, action, 0, block_pr_type_to_scsi(type), + &basic, iscsi_co_generic_cb, &iTask); + + if (iTask.task == NULL) { + qemu_mutex_unlock(&iscsilun->mutex); + return -ENOMEM; + } + + + iscsi_co_wait_for_task(&iTask, iscsilun); + + if (iTask.task != NULL) { + scsi_free_scsi_task(iTask.task); + iTask.task = NULL; + } + + if (iTask.do_retry) { + iTask.complete = 0; + goto retry; + } + + if (iTask.status != SCSI_STATUS_GOOD) { + error_report("iSCSI PERSISTENT_RESERVE_OUT failed: %s", iTask.err_str); + r = iTask.err_code; + } + + qemu_mutex_unlock(&iscsilun->mutex); + + g_free(iTask.err_str); + return r; +} + static const char *const iscsi_strong_runtime_opts[] = { "transport", @@ -2451,6 +2874,14 @@ static BlockDriver bdrv_iscsi = { .bdrv_co_writev = iscsi_co_writev, .bdrv_co_flush_to_disk = iscsi_co_flush, + .bdrv_co_pr_read_keys = iscsi_co_pr_read_keys, + .bdrv_co_pr_read_reservation = iscsi_co_pr_read_reservation, + .bdrv_co_pr_register = iscsi_co_pr_register, + .bdrv_co_pr_reserve = iscsi_co_pr_reserve, + .bdrv_co_pr_release = iscsi_co_pr_release, + .bdrv_co_pr_clear = iscsi_co_pr_clear, + .bdrv_co_pr_preempt = iscsi_co_pr_preempt, + #ifdef __linux__ .bdrv_aio_ioctl = iscsi_aio_ioctl, #endif