From patchwork Thu Aug 29 08:42: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: 13782790 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id A65BFC7EE3A for ; Thu, 29 Aug 2024 08:44:24 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1sjajs-0005Vw-1N; Thu, 29 Aug 2024 04:42:44 -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 1sjajr-0005RV-1M for qemu-devel@nongnu.org; Thu, 29 Aug 2024 04:42:43 -0400 Received: from mail-pj1-x1036.google.com ([2607:f8b0:4864:20::1036]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1sjajo-0000AG-00 for qemu-devel@nongnu.org; Thu, 29 Aug 2024 04:42:42 -0400 Received: by mail-pj1-x1036.google.com with SMTP id 98e67ed59e1d1-2d3e44b4613so295576a91.3 for ; Thu, 29 Aug 2024 01:42:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bytedance.com; s=google; t=1724920958; x=1725525758; 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=fmBCyXbDFDXZfd++HuSOGkWXjW5DHdU1ZXFrWmEMcuM=; b=PGR+25+81oE7wh0oAfQIpSGc83bQSebJJ4GzMxi0YSfVbe0WY+VAJm8iiz+uJm/jTt nUT2cLI4T+ymkrBxmrR0fmau8jZhOubxd7AQx268HFlZ4XuDtx8wd/nXKu/RcJcfN9KL yiTYqt4fwwEUZfZNW/NxOL1Zpkgq4U55c9q3MHdXCwQ3ZUupjLa2TSciG/kX80oOGDam UpqkqE7JhbY2bkQL4SmeRLanc0aqQjJLmEqUEzx3Vpbx6FHO3xhWrxcQGC6hzJbM6zE/ c7o6LPLFnohNFyb6/gvj5UzotoIfvJVfffwAytuOP1LRSBPw3EngocsGOHIc+HdMwmcY esxA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1724920958; x=1725525758; 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=fmBCyXbDFDXZfd++HuSOGkWXjW5DHdU1ZXFrWmEMcuM=; b=v3VtaNJO9EUaLjjKjiHFIjNibP433CFS0UGc+dKvy0dby7LkSCpaiHGb/Y2xflBu5V gN+alXbm2PZ9NoAfcaGhzLzzKbCGO8FLp1bDRNw17E7n38t0qrjkFuAF04Hhpl7gjo8T 5o1s1JlteH9yYW6HV52iY5ok+4tqM7jTJCUSsKwVOx7dpmBuHgNw/Usa2FwHtBhLvrJC I1u0E/nKF8f6O3f8GS8uKW/VzpkBvQsLwT24dnyOMNlbXSkggbb/jLtK2YvbZV7bjUSq uBz+LklBDYSeHh0lDdfPPo4XV7b6bvPSBxFCFubVYKKWcIiIg2bSvCJAg0Wom2wr1cGb ymOg== X-Forwarded-Encrypted: i=1; AJvYcCVJ7ePp/xUnk9ms/m3uVPbApv2u/lJp+Jtvf8bx2tK74IRUzjuHlpvXXvSiZv0G5YN4KiuLvTtnMQeS@nongnu.org X-Gm-Message-State: AOJu0YxOXsF2UtgE97OpSB/AYTHMJHf9d00SwaRsejFA33DiGixWDIYS DKXZqxTBV69wG/BuvgQva9LA6NsK/R5hQCFflEkIRjIDk1wa9Jz9a8zhii0MdBk= X-Google-Smtp-Source: AGHT+IEVxW08B5x6CS9ihG7KBestHeembd20Qu+djnaTXQbHlLgdNL4ooc0W8l2e1PYvxe+vvqYUJQ== X-Received: by 2002:a17:90b:1909:b0:2c4:b0f0:8013 with SMTP id 98e67ed59e1d1-2d8561b15b3mr1782148a91.11.1724920958361; Thu, 29 Aug 2024 01:42:38 -0700 (PDT) Received: from TF4D9JK212.bytedance.net ([61.213.176.6]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-2d8446f3897sm3431856a91.49.2024.08.29.01.42.33 (version=TLS1_3 cipher=TLS_CHACHA20_POLY1305_SHA256 bits=256/256); Thu, 29 Aug 2024 01:42: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, k.jensen@samsung.com, Changqi Lu Subject: [PATCH v10 01/10] block: add persistent reservation in/out api Date: Thu, 29 Aug 2024 16:42:05 +0800 Message-Id: <20240829084214.50548-2-luchangqi.123@bytedance.com> X-Mailer: git-send-email 2.39.2 (Apple Git-143) In-Reply-To: <20240829084214.50548-1-luchangqi.123@bytedance.com> References: <20240829084214.50548-1-luchangqi.123@bytedance.com> MIME-Version: 1.0 Received-SPF: pass client-ip=2607:f8b0:4864:20::1036; envelope-from=luchangqi.123@bytedance.com; helo=mail-pj1-x1036.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, T_SCC_BODY_TEXT_LINE=-0.01 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+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.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 338fe5ff7a..725b6174c2 100644 --- a/include/block/block-common.h +++ b/include/block/block-common.h @@ -526,6 +526,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 Thu Aug 29 08:42: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: 13782789 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 2092AC83010 for ; Thu, 29 Aug 2024 08:44:22 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1sjajv-0005lE-VU; Thu, 29 Aug 2024 04:42:48 -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 1sjaju-0005eh-5H for qemu-devel@nongnu.org; Thu, 29 Aug 2024 04:42:46 -0400 Received: from mail-pj1-x1036.google.com ([2607:f8b0:4864:20::1036]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1sjajs-0000Aw-GK for qemu-devel@nongnu.org; Thu, 29 Aug 2024 04:42:45 -0400 Received: by mail-pj1-x1036.google.com with SMTP id 98e67ed59e1d1-2d3c098792bso289560a91.1 for ; Thu, 29 Aug 2024 01:42:44 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bytedance.com; s=google; t=1724920963; x=1725525763; 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=HP2xz18og9fugiccsCMD/DezsDlDfWCIPE/VQ7rtl8zLYVrcvb/I+a81GMMNvxUeSU Av5wxnpzAu/xc8cgCP5x7LolLb6P/x0ZAhgK7GrfC8453l2Vaa1Kb5xYpfoxiHI1X/UB /UKtV25W60lifSPd8gppCwjCOJqCenP7L/xFM8WEZjBax34d4/gdm+I/lv6cpFDyHFoH 7AhEHx7EYppInmZHHrl0W+IL9rfB0rXvdFiTRUNOw9k/nAyS5zkX00+WvuG+J6EWqjPL TUJt99Hqbwp2tg8eFYWBnnnA8rsOE6D8/M9qqec4shbxSTtISdsogjPjAy8T0kIDxnMK lLNQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1724920963; x=1725525763; 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=jbYISMQ9ykJ8Sqoh8rF7NNwsbdYew+EYReDyqGt0R97ntXAi29ws0zuPxaVAoNCCvz hzuJxMDWMFd7u4vI2gShHhMwDdrHlNpENVJuCqK3L+ZiFUnLWwZyyZ3CnjC+aPyDlcOq CSiCiEv3d0AqKkbYmBtXAqqe8sHCNNp/GZeVkLzOrwT7iwpiWQ6gbr5SYlKcOpRhyU5Q 7w4V59nc3F4s54AS2kl1RL6iU/JojtFs96qkavCctwGR6ZO06Fz3lyYtW1G5iAaiWraD QUNvSicAgz4X4quda6wKL2CRQfwriEaoUnclr1OAbIHW7eofk0kLElcZEWsg3jftowf/ +mbw== X-Forwarded-Encrypted: i=1; AJvYcCWuPNuwxNeE9AyP9M5hgEoWqhaqHMvLvuxNjC6I+xaQfK9nPTaf0g3cvA/+8O5buBMAxBHXuMxqik6c@nongnu.org X-Gm-Message-State: AOJu0YwVt4/CfIhVEDN0Uly9nLVjIF816VbiDwKv2wjglO2rpD2KfMx+ OKHBDgERLOVD1+l+X7JdgDmqN7r35++bpgFGl15uv9AP6AZnklzLDBAWxiWZiMI= X-Google-Smtp-Source: AGHT+IH4M+4oC+6nGZGniMH0XPqecvkVga2rIO+AUe3/sWlg+1s8Qfpxu2npEECvjJaRPJhRNgewug== X-Received: by 2002:a17:90b:524a:b0:2c9:321:1bf1 with SMTP id 98e67ed59e1d1-2d8564a50cbmr2238273a91.39.1724920963252; Thu, 29 Aug 2024 01:42:43 -0700 (PDT) Received: from TF4D9JK212.bytedance.net ([61.213.176.6]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-2d8446f3897sm3431856a91.49.2024.08.29.01.42.38 (version=TLS1_3 cipher=TLS_CHACHA20_POLY1305_SHA256 bits=256/256); Thu, 29 Aug 2024 01:42:42 -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, k.jensen@samsung.com, Changqi Lu Subject: [PATCH v10 02/10] block/raw: add persistent reservation in/out driver Date: Thu, 29 Aug 2024 16:42:06 +0800 Message-Id: <20240829084214.50548-3-luchangqi.123@bytedance.com> X-Mailer: git-send-email 2.39.2 (Apple Git-143) In-Reply-To: <20240829084214.50548-1-luchangqi.123@bytedance.com> References: <20240829084214.50548-1-luchangqi.123@bytedance.com> MIME-Version: 1.0 Received-SPF: pass client-ip=2607:f8b0:4864:20::1036; envelope-from=luchangqi.123@bytedance.com; helo=mail-pj1-x1036.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, T_SCC_BODY_TEXT_LINE=-0.01 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+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.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 Thu Aug 29 08:42: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: 13782793 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 5993AC7EE3A for ; Thu, 29 Aug 2024 08:44:56 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1sjak2-00063b-BA; Thu, 29 Aug 2024 04:42:54 -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 1sjak0-000613-Dp for qemu-devel@nongnu.org; Thu, 29 Aug 2024 04:42:52 -0400 Received: from mail-pj1-x102e.google.com ([2607:f8b0:4864:20::102e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1sjajx-0000Bl-Ew for qemu-devel@nongnu.org; Thu, 29 Aug 2024 04:42:52 -0400 Received: by mail-pj1-x102e.google.com with SMTP id 98e67ed59e1d1-2d3da94f059so294608a91.2 for ; Thu, 29 Aug 2024 01:42:49 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bytedance.com; s=google; t=1724920968; x=1725525768; 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=MS23l1PTN2U9D6x/mEKT45kwkLRZxPD6GNHnUqS6lhdZ4dHZHixlJhvGOnl87GUZEN Pc3NevA3YVHAkg5EV7bHuKpHEbU10Npdtmaph+qy8mnIN3K5PEplBVkpBCQC4/Y0171f 2R71iEDoVkaKwnKDxlkvwOtm2MfDM7auUdhjPgZvSOFb9r7XPkWqNMMt23R/8nsLGAGE 2aksEEqohXK5En9Gmt1PzCXx909Le+VORv1DSqVkljJgA62ic7zb/8/kvwa5NEYMhq8W Ve1VZm9P99vIauiHOWE4UX04WhOooZaHlIFAoN1z5ieudzIyzc6GbPAlF1qW0nQrfg6s qi0w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1724920968; x=1725525768; 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=P/PenA0PBbofWnNBK6GC1D7n/nOn+r3E9A9JBjphjCxlKlziWEuWu3/AdXkR84tbc9 Zk2Wu+KQnwShtXKiPG7XFgJNkbE4zDBOGyD3McOzoKfR49pxcbii/ZEaIAvoTK3moq28 leV8iYQZ5McSZuHyYExWKYLctxSSzqobgcPp6j+aWgV8qsatguxCEaqbSs5Qyemgm60B ezUXDEH7qAaqB7zTrzMiVwzFrXJiku3988UmDZDxqT+/hRhqJ48pWM97FtPNh80xCfow EJmYYSX3w3KK4WlF7kneV0e+R3xd7POJGEac865UR8Ts3by3W6fhnNkxwayFFSinioA9 hG9A== X-Forwarded-Encrypted: i=1; AJvYcCXTpvFLIAamapfbxOYrqvFjKtiH7dMMqsUr8wjTmWqbj9I7oM07pRu6vExOEuKxodMGg9jTx2EFl7PY@nongnu.org X-Gm-Message-State: AOJu0YzkcdosPFOdEymzW4lw3BqOP8DM5e3mqvwB1Jzs8obZyzl/8vn1 QIwKHKZ9RYUIbZmcnJ7yEPFfmRn16Lam514mB9zWodN1OvioFf2PW6Pf22ZYyxpFQBY4/XcCDVc q X-Google-Smtp-Source: AGHT+IFp5X09+4k7P/wVbY1Fq6vN6Aw6Qdaaeeho14llkQJcASFXQsaQq7/aTzNOTlf0+NZUXzdpvg== X-Received: by 2002:a17:90a:fb94:b0:2cd:3e75:4e51 with SMTP id 98e67ed59e1d1-2d8564bb8d5mr2110422a91.39.1724920968150; Thu, 29 Aug 2024 01:42:48 -0700 (PDT) Received: from TF4D9JK212.bytedance.net ([61.213.176.6]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-2d8446f3897sm3431856a91.49.2024.08.29.01.42.43 (version=TLS1_3 cipher=TLS_CHACHA20_POLY1305_SHA256 bits=256/256); Thu, 29 Aug 2024 01:42:47 -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, k.jensen@samsung.com, Changqi Lu Subject: [PATCH v10 03/10] scsi/constant: add persistent reservation in/out protocol constants Date: Thu, 29 Aug 2024 16:42:07 +0800 Message-Id: <20240829084214.50548-4-luchangqi.123@bytedance.com> X-Mailer: git-send-email 2.39.2 (Apple Git-143) In-Reply-To: <20240829084214.50548-1-luchangqi.123@bytedance.com> References: <20240829084214.50548-1-luchangqi.123@bytedance.com> MIME-Version: 1.0 Received-SPF: pass client-ip=2607:f8b0:4864:20::102e; envelope-from=luchangqi.123@bytedance.com; helo=mail-pj1-x102e.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, T_SCC_BODY_TEXT_LINE=-0.01 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+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.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 Thu Aug 29 08:42: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: 13782791 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id C3C5AC7EE3A for ; Thu, 29 Aug 2024 08:44:29 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1sjak6-0006GE-4X; Thu, 29 Aug 2024 04:42:58 -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 1sjak4-0006Az-69 for qemu-devel@nongnu.org; Thu, 29 Aug 2024 04:42:56 -0400 Received: from mail-pf1-x42c.google.com ([2607:f8b0:4864:20::42c]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1sjak2-0000Cd-IN for qemu-devel@nongnu.org; Thu, 29 Aug 2024 04:42:55 -0400 Received: by mail-pf1-x42c.google.com with SMTP id d2e1a72fcca58-7142a93ea9cso353858b3a.3 for ; Thu, 29 Aug 2024 01:42:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bytedance.com; s=google; t=1724920973; x=1725525773; 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=TpE82v+YodejyieLPjfCU74PMlEXZLHQM4uGIePk9yaLUvuH0ZXoRQtzbMG8RkKAHJ LR9wioc0xKKP445N8q3BFioFvE5F9yM5dHjAdhuHaovsMIpU3QtfxRaxMaMI5vXf1bc9 +3t5ciUIv9f5PFLhAd1VqVngrdVf3wVnKvT0vIOWPzAacrSffWeJyDAFNLm9jUaxkwFB aTSfdDUVNwgkoq/WFv3RPPxdCzKCVZYhFtM9q7ZPgmp22jxGEz/gOqra7etD0PavuEtJ J0qxavbdxQqqjqLG6Wvqv98/bB73XuCMUA5l6RvRDpY7vPGbJtfYNxbnIlhmTUIuWDa/ 8KHA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1724920973; x=1725525773; 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=d6Efl4Fc36b0colsW6dFJYnodT5bYEwdJ3n4B0bm9mMhJJqicADxrXmxIEAoWSWQp7 j8gkqMcxwyfL62L4oN4VZMjkZf3pU7MJN1qmbIwn7WXXkk/is6GKPicoToK183hyW9bc fDCPytvJEr/CJSo9kzmh5C5l9DwNqMARiqM5Q9Els2sUxVT4tiyHggf5QRYtvWAhNXIf mnrjChOrhKgOpW2LaWO2YCqtdhtVCtGgmzlBLdtQEvx0ULdexeNzhVj8P8ZV9Ku6E3VA FaA8en3GI5EApTgF1+OS8aENOplbUNCkudbR6KLE1MLLkhez75QoJAOfBxnprPy0tza5 gBCQ== X-Forwarded-Encrypted: i=1; AJvYcCX1u+sLPyHnNdGOAcA9d4HjyJZye++IoRFwsc7z6LtQWGaoHVT/mTXeZ67P/l8DdndJcIwdXKD+umnc@nongnu.org X-Gm-Message-State: AOJu0Yx9DNXH6BEzDx0fzaFV1xPIrO5kYUXpaj+uUPrS0SKfaOW+/HQH ZsJGYMuccD3/wWrFMHaXau68dx7ciFWGdDO32+O72hHD7HXUn0oD1e5d6uTbz04= X-Google-Smtp-Source: AGHT+IHinefcYShIDv2eQqhIee6/kThuNiDzhJgLhwmeso0kgUEzOlqVUa6wQl674NJdNQIY/Vf0Ag== X-Received: by 2002:a05:6a21:60c4:b0:1c3:ba3d:3ec3 with SMTP id adf61e73a8af0-1cce109796cmr1898039637.36.1724920973166; Thu, 29 Aug 2024 01:42:53 -0700 (PDT) Received: from TF4D9JK212.bytedance.net ([61.213.176.6]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-2d8446f3897sm3431856a91.49.2024.08.29.01.42.48 (version=TLS1_3 cipher=TLS_CHACHA20_POLY1305_SHA256 bits=256/256); Thu, 29 Aug 2024 01:42:52 -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, k.jensen@samsung.com, Changqi Lu Subject: [PATCH v10 04/10] scsi/util: add helper functions for persistent reservation types conversion Date: Thu, 29 Aug 2024 16:42:08 +0800 Message-Id: <20240829084214.50548-5-luchangqi.123@bytedance.com> X-Mailer: git-send-email 2.39.2 (Apple Git-143) In-Reply-To: <20240829084214.50548-1-luchangqi.123@bytedance.com> References: <20240829084214.50548-1-luchangqi.123@bytedance.com> MIME-Version: 1.0 Received-SPF: pass client-ip=2607:f8b0:4864:20::42c; envelope-from=luchangqi.123@bytedance.com; helo=mail-pf1-x42c.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, T_SCC_BODY_TEXT_LINE=-0.01 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+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.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 Thu Aug 29 08:42: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: 13782788 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 649F4C8300F for ; Thu, 29 Aug 2024 08:43:33 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1sjakB-0006Ts-E7; Thu, 29 Aug 2024 04:43:03 -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 1sjak9-0006Sb-OZ for qemu-devel@nongnu.org; Thu, 29 Aug 2024 04:43:01 -0400 Received: from mail-pg1-x530.google.com ([2607:f8b0:4864:20::530]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1sjak7-0000D3-G1 for qemu-devel@nongnu.org; Thu, 29 Aug 2024 04:43:01 -0400 Received: by mail-pg1-x530.google.com with SMTP id 41be03b00d2f7-7b0c9bbddb4so251999a12.3 for ; Thu, 29 Aug 2024 01:42:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bytedance.com; s=google; t=1724920978; x=1725525778; 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=GyWZah7cSLBjeyidzg/5MhE8KB58XPtTKdjaKf+2eVc=; b=iNQEoJEz9nkKoY7HzR6+VsvA8nYDqJofy4B+5ykS3hvcLQTgviHU1yFfNAqiZ70V6b 1oNCcjI0e7BD8TvY581HVAev/mxGyqJUb4c8ncU4SZboZ2FiJ7oyMEdVmMCgo8A5Xnuo tlyfPCrjvkKdQ77qmZhG4xFrcF99MmZwY2udqLOpaGzXv4LlhgDkwuxVAWSKUbbO91su 8qLB3w6BGubnTIgzEwlUi+XAaduvJWJ72Vo/VQBo8md5+AjSjjShJurjkqiP39IBiz2o GLv0oqJRCR9r8yD7/3RmA+78yrJ9hyCNUkj0N9N/tpNSYQi1cV4Mpzc4wbrnp/5DLtYS VQCA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1724920978; x=1725525778; 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=GyWZah7cSLBjeyidzg/5MhE8KB58XPtTKdjaKf+2eVc=; b=wXWRaHgPgn3voSMbIEUm8j9u1N7pYrnkc9a8hhvDF3jn4zF456/RFA/o5jhHT/RRWU zgFtg0rSgyu+THwXbQrLAJ8H6XATGI5Mwuw53sxpGXiEkeSJgxMsftuZpi5Brmx/BdeJ eMCZFDIoJi+7/OgbhCxB5L0kqXhox1093BsBwd7ETSWWq4fw8Ef5SIXQ409+WUvUpsyS xPltYmgeQ6NYk0VOWnNV46hZ3RRFdYAks+2sC9tu/Cuqvw4rbv8yKtsNAYhig1MjxG2V q/3Q4wb4xiSqvD9HhSaOeLg1YyFfZHEl1ZWwGXYNuD02vSSZ8j03uQkWYWBqlUGNsKhK FPZA== X-Forwarded-Encrypted: i=1; AJvYcCX8zNEa210fOCKczkYJVMRcIxWw4xadOzsTMuyMbNj+5LxITcwZNVN5mlMc+dI8NzSl0ZweHhoO8C9q@nongnu.org X-Gm-Message-State: AOJu0Yz+YIyzbdWJ0BrTGUQ/jGU8oFtXI9Ysu3PhNZWhq527UlynDxcr yZcTQBV/qqSfmm6kIjtJT7UPTLLxcM3bcxdL3hnMU6e6h+s+WctCn3CN3WBap4g= X-Google-Smtp-Source: AGHT+IG2sz71fPlmqdOlDeaiiYyjwNZVJXm983UMyfw8cA581MovIQtmfRkHuMkilF6hUSEfyMSfDg== X-Received: by 2002:a17:90a:5d88:b0:2c9:90f5:cfca with SMTP id 98e67ed59e1d1-2d8564b14c9mr1887241a91.42.1724920978059; Thu, 29 Aug 2024 01:42:58 -0700 (PDT) Received: from TF4D9JK212.bytedance.net ([61.213.176.6]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-2d8446f3897sm3431856a91.49.2024.08.29.01.42.53 (version=TLS1_3 cipher=TLS_CHACHA20_POLY1305_SHA256 bits=256/256); Thu, 29 Aug 2024 01:42:57 -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, k.jensen@samsung.com, Changqi Lu Subject: [PATCH v10 05/10] hw/scsi: add persistent reservation in/out api for scsi device Date: Thu, 29 Aug 2024 16:42:09 +0800 Message-Id: <20240829084214.50548-6-luchangqi.123@bytedance.com> X-Mailer: git-send-email 2.39.2 (Apple Git-143) In-Reply-To: <20240829084214.50548-1-luchangqi.123@bytedance.com> References: <20240829084214.50548-1-luchangqi.123@bytedance.com> MIME-Version: 1.0 Received-SPF: pass client-ip=2607:f8b0:4864:20::530; envelope-from=luchangqi.123@bytedance.com; helo=mail-pg1-x530.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, T_SCC_BODY_TEXT_LINE=-0.01 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+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.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 Reviewed-by: Stefan Hajnoczi --- 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 0812d39c02..2441e5ffca 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 @@ -1477,6 +1479,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 > 0 ? ret : 0); + 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) { @@ -1960,6 +2318,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(); } @@ -2216,6 +2577,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])); @@ -2646,6 +3012,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 Thu Aug 29 08:42: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: 13782787 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 91BF9C83010 for ; Thu, 29 Aug 2024 08:43:33 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1sjakF-0006il-BL; Thu, 29 Aug 2024 04:43:07 -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 1sjakE-0006eQ-6k for qemu-devel@nongnu.org; Thu, 29 Aug 2024 04:43:06 -0400 Received: from mail-pg1-x529.google.com ([2607:f8b0:4864:20::529]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1sjakC-0000DZ-Db for qemu-devel@nongnu.org; Thu, 29 Aug 2024 04:43:05 -0400 Received: by mail-pg1-x529.google.com with SMTP id 41be03b00d2f7-6c5bcb8e8edso271185a12.2 for ; Thu, 29 Aug 2024 01:43:04 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bytedance.com; s=google; t=1724920983; x=1725525783; 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=LNfE2FvcIsikcgtI6Krtxtj2etktds/RmL9xP+AY0Zg=; b=hzwj0V5NlWMLNKBqS9AV7JN7q1fpiKRjSIfkG6UqhRSJiKQzTq4GrOoAfQGbjVKGmw BzCaLkrVLY6zTnbU9U/iY9pejUiIn8de850MDR1kXoQLl9BsO31WVWCf3EeRlOcCL+9k CaqToPhM8ews5wNi2LxBYJp+0DIfku7ODsW3UBjx5inc/HN3TXLT1nxbiCyt0ASHyqhf oL8pAuN//qznJr4rhve5NM7oLvA9o9u0f5M7chVLN5oJSHRCSyVQYNZdTg3GQQMdm3Pb r1KOcBhR4XVTFx2YKdD+A2uvB6t6JQko1vMHqo/Doe/Pwo88lMO3SuyEjo3egszu7gm/ 60WA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1724920983; x=1725525783; 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=LNfE2FvcIsikcgtI6Krtxtj2etktds/RmL9xP+AY0Zg=; b=u7ZmMy8G9A5EEmRTZcF0Kkb8CU5bEMYAcIq8y7tgYMdOgqQ9T4ZaTgyIr3x7Qa4iW9 xS4odYPU6XFWg44vjM8/vvLCh21E7BI0tlV/6+cGtrdBRrHFjeCOZwagytF4N0MoxeJB 63X5MuD5dzfeovf1/twsbSd3CCLzW/fGDG0H42+MYK465NIL4q01Cswenl5PiQqRCf2a 2XqA3WUNDqn+voMAcxVVoK2CkaWmNjNRh4U6ILjF1Cw8SCjF7o/l11RRCazTw0XuyWZM fSVQrDrCDhZddsxFsE/GOzVyHleBKd9cOyVQ0yydHujqu9FXBUngywRcg82hULXmJMwV /HJw== X-Forwarded-Encrypted: i=1; AJvYcCXkwwDrJlYD8JUqnD/uBjAwwKPV5Z7ezN4HqmseaEXXPFx9opoXBk5sgOGXulE/SSBl8zgZ7vc8N5Fe@nongnu.org X-Gm-Message-State: AOJu0YzWxd/OXzNJ1Fo8dZk/7r3paHsSxsG+Icg5dZC1lBmPGkCVW8sZ ClcJpDhQYnE4NykQDIOcUzXd28pVfBzffxaJ7zp8dHyZkVun4U+f9RyT/7yDvY4= X-Google-Smtp-Source: AGHT+IEkX3Y5gn4NSHa8xXuwvxeULy9gbQFimDiK0ihdGwSveBgePUFT5ckvUMRMCpzFDfW+yNq/Vg== X-Received: by 2002:a17:90a:8409:b0:2d3:d4ca:62f6 with SMTP id 98e67ed59e1d1-2d8564b3cf2mr1964392a91.42.1724920983009; Thu, 29 Aug 2024 01:43:03 -0700 (PDT) Received: from TF4D9JK212.bytedance.net ([61.213.176.6]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-2d8446f3897sm3431856a91.49.2024.08.29.01.42.58 (version=TLS1_3 cipher=TLS_CHACHA20_POLY1305_SHA256 bits=256/256); Thu, 29 Aug 2024 01:43: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, k.jensen@samsung.com, Changqi Lu Subject: [PATCH v10 06/10] block/nvme: add reservation command protocol constants Date: Thu, 29 Aug 2024 16:42:10 +0800 Message-Id: <20240829084214.50548-7-luchangqi.123@bytedance.com> X-Mailer: git-send-email 2.39.2 (Apple Git-143) In-Reply-To: <20240829084214.50548-1-luchangqi.123@bytedance.com> References: <20240829084214.50548-1-luchangqi.123@bytedance.com> MIME-Version: 1.0 Received-SPF: pass client-ip=2607:f8b0:4864:20::529; envelope-from=luchangqi.123@bytedance.com; helo=mail-pg1-x529.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, T_SCC_BODY_TEXT_LINE=-0.01 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+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.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. Reviewed-by: Stefan Hajnoczi Signed-off-by: Changqi Lu Signed-off-by: zhenwei pi --- 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 Thu Aug 29 08:42: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: 13782786 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 38D9FC8300F for ; Thu, 29 Aug 2024 08:43:30 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1sjakM-0007U9-W4; Thu, 29 Aug 2024 04:43:15 -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 1sjakL-0007Ef-A1 for qemu-devel@nongnu.org; Thu, 29 Aug 2024 04:43:13 -0400 Received: from mail-pj1-x102c.google.com ([2607:f8b0:4864:20::102c]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1sjakJ-0000E1-5d for qemu-devel@nongnu.org; Thu, 29 Aug 2024 04:43:12 -0400 Received: by mail-pj1-x102c.google.com with SMTP id 98e67ed59e1d1-2d3d58d6e08so283423a91.3 for ; Thu, 29 Aug 2024 01:43:09 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bytedance.com; s=google; t=1724920988; x=1725525788; 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=Tjqh17JUE1WkBpchsBFPlHMHCUXRZeQxBDgeEciSrXM=; b=V3bm4ADZN1/lWCOwKrclD0dziod58BwZl9AiFXP8Z40bJ6tZoFg+ik1/fsKzTmiReF 9ZZG8QMaZ0lUnTh68kybm5ldfSK7awn+SvskiZoX5mGwPo7faCoIB9SX8AVPEIva+Dwd IEUkXsoaImfoZStSSjIWlYHD5lsP7w3EZmbNw0W3cTpTqqCRnGMdIxoBu8K91pTSc/Jq fxM0j5Y55Qev0QZl3FDqCCZ7yVQKLX1eRLdwbsxXTy0Vade46tzE+lqnAfdCwEnYHMOI HbaxciN5KkR+TBfWvZVQZVz8ao4smRcGwHyirPDXeFMn8pS3/t0N/mjm+XYyvjzPNRKO xR9w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1724920988; x=1725525788; 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=Tjqh17JUE1WkBpchsBFPlHMHCUXRZeQxBDgeEciSrXM=; b=K8cI22HLY7dUJuZzDcjyWhnDKHPB+FPXTxGWJL4OJiO45CgXiL5dS3bHrxXqajCLTL bVilVbWs268MUwGzj4A92KzpND89jkCjwUmIrpoL99zkoGXX+a+Bsyzeyun1C4j4W1iA r7FCL6tGWNiYvzxnRqFrQ+BDvOXD2xHC6zJUNE8apMmRd5ItIe+qBR9y+AHdTsda9dR2 kcKnF7T980SLWxPFIwAgvkCDCUO6DiFJA9qGHI11x9c0bjV6qHh1xKFt1EZo7K/N+lyM LLOLtuNLVQxZt1qkBr6K4vrTvGhkPbYvgY4xUcBm6AxjE77qHeTDvmbe22wLDfkZxpQR ASKA== X-Forwarded-Encrypted: i=1; AJvYcCWBHYnU9jTyYKZ0PBwAogHcZcYtCy+imeiKHrFoh48fzX1uW1OmmKdCSESBEYTXSCPhcr2FpIBs/vgK@nongnu.org X-Gm-Message-State: AOJu0YzjcTc0rAJKcbZgJuM1YsDlpyWe8DqhYHpOARhy5A4DPcDG6z+O 1Cw/0ZwYjVUgzaphY6+1AZez7PxGyT8Cejwex1Uyzmadq4Rh2Z28O79XuZw1JUo= X-Google-Smtp-Source: AGHT+IEUEumExd3Oy0k/BoTWco3k2o7bE0LEEWTSrZRLY2onu4AHW6bgy3ZngvEkX+KxWKMvyEvZQQ== X-Received: by 2002:a17:90a:ff0d:b0:2c9:7aa6:e15d with SMTP id 98e67ed59e1d1-2d8561c5948mr2066756a91.20.1724920987864; Thu, 29 Aug 2024 01:43:07 -0700 (PDT) Received: from TF4D9JK212.bytedance.net ([61.213.176.6]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-2d8446f3897sm3431856a91.49.2024.08.29.01.43.03 (version=TLS1_3 cipher=TLS_CHACHA20_POLY1305_SHA256 bits=256/256); Thu, 29 Aug 2024 01:43:07 -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, k.jensen@samsung.com, Changqi Lu Subject: [PATCH v10 07/10] hw/nvme: add helper functions for converting reservation types Date: Thu, 29 Aug 2024 16:42:11 +0800 Message-Id: <20240829084214.50548-8-luchangqi.123@bytedance.com> X-Mailer: git-send-email 2.39.2 (Apple Git-143) In-Reply-To: <20240829084214.50548-1-luchangqi.123@bytedance.com> References: <20240829084214.50548-1-luchangqi.123@bytedance.com> MIME-Version: 1.0 Received-SPF: pass client-ip=2607:f8b0:4864:20::102c; envelope-from=luchangqi.123@bytedance.com; helo=mail-pj1-x102c.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, T_SCC_BODY_TEXT_LINE=-0.01 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+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.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: Klaus Jensen Reviewed-by: Stefan Hajnoczi Signed-off-by: Changqi Lu Signed-off-by: zhenwei pi --- 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 Thu Aug 29 08:42: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: 13782792 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 394C5C8300F for ; Thu, 29 Aug 2024 08:44:42 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1sjakV-0008Ld-PK; Thu, 29 Aug 2024 04:43:23 -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 1sjakU-0008Fx-Id for qemu-devel@nongnu.org; Thu, 29 Aug 2024 04:43:22 -0400 Received: from mail-pl1-x634.google.com ([2607:f8b0:4864:20::634]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1sjakM-0000ET-3S for qemu-devel@nongnu.org; Thu, 29 Aug 2024 04:43:22 -0400 Received: by mail-pl1-x634.google.com with SMTP id d9443c01a7336-201fae21398so2797055ad.1 for ; Thu, 29 Aug 2024 01:43:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bytedance.com; s=google; t=1724920993; x=1725525793; 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=FpXCvHD2Qslc03OqNFilh7DiBfbBLmsoxBWva+ViCzE=; b=g3J620TIsVM+zUtvV3F4JfujZTWw836uSQSFyCea0zEMuk5Ex0oFm7d9SzM4k9xUUa ZuWQI0rgaQtjM3en42TNSkTnpodsbKqB4SSu2s7O7AqWp+cgDduHJlWSqoe54emwmQAy ZCqPATvDGr/oC1RsTb/QpX+rqG0kgw0EmZL5RoIFZr0qysmzSo9YjV/VOkWaXtNKfIrB u1h2o58BVgbCGyrKFFYU7VGz11p19CXaowWsQwQwYn8Ct/DLWr9X6KEqXbEOL5shncBf mpLcsptlONv3xMISQM5lMNvvAM9McotKmy8Cz1mnfvBywqprCR4fuLmukRjw+MixJxwi GsGQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1724920993; x=1725525793; 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=FpXCvHD2Qslc03OqNFilh7DiBfbBLmsoxBWva+ViCzE=; b=AhdXAeSEyZUXpBHoTmQzAinNPBlPAE1u6QajKLyQ5gON0Sj4MXiXXp9Q9mm1Be6qLg rY1wkBMPMWGbDfUrZjwO6onql4AZ2KNr9Fco1XTslGcBuK+WTfRrY9mQNnUvFvnLqyq4 XYhyDZQQMMbhrafjwWvw0oCaq/p6ZWpY4WUvyyfd0+5ARc1a/+TCmmLmyYjKU8ajRhac 76gBCFQnAbNASu3f6O2wDSbZh8y6oqpww9R53JUhDpeJnqjYZihUXoaQrVTEf8ID/HzA G806ixlddaWO/IjJDc7EpNocbVOLRWsTB0iM4nmrwQnhCbWOo7sOH8Vjs1pWcIZ1X0Ov uQSA== X-Forwarded-Encrypted: i=1; AJvYcCULhvhZTtmuWUE+hFJ7bqxYCfGF9eMdsyiIjjYqAH+TlwqkmpaMByw8jhjMUTjt3dmr9JH07JT503ak@nongnu.org X-Gm-Message-State: AOJu0Ywfxqs2OJnewMfGDvkZooPhhwV1bxrml8TtFkJdKeaIMihP3qXl BCkG2jIWwR2lxv+dAgvgiASK7X7M837iEJJBpqJ1cfQ+MKA9Pa36VVmkA3nSRds= X-Google-Smtp-Source: AGHT+IGpw7Bom353pO8VG3nUJ1WWKgumEvfG4i6J219eVaw/qa0uZ9rStCznLLTQpAQAyZDCFKGqZA== X-Received: by 2002:a17:90a:ca8c:b0:2cb:50fa:b01e with SMTP id 98e67ed59e1d1-2d8564b351bmr1800616a91.41.1724920992725; Thu, 29 Aug 2024 01:43:12 -0700 (PDT) Received: from TF4D9JK212.bytedance.net ([61.213.176.6]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-2d8446f3897sm3431856a91.49.2024.08.29.01.43.08 (version=TLS1_3 cipher=TLS_CHACHA20_POLY1305_SHA256 bits=256/256); Thu, 29 Aug 2024 01:43:12 -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, k.jensen@samsung.com, Changqi Lu Subject: [PATCH v10 08/10] hw/nvme: enable ONCS and rescap function Date: Thu, 29 Aug 2024 16:42:12 +0800 Message-Id: <20240829084214.50548-9-luchangqi.123@bytedance.com> X-Mailer: git-send-email 2.39.2 (Apple Git-143) In-Reply-To: <20240829084214.50548-1-luchangqi.123@bytedance.com> References: <20240829084214.50548-1-luchangqi.123@bytedance.com> MIME-Version: 1.0 Received-SPF: pass client-ip=2607:f8b0:4864:20::634; envelope-from=luchangqi.123@bytedance.com; helo=mail-pl1-x634.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, T_SCC_BODY_TEXT_LINE=-0.01 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+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.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. Reviewed-by: Klaus Jensen Signed-off-by: Changqi Lu Signed-off-by: zhenwei pi Reviewed-by: Stefan Hajnoczi --- 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 Thu Aug 29 08:42: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: 13782794 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id D0CDEC8300F for ; Thu, 29 Aug 2024 08:44:56 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1sjakV-0008LI-NM; Thu, 29 Aug 2024 04:43:23 -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 1sjakT-0008BO-Th for qemu-devel@nongnu.org; Thu, 29 Aug 2024 04:43:21 -0400 Received: from mail-pj1-x1035.google.com ([2607:f8b0:4864:20::1035]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1sjakR-0000F6-9F for qemu-devel@nongnu.org; Thu, 29 Aug 2024 04:43:21 -0400 Received: by mail-pj1-x1035.google.com with SMTP id 98e67ed59e1d1-2d46f2816c0so286287a91.2 for ; Thu, 29 Aug 2024 01:43:18 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bytedance.com; s=google; t=1724920998; x=1725525798; 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=NMaZ9oBX1Yz/2ONgK+9C8PrrW2XoRxFPdUH+nbt2b9U=; b=EpPVcGPti8T7p43oQZhGvR9sF3NhGDdVgjtQhirG75YQ2YNISl3Q/RCazsNfYBDCDP FxEBHTrW19T1rWMRdBDZi8UX9UonCGiWRnNUwEHwtW5R3ZNL+wgGNyn7SBMZ7GPUpvxw /KB/CtMvQdq9vwOKuA8JmlZmhJdRLDBg5tc269OwE7bbqbQk8LUXCLzZ4+IlQr8pdGBA rbjA3A9wnIXrLFNwPMj2TCblU86WJt/yT0TWVV5rc5VvodsWEk2/5V/NV8TMoyfuU9pS oH3hlAo27bsc3QmELancfgKoNN3plWzSUJDMHoC9bk7svxfijoJkpdHTe4JJ0E4QpTjL bizg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1724920998; x=1725525798; 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=NMaZ9oBX1Yz/2ONgK+9C8PrrW2XoRxFPdUH+nbt2b9U=; b=pIzklEI9JBI7s2k2s853y2C/rHPRJQtKhoxZaPcIznFAMKfTK9SaxRbJy4toVlBm/b s50GryRbZh1bar0u367HxCs6lKkfz7VewaDk3bC/uAnkP63iBNSIwLLWQVGtUVKwGsZ3 J408LvIqELUOIlCc4TL951R6OgXfdLs4HRxViYGS7TiZLCXCO6J+YDyj4SmR5mESqu1s ZCa2QknugDVaYvBdkwT1z9XNCGw3vrULixigNfLyOqHnc3M7WMSEplHfTaXtHsErj9Je vK9GO9AJcVVCl/+f061bh6fK0Yyg5+vANvnZfKJD8Ai1IDOL6V+4u7TLPzDtrijcpMF/ NPHQ== X-Forwarded-Encrypted: i=1; AJvYcCUu5Ci03UKYYpgQ0LeU31v/0n4bEc68WFXpOoTdWIguu6NvJXfjErvmHfJT444esPZc2nAauszd+5Tw@nongnu.org X-Gm-Message-State: AOJu0YyRqStSCz6/fF2WYzCD9jbPw9TrTqEhMES7cJYpZ9AvVd/khi2j 4l9CSYlhmSFWa2MHbFtGB9/fXXG25p7PnEopvXKUbrrY7D8rphH4UVUzIg/IJBo= X-Google-Smtp-Source: AGHT+IGgUphDinX61huDwV5aR3fT0eflW4nEo0Oi2JKhVRWAFJ95jeZqy6TgKkzmZFlHwKEfYnGR2w== X-Received: by 2002:a17:90b:46d8:b0:2d3:b55e:5f2 with SMTP id 98e67ed59e1d1-2d8561a24f8mr2209951a91.14.1724920997691; Thu, 29 Aug 2024 01:43:17 -0700 (PDT) Received: from TF4D9JK212.bytedance.net ([61.213.176.6]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-2d8446f3897sm3431856a91.49.2024.08.29.01.43.13 (version=TLS1_3 cipher=TLS_CHACHA20_POLY1305_SHA256 bits=256/256); Thu, 29 Aug 2024 01:43:17 -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, k.jensen@samsung.com, Changqi Lu Subject: [PATCH v10 09/10] hw/nvme: add reservation protocal command Date: Thu, 29 Aug 2024 16:42:13 +0800 Message-Id: <20240829084214.50548-10-luchangqi.123@bytedance.com> X-Mailer: git-send-email 2.39.2 (Apple Git-143) In-Reply-To: <20240829084214.50548-1-luchangqi.123@bytedance.com> References: <20240829084214.50548-1-luchangqi.123@bytedance.com> MIME-Version: 1.0 Received-SPF: pass client-ip=2607:f8b0:4864:20::1035; envelope-from=luchangqi.123@bytedance.com; helo=mail-pj1-x1035.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, T_SCC_BODY_TEXT_LINE=-0.01 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+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.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 | 330 +++++++++++++++++++++++++++++++++++++++++++ hw/nvme/nvme.h | 4 + include/block/nvme.h | 37 +++++ 3 files changed, 371 insertions(+) diff --git a/hw/nvme/ctrl.c b/hw/nvme/ctrl.c index ad212de723..1f8a5659c9 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); @@ -1747,6 +1755,13 @@ static void nvme_aio_err(NvmeRequest *req, int ret) case NVME_CMD_READ: status = NVME_UNRECOVERED_READ; break; + case NVME_CMD_RESV_REPORT: + if (ret == -ENOTSUP) { + status = NVME_INVALID_OPCODE; + } else { + status = NVME_UNRECOVERED_READ; + } + break; case NVME_CMD_FLUSH: case NVME_CMD_WRITE: case NVME_CMD_WRITE_ZEROES: @@ -1754,6 +1769,15 @@ static void nvme_aio_err(NvmeRequest *req, int ret) case NVME_CMD_COPY: status = NVME_WRITE_FAULT; break; + case NVME_CMD_RESV_REGISTER: + case NVME_CMD_RESV_ACQUIRE: + case NVME_CMD_RESV_RELEASE: + if (ret == -ENOTSUP) { + status = NVME_INVALID_OPCODE; + } else { + status = NVME_WRITE_FAULT; + } + break; default: status = NVME_INTERNAL_DEV_ERROR; break; @@ -2692,6 +2716,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 +4791,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 Thu Aug 29 08:42: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: 13782795 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id EC082C8300F for ; Thu, 29 Aug 2024 08:45:01 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1sjake-0000PQ-7z; Thu, 29 Aug 2024 04:43:32 -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 1sjakY-0000B9-O3 for qemu-devel@nongnu.org; Thu, 29 Aug 2024 04:43:28 -0400 Received: from mail-pg1-x52b.google.com ([2607:f8b0:4864:20::52b]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1sjakW-0000GM-Ay for qemu-devel@nongnu.org; Thu, 29 Aug 2024 04:43:26 -0400 Received: by mail-pg1-x52b.google.com with SMTP id 41be03b00d2f7-7cdf2ac6130so113053a12.2 for ; Thu, 29 Aug 2024 01:43:23 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bytedance.com; s=google; t=1724921003; x=1725525803; 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=rgUCVYxpkn4gdGhPb4ljzj8elSOPnC8HJSAkqH9qe/g=; b=Bpgw9WWEHbIXOrJyb01An+mQCIGPUzMofFMUQmYMahG9vbVqYjUxbUxpSYzwt1bLqk FYmHXWpdqWOg/hQkMzr2SOJcNqoNK7hERs6RN/ff8ZPFn5AhtfT/+i5+09bHuoR2aJLK ZN8boHoGB0LUQWZkyp9Ahy4ja2Yvws8Ofa6Lg76TY7FAOufd+bEcDcFhJCy8lWcGMDdM Yc09/dZS+Ccr9v6aO0dZI/XKE8HgArlWqwCN8xIAZJDiBu9ICcLd9qags09Kusd8L1op cxjCqADyN9gNCyph9nr7KQ3t9/WdI8Yli/yhRUSiDC3voiltUJKWC3V1P4U4q5rUL390 zR4w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1724921003; x=1725525803; 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=rgUCVYxpkn4gdGhPb4ljzj8elSOPnC8HJSAkqH9qe/g=; b=FC+ZCQwZKCyIFc7ZlJPpce56Ya6LCv2cNTKYu+6e7YLe2qUnXTOFWDDbz/dAX8WBww YAXRVjAa2GMKsudEeJRYaK8Fj9keQb5tshToyJgy1WL9aYA+pXdJvGvzC+KrbqkeBhC9 7TNjFa1pBhC5Li+eiyVqSE1qrxYgojHv0QRTS8HnVDJKVCagKoB9rknf0EPAYO6TOJ/X iErGoF12ULEXitSGTgN4z0Et5mA2bJnl78No1OCT51HCcMeeIcSFmzez4oXiJDk6/iKT jpBqhDwEFfKkgt6VTosx9s9AcZgVI4yloDEDAcQicb4/xw5TOcFPZHd4kySN7fvPyJA5 3JFw== X-Forwarded-Encrypted: i=1; AJvYcCWphmoPcyy/c6wzCuVeETSDffJ25s9jYwX0TNgUQU2RSVOnuqL3F2DWXtB6w3ztrJZccVP9QpmFjPx7@nongnu.org X-Gm-Message-State: AOJu0YxPw1jQ1K3qPynM6Vdo2gomK2evki0hvFjexpoSV9/Q/DaSmpLG WlfPx8KoQPpUA1QGbgeTLvDCyH4EzC3hhu4FmoZMQ5jm7McpS/Ic7hp+ULB7j/Y= X-Google-Smtp-Source: AGHT+IHaV0P7/60vOSSezg6sn2ogadEv8qn/ni5tBstfbi/cLASf+TDgASlP1T+HcsWxEayY02vO/A== X-Received: by 2002:a17:90b:4b88:b0:2d3:dacd:d94f with SMTP id 98e67ed59e1d1-2d8561a7135mr2087523a91.13.1724921002713; Thu, 29 Aug 2024 01:43:22 -0700 (PDT) Received: from TF4D9JK212.bytedance.net ([61.213.176.6]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-2d8446f3897sm3431856a91.49.2024.08.29.01.43.18 (version=TLS1_3 cipher=TLS_CHACHA20_POLY1305_SHA256 bits=256/256); Thu, 29 Aug 2024 01:43:22 -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, k.jensen@samsung.com, Changqi Lu Subject: [PATCH v10 10/10] block/iscsi: add persistent reservation in/out driver Date: Thu, 29 Aug 2024 16:42:14 +0800 Message-Id: <20240829084214.50548-11-luchangqi.123@bytedance.com> X-Mailer: git-send-email 2.39.2 (Apple Git-143) In-Reply-To: <20240829084214.50548-1-luchangqi.123@bytedance.com> References: <20240829084214.50548-1-luchangqi.123@bytedance.com> MIME-Version: 1.0 Received-SPF: pass client-ip=2607:f8b0:4864:20::52b; envelope-from=luchangqi.123@bytedance.com; helo=mail-pg1-x52b.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, T_SCC_BODY_TEXT_LINE=-0.01 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+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.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 Reviewed-by: Stefan Hajnoczi --- block/iscsi.c | 423 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 423 insertions(+) diff --git a/block/iscsi.c b/block/iscsi.c index 2ff14b7472..7a12fd59eb 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,50 @@ static void iscsi_save_designator(IscsiLun *lun, } } +/* + * Ensure iscsi_open() must succeed, weather or not the target + * implement SCSI_PR_IN_REPORT_CAPABILITIES. + */ +static void iscsi_get_pr_cap_sync(IscsiLun *iscsilun) +{ + 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_report("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; + } + } 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_report("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 +2073,7 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags, bs->supported_zero_flags = BDRV_REQ_MAY_UNMAP; } + iscsi_get_pr_cap_sync(iscsilun); out: qemu_opts_del(opts); g_free(initiator_name); @@ -2110,6 +2160,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 +2460,369 @@ 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; + g_autofree 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); + 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); + g_autofree 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); + 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 +2866,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