From nobody Sun Jul 26 12:33:36 2026 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=quarantine dis=none) header.from=openvz.org ARC-Seal: i=1; a=rsa-sha256; t=1782228301; cv=none; d=zohomail.com; s=zohoarc; b=eQYD9hftvSr6hMLfEybSXlPLmZvcSue3phg0/OIMWOCmHES9FeuiT0t2PT8yO9KY4fiJAFxykbxCClzrNTX7XwTU0r6gnM8MM7KUcGVkMTLpv/Bnj+Apoe8EdY6VT/tCEIIuibJ/h7sJEmaeB5ASi0jwWQt6945ErdOCcn8JJKE= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1782228301; 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=/0VvjIeKyQ+VdrjQccUt1hft7SyBvtWdcKKSRrD52Lc=; b=Ik1+CwCrWTkgEy32lb3KIkem6bP18t1lo9nFw9oNpI1x+HaO3Uymy7tHCTYCValFLV9zmFH06mobzVRZoy+ID2sJb1WhKrb7Rdkeb9k+xZ7YgFVkIPLcSR25OZRScElEZp1YJkvogftJBboJA37bc2TmFeKNcKwviAuLZ7JSJgE= 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=quarantine dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1782228301310280.87675099392607; Tue, 23 Jun 2026 08:25:01 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wc2z6-0004lX-Nh; Tue, 23 Jun 2026 11:24:20 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wc2z1-0004jr-Ps for qemu-devel@nongnu.org; Tue, 23 Jun 2026 11:24:16 -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 1wc2yz-0003FR-3u for qemu-devel@nongnu.org; Tue, 23 Jun 2026 11:24:15 -0400 Received: by mail-wm1-x32d.google.com with SMTP id 5b1f17b1804b1-490b613a17bso48515255e9.3 for ; Tue, 23 Jun 2026 08:24:11 -0700 (PDT) Received: from athena.sw.ru ([2a06:5b06:b600:300:406b:7279:5a3e:280f]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-49240eef2basm406008895e9.2.2026.06.23.08.24.09 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 23 Jun 2026 08:24:09 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=openvz.org; s=google; t=1782228250; x=1782833050; 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=/0VvjIeKyQ+VdrjQccUt1hft7SyBvtWdcKKSRrD52Lc=; b=IWZbQFWgB3ESKH1jEd1Q2aj87891vxVKcntiiz+HEHVLnM1t8oppimbaHKPomdC8re bg43a6L/KHL93RAES7qubbIGA9HRIZtcsTWHWWNdMaVzsrKEe3/HweurRaWTNT17XljN tbwTYkDowFUi0qw5wz+RL9SOXgT5UZLSVASUQ7zhIrpENr2rlBSQamZ3qimdETkC57y5 USV7ob81GN+bpD2d7GHnK6wohEiv/lL3I8cM5hURqQAlrO0F8rbJlIv3sS2GJUQ+X2zl X0cDQNQZw5cQFujom5gJslIOGSLkplD1ViZm/lmE38e5vieH5IsbjKRrCPPkiTIpZ9CA 4yLA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1782228250; x=1782833050; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=/0VvjIeKyQ+VdrjQccUt1hft7SyBvtWdcKKSRrD52Lc=; b=tHOpZnvtT7PKzuvl1PNh/8XV8vaRr5zThe+lCzlRI7EeYMteNByWtxK2gDbDMWdAjt LAN8X5lXYEAJcWNKkA1/G05qslchE2b+r2BG9YlB0sEcXxId9fRGO4MwTin77yrP51Ep BdWhbzep8bpKFwL0fUmRCrNAenBapu6MMp/pWKNx8tgLf26DPhNMoLCXBTcgOWcyLzPG kpVdHuRvHfuEeeKt04yHprr4y7Js3+lZ6U0YvoLLXQIebBJ/KgHsSazjrWFbPi3iMJVC V1q266TNJAY3aoWpQQKaG2iQcLezcl/t6mREGt0XZevVMrsUKlPZXKdmO58a8Uonq7B8 t7tw== X-Gm-Message-State: AOJu0YwkCIOrhr1Cnws+y+CKyKdLIjJw7Es2iePyaF4t3I6J4b+WBL6+ GNrC9TUM8tuHxueO1XtFL9uDaoTq2/5WH449VYgXEIxP5nLnZB0euXE2A8uxjxsrUM8= X-Gm-Gg: AfdE7ckz4gQ0HW7ontCnGStrKCZ/4SIOeTGQWk+MegUf/OysaI5R+btJXahs76d10sf 9RsBq+qCZxEjuM14C2MS3QicgtDPSIVU8oigRTrKdG7e3EF9W/ST9OzjwUW6JHFgQgVdvzpP9t8 m6cHiOqcRqdwD4j3jhqnSvpas1w49GWPzuilPTd5B3YmGVekILl8rq94r+UOm65zpiSks2PuXT1 4F8l0RGJET9bTPyB9Lh7UnUoXHkgjyrQBRTdqxhWDAKKYhtdGk56ORrHJlP+xWI9kXaJareF9F7 ptLn4F7B8DjklVk3aV1Ie1IDyJJEd3tn3oZRpf94bm5VUg3PJKsB+N6rb2EvQRNXeFaeUCnYVMq kWq+RkdQCXPXRUDYkl0roOw90MJDnDYxz/r265439qix18L2ND/63pfKij5kSgiYfw3kdkTbUAT GggbL0rQ== X-Received: by 2002:a05:600c:500d:b0:492:37b7:6080 with SMTP id 5b1f17b1804b1-49249083ccamr234039725e9.7.1782228250170; Tue, 23 Jun 2026 08:24:10 -0700 (PDT) From: "Denis V. Lunev" To: qemu-block@nongnu.org Cc: qemu-devel@nongnu.org, John Snow , Vladimir Sementsov-Ogievskiy , "Denis V. Lunev" Subject: [PATCH 1/2] job: keep job paused across overlapping pause requests Date: Tue, 23 Jun 2026 17:24:05 +0200 Message-ID: <20260623152406.1180235-2-den@openvz.org> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260623152406.1180235-1-den@openvz.org> References: <20260623152406.1180235-1-den@openvz.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=lists1p.gnu.org; Received-SPF: pass client-ip=2a00:1450:4864:20::32d; envelope-from=den@openvz.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 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: qemu development 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 @openvz.org) X-ZM-MESSAGEID: 1782228303816158500 Content-Type: text/plain; charset="utf-8" job_pause_point_locked() sets job->paused before yielding and clears it unconditionally on wake, before re-checking whether a pause is still pending. job_pause() re-enters a parked job only while it is not yet paused, so the wake that resumes one comes from a drain *ending* (job_resume() -> job_enter_cond()). If the next drain begins before that wake runs, the woken coroutine clears job->paused while pause_count is already > 0 again: AioContext change (BQL thread) job coroutine (iothread) ----------------------------- ------------------------ parked in job_pause_point(): paused=3D1, pause_count=3D1, yielded drain ends -> job_resume(): pause_count =3D 0 job_enter_cond(): queue wake ..> (wake pending) bdrv_try_change_aio_context(): bdrv_drain_all_begin(): job_pause() per node pause_count =3D N (> 0) wake runs, leaves job_do_yield(): paused =3D 0 (pause_count =3D=3D N) tran_commit -> job_set_aio_context(): assert(paused || completed) --> abort: paused =3D=3D 0 bdrv_try_change_aio_context() drains precisely to quiesce the job before changing its AioContext, but that brief paused=3D=3D0 window trips the assertion. It is guest-triggerable: a virtio-blk reset (virtio_blk_stop_ioeventfd() -> blk_set_aio_context()) racing a running mirror/blockCopy job hits it, as do x-blockdev-set-iothread, blockdev hot-plug/unplug and job completion. Keep job->paused set while a pause is still pending: loop the yield until job_should_pause_locked() is false (or the job is cancelled), and only then clear job->paused. Drained-state consumers then never observe a pending-pause job as unpaused. Signed-off-by: Denis V. Lunev Reviewed-by: Vladimir Sementsov-Ogievskiy --- job.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/job.c b/job.c index e747908472..d7220aaf30 100644 --- a/job.c +++ b/job.c @@ -629,7 +629,14 @@ static void coroutine_fn job_pause_point_locked(Job *j= ob) ? JOB_STATUS_STANDBY : JOB_STATUS_PAUSED); job->paused =3D true; - job_do_yield_locked(job, -1); + /* + * Stay paused across back-to-back pause requests: a transient + * paused =3D=3D false while pause_count > 0 would be observed as + * "not paused" by job_set_aio_context() and other drain consumers. + */ + do { + job_do_yield_locked(job, -1); + } while (job_should_pause_locked(job) && !job_is_cancelled_locked(= job)); job->paused =3D false; job_state_transition_locked(job, status); } --=20 2.53.0 From nobody Sun Jul 26 12:33:36 2026 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=quarantine dis=none) header.from=openvz.org ARC-Seal: i=1; a=rsa-sha256; t=1782228310; cv=none; d=zohomail.com; s=zohoarc; b=GPBXV2sdPIwqDp5nU+yCZ44jHTr7OKDivGmUirhcoqhO80+M++DxkFl8HoFzc56ZjCIjwBWqvrkUqvTQLAGgx5/zGx+DvKwLQK9fDzhpTpoCPz2CQ/dUw2MLrVwu3mV8kVnkgH8jpFR88saez0fI5bu8VpGBMytovXQwPfWndcA= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1782228310; 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=XzsX0Wp5kYrKeC7ZDwHnYAxGPSqeFnF2AaqMrkEjN8Q=; b=LzgoMgX/ZxwH/ngQqKsr0cSqez0qW1NWSV39isqKEWKjjNdzLCs5jgLHjdlrY5mTRFSFvjqpyNV0lrr09uWK086YmzCWLQxdLZRPJeXRf9ALEqCK1W/RzENRt8y+RyUaAge3OCghvbMherIEFCRUO5x4ndcFDHw/cXGIbONcIuc= 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=quarantine dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1782228310154944.8514249387796; Tue, 23 Jun 2026 08:25:10 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wc2z6-0004lP-4b; Tue, 23 Jun 2026 11:24:20 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wc2z4-0004kS-6V for qemu-devel@nongnu.org; Tue, 23 Jun 2026 11:24:18 -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 1wc2z0-0003Fn-72 for qemu-devel@nongnu.org; Tue, 23 Jun 2026 11:24:17 -0400 Received: by mail-wm1-x32c.google.com with SMTP id 5b1f17b1804b1-490b613a17bso48515745e9.3 for ; Tue, 23 Jun 2026 08:24:13 -0700 (PDT) Received: from athena.sw.ru ([2a06:5b06:b600:300:406b:7279:5a3e:280f]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-49240eef2basm406008895e9.2.2026.06.23.08.24.10 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 23 Jun 2026 08:24:11 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=openvz.org; s=google; t=1782228252; x=1782833052; 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=XzsX0Wp5kYrKeC7ZDwHnYAxGPSqeFnF2AaqMrkEjN8Q=; b=sz9pweLZ88LLk7tXTf8DLQpWB2Zqo816OtUNIpdJNax46MenLZiF8rrz1GT005RPvK EIQ8FJOt/MgV4c2h0T/SLDRAAJygFYcunljqF4sIXwkR0trV6/NjseByUWzXGEUCBG8f f08wx/KH8jTQYMrmBka7CZDD7Wz4MPhXLyDZ7EO924iL4JMWjTWk/UC9v3blmcynqb3Y HOLGM0n05pYuff8RwfUsqnbLbcCkOw/fv0guxWTa52WsNJsqjfeH5wHxyDf0vXwYrrV1 SD5plgJRzi/cnPrFYN6uiJQWbzS2hR6QtjPvvlf3kOVuZYgCsVO4ZVuuOkhBKu/gn1F/ qPsw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1782228252; x=1782833052; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=XzsX0Wp5kYrKeC7ZDwHnYAxGPSqeFnF2AaqMrkEjN8Q=; b=GUKAu4QImDhU16vBkjIoa1RAfNZkqqdlEBTti2GE1dMMd1fRAwiCOwJGFCwGNoxxsj sGT9xnmu4+Ht8xFzVV4mvWoJrD9Y4HHN2VwnpZuvWc8ZF/a3nLCB5gmdk2nWRDPkoy7F kdwLaRf2xXy2lj0+OJLLUXz+/4z4asJvW8D2ym26A0KOgYtl9Js7ixCww6HcD4Y8XcL/ 8Je8XRBLp0BuaBc7ARdlIZmrMpPq1Qkwb1Ja4LHZQA0j6gPPKqGwKEYtJKPEi6AlTqFg XQbWw8gojEdRZmQCcE+uxBwLKcqpR23dPxq3wchHeqbR/0oja4+NvZDGeOCpqYsAILT2 JgAw== X-Gm-Message-State: AOJu0Yz/pO04iJCozUw/LCPIGsWWSXWL8ej5L4B+zPFLdGr9hMenRcXL vuWbmtCo//EnZDafBRScqQDxc4P+IUUeKQ7E4HmDHFRvFz9gUBeVFYvRD2Ekfk/zWtw2EBjWRJ1 M4jfouRPyDgHk X-Gm-Gg: AfdE7ckUKgepvQrQPPnrjLi92WPR2RzHQcBwf6z8N8RZr5UKPcUCmX4GNHxKezPxRv6 9gA7UFl/b1+FRLhWC5+0FcFKUD5xo2nGPOxgdUcoxbAfhjAnkUSC1RYFxpV5ogVX3x1G0lSeZzh H9878GYk0fObi1fqwubpdlCAOQ6ElfZNXYLVJPRZLNlvglL0JMfsA/q/4sbIG6+9mwLgwjH/zty GE/ckskn55gWT+YN+ZJIhL9FDtjg3PYQzPGwkz3p63Rc0WcnD9L04oJbRFWaNsH+bbbf2u8OkJk l6c2rzLmzW3gF10WP0GqFzG11NpOHqpAQTOwKw935wzLC/EbGpH6Cx7/ro6kXTe6gPOrpH/N6CR a57WwLb8SyOH2zqbCz9HfI61pmopVRQBG6b8H9IskwI85rWMBj3cH0uLSi+AuDj60oldG4/M= X-Received: by 2002:a05:600c:348b:b0:490:44eb:c1ea with SMTP id 5b1f17b1804b1-492490a771dmr237984845e9.24.1782228251614; Tue, 23 Jun 2026 08:24:11 -0700 (PDT) From: "Denis V. Lunev" To: qemu-block@nongnu.org Cc: qemu-devel@nongnu.org, John Snow , Vladimir Sementsov-Ogievskiy , "Denis V. Lunev" Subject: [PATCH 2/2] tests/unit/test-blockjob: cover keeping a job paused while a pause is pending Date: Tue, 23 Jun 2026 17:24:06 +0200 Message-ID: <20260623152406.1180235-3-den@openvz.org> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260623152406.1180235-1-den@openvz.org> References: <20260623152406.1180235-1-den@openvz.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=lists1p.gnu.org; Received-SPF: pass client-ip=2a00:1450:4864:20::32c; envelope-from=den@openvz.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 autolearn=unavailable autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development 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 @openvz.org) X-ZM-MESSAGEID: 1782228312158158500 Content-Type: text/plain; charset="utf-8" Add a regression test for the previous commit. A job that has reached its pause point is spuriously re-entered (job_enter()) while a pause is still pending (pause_count > 0), reproducing what an overlapping drain does: one drain's job_resume() wakes the job while the next drain's job_pause() is already counted. The job must stay parked - it must not run job code or clear job->paused, or job_set_aio_context() could observe paused =3D=3D false and abort. The test counts the job's run-loop iterations: without the fix the re-entered job clears job->paused, runs one iteration and re-pauses, so the counter advances; with the fix it stays parked and the counter is unchanged. It runs in the main AioContext, so job_enter() is synchronous and the check is deterministic. Signed-off-by: Denis V. Lunev Reviewed-by: Vladimir Sementsov-Ogievskiy Tested-by: Vladimir Sementsov-Ogievskiy --- tests/unit/test-blockjob.c | 100 +++++++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) diff --git a/tests/unit/test-blockjob.c b/tests/unit/test-blockjob.c index abdbe4b835..3b77d19b91 100644 --- a/tests/unit/test-blockjob.c +++ b/tests/unit/test-blockjob.c @@ -388,6 +388,105 @@ static void test_cancel_concluded(void) cancel_common(s); } =20 +typedef struct PauseCountJob { + BlockJob common; + int n; + bool should_complete; +} PauseCountJob; + +static void pause_count_job_complete(Job *job, Error **errp) +{ + PauseCountJob *s =3D container_of(job, PauseCountJob, common.job); + s->should_complete =3D true; +} + +static int coroutine_fn pause_count_job_run(Job *job, Error **errp) +{ + PauseCountJob *s =3D container_of(job, PauseCountJob, common.job); + + while (!s->should_complete) { + if (job_is_cancelled(&s->common.job)) { + return 0; + } + s->n++; + /* + * Yields; while a pause is pending the yield is skipped and the j= ob + * parks in job_pause_point() instead. + */ + job_sleep_ns(&s->common.job, 10 * 1000 * 1000); + } + + return 0; +} + +static const BlockJobDriver pause_count_job_driver =3D { + .job_driver =3D { + .instance_size =3D sizeof(PauseCountJob), + .free =3D block_job_free, + .user_resume =3D block_job_user_resume, + .run =3D pause_count_job_run, + .complete =3D pause_count_job_complete, + }, +}; + +/* + * A job that has reached its pause point must stay paused while a pause is + * still pending (pause_count > 0). An overlapping drain re-enters the job= (one + * drain's job_resume() wakes it while the next drain's job_pause() is alr= eady + * counted); the job must not run or clear job->paused, otherwise + * job_set_aio_context() can observe paused =3D=3D false and abort. + */ +static void test_pause_keeps_paused(void) +{ + BlockBackend *blk; + BlockJob *bjob; + PauseCountJob *s; + Job *job; + int n0; + + blk =3D create_blk(NULL); + bjob =3D mk_job(blk, "job0", &pause_count_job_driver, true, + JOB_MANUAL_FINALIZE | JOB_MANUAL_DISMISS); + s =3D container_of(bjob, PauseCountJob, common); + job =3D &bjob->job; + WITH_JOB_LOCK_GUARD() { + job_ref_locked(job); + } + + job_start(job); + + /* Pause the running job; it parks in job_pause_point() with paused se= t. */ + WITH_JOB_LOCK_GUARD() { + job_pause_locked(job); + g_assert_true(job->paused); + g_assert_cmpint(job->status, =3D=3D, JOB_STATUS_PAUSED); + } + n0 =3D s->n; + + /* + * Spurious wake while the pause is still pending. The job must stay p= arked: + * the bug clears job->paused, runs an iteration (s->n advances) and + * re-pauses, exposing a paused =3D=3D false window. + */ + job_enter(job); + WITH_JOB_LOCK_GUARD() { + g_assert_true(job->paused); + } + g_assert_cmpint(s->n, =3D=3D, n0); + + /* Resume and tear down. */ + WITH_JOB_LOCK_GUARD() { + job_resume_locked(job); + } + job_cancel_sync(job, true); + WITH_JOB_LOCK_GUARD() { + Job *dummy =3D job; + job_dismiss_locked(&dummy, &error_abort); + job_unref_locked(job); + } + destroy_blk(blk); +} + int main(int argc, char **argv) { qemu_init_main_loop(&error_abort); @@ -402,5 +501,6 @@ int main(int argc, char **argv) g_test_add_func("/blockjob/cancel/standby", test_cancel_standby); g_test_add_func("/blockjob/cancel/pending", test_cancel_pending); g_test_add_func("/blockjob/cancel/concluded", test_cancel_concluded); + g_test_add_func("/blockjob/pause/keep_paused", test_pause_keeps_paused= ); return g_test_run(); } --=20 2.53.0