From nobody Sun Nov 24 08:53:21 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=linaro.org ARC-Seal: i=1; a=rsa-sha256; t=1723814660; cv=none; d=zohomail.com; s=zohoarc; b=OWz4iQRXs10siJmAy9bmA5trFqftAe/37NzyQiUOO0iDx1g6ugW5ao0n1epuLkkiePqrfmfomWZfvs6qdxqJF7hKeQv0+zGTPWOFu7PAbEij6L0yyKhKqqxR7SXnmsWKExmcnpQnuv8IbEi4iUBJ8DdJdbxG9DmvgRUIs6u6w5Q= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1723814660; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=+qDfeY+CsvBUJu7CFKOtFh4EY2RJKFqnGcNsx1NoFx4=; b=CKr8a24VplSj9hUk7E2Z0ONKLX0OnCj15q3cTFkZ1oF3X+yi4QKDkHQnPvRjBDaVE8VVVppAA3iu4SN7+ZWcwrSAXKe6FOR7UNIMKtRzue2JvafvgNF6gPp+TsEi8imsEZlzl2Wd/AnSDxLDIMCIEA9Q6eRGSSG4T/9lpj07Xfw= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1723814660782935.3948101893379; Fri, 16 Aug 2024 06:24:20 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1sewuQ-0005Qt-Bl; Fri, 16 Aug 2024 09:22:26 -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 1sewuK-000597-MC for qemu-devel@nongnu.org; Fri, 16 Aug 2024 09:22:20 -0400 Received: from mail-wm1-x333.google.com ([2a00:1450:4864:20::333]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1sewuH-0007k0-7k for qemu-devel@nongnu.org; Fri, 16 Aug 2024 09:22:20 -0400 Received: by mail-wm1-x333.google.com with SMTP id 5b1f17b1804b1-4281faefea9so13831155e9.2 for ; Fri, 16 Aug 2024 06:22:16 -0700 (PDT) Received: from orth.archaic.org.uk (orth.archaic.org.uk. [2001:8b0:1d0::2]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-371898ab855sm3631948f8f.105.2024.08.16.06.22.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 16 Aug 2024 06:22:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1723814535; x=1724419335; 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=+qDfeY+CsvBUJu7CFKOtFh4EY2RJKFqnGcNsx1NoFx4=; b=lLNr/K3QeQ7ARwo1nnHRnMBfEQlxaklE85pxr8pvnjvvy0uZlsI2XHCHNi5rqmc86v p4ptX5iUDU8y/GQCngm2GnnwyZmOiPWadrhUVJGaUHHno/luJ/sJ3fUsRjGChozwydLD MyN128P2EfL0W0LC8vNr/kJenDTHv9nkjHzKGr5BnyG0B2iXz2oJQVQA8psXcSYwTXj/ 6Z4c0RENxm3JZDf4cRZq/a7SpDECAVjU2O86xi4xguqwTQd0KWt9trH9/5QCOptAGbtl dvNx0Y+xp+JlAvC9EJccwazEAdxZ1VVEt5Z9huS7qVMCGP0aFU+I+z6oMehyRbzpDQZr cNRw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1723814535; x=1724419335; 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=+qDfeY+CsvBUJu7CFKOtFh4EY2RJKFqnGcNsx1NoFx4=; b=Fs9w4JpsAhfSIa7Za3XiRkl3gjuOyRScIrtFqbREsRONZrP6TcYBlOoxXI2uET2/ig acM17I7StlfIg97E339aWQR2wjepxPf9l78fPXu3rtVS6yd63wYKDb8EqUkLqlarDqrV N7DLyH9puCmimVEQWgm3p2Zms3cslBvPzclI3Uc+6e2e8pVctLdC5DDFhlcz97Z/qOZV 38HDrvSwCHhJosrDTcmfqvjpK6zKtaGvbN/ruxBjTHPgEAhtbDeeNxQ2QjKz8oBmchiP J+LblCfevi3b39KVfTJA7kshQp3wAsK0j+LILJ/qpcTZlJYAL5cRkMJAbj9ZKseuGLct z50A== X-Gm-Message-State: AOJu0YzwZvsPEY3lWPuYlBJG/XDefxLerisb9lKMwBfqv88OB1yxQGLI ggOXBRPCAxSF1p8BJ6TMcSQfwJwAOCX/QSvNi+QSDlhK6o5EKlXnqgrQwMNWPu7rtY3UlP3lz1k Y X-Google-Smtp-Source: AGHT+IHD9HdZOmNwrGd38VGkIRMdVdizqRIEkJxVJwu/k/RfR7I6U6FI3bkIzZzQdErliciSB8959g== X-Received: by 2002:adf:ef4b:0:b0:368:3ee5:e3e1 with SMTP id ffacd0b85a97d-37194314e6emr2086023f8f.7.1723814534888; Fri, 16 Aug 2024 06:22:14 -0700 (PDT) From: Peter Maydell To: qemu-devel@nongnu.org Cc: Paolo Bonzini , Kevin Wolf , Hanna Reitz , Stefan Hajnoczi Subject: [PATCH 1/7] docs/devel/blkdebug: Convert to rST format Date: Fri, 16 Aug 2024 14:22:06 +0100 Message-Id: <20240816132212.3602106-2-peter.maydell@linaro.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240816132212.3602106-1-peter.maydell@linaro.org> References: <20240816132212.3602106-1-peter.maydell@linaro.org> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=2a00:1450:4864:20::333; envelope-from=peter.maydell@linaro.org; helo=mail-wm1-x333.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+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @linaro.org) X-ZM-MESSAGEID: 1723814661667116600 Content-Type: text/plain; charset="utf-8" Convert blkdebug.txt to rST format. We put it into index-build.rst because it falls under the "test" part of "QEMU Build and Test System". Signed-off-by: Peter Maydell Reviewed-by: Thomas Huth --- At least, index-build seemed the most plausible home to me... --- MAINTAINERS | 1 + docs/devel/blkdebug.rst | 177 +++++++++++++++++++++++++++++++++++++ docs/devel/blkdebug.txt | 162 --------------------------------- docs/devel/index-build.rst | 1 + 4 files changed, 179 insertions(+), 162 deletions(-) create mode 100644 docs/devel/blkdebug.rst delete mode 100644 docs/devel/blkdebug.txt diff --git a/MAINTAINERS b/MAINTAINERS index 3584d6a6c6d..ca0a5c731f5 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4015,6 +4015,7 @@ M: Hanna Reitz L: qemu-block@nongnu.org S: Supported F: block/blkdebug.c +F: docs/devel/blkdebug.rst =20 vpc M: Kevin Wolf diff --git a/docs/devel/blkdebug.rst b/docs/devel/blkdebug.rst new file mode 100644 index 00000000000..63887c9aa9c --- /dev/null +++ b/docs/devel/blkdebug.rst @@ -0,0 +1,177 @@ +Block I/O error injection using ``blkdebug`` +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +.. + Copyright (C) 2014-2015 Red Hat Inc + + This work is licensed under the terms of the GNU GPL, version 2 or late= r. See + the COPYING file in the top-level directory. + +The ``blkdebug`` block driver is a rule-based error injection engine. It = can be +used to exercise error code paths in block drivers including ``ENOSPC`` (o= ut of +space) and ``EIO``. + +This document gives an overview of the features available in ``blkdebug``. + +Background +---------- +Block drivers have many error code paths that handle I/O errors. Image fo= rmats +are especially complex since metadata I/O errors during cluster allocation= or +while updating tables happen halfway through request processing and require +discipline to keep image files consistent. + +Error injection allows test cases to trigger I/O errors at specific points. +This way, all error paths can be tested to make sure they are correct. + +Rules +----- +The ``blkdebug`` block driver takes a list of "rules" that tell the error = injection +engine when to fail an I/O request. + +Each I/O request is evaluated against the rules. If a rule matches the re= quest +then its "action" is executed. + +Rules can be placed in a configuration file; the configuration file +follows the same .ini-like format used by QEMU's ``-readconfig`` option, a= nd +each section of the file represents a rule. + +The following configuration file defines a single rule:: + + $ cat blkdebug.conf + [inject-error] + event =3D "read_aio" + errno =3D "28" + +This rule fails all aio read requests with ``ENOSPC`` (28). Note that the= errno +value depends on the host. On Linux, see +``/usr/include/asm-generic/errno-base.h`` for errno values. + +Invoke QEMU as follows:: + + $ qemu-system-x86_64 + -drive if=3Dnone,cache=3Dnone,file=3Dblkdebug:blkdebug.conf:test.i= mg,id=3Ddrive0 \ + -device virtio-blk-pci,drive=3Ddrive0,id=3Dvirtio-blk-pci0 + +Rules support the following attributes: + +``event`` + which type of operation to match (e.g. ``read_aio``, ``write_aio``, + ``flush_to_os``, ``flush_to_disk``). See `Events`_ for + information on events. + +``state`` + (optional) the engine must be in this state number in order for this + rule to match. See `State transitions`_ for information + on states. + +``errno`` + the numeric errno value to return when a request matches this rule. + The errno values depend on the host since the numeric values are not + standardized in the POSIX specification. + +``sector`` + (optional) a sector number that the request must overlap in order to + match this rule + +``once`` + (optional, default ``off``) only execute this action on the first + matching request + +``immediately`` + (optional, default ``off``) return a NULL ``BlockAIOCB`` + pointer and fail without an errno instead. This + exercises the code path where ``BlockAIOCB`` fails and the + caller's ``BlockCompletionFunc`` is not invoked. + +Events +------ +Block drivers provide information about the type of I/O request they are a= bout +to make so rules can match specific types of requests. For example, the `= `qcow2`` +block driver tells ``blkdebug`` when it accesses the L1 table so rules can= match +only L1 table accesses and not other metadata or guest data requests. + +The core events are: + +``read_aio`` + guest data read + +``write_aio`` + guest data write + +``flush_to_os`` + write out unwritten block driver state (e.g. cached metadata) + +``flush_to_disk`` + flush the host block device's disk cache + +See ``qapi/block-core.json:BlkdebugEvent`` for the full list of events. +You may need to grep block driver source code to understand the +meaning of specific events. + +State transitions +----------------- +There are cases where more power is needed to match a particular I/O reque= st in +a longer sequence of requests. For example:: + + write_aio + flush_to_disk + write_aio + +How do we match the 2nd ``write_aio`` but not the first? This is where st= ate +transitions come in. + +The error injection engine has an integer called the "state" that always s= tarts +initialized to 1. The state integer is internal to ``blkdebug`` and canno= t be +observed from outside but rules can interact with it for powerful matching +behavior. + +Rules can be conditional on the current state and they can transition to a= new +state. + +When a rule's "state" attribute is non-zero then the current state must eq= ual +the attribute in order for the rule to match. + +For example, to match the 2nd write_aio:: + + [set-state] + event =3D "write_aio" + state =3D "1" + new_state =3D "2" + + [inject-error] + event =3D "write_aio" + state =3D "2" + errno =3D "5" + +The first ``write_aio`` request matches the ``set-state`` rule and transit= ions from +state 1 to state 2. Once state 2 has been entered, the ``set-state`` rule= no +longer matches since it requires state 1. But the ``inject-error`` rule n= ow +matches the next ``write_aio`` request and injects ``EIO`` (5). + +State transition rules support the following attributes: + +``event`` + which type of operation to match (e.g. ``read_aio``, ``write_aio``, + ``flush_to_os`, ``flush_to_disk``). See `Events`_ for + information on events. + +``state`` + (optional) the engine must be in this state number in order for this + rule to match + +``new_state`` + transition to this state number + +Suspend and resume +------------------ +Exercising code paths in block drivers may require specific ordering among= st +concurrent requests. The "breakpoint" feature allows requests to be halte= d on +a ``blkdebug`` event and resumed later. This makes it possible to achieve +deterministic ordering when multiple requests are in flight. + +Breakpoints on ``blkdebug`` events are associated with a user-defined ``ta= g`` string. +This tag serves as an identifier by which the request can be resumed at a = later +point. + +See the ``qemu-io(1)`` ``break``, ``resume``, ``remove_break``, and ``wait= _break`` +commands for details. diff --git a/docs/devel/blkdebug.txt b/docs/devel/blkdebug.txt deleted file mode 100644 index 0b0c128d356..00000000000 --- a/docs/devel/blkdebug.txt +++ /dev/null @@ -1,162 +0,0 @@ -Block I/O error injection using blkdebug ----------------------------------------- -Copyright (C) 2014-2015 Red Hat Inc - -This work is licensed under the terms of the GNU GPL, version 2 or later. = See -the COPYING file in the top-level directory. - -The blkdebug block driver is a rule-based error injection engine. It can = be -used to exercise error code paths in block drivers including ENOSPC (out of -space) and EIO. - -This document gives an overview of the features available in blkdebug. - -Background ----------- -Block drivers have many error code paths that handle I/O errors. Image fo= rmats -are especially complex since metadata I/O errors during cluster allocation= or -while updating tables happen halfway through request processing and require -discipline to keep image files consistent. - -Error injection allows test cases to trigger I/O errors at specific points. -This way, all error paths can be tested to make sure they are correct. - -Rules ------ -The blkdebug block driver takes a list of "rules" that tell the error inje= ction -engine when to fail an I/O request. - -Each I/O request is evaluated against the rules. If a rule matches the re= quest -then its "action" is executed. - -Rules can be placed in a configuration file; the configuration file -follows the same .ini-like format used by QEMU's -readconfig option, and -each section of the file represents a rule. - -The following configuration file defines a single rule: - - $ cat blkdebug.conf - [inject-error] - event =3D "read_aio" - errno =3D "28" - -This rule fails all aio read requests with ENOSPC (28). Note that the err= no -value depends on the host. On Linux, see -/usr/include/asm-generic/errno-base.h for errno values. - -Invoke QEMU as follows: - - $ qemu-system-x86_64 - -drive if=3Dnone,cache=3Dnone,file=3Dblkdebug:blkdebug.conf:test.i= mg,id=3Ddrive0 \ - -device virtio-blk-pci,drive=3Ddrive0,id=3Dvirtio-blk-pci0 - -Rules support the following attributes: - - event - which type of operation to match (e.g. read_aio, write_aio, - flush_to_os, flush_to_disk). See the "Events" section for - information on events. - - state - (optional) the engine must be in this state number in order for = this - rule to match. See the "State transitions" section for informat= ion - on states. - - errno - the numeric errno value to return when a request matches this ru= le. - The errno values depend on the host since the numeric values are= not - standardized in the POSIX specification. - - sector - (optional) a sector number that the request must overlap in ord= er to - match this rule - - once - (optional, default "off") only execute this action on the first - matching request - - immediately - (optional, default "off") return a NULL BlockAIOCB - pointer and fail without an errno instead. This - exercises the code path where BlockAIOCB fails and the - caller's BlockCompletionFunc is not invoked. - -Events ------- -Block drivers provide information about the type of I/O request they are a= bout -to make so rules can match specific types of requests. For example, the q= cow2 -block driver tells blkdebug when it accesses the L1 table so rules can mat= ch -only L1 table accesses and not other metadata or guest data requests. - -The core events are: - - read_aio - guest data read - - write_aio - guest data write - - flush_to_os - write out unwritten block driver state (e.g. cached metada= ta) - - flush_to_disk - flush the host block device's disk cache - -See qapi/block-core.json:BlkdebugEvent for the full list of events. -You may need to grep block driver source code to understand the -meaning of specific events. - -State transitions ------------------ -There are cases where more power is needed to match a particular I/O reque= st in -a longer sequence of requests. For example: - - write_aio - flush_to_disk - write_aio - -How do we match the 2nd write_aio but not the first? This is where state -transitions come in. - -The error injection engine has an integer called the "state" that always s= tarts -initialized to 1. The state integer is internal to blkdebug and cannot be -observed from outside but rules can interact with it for powerful matching -behavior. - -Rules can be conditional on the current state and they can transition to a= new -state. - -When a rule's "state" attribute is non-zero then the current state must eq= ual -the attribute in order for the rule to match. - -For example, to match the 2nd write_aio: - - [set-state] - event =3D "write_aio" - state =3D "1" - new_state =3D "2" - - [inject-error] - event =3D "write_aio" - state =3D "2" - errno =3D "5" - -The first write_aio request matches the set-state rule and transitions from -state 1 to state 2. Once state 2 has been entered, the set-state rule no -longer matches since it requires state 1. But the inject-error rule now -matches the next write_aio request and injects EIO (5). - -State transition rules support the following attributes: - - event - which type of operation to match (e.g. read_aio, write_aio, - flush_to_os, flush_to_disk). See the "Events" section for - information on events. - - state - (optional) the engine must be in this state number in order for = this - rule to match - - new_state - transition to this state number - -Suspend and resume ------------------- -Exercising code paths in block drivers may require specific ordering among= st -concurrent requests. The "breakpoint" feature allows requests to be halte= d on -a blkdebug event and resumed later. This makes it possible to achieve -deterministic ordering when multiple requests are in flight. - -Breakpoints on blkdebug events are associated with a user-defined "tag" st= ring. -This tag serves as an identifier by which the request can be resumed at a = later -point. - -See the qemu-io(1) break, resume, remove_break, and wait_break commands for -details. diff --git a/docs/devel/index-build.rst b/docs/devel/index-build.rst index 90b406ca0ed..3a912aefcfa 100644 --- a/docs/devel/index-build.rst +++ b/docs/devel/index-build.rst @@ -18,3 +18,4 @@ the basics if you are adding new files and targets to the= build. qapi-code-gen fuzzing control-flow-integrity + blkdebug --=20 2.34.1 From nobody Sun Nov 24 08:53:21 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=linaro.org ARC-Seal: i=1; a=rsa-sha256; t=1723814568; cv=none; d=zohomail.com; s=zohoarc; b=LMbWYJRxWb4YRsYwmUrqnP6Up3kLc/tKNXvD2LS/i3R8gLwpQ6wi336HbUlDzzwOgiZ0IZLf3Kks0/WVagBSHAqY8mYr7I2o71ZCEhmeEYxRT3pqMzE/OndSgWwaMFb6bbm2IE4ADGvWct7lLG4WktX5O42sc5JlqhanAEyuSHA= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1723814568; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=L3BYyoFuiUhi097Go1IdQzbbTPVpAV8zdtNg6dApNEU=; b=ZAA0adJi4Agy+mNXZU8HmurHQ2Y4WENSVS4Q9We9NfI1v4qYVhe0ghZuzrwVe/ZFqlmcrfqleIFtlZVZnzMcbnogUxNUZqQz9+SkD/uj5Dhr6Irx5JO+THOkGRy1albjJTEQzGTnAAHeXrgRq4HP9FFf2dp0iiFsWB3XwH+ofZ0= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1723814568900133.6030367829568; Fri, 16 Aug 2024 06:22:48 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1sewuL-0005AY-T5; Fri, 16 Aug 2024 09:22:21 -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 1sewuK-00058M-9g for qemu-devel@nongnu.org; Fri, 16 Aug 2024 09:22:20 -0400 Received: from mail-wr1-x42d.google.com ([2a00:1450:4864:20::42d]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1sewuH-0007k3-FK for qemu-devel@nongnu.org; Fri, 16 Aug 2024 09:22:19 -0400 Received: by mail-wr1-x42d.google.com with SMTP id ffacd0b85a97d-3719753d365so329409f8f.2 for ; Fri, 16 Aug 2024 06:22:17 -0700 (PDT) Received: from orth.archaic.org.uk (orth.archaic.org.uk. [2001:8b0:1d0::2]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-371898ab855sm3631948f8f.105.2024.08.16.06.22.15 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 16 Aug 2024 06:22:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1723814535; x=1724419335; 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=L3BYyoFuiUhi097Go1IdQzbbTPVpAV8zdtNg6dApNEU=; b=J0EN+EmQx8V2LrNaxrckjspv+g/23rnQZw0XXM15V7rrJM1uKtjTKi/X0JW9vLmGel pfcxbAh2e1Ye0xxX4wqr2GyfhR8HOCR8xlQWgmBEV06B6UzkuhAQTGv1Y0MRWymgs/V0 BILz2Cq9Qor3obJomOx7U1vVE9oXoYScFlFVCji6Enpb6esIvHcWvf5x2HbdN8phLndy 8Awz6qsOMR959WUHAblHDIPE8W/iqwh+fZM9nKuYDFGlOxypx9Auvcb/uLqscNw3BELN qlgN93+Sxpi27tOcKaCldafuXaII1GVBEXRSMDKNGJUvwKfR+i97n4uxIoXQE4SD+Aka kQfw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1723814535; x=1724419335; 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=L3BYyoFuiUhi097Go1IdQzbbTPVpAV8zdtNg6dApNEU=; b=TAX0y+tE7HDNwvEkpOcL7ylYGZ7pEOdElBzqnc0LcjsYrtX+AtJihpkg/gaKtDt8mx aAYnvI2f0URi2jqT1heQOrxDi/nw9oHPeJnseAAoRV3Qql+2kc4NrdnxkKC4huFXhQ3H Xp8pvxwDqrzfIpD1lLi3LROrJqNRcObjcKuX1Fe5HCiUEhS46oDJoNW+OwG9tAW2iH5f TBvIkci5C32c4o8uX0Fo0EHoWL5sBV5lHSYZomFP3WimZgj4M/mY1q2FSQBVSYmqAMcK g1N7wlkslDQbEEenJSW/zoDjtiAEkEEZVE6S9fxUmK6FMK3hpwhPClR8g67z/rahxonN JMBg== X-Gm-Message-State: AOJu0Yw70+GqqqqeFVgz16nGA8fKxnvbEkQfTZ3YRAD6CKNHNyaLkCqy DExItae1iWEHCvsPm67Yg50eqTwOGiCZP4MOVnYst5PnhcV78LhmWL0SWNaToGsv7fdh0fKgFbQ Z X-Google-Smtp-Source: AGHT+IG4oyYbdCOLq7ErxdT7m0wtT+/At885LDS58iJUq46gVTm5u2Piyn9vS0USHKuQLXAnVcEx3Q== X-Received: by 2002:adf:f1c2:0:b0:368:3789:1a2 with SMTP id ffacd0b85a97d-37194641ac2mr1951421f8f.21.1723814535469; Fri, 16 Aug 2024 06:22:15 -0700 (PDT) From: Peter Maydell To: qemu-devel@nongnu.org Cc: Paolo Bonzini , Kevin Wolf , Hanna Reitz , Stefan Hajnoczi Subject: [PATCH 2/7] docs/devel/blkverify: Convert to rST format Date: Fri, 16 Aug 2024 14:22:07 +0100 Message-Id: <20240816132212.3602106-3-peter.maydell@linaro.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240816132212.3602106-1-peter.maydell@linaro.org> References: <20240816132212.3602106-1-peter.maydell@linaro.org> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=2a00:1450:4864:20::42d; envelope-from=peter.maydell@linaro.org; helo=mail-wr1-x42d.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+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @linaro.org) X-ZM-MESSAGEID: 1723814569828116600 Content-Type: text/plain; charset="utf-8" Convert blkverify.txt to rST format. Signed-off-by: Peter Maydell Reviewed-by: Thomas Huth --- MAINTAINERS | 1 + docs/devel/{blkverify.txt =3D> blkverify.rst} | 30 ++++++++++++--------- docs/devel/index-build.rst | 1 + 3 files changed, 19 insertions(+), 13 deletions(-) rename docs/devel/{blkverify.txt =3D> blkverify.rst} (77%) diff --git a/MAINTAINERS b/MAINTAINERS index ca0a5c731f5..e9dd1180077 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3938,6 +3938,7 @@ M: Stefan Hajnoczi L: qemu-block@nongnu.org S: Supported F: block/blkverify.c +F: docs/devel/blkverify.rst =20 bochs M: Stefan Hajnoczi diff --git a/docs/devel/blkverify.txt b/docs/devel/blkverify.rst similarity index 77% rename from docs/devel/blkverify.txt rename to docs/devel/blkverify.rst index aca826c51cc..2a71778b5e3 100644 --- a/docs/devel/blkverify.txt +++ b/docs/devel/blkverify.rst @@ -1,8 +1,10 @@ -=3D Block driver correctness testing with blkverify =3D +Block driver correctness testing with ``blkverify`` +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D =20 -=3D=3D Introduction =3D=3D +Introduction +------------ =20 -This document describes how to use the blkverify protocol to test that a b= lock +This document describes how to use the ``blkverify`` protocol to test that= a block driver is operating correctly. =20 It is difficult to test and debug block drivers against real guests. Often @@ -11,12 +13,13 @@ of the executable. Other times obscure errors are rais= ed by a program inside the guest. These issues are extremely hard to trace back to bugs in the b= lock driver. =20 -Blkverify solves this problem by catching data corruption inside QEMU the = first +``blkverify`` solves this problem by catching data corruption inside QEMU = the first time bad data is read and reporting the disk sector that is corrupted. =20 -=3D=3D How it works =3D=3D +How it works +------------ =20 -The blkverify protocol has two child block devices, the "test" device and = the +The ``blkverify`` protocol has two child block devices, the "test" device = and the "raw" device. Read/write operations are mirrored to both devices so their state should always be in sync. =20 @@ -25,13 +28,14 @@ contents to the "test" image. The idea is that the "ra= w" device will handle read/write operations correctly and not corrupt data. It can be used as a reference for comparison against the "test" device. =20 -After a mirrored read operation completes, blkverify will compare the data= and +After a mirrored read operation completes, ``blkverify`` will compare the = data and raise an error if it is not identical. This makes it possible to catch the first instance where corrupt data is read. =20 -=3D=3D Example =3D=3D +Example +------- =20 -Imagine raw.img has 0xcd repeated throughout its first sector: +Imagine raw.img has 0xcd repeated throughout its first sector:: =20 $ ./qemu-io -c 'read -v 0 512' raw.img 00000000: cd cd cd cd cd cd cd cd cd cd cd cd cd cd cd cd ..........= ...... @@ -42,7 +46,7 @@ Imagine raw.img has 0xcd repeated throughout its first se= ctor: read 512/512 bytes at offset 0 512.000000 bytes, 1 ops; 0.0000 sec (97.656 MiB/sec and 200000.0000 op= s/sec) =20 -And test.img is corrupt, its first sector is zeroed when it shouldn't be: +And test.img is corrupt, its first sector is zeroed when it shouldn't be:: =20 $ ./qemu-io -c 'read -v 0 512' test.img 00000000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ..........= ...... @@ -53,17 +57,17 @@ And test.img is corrupt, its first sector is zeroed whe= n it shouldn't be: read 512/512 bytes at offset 0 512.000000 bytes, 1 ops; 0.0000 sec (81.380 MiB/sec and 166666.6667 op= s/sec) =20 -This error is caught by blkverify: +This error is caught by ``blkverify``:: =20 $ ./qemu-io -c 'read 0 512' blkverify:a.img:b.img blkverify: read sector_num=3D0 nb_sectors=3D4 contents mismatch in sec= tor 0 =20 -A more realistic scenario is verifying the installation of a guest OS: +A more realistic scenario is verifying the installation of a guest OS:: =20 $ ./qemu-img create raw.img 16G $ ./qemu-img create -f qcow2 test.qcow2 16G $ ./qemu-system-x86_64 -cdrom debian.iso \ -drive file=3Dblkverify:raw.img:test.qcow2 =20 -If the installation is aborted when blkverify detects corruption, use qemu= -io +If the installation is aborted when ``blkverify`` detects corruption, use = ``qemu-io`` to explore the contents of the disk image at the sector in question. diff --git a/docs/devel/index-build.rst b/docs/devel/index-build.rst index 3a912aefcfa..a8f7c5cdebc 100644 --- a/docs/devel/index-build.rst +++ b/docs/devel/index-build.rst @@ -19,3 +19,4 @@ the basics if you are adding new files and targets to the= build. fuzzing control-flow-integrity blkdebug + blkverify --=20 2.34.1 From nobody Sun Nov 24 08:53:21 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=linaro.org ARC-Seal: i=1; a=rsa-sha256; t=1723814631; cv=none; d=zohomail.com; s=zohoarc; b=Xh759/vK9bhfSO8KEygnL383sglSmTxv9Yc8hvPxY4Gm06g5+bL/eyz6Qqgwqe+VMN/j+s6coTpd5GLmT3FTnALeLqrlU0e8yBMyWKpDCXai0uWNtfZPC9I8l7QdhSCOcgDXJZTFmIrA9tj+ATCVszm59jFdd/uLEmsKfKcA2Ck= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1723814631; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=w0Uc190Y4kUeif42FgIZy4DdRtiwAx6zfSHmj9YJomk=; b=SUBKmloj3GzMJHEiLST8QMFSr954OfwylMCOIXy+rwBxMrsUp5Na4tcCi29Qt+B5uZV/OGiDNQTQLEUG5cTyzbDRVRCd1IHiG5FIsP6VT5+TT6Bg/rrzlktxD+eYga7RnNSix8rLD5ae60zMrDG+5cUuj5CgBmY1dKciCxkU9qM= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1723814631358995.5979033828066; Fri, 16 Aug 2024 06:23:51 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1sewuM-0005Cm-9k; Fri, 16 Aug 2024 09:22:25 -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 1sewuK-00058S-Ff for qemu-devel@nongnu.org; Fri, 16 Aug 2024 09:22:20 -0400 Received: from mail-wm1-x32c.google.com ([2a00:1450:4864:20::32c]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1sewuH-0007k7-LS for qemu-devel@nongnu.org; Fri, 16 Aug 2024 09:22:20 -0400 Received: by mail-wm1-x32c.google.com with SMTP id 5b1f17b1804b1-42817bee9e8so13642215e9.3 for ; Fri, 16 Aug 2024 06:22:17 -0700 (PDT) Received: from orth.archaic.org.uk (orth.archaic.org.uk. [2001:8b0:1d0::2]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-371898ab855sm3631948f8f.105.2024.08.16.06.22.15 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 16 Aug 2024 06:22:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1723814536; x=1724419336; 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=w0Uc190Y4kUeif42FgIZy4DdRtiwAx6zfSHmj9YJomk=; b=uihpPkB0Xwo8tQ5R0pueH7EIBwakkhBYbhZfn0XHAyksQv1u/GC5qdrP37xOZNAQ1X RgypTqLKIF9oBFcE+Z9yLIkb8TVFHWwRvriyHn6sgv6UUUbs8YwFjkcPTlL1fycou58d rRArOKv3Rx/HsZJETyb9io/WAEor6haTx7ciJJtLvTyprFChm92Xo/KdwurvudHEVuv0 qKvAOK9pLSzlsCOZEVKiS2qEnxjtAsM1DEsE1DDLRWUxroniQsu07vte780DvS8b56WP pvSjL0pf5/TLtrNZA7sEor0QitSn39hPP9DnWFnz7OaBiR4GqaTBp/CI/Mvz66ORaOcr NCrA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1723814536; x=1724419336; 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=w0Uc190Y4kUeif42FgIZy4DdRtiwAx6zfSHmj9YJomk=; b=rjANr4cTQUtJeKPbeyhZeOq24hI7U4C/lPFK6BspmRzkiOwxOwpb+GOA0UIWm2NfVU T+QFLyBSIu9DHdoRTZ2YKw0K5MW+88uBAwTP9kX5R6yrGDcWzj+GKbUI5H0rnfrMpfva yd0mOGxNcYTnn2h/F1qUJ7d8VFyvwSBgu5LhnlvdoJ3De4WKwCcoLB+lyyc/WIDp3uPf 2pzFrKSLU9SVlbfLULIVkWRI23w1keBoC4ciNYXfHzfjjUxok49Z7mCuyo0aWU8jkqFS OxJMEAxrCazA1ClBN2eurfEIjwaoSqdNLw39YNQBH99nLNybBpPUpJ+b/HsRCnDfhuGt E39g== X-Gm-Message-State: AOJu0YxsbCpGb+b35RQEpHiolWWEocd4tm2ZgvsQ+yFrKiDjKCC0Hw/e 8FaMsYTRFFIUg5EY9Srn8cHN/5RWuBNWiTsJ2+nOf+aoXhhGzGEfwBwogvBKlsLl+a1vjtjSCPZ W X-Google-Smtp-Source: AGHT+IGvlbEIo3yJhwMKXrwrp2HWqNuFjep+ZGuuOWclqVlkx/ZA5nuiuF2palz7rwikNmxZ+Fiw4g== X-Received: by 2002:a5d:694a:0:b0:368:31c7:19d3 with SMTP id ffacd0b85a97d-3719431e723mr1869776f8f.9.1723814536038; Fri, 16 Aug 2024 06:22:16 -0700 (PDT) From: Peter Maydell To: qemu-devel@nongnu.org Cc: Paolo Bonzini , Kevin Wolf , Hanna Reitz , Stefan Hajnoczi Subject: [PATCH 3/7] docs/devel/lockcnt: Convert to rST format Date: Fri, 16 Aug 2024 14:22:08 +0100 Message-Id: <20240816132212.3602106-4-peter.maydell@linaro.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240816132212.3602106-1-peter.maydell@linaro.org> References: <20240816132212.3602106-1-peter.maydell@linaro.org> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=2a00:1450:4864:20::32c; envelope-from=peter.maydell@linaro.org; helo=mail-wm1-x32c.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+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @linaro.org) X-ZM-MESSAGEID: 1723814633666116600 Content-Type: text/plain; charset="utf-8" Convert docs/devel/lockcnt.txt to rST format. Signed-off-by: Peter Maydell --- MAINTAINERS | 2 +- docs/devel/index-api.rst | 1 + docs/devel/{lockcnt.txt =3D> lockcnt.rst} | 89 +++++++++++++------------ 3 files changed, 47 insertions(+), 45 deletions(-) rename docs/devel/{lockcnt.txt =3D> lockcnt.rst} (74%) diff --git a/MAINTAINERS b/MAINTAINERS index e9dd1180077..9e091a4e214 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3112,7 +3112,7 @@ F: qapi/run-state.json Read, Copy, Update (RCU) M: Paolo Bonzini S: Maintained -F: docs/devel/lockcnt.txt +F: docs/devel/lockcnt.rst F: docs/devel/rcu.txt F: include/qemu/rcu*.h F: tests/unit/rcutorture.c diff --git a/docs/devel/index-api.rst b/docs/devel/index-api.rst index fe01b2b488d..1c487c152ab 100644 --- a/docs/devel/index-api.rst +++ b/docs/devel/index-api.rst @@ -9,6 +9,7 @@ generated from in-code annotations to function prototypes. =20 bitops loads-stores + lockcnt memory modules pci diff --git a/docs/devel/lockcnt.txt b/docs/devel/lockcnt.rst similarity index 74% rename from docs/devel/lockcnt.txt rename to docs/devel/lockcnt.rst index a3fb3bc5d8d..994aeb57151 100644 --- a/docs/devel/lockcnt.txt +++ b/docs/devel/lockcnt.rst @@ -1,9 +1,9 @@ -DOCUMENTATION FOR LOCKED COUNTERS (aka QemuLockCnt) -=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D +Locked Counters (aka ``QemuLockCnt``) +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =20 QEMU often uses reference counts to track data structures that are being accessed and should not be freed. For example, a loop that invoke -callbacks like this is not safe: +callbacks like this is not safe:: =20 QLIST_FOREACH_SAFE(ioh, &io_handlers, next, pioh) { if (ioh->revents & G_IO_OUT) { @@ -11,11 +11,11 @@ callbacks like this is not safe: } } =20 -QLIST_FOREACH_SAFE protects against deletion of the current node (ioh) -by stashing away its "next" pointer. However, ioh->fd_write could +``QLIST_FOREACH_SAFE`` protects against deletion of the current node (``io= h``) +by stashing away its ``next`` pointer. However, ``ioh->fd_write`` could actually delete the next node from the list. The simplest way to avoid this is to mark the node as deleted, and remove it from the -list in the above loop: +list in the above loop:: =20 QLIST_FOREACH_SAFE(ioh, &io_handlers, next, pioh) { if (ioh->deleted) { @@ -29,7 +29,7 @@ list in the above loop: } =20 If however this loop must also be reentrant, i.e. it is possible that -ioh->fd_write invokes the loop again, some kind of counting is needed: +``ioh->fd_write`` invokes the loop again, some kind of counting is needed:: =20 walking_handlers++; QLIST_FOREACH_SAFE(ioh, &io_handlers, next, pioh) { @@ -46,8 +46,8 @@ ioh->fd_write invokes the loop again, some kind of counti= ng is needed: } walking_handlers--; =20 -One may think of using the RCU primitives, rcu_read_lock() and -rcu_read_unlock(); effectively, the RCU nesting count would take +One may think of using the RCU primitives, ``rcu_read_lock()`` and +``rcu_read_unlock()``; effectively, the RCU nesting count would take the place of the walking_handlers global variable. Indeed, reference counting and RCU have similar purposes, but their usage in general is complementary: @@ -70,14 +70,14 @@ general is complementary: this can improve performance, but also delay reclamation undesirably. With reference counting, reclamation is deterministic. =20 -This file documents QemuLockCnt, an abstraction for using reference +This file documents ``QemuLockCnt``, an abstraction for using reference counting in code that has to be both thread-safe and reentrant. =20 =20 -QemuLockCnt concepts --------------------- +``QemuLockCnt`` concepts +------------------------ =20 -A QemuLockCnt comprises both a counter and a mutex; it has primitives +A ``QemuLockCnt`` comprises both a counter and a mutex; it has primitives to increment and decrement the counter, and to take and release the mutex. The counter notes how many visits to the data structures are taking place (the visits could be from different threads, or there could @@ -95,13 +95,14 @@ not just frees, though there could be cases where this = is not necessary. =20 Reads, instead, can be done without taking the mutex, as long as the readers and writers use the same macros that are used for RCU, for -example qatomic_rcu_read, qatomic_rcu_set, QLIST_FOREACH_RCU, etc. This is -because the reads are done outside a lock and a set or QLIST_INSERT_HEAD +example ``qatomic_rcu_read``, ``qatomic_rcu_set``, ``QLIST_FOREACH_RCU``, +etc. This is because the reads are done outside a lock and a set +or ``QLIST_INSERT_HEAD`` can happen concurrently with the read. The RCU API ensures that the processor and the compiler see all required memory barriers. =20 This could be implemented simply by protecting the counter with the -mutex, for example: +mutex, for example:: =20 // (1) qemu_mutex_lock(&walking_handlers_mutex); @@ -125,33 +126,33 @@ mutex, for example: Here, no frees can happen in the code represented by the ellipsis. If another thread is executing critical section (2), that part of the code cannot be entered, because the thread will not be able -to increment the walking_handlers variable. And of course +to increment the ``walking_handlers`` variable. And of course during the visit any other thread will see a nonzero value for -walking_handlers, as in the single-threaded code. +``walking_handlers``, as in the single-threaded code. =20 Note that it is possible for multiple concurrent accesses to delay -the cleanup arbitrarily; in other words, for the walking_handlers +the cleanup arbitrarily; in other words, for the ``walking_handlers`` counter to never become zero. For this reason, this technique is more easily applicable if concurrent access to the structure is rare. =20 However, critical sections are easy to forget since you have to do -them for each modification of the counter. QemuLockCnt ensures that +them for each modification of the counter. ``QemuLockCnt`` ensures that all modifications of the counter take the lock appropriately, and it can also be more efficient in two ways: =20 - it avoids taking the lock for many operations (for example incrementing the counter while it is non-zero); =20 -- on some platforms, one can implement QemuLockCnt to hold the lock +- on some platforms, one can implement ``QemuLockCnt`` to hold the lock and the mutex in a single word, making the fast path no more expensive than simply managing a counter using atomic operations (see - docs/devel/atomics.rst). This can be very helpful if concurrent access = to + :doc:`atomics`). This can be very helpful if concurrent access to the data structure is expected to be rare. =20 =20 Using the same mutex for frees and writes can still incur some small inefficiencies; for example, a visit can never start if the counter is -zero and the mutex is taken---even if the mutex is taken by a write, +zero and the mutex is taken -- even if the mutex is taken by a write, which in principle need not block a visit of the data structure. However, these are usually not a problem if any of the following assumptions are valid: @@ -163,27 +164,27 @@ assumptions are valid: - writes are frequent, but this kind of write (e.g. appending to a list) has a very small critical section. =20 -For example, QEMU uses QemuLockCnt to manage an AioContext's list of +For example, QEMU uses ``QemuLockCnt`` to manage an ``AioContext``'s list = of bottom halves and file descriptor handlers. Modifications to the list of file descriptor handlers are rare. Creation of a new bottom half is frequent and can happen on a fast path; however: 1) it is almost never concurrent with a visit to the list of bottom halves; 2) it only has -three instructions in the critical path, two assignments and a smp_wmb(). +three instructions in the critical path, two assignments and a ``smp_wmb()= ``. =20 =20 -QemuLockCnt API ---------------- +``QemuLockCnt`` API +------------------- =20 -The QemuLockCnt API is described in include/qemu/thread.h. +The ``QemuLockCnt`` API is described in ``include/qemu/thread.h``. =20 =20 -QemuLockCnt usage ------------------ +``QemuLockCnt`` usage +--------------------- =20 -This section explains the typical usage patterns for QemuLockCnt functions. +This section explains the typical usage patterns for ``QemuLockCnt`` funct= ions. =20 Setting a variable to a non-NULL value can be done between -qemu_lockcnt_lock and qemu_lockcnt_unlock: +``qemu_lockcnt_lock`` and ``qemu_lockcnt_unlock``:: =20 qemu_lockcnt_lock(&xyz_lockcnt); if (!xyz) { @@ -193,8 +194,8 @@ qemu_lockcnt_lock and qemu_lockcnt_unlock: } qemu_lockcnt_unlock(&xyz_lockcnt); =20 -Accessing the value can be done between qemu_lockcnt_inc and -qemu_lockcnt_dec: +Accessing the value can be done between ``qemu_lockcnt_inc`` and +``qemu_lockcnt_dec``:: =20 qemu_lockcnt_inc(&xyz_lockcnt); if (xyz) { @@ -204,11 +205,11 @@ qemu_lockcnt_dec: } qemu_lockcnt_dec(&xyz_lockcnt); =20 -Freeing the object can similarly use qemu_lockcnt_lock and -qemu_lockcnt_unlock, but you also need to ensure that the count -is zero (i.e. there is no concurrent visit). Because qemu_lockcnt_inc -takes the QemuLockCnt's lock, the count cannot become non-zero while -the object is being freed. Freeing an object looks like this: +Freeing the object can similarly use ``qemu_lockcnt_lock`` and +``qemu_lockcnt_unlock``, but you also need to ensure that the count +is zero (i.e. there is no concurrent visit). Because ``qemu_lockcnt_inc`` +takes the ``QemuLockCnt``'s lock, the count cannot become non-zero while +the object is being freed. Freeing an object looks like this:: =20 qemu_lockcnt_lock(&xyz_lockcnt); if (!qemu_lockcnt_count(&xyz_lockcnt)) { @@ -218,7 +219,7 @@ the object is being freed. Freeing an object looks lik= e this: qemu_lockcnt_unlock(&xyz_lockcnt); =20 If an object has to be freed right after a visit, you can combine -the decrement, the locking and the check on count as follows: +the decrement, the locking and the check on count as follows:: =20 qemu_lockcnt_inc(&xyz_lockcnt); if (xyz) { @@ -232,7 +233,7 @@ the decrement, the locking and the check on count as fo= llows: qemu_lockcnt_unlock(&xyz_lockcnt); } =20 -QemuLockCnt can also be used to access a list as follows: +``QemuLockCnt`` can also be used to access a list as follows:: =20 qemu_lockcnt_inc(&io_handlers_lockcnt); QLIST_FOREACH_RCU(ioh, &io_handlers, pioh) { @@ -252,10 +253,10 @@ QemuLockCnt can also be used to access a list as foll= ows: } =20 Again, the RCU primitives are used because new items can be added to the -list during the walk. QLIST_FOREACH_RCU ensures that the processor and +list during the walk. ``QLIST_FOREACH_RCU`` ensures that the processor and the compiler see the appropriate memory barriers. =20 -An alternative pattern uses qemu_lockcnt_dec_if_lock: +An alternative pattern uses ``qemu_lockcnt_dec_if_lock``:: =20 qemu_lockcnt_inc(&io_handlers_lockcnt); QLIST_FOREACH_SAFE_RCU(ioh, &io_handlers, next, pioh) { @@ -273,5 +274,5 @@ An alternative pattern uses qemu_lockcnt_dec_if_lock: } qemu_lockcnt_dec(&io_handlers_lockcnt); =20 -Here you can use qemu_lockcnt_dec instead of qemu_lockcnt_dec_and_lock, +Here you can use ``qemu_lockcnt_dec`` instead of ``qemu_lockcnt_dec_and_lo= ck``, because there is no special task to do if the count goes from 1 to 0. --=20 2.34.1 From nobody Sun Nov 24 08:53:21 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=linaro.org ARC-Seal: i=1; a=rsa-sha256; t=1723814656; cv=none; d=zohomail.com; s=zohoarc; b=XPmV/xfwApFbWIBr86k5ks3s5JWxO6bPLA2fzQUDX8rDqBdRrr9NPPUdsfRDDtQqz1hrO78d7T8IFBLJ9f/VSjEY+vJggUY5sn2HdxXtRriL1SlknrLpXtF4/EaM/ZsGFx8eop9Z1blLwMbYcWq6t0fA+Wl1hbfUqYiIsjvCOEE= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1723814656; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=ePF/o/hQSoaSIDuJhqV/fjOlqlj+BNS3IyHKpKM6oQg=; b=kWnW3nyz8Igt9NQBTrTulZuGgjJeT+X2/DmDpGS7hhJa/6eCe5xpRs8GzlhobC+oLomGjdztsjaalgwO3+KYh8brWLRuzzSYQW/oASihvgkd/TWcLMq+nnqLB/mhpVtwNtxfuvv055Q+RagxdLtGsYJRTQCPjikBGfUzrbQNqQ8= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1723814656569179.86734995086908; Fri, 16 Aug 2024 06:24:16 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1sewuQ-0005Sz-WB; Fri, 16 Aug 2024 09:22:27 -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 1sewuM-0005Bi-1Z for qemu-devel@nongnu.org; Fri, 16 Aug 2024 09:22:22 -0400 Received: from mail-wr1-x431.google.com ([2a00:1450:4864:20::431]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1sewuJ-0007kL-Fo for qemu-devel@nongnu.org; Fri, 16 Aug 2024 09:22:21 -0400 Received: by mail-wr1-x431.google.com with SMTP id ffacd0b85a97d-3687ea0521cso1269392f8f.1 for ; Fri, 16 Aug 2024 06:22:18 -0700 (PDT) Received: from orth.archaic.org.uk (orth.archaic.org.uk. [2001:8b0:1d0::2]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-371898ab855sm3631948f8f.105.2024.08.16.06.22.16 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 16 Aug 2024 06:22:16 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1723814537; x=1724419337; 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=ePF/o/hQSoaSIDuJhqV/fjOlqlj+BNS3IyHKpKM6oQg=; b=mrqVp0OBcAe4Hn1oFWMxipmza+iw5QK4XAYyViPj8Zsck1o8LEqSTZij4kGPkX90yj MoEM/y+JrLduP8JKfWyAx6sksz6xYc3+lkxB7/qFfAEMcYOeNmlkBRueoQuW5fwCpmYc BkTR020xNhH2kHO1dO5DEeAht1mAHnDhaRNRAyDmSLV2cXLoMaXjo2VenG844KpEzLZD vgOdn/s3DXNtLnNSnwHHL9E3vkmnmWLHyWCcEIiM4jAbxuapDlRJBp1LkbTstZNpGSzB njm3SHDEEsphQfYGWetUQoTlcRoLVxVNyn2Op946Psj9QKOyHwoiR5PV8XEjXJDa0JKj D1Lw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1723814537; x=1724419337; 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=ePF/o/hQSoaSIDuJhqV/fjOlqlj+BNS3IyHKpKM6oQg=; b=XpYpxeMauC0YCoH1v0SoxxAYEKYb1wRe2e+6bUUkvj3ayvMsDGC8Bh6fb/POeykUZI sIf9ySNJQgHE+yZHaLuxbe/klfhhIRcCAd3f8HzOZiSdpLkRsbK7cuOAaQK46aENkvDV cmr0Gpj4Qf/kUZsHXmH6UxaotpobVX+jGlTGGP2LEpLrpPK2qZ4DF/V5rIT/pF43y9q6 QATxmVaoCDV6uj4C2fx6d3uKSh/sFdIz+xxT5Sn2ViIY8uca410G+Gs0AbxKPtU838Ha 0lzbdtiX4AMSvRkk2+1M5pzZDYXD+SDtdexkt6yfJGrg8CCLPBufIoZmTeZS2xnyuGKL ioRA== X-Gm-Message-State: AOJu0Yyur1tk8Fd/ra8HYQG8eYcTkFx0coAtdCK9/cdcwxy91gksQE60 F5ikkl5z3kkNOLYQLW8kPeVHob0Q50IV+JIxYsbayr5cOmxmgkYsCE/sLHuJofORs/lLKH2T1xx N X-Google-Smtp-Source: AGHT+IFoOGB36cUl+ANrXfK2uA5RyEUDPxaEqgm5wAdCd3EuuT4+mcUtxP9lKqQVSt7kurYPIY8uMA== X-Received: by 2002:a5d:4e42:0:b0:371:8eea:24b7 with SMTP id ffacd0b85a97d-371946a04e6mr2246256f8f.50.1723814537151; Fri, 16 Aug 2024 06:22:17 -0700 (PDT) From: Peter Maydell To: qemu-devel@nongnu.org Cc: Paolo Bonzini , Kevin Wolf , Hanna Reitz , Stefan Hajnoczi Subject: [PATCH 4/7] docs/devel/multiple-iothreads: Convert to rST format Date: Fri, 16 Aug 2024 14:22:09 +0100 Message-Id: <20240816132212.3602106-5-peter.maydell@linaro.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240816132212.3602106-1-peter.maydell@linaro.org> References: <20240816132212.3602106-1-peter.maydell@linaro.org> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=2a00:1450:4864:20::431; envelope-from=peter.maydell@linaro.org; helo=mail-wr1-x431.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+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @linaro.org) X-ZM-MESSAGEID: 1723814657610116600 Content-Type: text/plain; charset="utf-8" Convert docs/devel/multiple-iothreads.txt to rST format. Signed-off-by: Peter Maydell --- docs/devel/index-internals.rst | 1 + docs/devel/multiple-iothreads.rst | 139 ++++++++++++++++++++++++++++++ docs/devel/multiple-iothreads.txt | 130 ---------------------------- 3 files changed, 140 insertions(+), 130 deletions(-) create mode 100644 docs/devel/multiple-iothreads.rst delete mode 100644 docs/devel/multiple-iothreads.txt diff --git a/docs/devel/index-internals.rst b/docs/devel/index-internals.rst index 4ac7725d728..88fa0e9450d 100644 --- a/docs/devel/index-internals.rst +++ b/docs/devel/index-internals.rst @@ -21,3 +21,4 @@ Details about QEMU's various subsystems including how to = add features to them. writing-monitor-commands virtio-backends crypto + multiple-iothreads diff --git a/docs/devel/multiple-iothreads.rst b/docs/devel/multiple-iothre= ads.rst new file mode 100644 index 00000000000..d1f3fc4510a --- /dev/null +++ b/docs/devel/multiple-iothreads.rst @@ -0,0 +1,139 @@ +Using Multiple ``IOThread``\ s +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D + +.. + Copyright (c) 2014-2017 Red Hat Inc. + + This work is licensed under the terms of the GNU GPL, version 2 or late= r. See + the COPYING file in the top-level directory. + + +This document explains the ``IOThread`` feature and how to write code that= runs +outside the BQL. + +The main loop and ``IOThread``\ s +--------------------------------- +QEMU is an event-driven program that can do several things at once using an +event loop. The VNC server and the QMP monitor are both processed from the +same event loop, which monitors their file descriptors until they become +readable and then invokes a callback. + +The default event loop is called the main loop (see ``main-loop.c``). It = is +possible to create additional event loop threads using +``-object iothread,id=3Dmy-iothread``. + +Side note: The main loop and ``IOThread`` are both event loops but their c= ode is +not shared completely. Sometimes it is useful to remember that although t= hey +are conceptually similar they are currently not interchangeable. + +Why ``IOThread``\ s are useful +------------------------------ +``IOThread``\ s allow the user to control the placement of work. The main= loop is a +scalability bottleneck on hosts with many CPUs. Work can be spread across +several ``IOThread``\ s instead of just one main loop. When set up correc= tly this +can improve I/O latency and reduce jitter seen by the guest. + +The main loop is also deeply associated with the BQL, which is a +scalability bottleneck in itself. vCPU threads and the main loop use the = BQL +to serialize execution of QEMU code. This mutex is necessary because a lo= t of +QEMU's code historically was not thread-safe. + +The fact that all I/O processing is done in a single main loop and that the +BQL is contended by all vCPU threads and the main loop explain +why it is desirable to place work into ``IOThread``\ s. + +The experimental ``virtio-blk`` data-plane implementation has been benchma= rked and +shows these effects: +ftp://public.dhe.ibm.com/linux/pdfs/KVM_Virtualized_IO_Performance_Paper.p= df + +.. _how-to-program: + +How to program for ``IOThread``\ s +---------------------------------- +The main difference between legacy code and new code that can run in an +``IOThread`` is dealing explicitly with the event loop object, ``AioContex= t`` +(see ``include/block/aio.h``). Code that only works in the main loop +implicitly uses the main loop's ``AioContext``. Code that supports running +in ``IOThread``\ s must be aware of its ``AioContext``. + +AioContext supports the following services: + * File descriptor monitoring (read/write/error on POSIX hosts) + * Event notifiers (inter-thread signalling) + * Timers + * Bottom Halves (BH) deferred callbacks + +There are several old APIs that use the main loop AioContext: + * LEGACY ``qemu_aio_set_fd_handler()`` - monitor a file descriptor + * LEGACY ``qemu_aio_set_event_notifier()`` - monitor an event notifier + * LEGACY ``timer_new_ms()`` - create a timer + * LEGACY ``qemu_bh_new()`` - create a BH + * LEGACY ``qemu_bh_new_guarded()`` - create a BH with a device re-entranc= y guard + * LEGACY ``qemu_aio_wait()`` - run an event loop iteration + +Since they implicitly work on the main loop they cannot be used in code th= at +runs in an ``IOThread``. They might cause a crash or deadlock if called f= rom an +``IOThread`` since the BQL is not held. + +Instead, use the ``AioContext`` functions directly (see ``include/block/ai= o.h``): + * ``aio_set_fd_handler()`` - monitor a file descriptor + * ``aio_set_event_notifier()`` - monitor an event notifier + * ``aio_timer_new()`` - create a timer + * ``aio_bh_new()`` - create a BH + * ``aio_bh_new_guarded()`` - create a BH with a device re-entrancy guard + * ``aio_poll()`` - run an event loop iteration + +The ``qemu_bh_new_guarded``/``aio_bh_new_guarded`` APIs accept a +``MemReentrancyGuard`` +argument, which is used to check for and prevent re-entrancy problems. For +BHs associated with devices, the reentrancy-guard is contained in the +corresponding ``DeviceState`` and named ``mem_reentrancy_guard``. + +The ``AioContext`` can be obtained from the ``IOThread`` using +``iothread_get_aio_context()`` or for the main loop using +``qemu_get_aio_context()``. Code that takes an ``AioContext`` argument +works both in ``IOThread``\ s or the main loop, depending on which ``AioCo= ntext`` +instance the caller passes in. + +How to synchronize with an ``IOThread`` +--------------------------------------- +Variables that can be accessed by multiple threads require some form of +synchronization such as ``qemu_mutex_lock()``, ``rcu_read_lock()``, etc. + +``AioContext`` functions like ``aio_set_fd_handler()``, +``aio_set_event_notifier()``, ``aio_bh_new()``, and ``aio_timer_new()`` +are thread-safe. They can be used to trigger activity in an ``IOThread``. + +Side note: the best way to schedule a function call across threads is to c= all +``aio_bh_schedule_oneshot()``. + +The main loop thread can wait synchronously for a condition using +``AIO_WAIT_WHILE()``. + +``AioContext`` and the block layer +---------------------------------- +The ``AioContext`` originates from the QEMU block layer, even though nowad= ays +``AioContext`` is a generic event loop that can be used by any QEMU subsys= tem. + +The block layer has support for ``AioContext`` integrated. Each +``BlockDriverState`` is associated with an ``AioContext`` using +``bdrv_try_change_aio_context()`` and ``bdrv_get_aio_context()``. +This allows block layer code to process I/O inside the +right ``AioContext``. Other subsystems may wish to follow a similar appro= ach. + +Block layer code must therefore expect to run in an ``IOThread`` and avoid= using +old APIs that implicitly use the main loop. See +`How to program for IOThreads`_ for information on how to do that. + +Code running in the monitor typically needs to ensure that past +requests from the guest are completed. When a block device is running +in an ``IOThread``, the ``IOThread`` can also process requests from the gu= est +(via ioeventfd). To achieve both objects, wrap the code between +``bdrv_drained_begin()`` and ``bdrv_drained_end()``, thus creating a "drai= ned +section". + +Long-running jobs (usually in the form of coroutines) are often scheduled = in +the ``BlockDriverState``'s ``AioContext``. The functions +``bdrv_add``/``remove_aio_context_notifier``, or alternatively +``blk_add``/``remove_aio_context_notifier`` if you use ``BlockBackends``, +can be used to get a notification whenever ``bdrv_try_change_aio_context()= `` +moves a ``BlockDriverState`` to a different ``AioContext``. diff --git a/docs/devel/multiple-iothreads.txt b/docs/devel/multiple-iothre= ads.txt deleted file mode 100644 index de85767b124..00000000000 --- a/docs/devel/multiple-iothreads.txt +++ /dev/null @@ -1,130 +0,0 @@ -Copyright (c) 2014-2017 Red Hat Inc. - -This work is licensed under the terms of the GNU GPL, version 2 or later. = See -the COPYING file in the top-level directory. - - -This document explains the IOThread feature and how to write code that runs -outside the BQL. - -The main loop and IOThreads ---------------------------- -QEMU is an event-driven program that can do several things at once using an -event loop. The VNC server and the QMP monitor are both processed from the -same event loop, which monitors their file descriptors until they become -readable and then invokes a callback. - -The default event loop is called the main loop (see main-loop.c). It is -possible to create additional event loop threads using -object -iothread,id=3Dmy-iothread. - -Side note: The main loop and IOThread are both event loops but their code = is -not shared completely. Sometimes it is useful to remember that although t= hey -are conceptually similar they are currently not interchangeable. - -Why IOThreads are useful ------------------------- -IOThreads allow the user to control the placement of work. The main loop = is a -scalability bottleneck on hosts with many CPUs. Work can be spread across -several IOThreads instead of just one main loop. When set up correctly th= is -can improve I/O latency and reduce jitter seen by the guest. - -The main loop is also deeply associated with the BQL, which is a -scalability bottleneck in itself. vCPU threads and the main loop use the = BQL -to serialize execution of QEMU code. This mutex is necessary because a lo= t of -QEMU's code historically was not thread-safe. - -The fact that all I/O processing is done in a single main loop and that the -BQL is contended by all vCPU threads and the main loop explain -why it is desirable to place work into IOThreads. - -The experimental virtio-blk data-plane implementation has been benchmarked= and -shows these effects: -ftp://public.dhe.ibm.com/linux/pdfs/KVM_Virtualized_IO_Performance_Paper.p= df - -How to program for IOThreads ----------------------------- -The main difference between legacy code and new code that can run in an -IOThread is dealing explicitly with the event loop object, AioContext -(see include/block/aio.h). Code that only works in the main loop -implicitly uses the main loop's AioContext. Code that supports running -in IOThreads must be aware of its AioContext. - -AioContext supports the following services: - * File descriptor monitoring (read/write/error on POSIX hosts) - * Event notifiers (inter-thread signalling) - * Timers - * Bottom Halves (BH) deferred callbacks - -There are several old APIs that use the main loop AioContext: - * LEGACY qemu_aio_set_fd_handler() - monitor a file descriptor - * LEGACY qemu_aio_set_event_notifier() - monitor an event notifier - * LEGACY timer_new_ms() - create a timer - * LEGACY qemu_bh_new() - create a BH - * LEGACY qemu_bh_new_guarded() - create a BH with a device re-entrancy gu= ard - * LEGACY qemu_aio_wait() - run an event loop iteration - -Since they implicitly work on the main loop they cannot be used in code th= at -runs in an IOThread. They might cause a crash or deadlock if called from = an -IOThread since the BQL is not held. - -Instead, use the AioContext functions directly (see include/block/aio.h): - * aio_set_fd_handler() - monitor a file descriptor - * aio_set_event_notifier() - monitor an event notifier - * aio_timer_new() - create a timer - * aio_bh_new() - create a BH - * aio_bh_new_guarded() - create a BH with a device re-entrancy guard - * aio_poll() - run an event loop iteration - -The qemu_bh_new_guarded/aio_bh_new_guarded APIs accept a "MemReentrancyGua= rd" -argument, which is used to check for and prevent re-entrancy problems. For -BHs associated with devices, the reentrancy-guard is contained in the -corresponding DeviceState and named "mem_reentrancy_guard". - -The AioContext can be obtained from the IOThread using -iothread_get_aio_context() or for the main loop using qemu_get_aio_context= (). -Code that takes an AioContext argument works both in IOThreads or the main -loop, depending on which AioContext instance the caller passes in. - -How to synchronize with an IOThread ------------------------------------ -Variables that can be accessed by multiple threads require some form of -synchronization such as qemu_mutex_lock(), rcu_read_lock(), etc. - -AioContext functions like aio_set_fd_handler(), aio_set_event_notifier(), -aio_bh_new(), and aio_timer_new() are thread-safe. They can be used to tri= gger -activity in an IOThread. - -Side note: the best way to schedule a function call across threads is to c= all -aio_bh_schedule_oneshot(). - -The main loop thread can wait synchronously for a condition using -AIO_WAIT_WHILE(). - -AioContext and the block layer ------------------------------- -The AioContext originates from the QEMU block layer, even though nowadays -AioContext is a generic event loop that can be used by any QEMU subsystem. - -The block layer has support for AioContext integrated. Each BlockDriverSt= ate -is associated with an AioContext using bdrv_try_change_aio_context() and -bdrv_get_aio_context(). This allows block layer code to process I/O insid= e the -right AioContext. Other subsystems may wish to follow a similar approach. - -Block layer code must therefore expect to run in an IOThread and avoid usi= ng -old APIs that implicitly use the main loop. See the "How to program for -IOThreads" above for information on how to do that. - -Code running in the monitor typically needs to ensure that past -requests from the guest are completed. When a block device is running -in an IOThread, the IOThread can also process requests from the guest -(via ioeventfd). To achieve both objects, wrap the code between -bdrv_drained_begin() and bdrv_drained_end(), thus creating a "drained -section". - -Long-running jobs (usually in the form of coroutines) are often scheduled = in -the BlockDriverState's AioContext. The functions -bdrv_add/remove_aio_context_notifier, or alternatively -blk_add/remove_aio_context_notifier if you use BlockBackends, can be used = to -get a notification whenever bdrv_try_change_aio_context() moves a -BlockDriverState to a different AioContext. --=20 2.34.1 From nobody Sun Nov 24 08:53:21 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=linaro.org ARC-Seal: i=1; a=rsa-sha256; t=1723814606; cv=none; d=zohomail.com; s=zohoarc; b=UvOlj3ouMeJD8WQIK2KMh+EWTBlqq4s+nkYE+Y7Y4FlRkZcmsWCqpHjOpWTh8y3iA7994EGJmCv6HFVUwQ9rFdiXU0/FDjDDqT2ef4yKP6SOH0sxcbnJJaS5MQ581MAOsaP9llec7fmhfqNiHtTdB25TQcl38JTXHVD1ED4Rd5E= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1723814606; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=uQ6lW85Zu+/OmlzIIJ9luNAHJSF12nY6HV6G44fIzvs=; b=kuFcEmtjs5TYDGptUqkuyoP8JylvXt8hZZWkoASVeO5Ato/CRUEX+JN2WaxLTRCjozJYo7W87EJXKgYIgVNxcgL7Rocw15AGjmDdtKS+zqaqGu713jC42WMpzyO4LxrFpJFFzDXd1ZbXkYRFb/E0CPvbTYyU1lObpBNRsCxYHIw= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1723814606281394.89329745628356; Fri, 16 Aug 2024 06:23:26 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1sewuV-0005i6-By; Fri, 16 Aug 2024 09:22:31 -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 1sewuM-0005Dz-Hb for qemu-devel@nongnu.org; Fri, 16 Aug 2024 09:22:25 -0400 Received: from mail-wm1-x32a.google.com ([2a00:1450:4864:20::32a]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1sewuJ-0007kW-JD for qemu-devel@nongnu.org; Fri, 16 Aug 2024 09:22:22 -0400 Received: by mail-wm1-x32a.google.com with SMTP id 5b1f17b1804b1-429c4a4c6a8so14655295e9.0 for ; Fri, 16 Aug 2024 06:22:19 -0700 (PDT) Received: from orth.archaic.org.uk (orth.archaic.org.uk. [2001:8b0:1d0::2]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-371898ab855sm3631948f8f.105.2024.08.16.06.22.17 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 16 Aug 2024 06:22:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1723814538; x=1724419338; 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=uQ6lW85Zu+/OmlzIIJ9luNAHJSF12nY6HV6G44fIzvs=; b=DxifNPKuFxddrbkTOUSySSxiWM7MUaiuZYHDyl4W6IXf9nJSx5aamA7hcwNBMQE1UH 6pOXTYMphlAwDriEuHf3Z/M/6o+JPEcGo8X6EztzZ2oQkmSUos7yxLnW2/4qPh26d2Qf dp9dGI3ZQyd4KWJ6U+ROjDpm1EGi7JyjQT/EDnPK3flOSI29dQU7nhFc6JEtT5CZECuK TPCzLFi8GE/sSzg1WNZN24eGSADgGUkwF1wwJRbfcW6OxkHDaXDQo9KF4oFUYAp9Tn3v uPvMKPWGJpDRcIrWQZLLbEtrdR8wcF6BD9OZIX1dEnP68E2hDDGSjLOCNwAR9hMOfV06 gejw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1723814538; x=1724419338; 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=uQ6lW85Zu+/OmlzIIJ9luNAHJSF12nY6HV6G44fIzvs=; b=J4qHTxqqY12ZHkSuPiKpMLkmzDSZIS8BFrwNo2+4f8G7I+83yH9kK1ouXGnnT9UNR3 3kChlfobhWIaMP6HEEez8ou7xAzQvfhvOjQixCtFABqxAdD+DuoP/Le5O0hza4WpP7+n 7iuHAkhexKtYTzGqF4xTzGWJKcf3yXwxD8orJmS+fl+lNJ9pxdu0RxKwJTAi7xrU2NiK SPGNP0dlXKL3AFw0GnqxVpeQrwsIAbEKoVFyPcOMLnPotWArTfB3FUW3aU3a/ZfHBLrL rnRxj1aXbML86Yc+5t3qq+yZy0PoxZqXg6olmxMuuWV6tnqFp3bI4F9N1mM1QBQAJTQf o4cw== X-Gm-Message-State: AOJu0YyzyhNlt+J5zbAJR1y7+mbqO8ee6b6ISBnpLo21qzDMCpBDFC3O IEiXj64ErNUMeBiMoLCIxFu1MaUmfseNmBzHAQZEPliVPeggDWzxtXAReuWLLT8CnofpCOt6xyQ x X-Google-Smtp-Source: AGHT+IEQz65YMXJ9oS+9akpVK1HPO/yYExg0G5IkEnoSOYsk5yhRF3WleXZSxzr1rOO7lneL5Jl1XA== X-Received: by 2002:a05:6000:1112:b0:368:714e:5a5e with SMTP id ffacd0b85a97d-3719431764cmr2209985f8f.2.1723814537863; Fri, 16 Aug 2024 06:22:17 -0700 (PDT) From: Peter Maydell To: qemu-devel@nongnu.org Cc: Paolo Bonzini , Kevin Wolf , Hanna Reitz , Stefan Hajnoczi Subject: [PATCH 5/7] docs/devel/rcu: Convert to rST format Date: Fri, 16 Aug 2024 14:22:10 +0100 Message-Id: <20240816132212.3602106-6-peter.maydell@linaro.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240816132212.3602106-1-peter.maydell@linaro.org> References: <20240816132212.3602106-1-peter.maydell@linaro.org> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=2a00:1450:4864:20::32a; envelope-from=peter.maydell@linaro.org; helo=mail-wm1-x32a.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+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @linaro.org) X-ZM-MESSAGEID: 1723814607425116600 Content-Type: text/plain; charset="utf-8" Convert docs/devel/rcu.txt to rST format. Signed-off-by: Peter Maydell --- MAINTAINERS | 2 +- docs/devel/index-internals.rst | 1 + docs/devel/{rcu.txt =3D> rcu.rst} | 172 +++++++++++++++----------------- 3 files changed, 82 insertions(+), 93 deletions(-) rename docs/devel/{rcu.txt =3D> rcu.rst} (73%) diff --git a/MAINTAINERS b/MAINTAINERS index 9e091a4e214..f8f4df44460 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3113,7 +3113,7 @@ Read, Copy, Update (RCU) M: Paolo Bonzini S: Maintained F: docs/devel/lockcnt.rst -F: docs/devel/rcu.txt +F: docs/devel/rcu.rst F: include/qemu/rcu*.h F: tests/unit/rcutorture.c F: tests/unit/test-rcu-*.c diff --git a/docs/devel/index-internals.rst b/docs/devel/index-internals.rst index 88fa0e9450d..ab9fbc44826 100644 --- a/docs/devel/index-internals.rst +++ b/docs/devel/index-internals.rst @@ -8,6 +8,7 @@ Details about QEMU's various subsystems including how to ad= d features to them. =20 qom atomics + rcu block-coroutine-wrapper clocks ebpf_rss diff --git a/docs/devel/rcu.txt b/docs/devel/rcu.rst similarity index 73% rename from docs/devel/rcu.txt rename to docs/devel/rcu.rst index 2e6cc607a17..dd07c1d9195 100644 --- a/docs/devel/rcu.txt +++ b/docs/devel/rcu.rst @@ -20,7 +20,7 @@ for the execution of all *currently running* critical sec= tions before proceeding, or before asynchronously executing a callback. =20 The key point here is that only the currently running critical sections -are waited for; critical sections that are started _after_ the beginning +are waited for; critical sections that are started **after** the beginning of the wait do not extend the wait, despite running concurrently with the updater. This is the reason why RCU is more scalable than, for example, reader-writer locks. It is so much more scalable that @@ -37,7 +37,7 @@ do not matter; as soon as all previous critical sections = have finished, there cannot be any readers who hold references to the data structure, and these can now be safely reclaimed (e.g., freed or unref'ed). =20 -Here is a picture: +Here is a picture:: =20 thread 1 thread 2 thread 3 ------------------- ------------------------ ------------------- @@ -58,43 +58,38 @@ that critical section. =20 =20 RCU API -=3D=3D=3D=3D=3D=3D=3D +------- =20 The core RCU API is small: =20 - void rcu_read_lock(void); - +``void rcu_read_lock(void);`` Used by a reader to inform the reclaimer that the reader is entering an RCU read-side critical section. =20 - void rcu_read_unlock(void); - +``void rcu_read_unlock(void);`` Used by a reader to inform the reclaimer that the reader is exiting an RCU read-side critical section. Note that RCU read-side critical sections may be nested and/or overlapping. =20 - void synchronize_rcu(void); - +``void synchronize_rcu(void);`` Blocks until all pre-existing RCU read-side critical sections on all threads have completed. This marks the end of the removal phase and the beginning of reclamation phase. =20 Note that it would be valid for another update to come while - synchronize_rcu is running. Because of this, it is better that + ``synchronize_rcu`` is running. Because of this, it is better that the updater releases any locks it may hold before calling - synchronize_rcu. If this is not possible (for example, because - the updater is protected by the BQL), you can use call_rcu. + ``synchronize_rcu``. If this is not possible (for example, because + the updater is protected by the BQL), you can use ``call_rcu``. =20 - void call_rcu1(struct rcu_head * head, - void (*func)(struct rcu_head *head)); - - This function invokes func(head) after all pre-existing RCU +``void call_rcu1(struct rcu_head * head, void (*func)(struct rcu_head *hea= d));`` + This function invokes ``func(head)`` after all pre-existing RCU read-side critical sections on all threads have completed. This marks the end of the removal phase, with func taking care asynchronously of the reclamation phase. =20 - The foo struct needs to have an rcu_head structure added, - perhaps as follows: + The ``foo`` struct needs to have an ``rcu_head`` structure added, + perhaps as follows:: =20 struct foo { struct rcu_head rcu; @@ -103,8 +98,8 @@ The core RCU API is small: long c; }; =20 - so that the reclaimer function can fetch the struct foo address - and free it: + so that the reclaimer function can fetch the ``struct foo`` address + and free it:: =20 call_rcu1(&foo.rcu, foo_reclaim); =20 @@ -114,29 +109,27 @@ The core RCU API is small: g_free(fp); } =20 - For the common case where the rcu_head member is the first of the - struct, you can use the following macro. + ``call_rcu1`` is typically used via either the ``call_rcu`` or + ``g_free_rcu`` macros, which handle the common case where the + ``rcu_head`` member is the first of the struct. =20 - void call_rcu(T *p, - void (*func)(T *p), - field-name); - void g_free_rcu(T *p, - field-name); +``void call_rcu(T *p, void (*func)(T *p), field-name);`` + If the ``struct rcu_head`` is the first field in the struct, you c= an + use this macro instead of ``call_rcu1``. =20 - call_rcu1 is typically used through these macro, in the common case - where the "struct rcu_head" is the first field in the struct. If - the callback function is g_free, in particular, g_free_rcu can be - used. In the above case, one could have written simply: +``void g_free_rcu(T *p, field-name);`` + This is a special-case version of ``call_rcu`` where the callback + function is ``g_free``. + In the example given in ``call_rcu1``, one could have written simp= ly:: =20 g_free_rcu(&foo, rcu); =20 - typeof(*p) qatomic_rcu_read(p); +``typeof(*p) qatomic_rcu_read(p);`` + ``qatomic_rcu_read()`` is similar to ``qatomic_load_acquire()``, b= ut + it makes some assumptions on the code that calls it. This allows a + more optimized implementation. =20 - qatomic_rcu_read() is similar to qatomic_load_acquire(), but it ma= kes - some assumptions on the code that calls it. This allows a more - optimized implementation. - - qatomic_rcu_read assumes that whenever a single RCU critical + ``qatomic_rcu_read`` assumes that whenever a single RCU critical section reads multiple shared data, these reads are either data-dependent or need no ordering. This is almost always the case when using RCU, because read-side critical sections typically @@ -144,7 +137,7 @@ The core RCU API is small: every update) until reaching a data structure of interest, and then read from there. =20 - RCU read-side critical sections must use qatomic_rcu_read() to + RCU read-side critical sections must use ``qatomic_rcu_read()`` to read data, unless concurrent writes are prevented by another synchronization mechanism. =20 @@ -152,18 +145,17 @@ The core RCU API is small: data structure in a single direction, opposite to the direction in which the updater initializes it. =20 - void qatomic_rcu_set(p, typeof(*p) v); +``void qatomic_rcu_set(p, typeof(*p) v);`` + ``qatomic_rcu_set()`` is similar to ``qatomic_store_release()``, + though it also makes assumptions on the code that calls it in + order to allow a more optimized implementation. =20 - qatomic_rcu_set() is similar to qatomic_store_release(), though it= also - makes assumptions on the code that calls it in order to allow a mo= re - optimized implementation. - - In particular, qatomic_rcu_set() suffices for synchronization + In particular, ``qatomic_rcu_set()`` suffices for synchronization with readers, if the updater never mutates a field within a data item that is already accessible to readers. This is the case when initializing a new copy of the RCU-protected data - structure; just ensure that initialization of *p is carried out - before qatomic_rcu_set() makes the data item visible to readers. + structure; just ensure that initialization of ``*p`` is carried out + before ``qatomic_rcu_set()`` makes the data item visible to reader= s. If this rule is observed, writes will happen in the opposite order as reads in the RCU read-side critical sections (or if there is just one update), and there will be no need for other @@ -171,58 +163,54 @@ The core RCU API is small: =20 The following APIs must be used before RCU is used in a thread: =20 - void rcu_register_thread(void); - +``void rcu_register_thread(void);`` Mark a thread as taking part in the RCU mechanism. Such a thread will have to report quiescent points regularly, either manually - or through the QemuCond/QemuSemaphore/QemuEvent APIs. - - void rcu_unregister_thread(void); + or through the ``QemuCond``/``QemuSemaphore``/``QemuEvent`` APIs. =20 +``void rcu_unregister_thread(void);`` Mark a thread as not taking part anymore in the RCU mechanism. It is not a problem if such a thread reports quiescent points, - either manually or by using the QemuCond/QemuSemaphore/QemuEvent - APIs. + either manually or by using the + ``QemuCond``/``QemuSemaphore``/``QemuEvent`` APIs. =20 -Note that these APIs are relatively heavyweight, and should _not_ be +Note that these APIs are relatively heavyweight, and should **not** be nested. =20 Convenience macros -=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D +------------------ =20 Two macros are provided that automatically release the read lock at the end of the scope. =20 - RCU_READ_LOCK_GUARD() - +``RCU_READ_LOCK_GUARD()`` Takes the lock and will release it at the end of the block it's used in. =20 - WITH_RCU_READ_LOCK_GUARD() { code } - +``WITH_RCU_READ_LOCK_GUARD() { code }`` Is used at the head of a block to protect the code within the blo= ck. =20 -Note that 'goto'ing out of the guarded block will also drop the lock. +Note that a ``goto`` out of the guarded block will also drop the lock. =20 -DIFFERENCES WITH LINUX -=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D +Differences with Linux +---------------------- =20 - Waiting on a mutex is possible, though discouraged, within an RCU critic= al section. This is because spinlocks are rarely (if ever) used in userspa= ce programming; not allowing this would prevent upgrading an RCU read-side critical section to become an updater. =20 -- qatomic_rcu_read and qatomic_rcu_set replace rcu_dereference and - rcu_assign_pointer. They take a _pointer_ to the variable being accesse= d. +- ``qatomic_rcu_read`` and ``qatomic_rcu_set`` replace ``rcu_dereference``= and + ``rcu_assign_pointer``. They take a **pointer** to the variable being a= ccessed. =20 -- call_rcu is a macro that has an extra argument (the name of the first - field in the struct, which must be a struct rcu_head), and expects the +- ``call_rcu`` is a macro that has an extra argument (the name of the first + field in the struct, which must be a struct ``rcu_head``), and expects t= he type of the callback's argument to be the type of the first argument. - call_rcu1 is the same as Linux's call_rcu. + ``call_rcu1`` is the same as Linux's ``call_rcu``. =20 =20 -RCU PATTERNS -=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D +RCU Patterns +------------ =20 Many patterns using read-writer locks translate directly to RCU, with the advantages of higher scalability and deadlock immunity. @@ -243,28 +231,28 @@ Here are some frequently-used RCU idioms that are wor= th noting. =20 =20 RCU list processing -------------------- +^^^^^^^^^^^^^^^^^^^ =20 TBD (not yet used in QEMU) =20 =20 RCU reference counting ----------------------- +^^^^^^^^^^^^^^^^^^^^^^ =20 Because grace periods are not allowed to complete while there is an RCU read-side critical section in progress, the RCU read-side primitives may be used as a restricted reference-counting mechanism. For example, -consider the following code fragment: +consider the following code fragment:: =20 rcu_read_lock(); p =3D qatomic_rcu_read(&foo); /* do something with p. */ rcu_read_unlock(); =20 -The RCU read-side critical section ensures that the value of "p" remains -valid until after the rcu_read_unlock(). In some sense, it is acquiring -a reference to p that is later released when the critical section ends. -The write side looks simply like this (with appropriate locking): +The RCU read-side critical section ensures that the value of ``p`` remains +valid until after the ``rcu_read_unlock()``. In some sense, it is acquiri= ng +a reference to ``p`` that is later released when the critical section ends. +The write side looks simply like this (with appropriate locking):: =20 qemu_mutex_lock(&foo_mutex); old =3D foo; @@ -274,7 +262,7 @@ The write side looks simply like this (with appropriate= locking): free(old); =20 If the processing cannot be done purely within the critical section, it -is possible to combine this idiom with a "real" reference count: +is possible to combine this idiom with a "real" reference count:: =20 rcu_read_lock(); p =3D qatomic_rcu_read(&foo); @@ -283,7 +271,7 @@ is possible to combine this idiom with a "real" referen= ce count: /* do something with p. */ foo_unref(p); =20 -The write side can be like this: +The write side can be like this:: =20 qemu_mutex_lock(&foo_mutex); old =3D foo; @@ -292,7 +280,7 @@ The write side can be like this: synchronize_rcu(); foo_unref(old); =20 -or with call_rcu: +or with ``call_rcu``:: =20 qemu_mutex_lock(&foo_mutex); old =3D foo; @@ -301,10 +289,10 @@ or with call_rcu: call_rcu(foo_unref, old, rcu); =20 In both cases, the write side only performs removal. Reclamation -happens when the last reference to a "foo" object is dropped. -Using synchronize_rcu() is undesirably expensive, because the +happens when the last reference to a ``foo`` object is dropped. +Using ``synchronize_rcu()`` is undesirably expensive, because the last reference may be dropped on the read side. Hence you can -use call_rcu() instead: +use ``call_rcu()`` instead:: =20 foo_unref(struct foo *p) { if (qatomic_fetch_dec(&p->refcount) =3D=3D 1) { @@ -314,7 +302,7 @@ use call_rcu() instead: =20 =20 Note that the same idioms would be possible with reader/writer -locks: +locks:: =20 read_lock(&foo_rwlock); write_mutex_lock(&foo_rwlock); p =3D foo; p =3D foo; @@ -334,15 +322,15 @@ locks: foo_unref(p); read_unlock(&foo_rwlock); =20 -foo_unref could use a mechanism such as bottom halves to move deallocation +``foo_unref`` could use a mechanism such as bottom halves to move dealloca= tion out of the write-side critical section. =20 =20 RCU resizable arrays --------------------- +^^^^^^^^^^^^^^^^^^^^ =20 Resizable arrays can be used with RCU. The expensive RCU synchronization -(or call_rcu) only needs to take place when the array is resized. +(or ``call_rcu``) only needs to take place when the array is resized. The two items to take care of are: =20 - ensuring that the old version of the array is available between removal @@ -351,10 +339,10 @@ The two items to take care of are: - avoiding mismatches in the read side between the array data and the array size. =20 -The first problem is avoided simply by not using realloc. Instead, +The first problem is avoided simply by not using ``realloc``. Instead, each resize will allocate a new array and copy the old data into it. The second problem would arise if the size and the data pointers were -two members of a larger struct: +two members of a larger struct:: =20 struct mystuff { ... @@ -364,7 +352,7 @@ two members of a larger struct: ... }; =20 -Instead, we store the size of the array with the array itself: +Instead, we store the size of the array with the array itself:: =20 struct arr { int size; @@ -400,7 +388,7 @@ Instead, we store the size of the array with the array = itself: } =20 =20 -SOURCES -=3D=3D=3D=3D=3D=3D=3D +References +---------- =20 -* Documentation/RCU/ from the Linux kernel +* The `Linux kernel RCU documentation `__ --=20 2.34.1 From nobody Sun Nov 24 08:53:21 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=linaro.org ARC-Seal: i=1; a=rsa-sha256; t=1723814639; cv=none; d=zohomail.com; s=zohoarc; b=gVuVtu/1ESJUOK6s5gfGcm+VAipRjezHMxMT/HQldUy8bWoM3Qik3WF04vmXjz5WVQBHysZP+v4mEX9NUeYU5OwfVURGZUuL1WTJCd/33+3K5D3RZFBmwnSwq6fPf0LchTLooFOv324eILuPGPBQ6VdUetGlQgJSO8e/UJ8pnZM= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1723814639; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=tbFKdbxYbnOhLfqgIpN9vAb16GVhlAA5iH79ZtRgaj8=; b=GgcnBtWsnaxKn9tj56Z8Cwm45mZP7vQD62AMfizSUC6bmgvNYy+bdV1VvL3YNBCgRpKxbujACO85kL63ObHQMoQsyMjJIzraNE5Eg/kkMheY1HvKwQcLeZM3U0R+rK4YrpH/LY5by/F+bYV7xwgnSLebKK+5B5nOWPLAdcKIl0E= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1723814639423446.8940632183575; Fri, 16 Aug 2024 06:23:59 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1sewuR-0005Wv-T0; Fri, 16 Aug 2024 09:22:27 -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 1sewuM-0005EY-La for qemu-devel@nongnu.org; Fri, 16 Aug 2024 09:22:25 -0400 Received: from mail-wm1-x32e.google.com ([2a00:1450:4864:20::32e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1sewuK-0007kd-50 for qemu-devel@nongnu.org; Fri, 16 Aug 2024 09:22:22 -0400 Received: by mail-wm1-x32e.google.com with SMTP id 5b1f17b1804b1-42816ca782dso14897415e9.2 for ; Fri, 16 Aug 2024 06:22:19 -0700 (PDT) Received: from orth.archaic.org.uk (orth.archaic.org.uk. [2001:8b0:1d0::2]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-371898ab855sm3631948f8f.105.2024.08.16.06.22.17 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 16 Aug 2024 06:22:18 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1723814539; x=1724419339; 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=tbFKdbxYbnOhLfqgIpN9vAb16GVhlAA5iH79ZtRgaj8=; b=Dj9mRKkwOdmGubtl7nJltjaSORRqagS7qtH1KIoSJNcQ0qQpFe8lURqD+l483ewK+G WaGBw+wn9APLCnOlGi5xPDQEJbjV8YYx23tJE4GHPD7HRoCAVNwplHWgCbfY2U/JS9FK 1B8zjXKXGhmY0z/J98XN/b9AwXITeWNIu9xlm+JuNGyB+liwe1h8z1o4FmPx8FVOmm6e aHK7JMl+k+eINFPKiLU+uvREbDjfdXZZzjG2Gy0ysB3hEVOxWeGJrNUHDeRblx0ByH86 cpnYWPbV256gd+wulRRqtMAfsPPq4GPJfqjDi67BgnoF97Dnrun/MUxTcfURftBtzxRQ eHsA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1723814539; x=1724419339; 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=tbFKdbxYbnOhLfqgIpN9vAb16GVhlAA5iH79ZtRgaj8=; b=brMYq/kVX3iieGRnmg9UQw3/IjZBphvSednGZj2d16N3GJPwroT8khPzWjOXvuQiBt lL7XZzBbEI1jubTJ+/rvennvUFUb0VzT2pxEUoPZtS9zchMljdIeOgwvjn96naGh1z0t 7d0v/rgfV5herf0MxpYy678SDxJg/05/RIqYbCUf1J69XAi/neuzsMbMYY//HIGgBPI7 H2K/XNylXDzJ5nFgZ2Xlr8Vs//A1A0jSNiHBRFce9Ei+/iykFSQiXWNlV2DHk2cv+5h6 gmLs4r+q8DAkophbkW4tPOkjgdOwGSoFIp85IdoHZebj1P+lOBjulQ+/+Hri6veC48/m MzWQ== X-Gm-Message-State: AOJu0YzrDbLLZ2cADwOMo5NuQp9N9WICY60q04J4aA+AmSXTGK12KEy5 K1WRCcf4S0vX1SD09nsypniCj32c2B43V+j8oWCCYzj5E22cCoxS7vC2rqGDlKaR2gaJNuTqvGX 3 X-Google-Smtp-Source: AGHT+IGHybU9Txyn8OmYaoT6edezR8sDktJlr/6kIrcsbP5ZDHobMtGaaDAebnnJZnqUtXFoZzvRCw== X-Received: by 2002:a05:6000:1365:b0:367:980a:6aa with SMTP id ffacd0b85a97d-371946bf62dmr2252621f8f.54.1723814538477; Fri, 16 Aug 2024 06:22:18 -0700 (PDT) From: Peter Maydell To: qemu-devel@nongnu.org Cc: Paolo Bonzini , Kevin Wolf , Hanna Reitz , Stefan Hajnoczi Subject: [PATCH 6/7] include: Move QemuLockCnt APIs to their own header Date: Fri, 16 Aug 2024 14:22:11 +0100 Message-Id: <20240816132212.3602106-7-peter.maydell@linaro.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240816132212.3602106-1-peter.maydell@linaro.org> References: <20240816132212.3602106-1-peter.maydell@linaro.org> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=2a00:1450:4864:20::32e; envelope-from=peter.maydell@linaro.org; helo=mail-wm1-x32e.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+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @linaro.org) X-ZM-MESSAGEID: 1723814641512116600 Content-Type: text/plain; charset="utf-8" Currently the QemuLockCnt data structure and associated functions are in the include/qemu/thread.h header. Move them to their own qemu/lockcnt.h. The main reason for doing this is that it means we can autogenerate the documentation comments into the docs/devel documentation. The copyright/author in the new header is drawn from lockcnt.c, since the header changes were added in the same commit as lockcnt.c; since neither thread.h nor lockcnt.c state an explicit license, the standard default of GPL-2-or-later applies. We include the new header (and the .c file, which was accidentally omitted previously) in the "RCU" part of MAINTAINERS, since that is where the lockcnt.rst documentation is categorized. Signed-off-by: Peter Maydell Acked-by: Paolo Bonzini Reviewed-by: Philippe Mathieu-Daud=C3=A9 --- Paolo: could you confirm that you meant GPL2+ for this code? --- MAINTAINERS | 2 + docs/devel/lockcnt.rst | 2 +- include/block/aio.h | 1 + include/hw/core/cpu.h | 1 + include/qemu/lockcnt.h | 130 +++++++++++++++++++++++++++++++++++++++++ include/qemu/thread.h | 111 ----------------------------------- accel/accel-blocker.c | 1 + hw/core/cpu-common.c | 1 + util/aio-posix.c | 1 + util/aio-win32.c | 1 + util/async.c | 1 + util/fdmon-epoll.c | 1 + util/lockcnt.c | 1 + 13 files changed, 142 insertions(+), 112 deletions(-) create mode 100644 include/qemu/lockcnt.h diff --git a/MAINTAINERS b/MAINTAINERS index f8f4df44460..2da11411ff3 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3115,8 +3115,10 @@ S: Maintained F: docs/devel/lockcnt.rst F: docs/devel/rcu.rst F: include/qemu/rcu*.h +F: include/qemu/lockcnt.h F: tests/unit/rcutorture.c F: tests/unit/test-rcu-*.c +F: util/lockcnt.c F: util/rcu.c =20 Human Monitor (HMP) diff --git a/docs/devel/lockcnt.rst b/docs/devel/lockcnt.rst index 994aeb57151..728594bcea3 100644 --- a/docs/devel/lockcnt.rst +++ b/docs/devel/lockcnt.rst @@ -175,7 +175,7 @@ three instructions in the critical path, two assignment= s and a ``smp_wmb()``. ``QemuLockCnt`` API ------------------- =20 -The ``QemuLockCnt`` API is described in ``include/qemu/thread.h``. +The ``QemuLockCnt`` API is described in ``include/qemu/lockcnt.h``. =20 =20 ``QemuLockCnt`` usage diff --git a/include/block/aio.h b/include/block/aio.h index 4ee81936ed5..43883a8a33a 100644 --- a/include/block/aio.h +++ b/include/block/aio.h @@ -20,6 +20,7 @@ #include "qemu/coroutine-core.h" #include "qemu/queue.h" #include "qemu/event_notifier.h" +#include "qemu/lockcnt.h" #include "qemu/thread.h" #include "qemu/timer.h" #include "block/graph-lock.h" diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h index 1c9c775df65..ecbeeb1c0dd 100644 --- a/include/hw/core/cpu.h +++ b/include/hw/core/cpu.h @@ -33,6 +33,7 @@ #include "qemu/bitmap.h" #include "qemu/rcu_queue.h" #include "qemu/queue.h" +#include "qemu/lockcnt.h" #include "qemu/thread.h" #include "qom/object.h" =20 diff --git a/include/qemu/lockcnt.h b/include/qemu/lockcnt.h new file mode 100644 index 00000000000..2c92ae17c9e --- /dev/null +++ b/include/qemu/lockcnt.h @@ -0,0 +1,130 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * QemuLockCnt implementation + * + * Copyright Red Hat, Inc. 2017 + * + * Author: + * Paolo Bonzini + * + */ + +#ifndef QEMU_LOCKCNT_H +#define QEMU_LOCKCNT_H + +#include "qemu/thread.h" + +typedef struct QemuLockCnt QemuLockCnt; + +struct QemuLockCnt { +#ifndef CONFIG_LINUX + QemuMutex mutex; +#endif + unsigned count; +}; + +/** + * qemu_lockcnt_init: initialize a QemuLockcnt + * @lockcnt: the lockcnt to initialize + * + * Initialize lockcnt's counter to zero and prepare its mutex + * for usage. + */ +void qemu_lockcnt_init(QemuLockCnt *lockcnt); + +/** + * qemu_lockcnt_destroy: destroy a QemuLockcnt + * @lockcnt: the lockcnt to destruct + * + * Destroy lockcnt's mutex. + */ +void qemu_lockcnt_destroy(QemuLockCnt *lockcnt); + +/** + * qemu_lockcnt_inc: increment a QemuLockCnt's counter + * @lockcnt: the lockcnt to operate on + * + * If the lockcnt's count is zero, wait for critical sections + * to finish and increment lockcnt's count to 1. If the count + * is not zero, just increment it. + * + * Because this function can wait on the mutex, it must not be + * called while the lockcnt's mutex is held by the current thread. + * For the same reason, qemu_lockcnt_inc can also contribute to + * AB-BA deadlocks. This is a sample deadlock scenario: + * + * thread 1 thread 2 + * ------------------------------------------------------- + * qemu_lockcnt_lock(&lc1); + * qemu_lockcnt_lock(&lc2); + * qemu_lockcnt_inc(&lc2); + * qemu_lockcnt_inc(&lc1); + */ +void qemu_lockcnt_inc(QemuLockCnt *lockcnt); + +/** + * qemu_lockcnt_dec: decrement a QemuLockCnt's counter + * @lockcnt: the lockcnt to operate on + */ +void qemu_lockcnt_dec(QemuLockCnt *lockcnt); + +/** + * qemu_lockcnt_dec_and_lock: decrement a QemuLockCnt's counter and + * possibly lock it. + * @lockcnt: the lockcnt to operate on + * + * Decrement lockcnt's count. If the new count is zero, lock + * the mutex and return true. Otherwise, return false. + */ +bool qemu_lockcnt_dec_and_lock(QemuLockCnt *lockcnt); + +/** + * qemu_lockcnt_dec_if_lock: possibly decrement a QemuLockCnt's counter and + * lock it. + * @lockcnt: the lockcnt to operate on + * + * If the count is 1, decrement the count to zero, lock + * the mutex and return true. Otherwise, return false. + */ +bool qemu_lockcnt_dec_if_lock(QemuLockCnt *lockcnt); + +/** + * qemu_lockcnt_lock: lock a QemuLockCnt's mutex. + * @lockcnt: the lockcnt to operate on + * + * Remember that concurrent visits are not blocked unless the count is + * also zero. You can use qemu_lockcnt_count to check for this inside a + * critical section. + */ +void qemu_lockcnt_lock(QemuLockCnt *lockcnt); + +/** + * qemu_lockcnt_unlock: release a QemuLockCnt's mutex. + * @lockcnt: the lockcnt to operate on. + */ +void qemu_lockcnt_unlock(QemuLockCnt *lockcnt); + +/** + * qemu_lockcnt_inc_and_unlock: combined unlock/increment on a QemuLockCnt. + * @lockcnt: the lockcnt to operate on. + * + * This is the same as + * + * qemu_lockcnt_unlock(lockcnt); + * qemu_lockcnt_inc(lockcnt); + * + * but more efficient. + */ +void qemu_lockcnt_inc_and_unlock(QemuLockCnt *lockcnt); + +/** + * qemu_lockcnt_count: query a LockCnt's count. + * @lockcnt: the lockcnt to query. + * + * Note that the count can change at any time. Still, while the + * lockcnt is locked, one can usefully check whether the count + * is non-zero. + */ +unsigned qemu_lockcnt_count(QemuLockCnt *lockcnt); + +#endif diff --git a/include/qemu/thread.h b/include/qemu/thread.h index fb74e21c08a..7eba27a7049 100644 --- a/include/qemu/thread.h +++ b/include/qemu/thread.h @@ -293,115 +293,4 @@ static inline void qemu_spin_unlock(QemuSpin *spin) #endif } =20 -struct QemuLockCnt { -#ifndef CONFIG_LINUX - QemuMutex mutex; -#endif - unsigned count; -}; - -/** - * qemu_lockcnt_init: initialize a QemuLockcnt - * @lockcnt: the lockcnt to initialize - * - * Initialize lockcnt's counter to zero and prepare its mutex - * for usage. - */ -void qemu_lockcnt_init(QemuLockCnt *lockcnt); - -/** - * qemu_lockcnt_destroy: destroy a QemuLockcnt - * @lockcnt: the lockcnt to destruct - * - * Destroy lockcnt's mutex. - */ -void qemu_lockcnt_destroy(QemuLockCnt *lockcnt); - -/** - * qemu_lockcnt_inc: increment a QemuLockCnt's counter - * @lockcnt: the lockcnt to operate on - * - * If the lockcnt's count is zero, wait for critical sections - * to finish and increment lockcnt's count to 1. If the count - * is not zero, just increment it. - * - * Because this function can wait on the mutex, it must not be - * called while the lockcnt's mutex is held by the current thread. - * For the same reason, qemu_lockcnt_inc can also contribute to - * AB-BA deadlocks. This is a sample deadlock scenario: - * - * thread 1 thread 2 - * ------------------------------------------------------- - * qemu_lockcnt_lock(&lc1); - * qemu_lockcnt_lock(&lc2); - * qemu_lockcnt_inc(&lc2); - * qemu_lockcnt_inc(&lc1); - */ -void qemu_lockcnt_inc(QemuLockCnt *lockcnt); - -/** - * qemu_lockcnt_dec: decrement a QemuLockCnt's counter - * @lockcnt: the lockcnt to operate on - */ -void qemu_lockcnt_dec(QemuLockCnt *lockcnt); - -/** - * qemu_lockcnt_dec_and_lock: decrement a QemuLockCnt's counter and - * possibly lock it. - * @lockcnt: the lockcnt to operate on - * - * Decrement lockcnt's count. If the new count is zero, lock - * the mutex and return true. Otherwise, return false. - */ -bool qemu_lockcnt_dec_and_lock(QemuLockCnt *lockcnt); - -/** - * qemu_lockcnt_dec_if_lock: possibly decrement a QemuLockCnt's counter and - * lock it. - * @lockcnt: the lockcnt to operate on - * - * If the count is 1, decrement the count to zero, lock - * the mutex and return true. Otherwise, return false. - */ -bool qemu_lockcnt_dec_if_lock(QemuLockCnt *lockcnt); - -/** - * qemu_lockcnt_lock: lock a QemuLockCnt's mutex. - * @lockcnt: the lockcnt to operate on - * - * Remember that concurrent visits are not blocked unless the count is - * also zero. You can use qemu_lockcnt_count to check for this inside a - * critical section. - */ -void qemu_lockcnt_lock(QemuLockCnt *lockcnt); - -/** - * qemu_lockcnt_unlock: release a QemuLockCnt's mutex. - * @lockcnt: the lockcnt to operate on. - */ -void qemu_lockcnt_unlock(QemuLockCnt *lockcnt); - -/** - * qemu_lockcnt_inc_and_unlock: combined unlock/increment on a QemuLockCnt. - * @lockcnt: the lockcnt to operate on. - * - * This is the same as - * - * qemu_lockcnt_unlock(lockcnt); - * qemu_lockcnt_inc(lockcnt); - * - * but more efficient. - */ -void qemu_lockcnt_inc_and_unlock(QemuLockCnt *lockcnt); - -/** - * qemu_lockcnt_count: query a LockCnt's count. - * @lockcnt: the lockcnt to query. - * - * Note that the count can change at any time. Still, while the - * lockcnt is locked, one can usefully check whether the count - * is non-zero. - */ -unsigned qemu_lockcnt_count(QemuLockCnt *lockcnt); - #endif diff --git a/accel/accel-blocker.c b/accel/accel-blocker.c index e083f24aa80..75daaa29113 100644 --- a/accel/accel-blocker.c +++ b/accel/accel-blocker.c @@ -25,6 +25,7 @@ */ =20 #include "qemu/osdep.h" +#include "qemu/lockcnt.h" #include "qemu/thread.h" #include "qemu/main-loop.h" #include "hw/core/cpu.h" diff --git a/hw/core/cpu-common.c b/hw/core/cpu-common.c index 7982ecd39a5..09c79035949 100644 --- a/hw/core/cpu-common.c +++ b/hw/core/cpu-common.c @@ -24,6 +24,7 @@ #include "sysemu/hw_accel.h" #include "qemu/log.h" #include "qemu/main-loop.h" +#include "qemu/lockcnt.h" #include "exec/log.h" #include "exec/gdbstub.h" #include "sysemu/tcg.h" diff --git a/util/aio-posix.c b/util/aio-posix.c index 266c9dd35fa..06bf9f456cf 100644 --- a/util/aio-posix.c +++ b/util/aio-posix.c @@ -17,6 +17,7 @@ #include "block/block.h" #include "block/thread-pool.h" #include "qemu/main-loop.h" +#include "qemu/lockcnt.h" #include "qemu/rcu.h" #include "qemu/rcu_queue.h" #include "qemu/sockets.h" diff --git a/util/aio-win32.c b/util/aio-win32.c index d144f9391fb..6583d5c5f31 100644 --- a/util/aio-win32.c +++ b/util/aio-win32.c @@ -18,6 +18,7 @@ #include "qemu/osdep.h" #include "block/block.h" #include "qemu/main-loop.h" +#include "qemu/lockcnt.h" #include "qemu/queue.h" #include "qemu/sockets.h" #include "qapi/error.h" diff --git a/util/async.c b/util/async.c index 3e3e4fc7126..99db28389f6 100644 --- a/util/async.c +++ b/util/async.c @@ -30,6 +30,7 @@ #include "block/graph-lock.h" #include "qemu/main-loop.h" #include "qemu/atomic.h" +#include "qemu/lockcnt.h" #include "qemu/rcu_queue.h" #include "block/raw-aio.h" #include "qemu/coroutine_int.h" diff --git a/util/fdmon-epoll.c b/util/fdmon-epoll.c index c6413cb18fe..9fb8800dde8 100644 --- a/util/fdmon-epoll.c +++ b/util/fdmon-epoll.c @@ -5,6 +5,7 @@ =20 #include "qemu/osdep.h" #include +#include "qemu/lockcnt.h" #include "qemu/rcu_queue.h" #include "aio-posix.h" =20 diff --git a/util/lockcnt.c b/util/lockcnt.c index 5da36946b1b..d07c6cc5cee 100644 --- a/util/lockcnt.c +++ b/util/lockcnt.c @@ -7,6 +7,7 @@ * Paolo Bonzini */ #include "qemu/osdep.h" +#include "qemu/lockcnt.h" #include "qemu/thread.h" #include "qemu/atomic.h" #include "trace.h" --=20 2.34.1 From nobody Sun Nov 24 08:53:21 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=linaro.org ARC-Seal: i=1; a=rsa-sha256; t=1723814582; cv=none; d=zohomail.com; s=zohoarc; b=FgP1pDbJcjojSl1wk/n8oDx6oQ7l0eO2oZlVP6Y88SvkFRjJ4tWLHN3BKmZXNjMvu0J0lGnZeB1rzn0cfhov9PJHezI18g7RGm5Z0sbu/fYg2ed7UsNEeiayPKvTEldfBVBOqJCyuqUcOp4qOOSQIO11XXDwyRRCgumKqxk1k0Y= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1723814582; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=2vFh0taXho/PjkpHjQyE36dh+SvBwU6eZKgiDGqrkEc=; b=RFtBUXc2olrbB3bIpFcPko6TC7U0y8ebgXqq821rPoOvKe2RE5dQOYh8ETpTtUKWnYZm6t3z66zrLmwHfx/19saURecLcXJUbqXvMDL4v2P5C4GuhqI0+4g2nOKQR+QhgV697zlLx5kG9XMU6KXFaJJME+S5lpOLTf/P7kUSMqs= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 172381458284068.41704015240055; Fri, 16 Aug 2024 06:23:02 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1sewuT-0005dR-Ir; Fri, 16 Aug 2024 09:22:30 -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 1sewuN-0005Gv-8u for qemu-devel@nongnu.org; Fri, 16 Aug 2024 09:22:25 -0400 Received: from mail-wm1-x32d.google.com ([2a00:1450:4864:20::32d]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1sewuK-0007ki-TR for qemu-devel@nongnu.org; Fri, 16 Aug 2024 09:22:23 -0400 Received: by mail-wm1-x32d.google.com with SMTP id 5b1f17b1804b1-428ec6c190eso14950045e9.1 for ; Fri, 16 Aug 2024 06:22:20 -0700 (PDT) Received: from orth.archaic.org.uk (orth.archaic.org.uk. [2001:8b0:1d0::2]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-371898ab855sm3631948f8f.105.2024.08.16.06.22.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 16 Aug 2024 06:22:18 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1723814539; x=1724419339; 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=2vFh0taXho/PjkpHjQyE36dh+SvBwU6eZKgiDGqrkEc=; b=UEv4R0fK1fD2+IcqqzEhOY+HRTxO/MHpZp7CFHeXHtkVG2Inwc2FNTzDDUrSDV2rCp yBLqLYIqr0P1p76qzhEHme0U4bk+7jpcJqtMkzlnLPqfAJ7SEMPg4Fzs1FjHofVZmAB6 LWsQphDDhHiX0VLHBBfPTxhW2KKqUEyTaGGaHe0r9445Fmmha2nPpooVyoJr42dMAHSq I7/UUVZVPdG++fvlRzYB8BrFsDOSbgM77eQVqgcHbUwKdXTQd9zdHRt7TBHTKIkP0HTr CPWEVX66dvboqAK/aV9mOzQgRJQfI1d6pr5xal1Uk4ByWNYOvN9/Es3hcWUf+70dmOWX 7lVg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1723814539; x=1724419339; 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=2vFh0taXho/PjkpHjQyE36dh+SvBwU6eZKgiDGqrkEc=; b=NMPsmi0Rg1EsUwfelgOEvxUZimaGrK0q4l7G1x+tHmPhNsjlIAP3/u1nBOciZ1N2bl rGGyda6xvZzBxPXTHJ926VKQCzn7/VDBYAyeauKGiNEUCh1MYGyAgwj+bkVPO2taXcje boTQ0Kua6ZKEsgwaBCd4cRUtVt1Oi81xK62tcO4SVMQIv+ArRlo8YWZXZ46bQIs3fKth QwMOGcudVRj0i12wpYFeLePo7IuzWud/P47+nO1CFW7Y/1Ox2wvD1yiyLMVRwYUeTFo2 /7/d0Jy9wZcws8e58Ji39L3UTxDeU6CZ5T+Ho7t9AW9FPEBB2ipQBnhFK0moT0Y2/ahX QYkQ== X-Gm-Message-State: AOJu0YygDE58M4ahfg6RxumB3SmLqW+QBf+SXsgVaJhepw82JLoBFj6e ZGhzIRfWFWa+ZsuW2CP9S6/fnOEb3Uol9UTX2er3pDLQpxAwuroMblpAL1Q0io/Q2qWNj906GNw t X-Google-Smtp-Source: AGHT+IHaaNIIpIuBbwgzlYn/WAMs06Fi2U1MnoQxNqE7h9aMHTYqMtvzIeghzT/x/aWWqudAlx59tg== X-Received: by 2002:adf:fa50:0:b0:371:72a8:15e with SMTP id ffacd0b85a97d-371943292ecmr1600973f8f.16.1723814539070; Fri, 16 Aug 2024 06:22:19 -0700 (PDT) From: Peter Maydell To: qemu-devel@nongnu.org Cc: Paolo Bonzini , Kevin Wolf , Hanna Reitz , Stefan Hajnoczi Subject: [PATCH 7/7] docs/devel/lockcnt: Include kernel-doc API documentation Date: Fri, 16 Aug 2024 14:22:12 +0100 Message-Id: <20240816132212.3602106-8-peter.maydell@linaro.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240816132212.3602106-1-peter.maydell@linaro.org> References: <20240816132212.3602106-1-peter.maydell@linaro.org> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=2a00:1450:4864:20::32d; envelope-from=peter.maydell@linaro.org; helo=mail-wm1-x32d.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+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @linaro.org) X-ZM-MESSAGEID: 1723814583364116600 Content-Type: text/plain; charset="utf-8" Pull in the kernel-doc API documentation into the lockcnt docs. This requires us to fix one rST markup syntax error in the header file comments. Signed-off-by: Peter Maydell --- docs/devel/lockcnt.rst | 2 +- include/qemu/lockcnt.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/devel/lockcnt.rst b/docs/devel/lockcnt.rst index 728594bcea3..8b43578f6c7 100644 --- a/docs/devel/lockcnt.rst +++ b/docs/devel/lockcnt.rst @@ -175,7 +175,7 @@ three instructions in the critical path, two assignment= s and a ``smp_wmb()``. ``QemuLockCnt`` API ------------------- =20 -The ``QemuLockCnt`` API is described in ``include/qemu/lockcnt.h``. +.. kernel-doc:: include/qemu/lockcnt.h =20 =20 ``QemuLockCnt`` usage diff --git a/include/qemu/lockcnt.h b/include/qemu/lockcnt.h index 2c92ae17c9e..f4b62a3f701 100644 --- a/include/qemu/lockcnt.h +++ b/include/qemu/lockcnt.h @@ -51,7 +51,7 @@ void qemu_lockcnt_destroy(QemuLockCnt *lockcnt); * Because this function can wait on the mutex, it must not be * called while the lockcnt's mutex is held by the current thread. * For the same reason, qemu_lockcnt_inc can also contribute to - * AB-BA deadlocks. This is a sample deadlock scenario: + * AB-BA deadlocks. This is a sample deadlock scenario:: * * thread 1 thread 2 * ------------------------------------------------------- --=20 2.34.1