From nobody Sat Nov 15 12:14:53 2025 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=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1751370559; cv=none; d=zohomail.com; s=zohoarc; b=BHLeKuSberesCd2iQtmmepJFs2Hey8bGwWqGJ6BGWaaMtqaN3AZzv9eXxIbiqDv29S6SKUuRkDFbkzwVpMTl349TtDr5O/srXLp5gx1d1wdHikPped2FIvWTEBp81hNCGh4AnpamshtVFZ7NxzsHyeEZYk4NDXNy4cF+Pj8jUIs= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1751370559; h=Content-Type: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=u4jDpSscWb0JSj8RJizyplK1NIFS8/wzix5MvD06Lss=; b=bBevw2jMVgq2zlne9bOG2JVgcfHwpDUXKLbOEdtU8u4O1dlVUVjjxzeK57BQ/HZNywbRwkbN3yE28VnWZoT0fZkR1bN0vm8qLMEczHT+4mjLUNuScwYGyn/X4rt69JIc+6JTblLe8blsI70+7Vvg5R9gva7kh2PAUg6+V+VM3bU= 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 lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1751370559597346.15950550093294; Tue, 1 Jul 2025 04:49:19 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1uWZQG-0005DQ-37; Tue, 01 Jul 2025 07:45:12 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uWZQ5-00059o-AW for qemu-devel@nongnu.org; Tue, 01 Jul 2025 07:45:02 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uWZPx-0003EX-Bi for qemu-devel@nongnu.org; Tue, 01 Jul 2025 07:45:00 -0400 Received: from mail-wr1-f71.google.com (mail-wr1-f71.google.com [209.85.221.71]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-335-DYVcDE4TPwKCySOT0MiZxQ-1; Tue, 01 Jul 2025 07:44:49 -0400 Received: by mail-wr1-f71.google.com with SMTP id ffacd0b85a97d-3a4f85f31d9so2290617f8f.1 for ; Tue, 01 Jul 2025 04:44:49 -0700 (PDT) Received: from localhost (p200300cfd700f38d3df6a1ca7d40fe1f.dip0.t-ipconnect.de. [2003:cf:d700:f38d:3df6:a1ca:7d40:fe1f]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-3a88c7e6f8bsm13451388f8f.17.2025.07.01.04.44.45 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 01 Jul 2025 04:44:45 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1751370290; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=u4jDpSscWb0JSj8RJizyplK1NIFS8/wzix5MvD06Lss=; b=GtLFUVU19XOPu+PqZiFB3rFKO3mGGwcxjd4vDRTx8dX5wcp7vI63GSj4CdwPvMce9TveFC AH0upkpiGOk+7C6Ke4CwHgJJ45xDGSnYuKqCf/sd59aMOF63sr2P1XdOJuHy8E2g/COKGV jzlWcjvCGDuI3JlnSgxTf/87gE6AYU8= X-MC-Unique: DYVcDE4TPwKCySOT0MiZxQ-1 X-Mimecast-MFC-AGG-ID: DYVcDE4TPwKCySOT0MiZxQ_1751370288 X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1751370288; x=1751975088; 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=u4jDpSscWb0JSj8RJizyplK1NIFS8/wzix5MvD06Lss=; b=QIJ/0GSfGAFWr8QgE0jqGHIMdLm5W15LdEVEjfQ2zmV+DFNaE6qWh+OqtznXTUFIRB 53dT1+fIS8p2TOdGXsvPZaEPMV0wkiwmInppmBkXHW9Oj+VdVmGqSZdwdfPWdSU9RBTZ c7OIKNSJzzZmSVQ8bPWOqAQ/kVBL2UVmNzNgVCk67hHdfydP6+AuikHNkVhGr01OkFib qsP43C9LnDIFqRnLkFp1vNt2xK2xAOUH66tztjqzcN4ibRRYzvFVPb8azrw215Tpl1k3 NoD2zHrVbUziadjKd7WgeofOcIyOVwU4zFd0Vfiqv6eMQuKP68areo1DZobg7GC79nJn +XDw== X-Gm-Message-State: AOJu0YzxOFk9l4rUCUI3czjsyllvWYuv1G8atNfTM4zZqconDY1YHKs5 qsaDOjHZlywt849pZ1j9vI8haGcJQxnnpV8Ct6qmADz/hPytnLF4GYuO1S+bLBgImuIeXgkeo3L 6zQvu7x05gDY/v7dxd1uASSnTLV1cXy0mpb83zzjQq5KQRK/5eFFhqglp X-Gm-Gg: ASbGncujQyPkWb4itC145815IN/WotBhGSwsFEUogVj7RU6baNcIDC0LdcO40XaL2pD NPJAYhrZhnyg9IYtVme043lzCXWqkZD23eiyLuHTw/GA9lU5Z3cheaNUCmC7zucP4tgFHVbDQnc 5NaZOGMDOYKQAd7OO85kH/W1LdurgmUmNf3osHkx7qsWSwPk8MIrmB+MTo7PIXDrHM7OKPCK96+ M93aqeaf8CF9ALlgzLGaDngWsOz54oFWVRSbzWakX+TMlNO0LUTUnuPp52ZYqHzNmxlVEf6VfS+ +Urnqb6rPMSjooWGT7HhxMrPBrjTcmgcptdcJuJzB1Qd1pQUMSrIo2Fd0yRVLlEz127QGE0rfsM i79rb X-Received: by 2002:a05:6000:22c2:b0:3a5:1c71:432a with SMTP id ffacd0b85a97d-3a8fe1deba9mr12962593f8f.14.1751370287701; Tue, 01 Jul 2025 04:44:47 -0700 (PDT) X-Google-Smtp-Source: AGHT+IH/1qzFgbegKk/5YP7M7Mip9i03TsCFGkjhTBd3WAllWjteIMDpFIhnzs8IDLvbUy+3qFx0dw== X-Received: by 2002:a05:6000:22c2:b0:3a5:1c71:432a with SMTP id ffacd0b85a97d-3a8fe1deba9mr12962563f8f.14.1751370287140; Tue, 01 Jul 2025 04:44:47 -0700 (PDT) From: Hanna Czenczek To: qemu-block@nongnu.org Cc: qemu-devel@nongnu.org, Hanna Czenczek , Stefan Hajnoczi , Kevin Wolf , Markus Armbruster , Brian Song Subject: [PATCH v3 01/21] fuse: Copy write buffer content before polling Date: Tue, 1 Jul 2025 13:44:17 +0200 Message-ID: <20250701114437.207419-2-hreitz@redhat.com> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250701114437.207419-1-hreitz@redhat.com> References: <20250701114437.207419-1-hreitz@redhat.com> 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=170.10.129.124; envelope-from=hreitz@redhat.com; helo=us-smtp-delivery-124.mimecast.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, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1751370560962124100 Content-Type: text/plain; charset="utf-8" aio_poll() in I/O functions can lead to nested read_from_fuse_export() calls, overwriting the request buffer's content. The only function affected by this is fuse_write(), which therefore must use a bounce buffer or corruption may occur. Note that in addition we do not know whether libfuse-internal structures can cope with this nesting, and even if we did, we probably cannot rely on it in the future. This is the main reason why we want to remove libfuse from the I/O path. I do not have a good reproducer for this other than: $ dd if=3D/dev/urandom of=3Dimage bs=3D1M count=3D4096 $ dd if=3D/dev/zero of=3Dcopy bs=3D1M count=3D4096 $ touch fuse-export $ qemu-storage-daemon \ --blockdev file,node-name=3Dfile,filename=3Dcopy \ --export \ fuse,id=3Dexp,node-name=3Dfile,mountpoint=3Dfuse-export,writable=3Dtrue= \ & Other shell: $ qemu-img convert -p -n -f raw -O raw -t none image fuse-export $ killall -SIGINT qemu-storage-daemon $ qemu-img compare image copy Content mismatch at offset 0! (The -t none in qemu-img convert is important.) I tried reproducing this with throttle and small aio_write requests from another qemu-io instance, but for some reason all requests are perfectly serialized then. I think in theory we should get parallel writes only if we set fi->parallel_direct_writes in fuse_open(). In fact, I can confirm that if we do that, that throttle-based reproducer works (i.e. does get parallel (nested) write requests). I have no idea why we still get parallel requests with qemu-img convert anyway. Also, a later patch in this series will set fi->parallel_direct_writes and note that it makes basically no difference when running fio on the current libfuse-based version of our code. It does make a difference without libfuse. So something quite fishy is going on. I will try to investigate further what the root cause is, but I think for now let's assume that calling blk_pwrite() can invalidate the buffer contents through nested polling. Cc: qemu-stable@nongnu.org Reviewed-by: Stefan Hajnoczi Signed-off-by: Hanna Czenczek Reviewed-by: Kevin Wolf --- block/export/fuse.c | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/block/export/fuse.c b/block/export/fuse.c index 465cc9891d..b967e88d2b 100644 --- a/block/export/fuse.c +++ b/block/export/fuse.c @@ -301,6 +301,12 @@ static void read_from_fuse_export(void *opaque) goto out; } =20 + /* + * Note that aio_poll() in any request-processing function can lead to= a + * nested read_from_fuse_export() call, which will overwrite the conte= nts of + * exp->fuse_buf. Anything that takes a buffer needs to take care tha= t the + * content is copied before potentially polling via aio_poll(). + */ fuse_session_process_buf(exp->fuse_session, &exp->fuse_buf); =20 out: @@ -624,6 +630,7 @@ static void fuse_write(fuse_req_t req, fuse_ino_t inode= , const char *buf, size_t size, off_t offset, struct fuse_file_info *f= i) { FuseExport *exp =3D fuse_req_userdata(req); + void *copied; int64_t length; int ret; =20 @@ -638,6 +645,14 @@ static void fuse_write(fuse_req_t req, fuse_ino_t inod= e, const char *buf, return; } =20 + /* + * Heed the note on read_from_fuse_export(): If we call aio_poll() (wh= ich + * any blk_*() I/O function may do), read_from_fuse_export() may be ne= sted, + * overwriting the request buffer content. Therefore, we must copy it= here. + */ + copied =3D blk_blockalign(exp->common.blk, size); + memcpy(copied, buf, size); + /** * Clients will expect short writes at EOF, so we have to limit * offset+size to the image length. @@ -645,7 +660,7 @@ static void fuse_write(fuse_req_t req, fuse_ino_t inode= , const char *buf, length =3D blk_getlength(exp->common.blk); if (length < 0) { fuse_reply_err(req, -length); - return; + goto free_buffer; } =20 if (offset + size > length) { @@ -653,19 +668,22 @@ static void fuse_write(fuse_req_t req, fuse_ino_t ino= de, const char *buf, ret =3D fuse_do_truncate(exp, offset + size, true, PREALLOC_MO= DE_OFF); if (ret < 0) { fuse_reply_err(req, -ret); - return; + goto free_buffer; } } else { size =3D length - offset; } } =20 - ret =3D blk_pwrite(exp->common.blk, offset, size, buf, 0); + ret =3D blk_pwrite(exp->common.blk, offset, size, copied, 0); if (ret >=3D 0) { fuse_reply_write(req, size); } else { fuse_reply_err(req, -ret); } + +free_buffer: + qemu_vfree(copied); } =20 /** --=20 2.49.0 From nobody Sat Nov 15 12:14:53 2025 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=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1751370392; cv=none; d=zohomail.com; s=zohoarc; b=ISXqMDIJ+61ZKMcug36gnt18YKqZJj4jHKTccr8sscWnGWBn8XBlzkIUI5T3EVTXYFUbHVQl4zuOZ6FNoH8/+z6mI/aryk2PtYi2IMJjDgVgxSiFPTN0ws7WPyZeofv1H1r3IY27tl66E5aPxrhrzZmNbfP++wtxARs8zTUnURE= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1751370392; h=Content-Type: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=vicT1n12Q3bt43l0BKSXkJu6cLKKIkPFHwd4M2fi9jo=; b=heyIltPCrjg/UmbCLb5G00G9IJ1eGt0fJND+PMB6vbnHjVb4R0lROdTIPA94JXIbJr8OCatyMONjpbo7Xs+c9SYI5dEigmn6frcHW6LabdfBPxgjNvod2drDxOS+m488Qi5ki0/5eJ6+tBD2qXLRiqJpgHLpkNiyo6afu43mt6U= 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 lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1751370392731230.62450392909727; Tue, 1 Jul 2025 04:46:32 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1uWZQI-0005Dv-Cl; Tue, 01 Jul 2025 07:45:14 -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 1uWZQ9-0005AY-7p for qemu-devel@nongnu.org; Tue, 01 Jul 2025 07:45:06 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uWZPy-0003F7-Q3 for qemu-devel@nongnu.org; Tue, 01 Jul 2025 07:45:04 -0400 Received: from mail-wm1-f69.google.com (mail-wm1-f69.google.com [209.85.128.69]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-400-3AUkznmzNfKKaEhcs2JBDQ-1; Tue, 01 Jul 2025 07:44:51 -0400 Received: by mail-wm1-f69.google.com with SMTP id 5b1f17b1804b1-45311704d22so22759865e9.2 for ; Tue, 01 Jul 2025 04:44:51 -0700 (PDT) Received: from localhost (p200300cfd700f38d3df6a1ca7d40fe1f.dip0.t-ipconnect.de. [2003:cf:d700:f38d:3df6:a1ca:7d40:fe1f]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4538233c49fsm192090365e9.7.2025.07.01.04.44.47 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 01 Jul 2025 04:44:48 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1751370293; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=vicT1n12Q3bt43l0BKSXkJu6cLKKIkPFHwd4M2fi9jo=; b=R9qCZ0APZihsCo14WpIxZ7GApYV1EdjOlTDWmQBUroZ9pehQV0W+pynxhVzWL5vIqegqHl 4BhX/lsb9MCjHmWg5+cvVM/jxDfsUw86sllb7zpdkIyJG76nU2suI+EQpb1qHD/Lmdo5Es bVNLgBUkl1YLdDZ31KAhPoVRsneijsM= X-MC-Unique: 3AUkznmzNfKKaEhcs2JBDQ-1 X-Mimecast-MFC-AGG-ID: 3AUkznmzNfKKaEhcs2JBDQ_1751370291 X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1751370290; x=1751975090; 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=vicT1n12Q3bt43l0BKSXkJu6cLKKIkPFHwd4M2fi9jo=; b=SIQtCcbGWobvPXxXtSbP/RKP6Y6Ub+RIi3fj1kvRyuc3LzC7ygkIpxMtVV+NIjEaTc 3IrP9p8Yo4dmmaMtJBxji47iGIoTXbvNbOrd4XEXls0l7lvHwL/GtseYkOrzP80v6F0d Lz6CrbnGGmnACp5PlUnCTKaQPysHDP9eF6hvnsGvLclX1/dVsZwNqckbwr7XJG9y5i61 XuqAuKDz3WlglVaxfEGgsdd6ag+tfiXlEOCfVz/X17tUbcdjnJdVZyzEyhDHBUdKOQFd wBh2tBr6Cyb2FWlEm5O5HIf+u3v2vUL4+/H/lv3pSh2ffU2KQC/WN+KcY3+pdV2UY3HX SKjw== X-Gm-Message-State: AOJu0YxvLxQn/Vp4PKxAG2BZyyo0lxe7pgtVpTIiqeqs8B8Rf9v+4mBM OEX39aNSSWQGm2YBZQGyVDJ2VRH45LKvsDiuzHqs2PhcE6I75VBj0fqIIVYPfMhu4yYkZ8008kI c+HTqjxeIpOXW1lO+8bM88fRaInUli3pAbonwdVc8uOmMyMwgPCvoQfYV X-Gm-Gg: ASbGncsvjCzK0O1M13l/NErCCNAoY+3uwqScee5kkkKRZk2zRrzpURGLm5mobeo7TZJ uEdRyHaZcmmv/jjqQfLd0FdNge8QpEAqaxfpwnCgPAFzcY2GNWAMs/3IahmHCiXOiA6shXPFHLv LTd6Yaw6Jv3iRyAiA6oJBeJkDeYXFhQIxIhtoWlidrQg7FzQkVmjEyN4snLcU4/8KqOKnswsnf3 AJlfmemrrJdlJqZPo4I7G/o12iq9QE1FE4Z+XjFfM2aWy3NL9a6rCAB5VKMjqhRmM/zaFjBE1f9 qvckzsrnb7rqlYXdj1yjYb4AV8CVWwnQRNhqxsoYRl/bjmtOdDYWzx/Z7HLaBcEFoFgbjaGwGdb WQ3Un X-Received: by 2002:a05:600c:138d:b0:442:f482:c429 with SMTP id 5b1f17b1804b1-453a84069b7mr26196255e9.8.1751370290492; Tue, 01 Jul 2025 04:44:50 -0700 (PDT) X-Google-Smtp-Source: AGHT+IH/KSSaExI7tSriJSKh3CJ+W2i4cwOnH2U7DfkF2usMOGbDo55o7tUhWNC/XHbKk+nII1a6UA== X-Received: by 2002:a05:600c:138d:b0:442:f482:c429 with SMTP id 5b1f17b1804b1-453a84069b7mr26195905e9.8.1751370289969; Tue, 01 Jul 2025 04:44:49 -0700 (PDT) From: Hanna Czenczek To: qemu-block@nongnu.org Cc: qemu-devel@nongnu.org, Hanna Czenczek , Stefan Hajnoczi , Kevin Wolf , Markus Armbruster , Brian Song Subject: [PATCH v3 02/21] fuse: Ensure init clean-up even with error_fatal Date: Tue, 1 Jul 2025 13:44:18 +0200 Message-ID: <20250701114437.207419-3-hreitz@redhat.com> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250701114437.207419-1-hreitz@redhat.com> References: <20250701114437.207419-1-hreitz@redhat.com> 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=170.10.133.124; envelope-from=hreitz@redhat.com; helo=us-smtp-delivery-124.mimecast.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, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=unavailable autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1751370398556116600 Content-Type: text/plain; charset="utf-8" When exports are created on the command line (with the storage daemon), errp is going to point to error_fatal. Without ERRP_GUARD, we would exit immediately when *errp is set, i.e. skip the clean-up code under the `fail` label. Use ERRP_GUARD so we always run that code. As far as I know, this has no actual impact right now[1], but it is still better to make this right. [1] Not cleaning up the mount point is the only thing I can imagine would be problematic, but that is the last thing we attempt, so if it fails, it will clean itself up. Reviewed-by: Stefan Hajnoczi Signed-off-by: Hanna Czenczek --- block/export/fuse.c | 1 + 1 file changed, 1 insertion(+) diff --git a/block/export/fuse.c b/block/export/fuse.c index b967e88d2b..b224ce591d 100644 --- a/block/export/fuse.c +++ b/block/export/fuse.c @@ -119,6 +119,7 @@ static int fuse_export_create(BlockExport *blk_exp, BlockExportOptions *blk_exp_args, Error **errp) { + ERRP_GUARD(); /* ensure clean-up even with error_fatal */ FuseExport *exp =3D container_of(blk_exp, FuseExport, common); BlockExportOptionsFuse *args =3D &blk_exp_args->u.fuse; int ret; --=20 2.49.0 From nobody Sat Nov 15 12:14:53 2025 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=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1751370546; cv=none; d=zohomail.com; s=zohoarc; b=OD23Uayq6bfSk+COCmZc2uGE4vt8ei7SuSu6KzQaAfiArVBSA7Nh5YXGbU71U9NpY8tYGkDoq/G7PlAZIbL825EDD/MA6Xa8hUmKm+oGxsz/vf/NQ+LNuWh+QrOUJGG1zgCfi/uxSCkiUjRSFEqBerJkNK94FTQb72IXijjeW/g= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1751370546; h=Content-Type: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=Xnb6fY77tTZ5nf3Ugq1ke10+nz2hG2kWSwmOHbAyR9g=; b=Ks0wbKSiHa8zgDOdIYvszZ+uTrtBSni08fOYyvYwoK4PYWBFBB3udOZk/KC3UA/lZxm/9+T+ONw7lh/d93jOfUlOnPrkZKr9qHmWp7iUQt+70PNLwPEaF9Qzp2FshhkFOAKsfuY0T+K4yliV8/aJ/uYcTmw74/HyayngkOoEBF4= 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 lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1751370546463543.1878671871208; Tue, 1 Jul 2025 04:49:06 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1uWZQE-0005CP-2B; Tue, 01 Jul 2025 07:45:10 -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 1uWZQ6-00059p-5r for qemu-devel@nongnu.org; Tue, 01 Jul 2025 07:45:02 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uWZQ2-0003Fd-6f for qemu-devel@nongnu.org; Tue, 01 Jul 2025 07:45:01 -0400 Received: from mail-wr1-f69.google.com (mail-wr1-f69.google.com [209.85.221.69]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-519-6r_JqRcGM7-JECYHY1dCiw-1; Tue, 01 Jul 2025 07:44:55 -0400 Received: by mail-wr1-f69.google.com with SMTP id ffacd0b85a97d-3a4f7ebfd00so2808055f8f.2 for ; Tue, 01 Jul 2025 04:44:54 -0700 (PDT) Received: from localhost (p200300cfd700f38d3df6a1ca7d40fe1f.dip0.t-ipconnect.de. [2003:cf:d700:f38d:3df6:a1ca:7d40:fe1f]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-3a892e5f92esm13149118f8f.90.2025.07.01.04.44.50 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 01 Jul 2025 04:44:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1751370296; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=Xnb6fY77tTZ5nf3Ugq1ke10+nz2hG2kWSwmOHbAyR9g=; b=F9mtPScTMHzlq0gd5Lef7arunFOoxIxhqPI97LJfbSsOxTcJtNaCU2zO37PDU82NUqrMvI h5+/ZKBkxgLybNnW1R4a6jw8kyUvh3nfN/Mk2LF8UFiVUZUVdf2n7qUQYkKZIOVYnWZC/t /K0JmRcyd8gXnDoNC2Jkw3V2g1grKBQ= X-MC-Unique: 6r_JqRcGM7-JECYHY1dCiw-1 X-Mimecast-MFC-AGG-ID: 6r_JqRcGM7-JECYHY1dCiw_1751370294 X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1751370294; x=1751975094; 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=Xnb6fY77tTZ5nf3Ugq1ke10+nz2hG2kWSwmOHbAyR9g=; b=H6lpwCFtbYDenPfln1MWKMvxfLaS9pBXrh2JRHj8mZ2fwwqG6w0d2tKsF+cMwAvzL5 53Kc4a0D4sa9neUbiGl//LLzBDhVXi0cGmi2JUhyYQQPJXrytW6u7AkwfYfNZ/KxHm4K eiZBYXeyF4C5pynDIVyGC2BQxj9axZ1P1MQSb2eo+/CYoZ/8jbbHjRgpmaeuZitRvYOq P+GiII7qCjPGuxXAQFVb52AvhLAHVVDe8cxRasmVVdPIKgrqIc3l2hL/JrXWG3EqvjbI DmMXcM1jNy0l+l1WIHT28aRUiPAkomlvD9flYOqmO4B34eyb9Jjrsn6G/erKs+6m/ddU 9Baw== X-Gm-Message-State: AOJu0YxTvooY56NHLDJtsTpnFAjYiGy5XDnnf1irSC9LCy6t5/xwaUdM qe5UaCU1inxE2M3I0KQvzcxVGG0vTIgk9BPFhPybS3RSY/BXOJtRQ0hCycS8rfbWpIqz0pkQcyr Wij292czg0gjGs/+Xh+KAmNVvgmx+A6cDGDz12KSGf+NoTz/2SU2AQLsf X-Gm-Gg: ASbGncvtaRiNf64XJ0M959kdr/l6Cwo7gBbbVsIWmnIbVPLMzGVIx6mzQOu/SEvvdIx MCCycglIFeSJTrDwUEcHctrZ3cX78s9KYNxHBVK5gFd/YUGEWxpqk0jshJ8JOkfU9y+TRFaCMPk gzrfgGO07BNlY0gIfom/b3yYrH3VI24NiTzAej4S2/SGT3EjJGeS1+e1JqD5O/6oIltUny9tvSl EXrqyUodU7Q2ydipbtzDqw50dDTlLoTxfahgfRI0Wdh9Uz6PxslcHYKWC+4lb9v3NBK0cIQeRLq sdFZ2UDLNAkreI4slMjQd3KBfWjW+lVr0Y+RL+/7h4iBVRwdaMfY6f3ycchO3oCkG7hXLWNmJWB YZ9+6 X-Received: by 2002:a05:6000:25e8:b0:3a4:e8c4:7a78 with SMTP id ffacd0b85a97d-3a90bc9e3eamr12601742f8f.52.1751370293822; Tue, 01 Jul 2025 04:44:53 -0700 (PDT) X-Google-Smtp-Source: AGHT+IFSNOWJQyimuD7LPvKUBTfe6V4kPOXuANgbtrBAWCiOMYuVHrcDGYZwRx4dbM251wKQUMI4UQ== X-Received: by 2002:a05:6000:25e8:b0:3a4:e8c4:7a78 with SMTP id ffacd0b85a97d-3a90bc9e3eamr12601722f8f.52.1751370293379; Tue, 01 Jul 2025 04:44:53 -0700 (PDT) From: Hanna Czenczek To: qemu-block@nongnu.org Cc: qemu-devel@nongnu.org, Hanna Czenczek , Stefan Hajnoczi , Kevin Wolf , Markus Armbruster , Brian Song Subject: [PATCH v3 03/21] fuse: Remove superfluous empty line Date: Tue, 1 Jul 2025 13:44:19 +0200 Message-ID: <20250701114437.207419-4-hreitz@redhat.com> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250701114437.207419-1-hreitz@redhat.com> References: <20250701114437.207419-1-hreitz@redhat.com> 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=170.10.129.124; envelope-from=hreitz@redhat.com; helo=us-smtp-delivery-124.mimecast.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, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1751370550518124100 Content-Type: text/plain; charset="utf-8" Reviewed-by: Stefan Hajnoczi Signed-off-by: Hanna Czenczek --- block/export/fuse.c | 1 - 1 file changed, 1 deletion(-) diff --git a/block/export/fuse.c b/block/export/fuse.c index b224ce591d..a93316e1f4 100644 --- a/block/export/fuse.c +++ b/block/export/fuse.c @@ -464,7 +464,6 @@ static int fuse_do_truncate(const FuseExport *exp, int6= 4_t size, } =20 if (add_resize_perm) { - if (!qemu_in_main_thread()) { /* Changing permissions like below only works in the main thre= ad */ return -EPERM; --=20 2.49.0 From nobody Sat Nov 15 12:14:53 2025 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=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1751370446; cv=none; d=zohomail.com; s=zohoarc; b=Kd1htoGqkOEIyH/zqHA9vr5LtLIASQiT5Riv6+7zraJdBM9EUFMIjUzSFfMpAak/b6Dz88+8c7AvqQehA011kl3V/m543gHQ0CG8ayCe0MXsXOQGXinoCr0zim/XG4yztKxEO5F7ETZ6X8JdKU1TuG2AZmp+xSbI/kgmzaxowqQ= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1751370446; h=Content-Type: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=7vKpmgPjmhYXTuu7BvlQEe4nDt+V2FcjCdZIcprXjuI=; b=m/P8bsegITQygUNdcCWz4JaUCQLX2bPU3wAsyN9TjDQneCbC0G8YHDdBiyIDJ+3BYaDPhXMNQD8UuUN7xHVGOaIG3NnIXX/LL5jC3mnlI5XdXJsyHHPG7rOgfhwL2/YutU/0VzQ+Z1sNtu40k1vBx/1DzlqHkyK++9YuCynbDR8= 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 lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1751370446395849.8370419127529; Tue, 1 Jul 2025 04:47:26 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1uWZQE-0005Cj-QU; Tue, 01 Jul 2025 07:45:10 -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 1uWZQA-0005Ay-QG for qemu-devel@nongnu.org; Tue, 01 Jul 2025 07:45:07 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uWZQ7-0003Gn-7u for qemu-devel@nongnu.org; Tue, 01 Jul 2025 07:45:06 -0400 Received: from mail-wm1-f70.google.com (mail-wm1-f70.google.com [209.85.128.70]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-284-X4mlzZbNMVCjoQ7-8TznqA-1; Tue, 01 Jul 2025 07:45:00 -0400 Received: by mail-wm1-f70.google.com with SMTP id 5b1f17b1804b1-453a190819bso13754785e9.1 for ; Tue, 01 Jul 2025 04:44:59 -0700 (PDT) Received: from localhost (p200300cfd700f38d3df6a1ca7d40fe1f.dip0.t-ipconnect.de. [2003:cf:d700:f38d:3df6:a1ca:7d40:fe1f]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-453823ad0fesm198409125e9.25.2025.07.01.04.44.54 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 01 Jul 2025 04:44:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1751370301; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=7vKpmgPjmhYXTuu7BvlQEe4nDt+V2FcjCdZIcprXjuI=; b=DnLKSwc0yc0Njdd+XFQuzZpODYkbj9gVOG5utZ12UBbj6+jvQbCpDbVCDnsmBywJD5acTU W5XkGPe8urDnydGCmeEnGI15BoIs3JWpJIxu7nylkXQD6uGASJfDKM4MhJvimj4lzbt5Ug WWab1GmBkcy/EqysOH6WvKwr7Laq2Ck= X-MC-Unique: X4mlzZbNMVCjoQ7-8TznqA-1 X-Mimecast-MFC-AGG-ID: X4mlzZbNMVCjoQ7-8TznqA_1751370299 X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1751370296; x=1751975096; 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=7vKpmgPjmhYXTuu7BvlQEe4nDt+V2FcjCdZIcprXjuI=; b=lhUqJ1t5+5tNf9SZtq5nU4miSgC2bDXLG37GdsEyrdEYs3TG2r0pKMPw6PJa2k33K4 GZ/YBVlGh5fvgWLxufqVWX9RvogwoDavBs1mlqQCi3zX15bSiCbwszK7SUR0aTA4FMG8 ajLrzWg35QeD9k7ZUMq/NZGXcZ2/AcVXHxsIXTid51TYaL5rAzSxbxpu8gBwxWIXlrY5 YZo18/+uSBJlpH1YtUFtQ53xg5jTkn1uChkeGuL9MnDj8sO//WrosO/hrC0SbxU4JxFy U/tFOXcO1EwHVEN7caRvg0+TqPs9aKSvd/vVWxyn8Qro94w1TnScPN07BrdhF9LyEOHI HvOQ== X-Gm-Message-State: AOJu0YzZDuUyOV4F//zQZNhea5zg4NiMXjgNL3KRjzC7elsQaj1Ucg5w oFTMYiy17qdFDzj5f8zpqZokSxqtXuuCqLoVWpo5vFDAeo8e8hxw14VC3oL3LiYHCcm/mpKnjVh iFfc2fndyg8oNbu/nxBN5qNi7qajBgs8xEAQTOQI+qBRLtibDaYTf+IDKkkDg5nUG X-Gm-Gg: ASbGncsgiNJd2+Y9RLvOnUuzLv5CDbT3IymWt4zwFTHq/Un/M4zlVLSHwSm1okJ7/Ig edPoKu8zlQHR/GF0cU7MBGhrOoWqfS4/MihUSLY8P9qg9Ne/JZPM6XrRekX/KB3c6MEsd6mJ6SR BRDoMcY2rl2qvVu3t3cRwd39u8jtQjVkX969ben1jvKj2a19VN2Z1PsEuO2+StabBtmHBSOLJTa iQJL80n6DpOKBTneoA31qXwN1znhfy745THbrEXjX7sfVK4uvMiWtviRLT5N+KFEIPy8r6qYhTA yCptF7t/q6pJ8NC0Ocz0iClqFN0A/iIu+l6RScRwm8FIf+iyk2uW7WuelrFJs+EBK/IEKyvlqys UQJwK X-Received: by 2002:a05:600c:8709:b0:453:d3d:d9fd with SMTP id 5b1f17b1804b1-4538ee2786dmr171246055e9.12.1751370296493; Tue, 01 Jul 2025 04:44:56 -0700 (PDT) X-Google-Smtp-Source: AGHT+IGFnVhx8+S9QGIssPmVdFf2ggMvJmYrd9b7sgyt89dbVdhE/K2xro+o+esmdMZUNda9jdmdag== X-Received: by 2002:a05:600c:8709:b0:453:d3d:d9fd with SMTP id 5b1f17b1804b1-4538ee2786dmr171245865e9.12.1751370296118; Tue, 01 Jul 2025 04:44:56 -0700 (PDT) From: Hanna Czenczek To: qemu-block@nongnu.org Cc: qemu-devel@nongnu.org, Hanna Czenczek , Stefan Hajnoczi , Kevin Wolf , Markus Armbruster , Brian Song Subject: [PATCH v3 04/21] fuse: Explicitly set inode ID to 1 Date: Tue, 1 Jul 2025 13:44:20 +0200 Message-ID: <20250701114437.207419-5-hreitz@redhat.com> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250701114437.207419-1-hreitz@redhat.com> References: <20250701114437.207419-1-hreitz@redhat.com> 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=170.10.133.124; envelope-from=hreitz@redhat.com; helo=us-smtp-delivery-124.mimecast.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, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1751370447228116600 Content-Type: text/plain; charset="utf-8" Setting .st_ino to the FUSE inode ID is kind of arbitrary. While in practice it is going to be fixed (to FUSE_ROOT_ID, which is 1) because we only have the root inode, that is not obvious in fuse_getattr(). Just explicitly set it to 1 (i.e. no functional change). Reviewed-by: Stefan Hajnoczi Signed-off-by: Hanna Czenczek --- block/export/fuse.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/block/export/fuse.c b/block/export/fuse.c index a93316e1f4..60d68d8fdd 100644 --- a/block/export/fuse.c +++ b/block/export/fuse.c @@ -432,7 +432,7 @@ static void fuse_getattr(fuse_req_t req, fuse_ino_t ino= de, } =20 statbuf =3D (struct stat) { - .st_ino =3D inode, + .st_ino =3D 1, .st_mode =3D exp->st_mode, .st_nlink =3D 1, .st_uid =3D exp->st_uid, --=20 2.49.0 From nobody Sat Nov 15 12:14:53 2025 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=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1751370485; cv=none; d=zohomail.com; s=zohoarc; b=UhD0lnhNiHI86w4P36epTNabtgQihIkCYQ/pOC7xX2/6IMc+m0CQgU44S07DthHHu0VOVdYNATjR25hToclVtkwo+V7KeUgz9I0Ql8irGjwDqEZSjAZ2CA4DtiDkT1Yf6rPeGbw2y7KxW513EvX1IrMDasEoGJLmf0tVrJkeVjY= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1751370485; h=Content-Type: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=VhSz5JkY5LLfO9JP0DfYyzUrOP4ozA4C0+gHoyFHmps=; b=W5K1WsopzKLkBWV8e7CpeNyTnuHn5bMXxICQ+oqeKVSrVOPuw2UW9zf+Ui+Dm2vjRAdMo72t0ekn+ubWzv7uBw7yotCPwdZUlARK01vhJEqQDWEgdHeXJSTMdXn9lWw94tYMS6SjuuPkDIsHvRUSN+tvHfCG09QTycj5b9OqSPs= 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 lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1751370485841482.7523916921999; Tue, 1 Jul 2025 04:48:05 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1uWZQI-0005Fo-Q4; Tue, 01 Jul 2025 07:45:14 -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 1uWZQB-0005BZ-Hl for qemu-devel@nongnu.org; Tue, 01 Jul 2025 07:45:08 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uWZQ8-0003H3-K0 for qemu-devel@nongnu.org; Tue, 01 Jul 2025 07:45:07 -0400 Received: from mail-wr1-f71.google.com (mail-wr1-f71.google.com [209.85.221.71]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-371-uzNVJGa2PEWTrAYqB2Jc7g-1; Tue, 01 Jul 2025 07:45:01 -0400 Received: by mail-wr1-f71.google.com with SMTP id ffacd0b85a97d-3a3696a0d3aso1464747f8f.2 for ; Tue, 01 Jul 2025 04:45:00 -0700 (PDT) Received: from localhost (p200300cfd700f38d3df6a1ca7d40fe1f.dip0.t-ipconnect.de. [2003:cf:d700:f38d:3df6:a1ca:7d40:fe1f]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-3a892e5963csm13041023f8f.79.2025.07.01.04.44.57 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 01 Jul 2025 04:44:57 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1751370302; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=VhSz5JkY5LLfO9JP0DfYyzUrOP4ozA4C0+gHoyFHmps=; b=Vqc7y5O3z3gtT5lE44aKUPdf0C5xp/oe+o2e7aFxJI++EPdlBa3hM34+tU46AmaFJwO17p EFGuvbxVpQYjMiHaVKkiMA5Pizi1PthaLgGRa49dbQP++uBKC4ZzGMsJZPhQFMXWZtgW9j PeFHI0xngFA5kCxVY9hSZunZvLx9UkQ= X-MC-Unique: uzNVJGa2PEWTrAYqB2Jc7g-1 X-Mimecast-MFC-AGG-ID: uzNVJGa2PEWTrAYqB2Jc7g_1751370300 X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1751370299; x=1751975099; 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=VhSz5JkY5LLfO9JP0DfYyzUrOP4ozA4C0+gHoyFHmps=; b=DSufQhPMfBKFE6GXdzQ+NwQy/1GHQa7uuAXilEzyj7kKZk5U8u+yxH8l0x/X7saOin E6mYVOEx2Bqbyv3Co3/njlybH/F8pN5GhCM/MYfFg7xqOn029YNx7jYMu5kloS5AUSpO 9uDygcMIrrQRluSj/HIo/4Uh/uTOPpg/thAhujKmj7XkFrmQf17W2J2QUUDfXeDcG2oB aEJfTfKn7dI8mZPPe4RvHYZke6olq4G3s2rME7sQezHjY47AmJKA6tQWj/3zN8l18OPP EinkAVReeMcx+WPwMPvJ7UqfN9eD8Zb1s5Gj8thRYMRvmG/L2i+6DuwWkh9gyLWzAsg7 NRbg== X-Gm-Message-State: AOJu0YzZHhiLH4Kv2RMKfyu7Ec25iYVu2JlCnfx6i/tLn3uwR+n8rZTa M0LIt2IUmTZpi5KjcXb5jMSe5r5gTVTuH222yqhLkmgXN4ei8srQzoTqKdC9MUrtKCQE2ArKPao V9EmgcZ9nJ/7lLDQFRjf8ZAScxgTRGQKkkhSfpeH22/dUYGs1GizgyZQp X-Gm-Gg: ASbGncsNnRCx9yDReAPUi/K1jQAI6XD8BTvyhb5dwCCooUmt5HW8SCCigb8RzA71VVd AgHZPsqoI9CrFRAQbxtAdss2buMXmGxZu2YB8c7h3uKN1Votx1uc/ElFR+OjjPGcwAh5LQsX6mh VMMlFH8uyTVBE1Q9Mnt7QsQSFnmAK9JJunx+CdMVWXXPhynx2UWabjnP22YfNeF+XG2R26oTg2y 49pbWNOAfkX384u9SQzAWeObjhxinh2HvqyAmKrtdIAiVvwN3kqPe9fo9/isfouQLcioWYfzHfz MdJ3pVVsm1+pbeiBMkiSW0uNzdPseG8ois3NOuLEbBTBZijA+wF6kJKuDzWysdwVvFhgUEGzlpV a8iD+ X-Received: by 2002:a05:6000:2b09:b0:3a5:2cb5:642f with SMTP id ffacd0b85a97d-3a8fe5b1d4dmr8934138f8f.34.1751370299357; Tue, 01 Jul 2025 04:44:59 -0700 (PDT) X-Google-Smtp-Source: AGHT+IFSum46C+sIOIctlh83vD/7gJP3Uw8Y5RQY+cY8sucAuXy+g5PqLHUlhMDYGnEjEVVgSLjtwg== X-Received: by 2002:a05:6000:2b09:b0:3a5:2cb5:642f with SMTP id ffacd0b85a97d-3a8fe5b1d4dmr8934123f8f.34.1751370298879; Tue, 01 Jul 2025 04:44:58 -0700 (PDT) From: Hanna Czenczek To: qemu-block@nongnu.org Cc: qemu-devel@nongnu.org, Hanna Czenczek , Stefan Hajnoczi , Kevin Wolf , Markus Armbruster , Brian Song Subject: [PATCH v3 05/21] fuse: Change setup_... to mount_fuse_export() Date: Tue, 1 Jul 2025 13:44:21 +0200 Message-ID: <20250701114437.207419-6-hreitz@redhat.com> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250701114437.207419-1-hreitz@redhat.com> References: <20250701114437.207419-1-hreitz@redhat.com> 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=170.10.129.124; envelope-from=hreitz@redhat.com; helo=us-smtp-delivery-124.mimecast.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, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1751370487781116600 Content-Type: text/plain; charset="utf-8" There is no clear separation between what should go into setup_fuse_export() and what should stay in fuse_export_create(). Make it clear that setup_fuse_export() is for mounting only. Rename it, and move everything that has nothing to do with mounting up into fuse_export_create(). Reviewed-by: Stefan Hajnoczi Signed-off-by: Hanna Czenczek --- block/export/fuse.c | 49 ++++++++++++++++++++------------------------- 1 file changed, 22 insertions(+), 27 deletions(-) diff --git a/block/export/fuse.c b/block/export/fuse.c index 60d68d8fdd..01a5716bdd 100644 --- a/block/export/fuse.c +++ b/block/export/fuse.c @@ -72,8 +72,7 @@ static void fuse_export_delete(BlockExport *exp); =20 static void init_exports_table(void); =20 -static int setup_fuse_export(FuseExport *exp, const char *mountpoint, - bool allow_other, Error **errp); +static int mount_fuse_export(FuseExport *exp, Error **errp); static void read_from_fuse_export(void *opaque); =20 static bool is_regular_file(const char *path, Error **errp); @@ -193,23 +192,32 @@ static int fuse_export_create(BlockExport *blk_exp, exp->st_gid =3D getgid(); =20 if (args->allow_other =3D=3D FUSE_EXPORT_ALLOW_OTHER_AUTO) { - /* Ignore errors on our first attempt */ - ret =3D setup_fuse_export(exp, args->mountpoint, true, NULL); - exp->allow_other =3D ret =3D=3D 0; + /* Try allow_other =3D=3D true first, ignore errors */ + exp->allow_other =3D true; + ret =3D mount_fuse_export(exp, NULL); if (ret < 0) { - ret =3D setup_fuse_export(exp, args->mountpoint, false, errp); + exp->allow_other =3D false; + ret =3D mount_fuse_export(exp, errp); } } else { exp->allow_other =3D args->allow_other =3D=3D FUSE_EXPORT_ALLOW_OT= HER_ON; - ret =3D setup_fuse_export(exp, args->mountpoint, exp->allow_other,= errp); + ret =3D mount_fuse_export(exp, errp); } if (ret < 0) { goto fail; } =20 + g_hash_table_insert(exports, g_strdup(exp->mountpoint), NULL); + + aio_set_fd_handler(exp->common.ctx, + fuse_session_fd(exp->fuse_session), + read_from_fuse_export, NULL, NULL, NULL, exp); + exp->fd_handler_set_up =3D true; + return 0; =20 fail: + fuse_export_shutdown(blk_exp); fuse_export_delete(blk_exp); return ret; } @@ -227,10 +235,10 @@ static void init_exports_table(void) } =20 /** - * Create exp->fuse_session and mount it. + * Create exp->fuse_session and mount it. Expects exp->mountpoint, + * exp->writable, and exp->allow_other to be set as intended for the mount. */ -static int setup_fuse_export(FuseExport *exp, const char *mountpoint, - bool allow_other, Error **errp) +static int mount_fuse_export(FuseExport *exp, Error **errp) { const char *fuse_argv[4]; char *mount_opts; @@ -243,7 +251,7 @@ static int setup_fuse_export(FuseExport *exp, const cha= r *mountpoint, */ mount_opts =3D g_strdup_printf("max_read=3D%zu,default_permissions%s", FUSE_MAX_BOUNCE_BYTES, - allow_other ? ",allow_other" : ""); + exp->allow_other ? ",allow_other" : ""); =20 fuse_argv[0] =3D ""; /* Dummy program name */ fuse_argv[1] =3D "-o"; @@ -256,30 +264,17 @@ static int setup_fuse_export(FuseExport *exp, const c= har *mountpoint, g_free(mount_opts); if (!exp->fuse_session) { error_setg(errp, "Failed to set up FUSE session"); - ret =3D -EIO; - goto fail; + return -EIO; } =20 - ret =3D fuse_session_mount(exp->fuse_session, mountpoint); + ret =3D fuse_session_mount(exp->fuse_session, exp->mountpoint); if (ret < 0) { error_setg(errp, "Failed to mount FUSE session to export"); - ret =3D -EIO; - goto fail; + return -EIO; } exp->mounted =3D true; =20 - g_hash_table_insert(exports, g_strdup(mountpoint), NULL); - - aio_set_fd_handler(exp->common.ctx, - fuse_session_fd(exp->fuse_session), - read_from_fuse_export, NULL, NULL, NULL, exp); - exp->fd_handler_set_up =3D true; - return 0; - -fail: - fuse_export_shutdown(&exp->common); - return ret; } =20 /** --=20 2.49.0 From nobody Sat Nov 15 12:14:53 2025 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=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1751370469; cv=none; d=zohomail.com; s=zohoarc; b=J27+eOIVylYZSJXJNhQRqpsLFLv6V1yXiy09/ltHXCxS79iftj/HaKd0biK8r1/CZss5XZPtV5hpfMYOc/j4He1oLJZpn5GEWgtoxCHYUFQau6SQNJPVEd1C0bG2hiZdiQ+52x9H8ejv23Ah/Azsv8VGc5Gxjq15khQ6Ez/vWlI= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1751370469; h=Content-Type: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=Y7T0WUQX6dKp3F4OQGLY2PFpVPrz9o7a5DFL8e21WBo=; b=PBXXnzAhM3+SbpJHx7D3tm0ZBUMoxdUJ0iT8h7/Q1Q/HRUkwo9PFHs6Y5FklVF8s+QWayz7KmFz7tjogUg5a/cR4y5zQMU5qfhuFxCc2MrN4StaSWeRQvaBGi9hqp2nCHTgV0INS4bF7I2rQf7Ryw8YolDiYU8gnHKtszrc86Rs= 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 lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1751370469453534.9805730169056; Tue, 1 Jul 2025 04:47:49 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1uWZQM-0005Hj-MQ; Tue, 01 Jul 2025 07:45:19 -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 1uWZQI-0005Fk-Jk for qemu-devel@nongnu.org; Tue, 01 Jul 2025 07:45:14 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uWZQA-0003Se-Sq for qemu-devel@nongnu.org; Tue, 01 Jul 2025 07:45:13 -0400 Received: from mail-wm1-f72.google.com (mail-wm1-f72.google.com [209.85.128.72]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-550-V8hCM8NpMNaiEQKb4kF5-Q-1; Tue, 01 Jul 2025 07:45:04 -0400 Received: by mail-wm1-f72.google.com with SMTP id 5b1f17b1804b1-450de98b28eso30671895e9.0 for ; Tue, 01 Jul 2025 04:45:04 -0700 (PDT) Received: from localhost (p200300cfd700f38d3df6a1ca7d40fe1f.dip0.t-ipconnect.de. [2003:cf:d700:f38d:3df6:a1ca:7d40:fe1f]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-3a88c80b5a3sm12899457f8f.40.2025.07.01.04.44.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 01 Jul 2025 04:45:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1751370305; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=Y7T0WUQX6dKp3F4OQGLY2PFpVPrz9o7a5DFL8e21WBo=; b=LrnBlQuf698UQERNPmA5JeKPPHmQwqZxY5Xkc2JR8gnO5tt8Ghh8+LOrXs2ZC7zpjWwaCb 1ZXKMuIrIk/X5/+w1lNrGaDlhSTqfmRUeF7oXXicPiy5svMJ3R9iU1BjxgKqvc7VwB+KrB oS4i/2es7QLNGqfufyZoNA98bZSKQMg= X-MC-Unique: V8hCM8NpMNaiEQKb4kF5-Q-1 X-Mimecast-MFC-AGG-ID: V8hCM8NpMNaiEQKb4kF5-Q_1751370303 X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1751370303; x=1751975103; 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=Y7T0WUQX6dKp3F4OQGLY2PFpVPrz9o7a5DFL8e21WBo=; b=RovdqRIWQPQEi+PUCk4atP9IdhwKMfVhWzJv7CYPAl94kB5ya3TF6DU5xvqNuuoVgb Ww/tsP6rUuHV/71/sfQpPWDicj03O167DVotRIDKZ+YCap9BsRv2WYDUPOVXsOfp5IZu w0FWm2BPbnx69vLJDXCbpexe8OnYzo9URVbWXCIbp+NR0Sf4VMXbsTB/2l/5kZlN4e8f KWwDN2mRaYcwY4wW/MDTM0iOHYAQ5lsPEyKgOYNzrThSdICO3MPJldlAH84RqF+YSvYm NFLyl9v3IrrTswyxz2ecJ0M7MnLvd7DRFJzFTY0tesbhuWvG+KXpeD0H0Iu0Fs8u6Dc0 JE6w== X-Gm-Message-State: AOJu0YyjeWbLGJNYThISoKxCPElAfMnIg551p3+Ops+Gh8tdwzTyTnxN /rVh2RHweDTPI3gCrMxenCrHj6C5KEAterj6DjI4Xgrezz3uN+lQQHb6QrjxjncGezTf7SgIX/F AlwuZ66IBekLxytXqotwnWLAyuMaTbqYUVQ+Nfv6VXL914A92hZq+Sm5H X-Gm-Gg: ASbGncsUfE2/lvvIkb1vcjaOHyUQz4ZkYXcy9hwqre6o78gUb1NQH/eVS15i3goxY5X JrbZO5XdhjV5o2CaC6jAKmgfn3Fxrm5n5Dx5vYsiosCxgsJzOrG3r8Is4qIYGEyPo/kwWau0poo kr2NSJdL/Ly0O+UlqH4N94UQbnYPx5peOo0KOolHHgArrTr8KGcGACYP+N6t1FPF4uCmEhLpBtC JibgBmkRc4eDFbld5ndc0BS8hy6bWvX2Lxm8O9Rg5EgCGmLmL793o6WxwSj6rVqZQiWBWZ5ge3r GdgyQGUupGTrU4ZgSEacemYu7nOQQkxvk77De8kJqtq+7vqhFd7qMZCgGHALsLkJcK0THkiCMIW yNXgP X-Received: by 2002:a05:6000:4603:b0:3a5:23c6:eeee with SMTP id ffacd0b85a97d-3afb0247991mr1961373f8f.21.1751370303153; Tue, 01 Jul 2025 04:45:03 -0700 (PDT) X-Google-Smtp-Source: AGHT+IGmjBvzQ/5k50VZZc5Jyr7+TLPvBxhbHjQhsPVZGTVtF2xObUsjRv7C1LPflqlKzQyj2hqjtg== X-Received: by 2002:a05:6000:4603:b0:3a5:23c6:eeee with SMTP id ffacd0b85a97d-3afb0247991mr1961331f8f.21.1751370302587; Tue, 01 Jul 2025 04:45:02 -0700 (PDT) From: Hanna Czenczek To: qemu-block@nongnu.org Cc: qemu-devel@nongnu.org, Hanna Czenczek , Stefan Hajnoczi , Kevin Wolf , Markus Armbruster , Brian Song Subject: [PATCH v3 06/21] fuse: Fix mount options Date: Tue, 1 Jul 2025 13:44:22 +0200 Message-ID: <20250701114437.207419-7-hreitz@redhat.com> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250701114437.207419-1-hreitz@redhat.com> References: <20250701114437.207419-1-hreitz@redhat.com> 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=170.10.133.124; envelope-from=hreitz@redhat.com; helo=us-smtp-delivery-124.mimecast.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, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1751370475839116600 Content-Type: text/plain; charset="utf-8" Since I actually took a look into how mounting with libfuse works[1], I now know that the FUSE mount options are not exactly standard mount system call options. Specifically: - We should add "nosuid,nodev,noatime" because that is going to be translated into the respective MS_ mount flags; and those flags make sense for us. - We can set rw/ro to make the mount writable or not. It makes sense to set this flag to produce a better error message for read-only exports (EROFS instead of EACCES). This changes behavior as can be seen in iotest 308: It is no longer possible to modify metadata of read-only exports. In addition, in the comment, we can note that the FUSE mount() system call actually expects some more parameters that we can omit because fusermount3 (i.e. libfuse) will figure them out by itself: - fd: /dev/fuse fd - rootmode: Inode mode of the root node - user_id/group_id: Mounter's UID/GID [1] It invokes fusermount3, an SUID libfuse helper program, which parses and processes some mount options before actually invoking the mount() system call. Reviewed-by: Stefan Hajnoczi Signed-off-by: Hanna Czenczek --- block/export/fuse.c | 14 +++++++++++--- tests/qemu-iotests/308 | 4 ++-- tests/qemu-iotests/308.out | 3 ++- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/block/export/fuse.c b/block/export/fuse.c index 01a5716bdd..9d110ce949 100644 --- a/block/export/fuse.c +++ b/block/export/fuse.c @@ -246,10 +246,18 @@ static int mount_fuse_export(FuseExport *exp, Error *= *errp) int ret; =20 /* - * max_read needs to match what fuse_init() sets. - * max_write need not be supplied. + * Note that these mount options differ from what we would pass to a d= irect + * mount() call: + * - nosuid, nodev, and noatime are not understood by the kernel; libf= use + * uses those options to construct the mount flags (MS_*) + * - The FUSE kernel driver requires additional options (fd, rootmode, + * user_id, group_id); these will be set by libfuse. + * Note that max_read is set here, while max_write is set via the FUSE= INIT + * operation. */ - mount_opts =3D g_strdup_printf("max_read=3D%zu,default_permissions%s", + mount_opts =3D g_strdup_printf("%s,nosuid,nodev,noatime,max_read=3D%zu= ," + "default_permissions%s", + exp->writable ? "rw" : "ro", FUSE_MAX_BOUNCE_BYTES, exp->allow_other ? ",allow_other" : ""); =20 diff --git a/tests/qemu-iotests/308 b/tests/qemu-iotests/308 index 6eced3aefb..033d5cbe22 100755 --- a/tests/qemu-iotests/308 +++ b/tests/qemu-iotests/308 @@ -178,7 +178,7 @@ stat -c 'Permissions pre-chmod: %a' "$EXT_MP" chmod u+w "$EXT_MP" 2>&1 | _filter_testdir | _filter_imgfmt stat -c 'Permissions post-+w: %a' "$EXT_MP" =20 -# But that we can set, say, +x (if we are so inclined) +# Same for other flags, like, say +x chmod u+x "$EXT_MP" 2>&1 | _filter_testdir | _filter_imgfmt stat -c 'Permissions post-+x: %a' "$EXT_MP" =20 @@ -236,7 +236,7 @@ output=3D$($QEMU_IO -f raw -c 'write -P 42 1M 64k' "$TE= ST_IMG" 2>&1 \ =20 # Expected reference output: Opening the file fails because it has no # write permission -reference=3D"Could not open 'TEST_DIR/t.IMGFMT': Permission denied" +reference=3D"Could not open 'TEST_DIR/t.IMGFMT': Read-only file system" =20 if echo "$output" | grep -q "$reference"; then echo "Writing to read-only export failed: OK" diff --git a/tests/qemu-iotests/308.out b/tests/qemu-iotests/308.out index e5e233691d..aa96faab6d 100644 --- a/tests/qemu-iotests/308.out +++ b/tests/qemu-iotests/308.out @@ -53,7 +53,8 @@ Images are identical. Permissions pre-chmod: 400 chmod: changing permissions of 'TEST_DIR/t.IMGFMT.fuse': Read-only file sy= stem Permissions post-+w: 400 -Permissions post-+x: 500 +chmod: changing permissions of 'TEST_DIR/t.IMGFMT.fuse': Read-only file sy= stem +Permissions post-+x: 400 =20 =3D=3D=3D Mount over existing file =3D=3D=3D {'execute': 'block-export-add', --=20 2.49.0 From nobody Sat Nov 15 12:14:53 2025 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=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1751370598; cv=none; d=zohomail.com; s=zohoarc; b=muk+aJf6A5FyNXx/D5lm4SoM7f8mWv4M/ObuHaq6qyBdpbJ4OQZ6txs1mlB8tfLBed6D62BUWWJfRJ65TXg3mN9+xFjV80V3CVuMWQnfTXUA/xgVUH8EKuEzzgqvtLwPVDdutCqlL8Qu1b2j6Q1R1ke9xsN4W3EjhTZhjzsD+AU= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1751370598; h=Content-Type: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=B9wF3F+3bQ/mxGLpNGnaivuKHU4J9Rkz4uaRH9vksus=; b=bkIr1VcxZG2oMChyn+jGjXQAA3B14WS6PSlUj+dnZzev4PfeGRMNIT8dk43uze499JHVWzbUTJPzpZeVmBZtzFqgCbAhERn31XM7Y5lPjHuFJqSaU5ktZ+FlYVbtwK44Hhpl2UMI+Iy+jr4q48mZxFfU3FXd4dsp7/ot7qly2A0= 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 lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 175137059895981.33896064203941; Tue, 1 Jul 2025 04:49:58 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1uWZQO-0005JB-Ik; Tue, 01 Jul 2025 07:45:20 -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 1uWZQJ-0005Fn-Ka for qemu-devel@nongnu.org; Tue, 01 Jul 2025 07:45:15 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uWZQD-0003UD-Fn for qemu-devel@nongnu.org; Tue, 01 Jul 2025 07:45:13 -0400 Received: from mail-wm1-f70.google.com (mail-wm1-f70.google.com [209.85.128.70]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-624-6K8QkWwdPnG1k35Bm97J8w-1; Tue, 01 Jul 2025 07:45:07 -0400 Received: by mail-wm1-f70.google.com with SMTP id 5b1f17b1804b1-450d290d542so35349755e9.1 for ; Tue, 01 Jul 2025 04:45:07 -0700 (PDT) Received: from localhost (p200300cfd700f38d3df6a1ca7d40fe1f.dip0.t-ipconnect.de. [2003:cf:d700:f38d:3df6:a1ca:7d40:fe1f]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-453835798acsm192848075e9.10.2025.07.01.04.45.03 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 01 Jul 2025 04:45:03 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1751370308; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=B9wF3F+3bQ/mxGLpNGnaivuKHU4J9Rkz4uaRH9vksus=; b=hBQmVBTrJW8THF02YA16sxBSaE5oh9Muve0OimSK1cE7Qcv8dCd2kPxwqmT+FnQBuBMpJj Bz3mD+m/Gu9mwC5hTEBhBDIhic93VcnxTWkMa4a8h5NJVsl82Kthsovf7ilM9IXYqM4i06 EdJ/nGFa2gwmvzDgk8Cab09qUn2fCGc= X-MC-Unique: 6K8QkWwdPnG1k35Bm97J8w-1 X-Mimecast-MFC-AGG-ID: 6K8QkWwdPnG1k35Bm97J8w_1751370306 X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1751370306; x=1751975106; 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=B9wF3F+3bQ/mxGLpNGnaivuKHU4J9Rkz4uaRH9vksus=; b=X9hdgSIGmSZC4/b47uxwo6tk0HMiFeErY1fFWi/+QzGrV2O7bm6rruuDn02qarhRWU 83NiENcXGH5+4ZgKAl2siY2hDkdfdp4wnmS/hGpnG3n3PUcw7W3/fbPBfU6hAqdXk95U PabzHi/GVEO5mFaO4G7/7xk0afjWblXMQGEBhlm9A7qliHVITy8D5CmqDAxyUwPPEaQ1 guglzCIj3MXwyzoRWjm1YXJfR+h+L2k63nNqVgNFSqTRaDpX2s1EAtr0Ot5Plg0c09Tw cYJ/TcGO4f4I3+v3we1Z987jy6qsXFY/Hjw8VkJu+wkNctC2VLfOsNdw98OYnYQq/Mj2 fo7w== X-Gm-Message-State: AOJu0YyxQ5l6oTHgz+oq3W5rHmLXSztbUD45XYk4RecjHuvBkCu4WG4N PRIkQgV7rzJc1Sg38cxDHNtZlcR3AyqerQu4KQxjVeawU9TeiM5pHfFEwvzJ4/pGceb0qnn38qE xlRbQ+3NZoOoglZLbm1/Md3XFEeiwLbaDgoSP2gl18FakYT77hnxS8A85 X-Gm-Gg: ASbGnct9YK95n+XHDx27v/oJi2QoLiX9Bh60sGtJihCHyO1WGgcylv1eeZrMblFGgDi dQB3FospiDFKY05D7YEVZ05hIOfcnJOseOm1wBJh7VRInvB1OmaB7FeyigZFg0HTpBsOGOiurJn VRLc40piEn1FSBbi45C0/1Vf7WTBPsfJho37+0NT9aZlwA/8sOGhFXDlGCjaBJ60nR7djwkT3K/ 92wujNg9/8OcH++0YCEkdd/NVAob1PTWALCKV7+AOSmiRhxAF7nI1QrC01YIxhcc4IPLczd03Li 5F0TjPV1WGYIiCa8MpRS/kzg1dG/+jJehwDlbFvgjC38DMnMYqaUG89l16aERf8hpvtifemuPOz yyWLx X-Received: by 2002:a05:600c:4eca:b0:453:78f:fa9f with SMTP id 5b1f17b1804b1-4538ee5e82amr169827625e9.11.1751370306062; Tue, 01 Jul 2025 04:45:06 -0700 (PDT) X-Google-Smtp-Source: AGHT+IFMhd21T9277IdZYSF4DhSxosr6zQDzNI/f5HhtW60GKMwy//k3k/ElVlNSAo70ots5b5hD1w== X-Received: by 2002:a05:600c:4eca:b0:453:78f:fa9f with SMTP id 5b1f17b1804b1-4538ee5e82amr169827205e9.11.1751370305601; Tue, 01 Jul 2025 04:45:05 -0700 (PDT) From: Hanna Czenczek To: qemu-block@nongnu.org Cc: qemu-devel@nongnu.org, Hanna Czenczek , Stefan Hajnoczi , Kevin Wolf , Markus Armbruster , Brian Song Subject: [PATCH v3 07/21] fuse: Set direct_io and parallel_direct_writes Date: Tue, 1 Jul 2025 13:44:23 +0200 Message-ID: <20250701114437.207419-8-hreitz@redhat.com> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250701114437.207419-1-hreitz@redhat.com> References: <20250701114437.207419-1-hreitz@redhat.com> 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=170.10.133.124; envelope-from=hreitz@redhat.com; helo=us-smtp-delivery-124.mimecast.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, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1751370601052124100 Content-Type: text/plain; charset="utf-8" In fuse_open(), set these flags: - direct_io: We probably actually don't want to have the host page cache be used for our exports. QEMU block exports are supposed to represent the image as-is (and thus potentially changing). This causes a change in iotest 308's reference output. - parallel_direct_writes: We can (now) cope with parallel writes, so we should set this flag. For some reason, it doesn't seem to make an actual performance difference with libfuse, but it does make a difference without it, so let's set it. (See "fuse: Copy write buffer content before polling" for further discussion.) Reviewed-by: Stefan Hajnoczi Signed-off-by: Hanna Czenczek --- block/export/fuse.c | 2 ++ tests/qemu-iotests/308.out | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/block/export/fuse.c b/block/export/fuse.c index 9d110ce949..e1134a27d6 100644 --- a/block/export/fuse.c +++ b/block/export/fuse.c @@ -576,6 +576,8 @@ static void fuse_setattr(fuse_req_t req, fuse_ino_t ino= de, struct stat *statbuf, static void fuse_open(fuse_req_t req, fuse_ino_t inode, struct fuse_file_info *fi) { + fi->direct_io =3D true; + fi->parallel_direct_writes =3D true; fuse_reply_open(req, fi); } =20 diff --git a/tests/qemu-iotests/308.out b/tests/qemu-iotests/308.out index aa96faab6d..2d7a38d63d 100644 --- a/tests/qemu-iotests/308.out +++ b/tests/qemu-iotests/308.out @@ -131,7 +131,7 @@ wrote 65536/65536 bytes at offset 1048576 =20 --- Try growing non-growable export --- (OK: Lengths of export and original are the same) -dd: error writing 'TEST_DIR/t.IMGFMT.fuse': Input/output error +dd: error writing 'TEST_DIR/t.IMGFMT.fuse': No space left on device 1+0 records in 0+0 records out =20 --=20 2.49.0 From nobody Sat Nov 15 12:14:53 2025 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=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1751370554; cv=none; d=zohomail.com; s=zohoarc; b=C2porUZ3qXClZ3X0RBmfUtZ74/Y4pXCa66ql4dWOKVNRCN4gpa730LbrawzrJkyFSn3uT0q2RdwZ5v2SHTyfkFI0CDYLW7uGQF+BYBUEC3sMXFBtNc1DAHH9kq/gh4Plx4znyU0cvQJq5kANowk6oF63ScYgghAglwcYbOlxIcI= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1751370554; h=Content-Type: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=iBWE4FPpwD87XkHHPVGSv5gJzue+dVBIat7kcbz/nkQ=; b=Ms6jv45p2ZMgZvKJLWq62FvycOrukZJaWxaTnUj6pe1xFqiqnImP3YgRv51rr1o7PT3jNOXVKbB94yWqYgtgGvVXL6fAJS7e/fBi5qKc4d0nu1KWlwykH9RV2L/UPYdbPd9MgzxmFyaLmZlobURYqHH0QuY3d57l2k3kBK4YrvM= 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 lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 175137055441998.48894590068062; Tue, 1 Jul 2025 04:49:14 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1uWZQQ-0005N8-OV; Tue, 01 Jul 2025 07:45:22 -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 1uWZQK-0005HV-Ox for qemu-devel@nongnu.org; Tue, 01 Jul 2025 07:45:16 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uWZQI-0003VG-F6 for qemu-devel@nongnu.org; Tue, 01 Jul 2025 07:45:16 -0400 Received: from mail-wm1-f69.google.com (mail-wm1-f69.google.com [209.85.128.69]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-303-LWzM9_UwNZu4J7MF3SZ37A-1; Tue, 01 Jul 2025 07:45:11 -0400 Received: by mail-wm1-f69.google.com with SMTP id 5b1f17b1804b1-4535ee06160so23943755e9.3 for ; Tue, 01 Jul 2025 04:45:10 -0700 (PDT) Received: from localhost (p200300cfd700f38d3df6a1ca7d40fe1f.dip0.t-ipconnect.de. [2003:cf:d700:f38d:3df6:a1ca:7d40:fe1f]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-3a892e52b9esm13187556f8f.61.2025.07.01.04.45.06 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 01 Jul 2025 04:45:06 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1751370312; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=iBWE4FPpwD87XkHHPVGSv5gJzue+dVBIat7kcbz/nkQ=; b=RI6z4t+yd6QTOelpXtAij0vpo4DN454w4d7ZVLJA03Afwc+p/7y1+F5+MxvXyy3ZoSEUf3 Z19GezT3UVkdsvjeaLz4asqMpxHy+b/VZWZN2pgEIjw7E/hcfN+PbwBuPRclTtxE/gg1v4 mrTXYL5T0/bVPkrctv1u2KOqSuPVqTU= X-MC-Unique: LWzM9_UwNZu4J7MF3SZ37A-1 X-Mimecast-MFC-AGG-ID: LWzM9_UwNZu4J7MF3SZ37A_1751370310 X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1751370310; x=1751975110; 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=iBWE4FPpwD87XkHHPVGSv5gJzue+dVBIat7kcbz/nkQ=; b=N53/HEVFqONnaweopmzxJw/X/11/IKoxtoqnIFj/zqI/gdEzmOEtMTN7WW3YlCfodu STKf3K9ENH2DBUdkzTGEO7w6XBzHQwTBo9kJdsxk1YoW9SJG3r/9G8qxWnyKdXHS1aQ4 cCv+OpClVYCDfaQsaKs8vRzp6YY2eAMskNRHj13CDRMM0VPCaTGUlu3jbGwCWEtVBhk3 qk2fTYKTjcKVg9/CHc1FNC+l72meZ5o5jlJ8iaVw6eET68pCXcxDZW2Rpswid1hfp1jA 84di9LRU2hT+13KE7FRYOYPOO2mddJPuX7dbeiFRc0moG6TIiaRG2jZ5BT+jtIA3GmUx ULhQ== X-Gm-Message-State: AOJu0YwpOvZ/RbA7i7iIDGyd9/FXHdnRXWP81znb4l6V4oC9saCwZTo9 H6qZU6ll9gCagZoUf3vtJ9c3uXYDgFhwXAAO6O8Eg7ry/1TXIv2LuPALCRpWhZd4+xUKVKBq4zD DDDaCiv+xgGnrrSHag9cBU95dIjGgZAzklwKmnfKueD2IEyYt6RlhwsjC X-Gm-Gg: ASbGncvtWmT283NyCvsiRm1zHHgu7fOe2qeePLaRN/1A43Gd//PG9+IjuUNKe2iBkYa ZfSG0/2cf5VV8PhHRxigurZ+YDIXpCdH5fzv6Gurk9ilEHjZqtCgpQZf3QW5YrfGM2++IX9TbOe Jn6nnsuz6D6OBMGa+LstwlWyi092yIr4isk171Z8llq6ctSg/BcJDIYNFIBnXSW2/RaiEiiFLf3 6oxhBmpd7hKKhBQ6R1Mb5VaNKo6sANa17qal2sD7BTWKt4nsZQpQ34TbxEgUqfBD9pNESE/YE/8 88H3dJpqUZdvwmhSxK9FVSZDL3rpgSofrZKaNa6KNfSz9TzF/cBDN/OP3BEyHsIXsbzJm+iyR8t Wm1rt X-Received: by 2002:a05:600c:1d18:b0:444:34c7:3ed9 with SMTP id 5b1f17b1804b1-4538ee7995emr158470745e9.26.1751370309633; Tue, 01 Jul 2025 04:45:09 -0700 (PDT) X-Google-Smtp-Source: AGHT+IElVEXsmx8FELqsitwXiXkQCojBQWjSiXX6hTs1cbcuGPjoW3Jmx2KoPkV4xwdmu6nlVnnWKA== X-Received: by 2002:a05:600c:1d18:b0:444:34c7:3ed9 with SMTP id 5b1f17b1804b1-4538ee7995emr158470175e9.26.1751370308836; Tue, 01 Jul 2025 04:45:08 -0700 (PDT) From: Hanna Czenczek To: qemu-block@nongnu.org Cc: qemu-devel@nongnu.org, Hanna Czenczek , Stefan Hajnoczi , Kevin Wolf , Markus Armbruster , Brian Song Subject: [PATCH v3 08/21] fuse: Introduce fuse_{at,de}tach_handlers() Date: Tue, 1 Jul 2025 13:44:24 +0200 Message-ID: <20250701114437.207419-9-hreitz@redhat.com> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250701114437.207419-1-hreitz@redhat.com> References: <20250701114437.207419-1-hreitz@redhat.com> 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=170.10.129.124; envelope-from=hreitz@redhat.com; helo=us-smtp-delivery-124.mimecast.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, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1751370556581124100 Content-Type: text/plain; charset="utf-8" Pull setting up and tearing down the AIO context handlers into two dedicated functions. Reviewed-by: Stefan Hajnoczi Signed-off-by: Hanna Czenczek --- block/export/fuse.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/block/export/fuse.c b/block/export/fuse.c index e1134a27d6..15ec7a5c05 100644 --- a/block/export/fuse.c +++ b/block/export/fuse.c @@ -78,27 +78,34 @@ static void read_from_fuse_export(void *opaque); static bool is_regular_file(const char *path, Error **errp); =20 =20 -static void fuse_export_drained_begin(void *opaque) +static void fuse_attach_handlers(FuseExport *exp) { - FuseExport *exp =3D opaque; + aio_set_fd_handler(exp->common.ctx, + fuse_session_fd(exp->fuse_session), + read_from_fuse_export, NULL, NULL, NULL, exp); + exp->fd_handler_set_up =3D true; +} =20 +static void fuse_detach_handlers(FuseExport *exp) +{ aio_set_fd_handler(exp->common.ctx, fuse_session_fd(exp->fuse_session), NULL, NULL, NULL, NULL, NULL); exp->fd_handler_set_up =3D false; } =20 +static void fuse_export_drained_begin(void *opaque) +{ + fuse_detach_handlers(opaque); +} + static void fuse_export_drained_end(void *opaque) { FuseExport *exp =3D opaque; =20 /* Refresh AioContext in case it changed */ exp->common.ctx =3D blk_get_aio_context(exp->common.blk); - - aio_set_fd_handler(exp->common.ctx, - fuse_session_fd(exp->fuse_session), - read_from_fuse_export, NULL, NULL, NULL, exp); - exp->fd_handler_set_up =3D true; + fuse_attach_handlers(exp); } =20 static bool fuse_export_drained_poll(void *opaque) @@ -209,11 +216,7 @@ static int fuse_export_create(BlockExport *blk_exp, =20 g_hash_table_insert(exports, g_strdup(exp->mountpoint), NULL); =20 - aio_set_fd_handler(exp->common.ctx, - fuse_session_fd(exp->fuse_session), - read_from_fuse_export, NULL, NULL, NULL, exp); - exp->fd_handler_set_up =3D true; - + fuse_attach_handlers(exp); return 0; =20 fail: @@ -329,10 +332,7 @@ static void fuse_export_shutdown(BlockExport *blk_exp) fuse_session_exit(exp->fuse_session); =20 if (exp->fd_handler_set_up) { - aio_set_fd_handler(exp->common.ctx, - fuse_session_fd(exp->fuse_session), - NULL, NULL, NULL, NULL, NULL); - exp->fd_handler_set_up =3D false; + fuse_detach_handlers(exp); } } =20 --=20 2.49.0 From nobody Sat Nov 15 12:14:53 2025 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=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1751370433; cv=none; d=zohomail.com; s=zohoarc; b=YTjTn84wG9/+esvK0wz2zykm5oeVgtM/Mxt8NNb4JHuUx2QY7LB91D2nQv79vk+ylmaqXOhT1fitRXlrcqzirOxr5BguItFpgF6RJRzO7R4G3L6HlbRXkt/79gRv5C/wKNPCNS5QBexhShq2x7tdkvFmBO3cz39T6S4RPAlEpVI= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1751370433; h=Content-Type: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=/2MYp3UhabT2qS0mTPTCo+T0B/SM6NTgMC1jdFmgg9Q=; b=UGLXEZbkWQYsQ66IqYsh0GD/So8GnGuTwPid9Zbh+nU9xRS3HR+TRv+7hwPgSnJ5FmpyZT+5r1zGMvQfC+3LbIhDpHT84wmwJoauQlMTt5ust5M266f4JW6oNY+6W2LB2F15iqT1emzapvsRs+7Uvvk9ZaJ2Qtgw8OvgjsZhti0= 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 lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1751370433073976.8657875656967; Tue, 1 Jul 2025 04:47:13 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1uWZQQ-0005N9-OT; Tue, 01 Jul 2025 07:45:22 -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 1uWZQL-0005I9-Um for qemu-devel@nongnu.org; Tue, 01 Jul 2025 07:45:18 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uWZQI-0003Va-TN for qemu-devel@nongnu.org; Tue, 01 Jul 2025 07:45:17 -0400 Received: from mail-wr1-f71.google.com (mail-wr1-f71.google.com [209.85.221.71]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-669-IVc0rBHpOAythf3167p9kw-1; Tue, 01 Jul 2025 07:45:12 -0400 Received: by mail-wr1-f71.google.com with SMTP id ffacd0b85a97d-3a4fac7fa27so1111755f8f.0 for ; Tue, 01 Jul 2025 04:45:12 -0700 (PDT) Received: from localhost (p200300cfd700f38d3df6a1ca7d40fe1f.dip0.t-ipconnect.de. [2003:cf:d700:f38d:3df6:a1ca:7d40:fe1f]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-3a892e529c5sm13290493f8f.63.2025.07.01.04.45.09 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 01 Jul 2025 04:45:09 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1751370313; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=/2MYp3UhabT2qS0mTPTCo+T0B/SM6NTgMC1jdFmgg9Q=; b=UqZkmcfk2vq7Z/JU2eZaukbC4IvBmcw/Yi6epvIl1b4If6GVW/WSnEhZDY716Xw/OCIQ/u 8iOrncP9JIgVPL33wTNq2wFiyNXl0oVo4DYD9aunihDJyln/RrOiEGi514Xm09Rfyu4B17 gP/9Z+N9KNwDo5U6uabNRqrYjlz1QfQ= X-MC-Unique: IVc0rBHpOAythf3167p9kw-1 X-Mimecast-MFC-AGG-ID: IVc0rBHpOAythf3167p9kw_1751370311 X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1751370311; x=1751975111; 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=/2MYp3UhabT2qS0mTPTCo+T0B/SM6NTgMC1jdFmgg9Q=; b=GoAW/ZSQ2cepE8P/IV2ca7WvyjiORkDU3fIer+Y6np6y6ZyGPvMtn6DaBngWb4SP8v DInZJ6uk6sKx5cIUbuiQEY6v+8JJ66RwgQK1xH8HhQyGYi+wuNsm67k0e4XAPUhrcONg 5YQkiHyGiOw9kmRKdNbrpBN0eNCXUe1YSH5HMoz3NnYZcrk+TMobSk+bdf0GEAkYyOE0 CI8KP10AcuiWOyGB+q80rSnHEqKctWMJJTvezoQa4vaQeUBRWv1YU4+rJpwYGEp3MnN3 i4en3YJUoiGTCv9mhlDvNkWut/TVB9LpJWWmPj1lB5KaQj3hssRpw/s+cqqXsG576XwU tWpA== X-Gm-Message-State: AOJu0YzWcnhjUnV9HlN4DQE3e5fTd3Uha0tHFxKyS4uy/1bIXYTmKGPN yzogXAsz/0WbptGWxmWFSia3SV+0dkN55ZcHxRd+ALxjyWdJN00C03WIuYmMnl5E/yq5UCY5/nD ZF/SEMSMgszQK9a1c15e4LJoizYr8T320WhHYX7AXO0X9sLST7vAXS6g7 X-Gm-Gg: ASbGnctJ5DZuhGA1xrqnbHC2BBW2+SAV1XO4eyu/i1ZvsOnpwTTgQWfQddII/QTe4kh eruK3wn1YJw4VcQ9EVQSYWHtwU/4DrZYughJ6RwNyOXy2vpE/35EYzHOWKUnWY9blzEs/BAwl0z ASkszI1IIiY1nuC3xAZbrPNB7qnp5hRwYVulx586Zl8pPXqz1VHGCkjIz/F3x2yqImB0rHQ9VZ1 VK2vrtE2oUmMNnRC0DBD+tXYK9QEjlKjkOg0G8q1+HeSVBFnYZqji1A5AttXKWhm/QhXRx06DYy r/GLPFeckod3Z50IF1JOWogesbGcfMbP0nZfWkjd99yM6FcgDojg54Dr7lPMMZ0u4V1dJazc8rz lF46F X-Received: by 2002:a05:6000:2307:b0:3a4:d02e:84af with SMTP id ffacd0b85a97d-3a9038fb216mr13616466f8f.58.1751370311177; Tue, 01 Jul 2025 04:45:11 -0700 (PDT) X-Google-Smtp-Source: AGHT+IEMGJU1ndauWgPN5Lbp8PmBB30xXxuL+JLwUB6hHOqq8E3n/IK/rxWkZ/GABI/k+vpT1CpwJw== X-Received: by 2002:a05:6000:2307:b0:3a4:d02e:84af with SMTP id ffacd0b85a97d-3a9038fb216mr13616447f8f.58.1751370310764; Tue, 01 Jul 2025 04:45:10 -0700 (PDT) From: Hanna Czenczek To: qemu-block@nongnu.org Cc: qemu-devel@nongnu.org, Hanna Czenczek , Stefan Hajnoczi , Kevin Wolf , Markus Armbruster , Brian Song Subject: [PATCH v3 09/21] fuse: Introduce fuse_{inc,dec}_in_flight() Date: Tue, 1 Jul 2025 13:44:25 +0200 Message-ID: <20250701114437.207419-10-hreitz@redhat.com> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250701114437.207419-1-hreitz@redhat.com> References: <20250701114437.207419-1-hreitz@redhat.com> 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=170.10.129.124; envelope-from=hreitz@redhat.com; helo=us-smtp-delivery-124.mimecast.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, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1751370435137116600 Content-Type: text/plain; charset="utf-8" This is how vduse-blk.c does it, and it does seem better to have dedicated functions for it. Reviewed-by: Stefan Hajnoczi Signed-off-by: Hanna Czenczek --- block/export/fuse.c | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/block/export/fuse.c b/block/export/fuse.c index 15ec7a5c05..bcbeaf92f4 100644 --- a/block/export/fuse.c +++ b/block/export/fuse.c @@ -78,6 +78,25 @@ static void read_from_fuse_export(void *opaque); static bool is_regular_file(const char *path, Error **errp); =20 =20 +static void fuse_inc_in_flight(FuseExport *exp) +{ + if (qatomic_fetch_inc(&exp->in_flight) =3D=3D 0) { + /* Prevent export from being deleted */ + blk_exp_ref(&exp->common); + } +} + +static void fuse_dec_in_flight(FuseExport *exp) +{ + if (qatomic_fetch_dec(&exp->in_flight) =3D=3D 1) { + /* Wake AIO_WAIT_WHILE() */ + aio_wait_kick(); + + /* Now the export can be deleted */ + blk_exp_unref(&exp->common); + } +} + static void fuse_attach_handlers(FuseExport *exp) { aio_set_fd_handler(exp->common.ctx, @@ -297,9 +316,7 @@ static void read_from_fuse_export(void *opaque) FuseExport *exp =3D opaque; int ret; =20 - blk_exp_ref(&exp->common); - - qatomic_inc(&exp->in_flight); + fuse_inc_in_flight(exp); =20 do { ret =3D fuse_session_receive_buf(exp->fuse_session, &exp->fuse_buf= ); @@ -317,11 +334,7 @@ static void read_from_fuse_export(void *opaque) fuse_session_process_buf(exp->fuse_session, &exp->fuse_buf); =20 out: - if (qatomic_fetch_dec(&exp->in_flight) =3D=3D 1) { - aio_wait_kick(); /* wake AIO_WAIT_WHILE() */ - } - - blk_exp_unref(&exp->common); + fuse_dec_in_flight(exp); } =20 static void fuse_export_shutdown(BlockExport *blk_exp) --=20 2.49.0 From nobody Sat Nov 15 12:14:53 2025 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=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1751370449; cv=none; d=zohomail.com; s=zohoarc; b=l4/2GF0sv9EzgGCEY9+wQLTUpysdFID9TMZbErsIztNFCMeCdpeOBcaeot32xja7SZ65/L+at40SaZkm3PqrJPHd6cNXllrRFIo+s4BHPABllnrR6cOPpgtUaedDzLRL2ygmaHPBrB37U+e1dDSbrW2mG57CQPelgqs0nhjytUo= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1751370449; h=Content-Type: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=nk418H24kCz2+AUWTyV3Eb4pfrMBZv0WmNVH2UyfbVo=; b=StPPmEip3FscB3Ym4HLPrSY6ZHxbqsbtjrt2aDiswWzUEXxmnKAC3NMBtDJDIGWfqHZyUXBQsmjgLsi/sy+UeWEuRJaJ/ocWtlUjtbG4WwEsQ9De/LcR9RFiB5ufWYcGIZ3bIIX6lTn5/JRLrPWDiemAwaLQAdEP3ojiZHHtg7o= 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 lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1751370449723636.4632462510253; Tue, 1 Jul 2025 04:47:29 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1uWZQV-0005Pz-MI; Tue, 01 Jul 2025 07:45:28 -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 1uWZQT-0005P0-0A for qemu-devel@nongnu.org; Tue, 01 Jul 2025 07:45:25 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uWZQN-0003XF-9Y for qemu-devel@nongnu.org; Tue, 01 Jul 2025 07:45:24 -0400 Received: from mail-wr1-f71.google.com (mail-wr1-f71.google.com [209.85.221.71]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-35-oYC8NnRVOAWk8iKQ1Xtvvg-1; Tue, 01 Jul 2025 07:45:16 -0400 Received: by mail-wr1-f71.google.com with SMTP id ffacd0b85a97d-3a54a8a0122so2765942f8f.2 for ; Tue, 01 Jul 2025 04:45:16 -0700 (PDT) Received: from localhost (p200300cfd700f38d3df6a1ca7d40fe1f.dip0.t-ipconnect.de. [2003:cf:d700:f38d:3df6:a1ca:7d40:fe1f]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-3a892e5972bsm13136456f8f.68.2025.07.01.04.45.11 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 01 Jul 2025 04:45:12 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1751370318; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=nk418H24kCz2+AUWTyV3Eb4pfrMBZv0WmNVH2UyfbVo=; b=Z28GYpujTljYSX3IjmEvDIAY2Xkc2aVLqtjCj7JVBMU66NsJt0JaNwwD2sf8a8hrYlfqVY zM9WJOughFvMsauwvT390mJM/uSLfx2H2pRxSLDURDyvpaqWrrqgqEKvjIyKFFO4Do1yDC aDte5C25G/PvvhemVIXcIA3BcN2RmO4= X-MC-Unique: oYC8NnRVOAWk8iKQ1Xtvvg-1 X-Mimecast-MFC-AGG-ID: oYC8NnRVOAWk8iKQ1Xtvvg_1751370315 X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1751370315; x=1751975115; 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=nk418H24kCz2+AUWTyV3Eb4pfrMBZv0WmNVH2UyfbVo=; b=GV/S5Zc9UpGAQ40lt1NC2emcaPm3MO5tM5yB85cs8tkb+kPVuY9+ABnyqCMbb3bzRd h8iWDOfKZyJRUH7lH230G1Kap317BEa9UBPNWWCkMyUHYcELdSy1N63+DoVIL83430Dm a2npz4xe4EfBJRPD1AR8rdLT+Y6obHbcJJvbnut8T2Jaf0X+3KL19fBbkIKYOh6osDmj shJj1vEmdgP0MGViWCPA2MK1r6zuAMhGZXrYB77jLdRVkxzhLuAX9mhWgVXOKy1w17aR cIO+/HMsUeKhX0pF5K4UT5E590xy2EJ99G9ATgBsbLCZRRGDbWUODSnGT3RCMFnbGPm6 2D+A== X-Gm-Message-State: AOJu0YzkbWKoR7y4R+z4xadUmb96lZA9QkmALZZqqCium5pTZfaE5lHv +W1VLQeQfXGQTvasfRNelc1q1xKYwC1P+Sb2H4mk6zab3u7v2nhufAzOIw2b9Ozr3N9UnXoagTn /zaX/I+Z7jcVdM6Emo8gOqy9JSYKNxAie4gGlUe9X/GG3nZ8HhXpVdbNZ X-Gm-Gg: ASbGncvpwEOIG+keNv0b0SKU1LlFT7hsPC4YmGqEXA69CXdxhA05iE49mjiUQVEOLzS B1mrMe031wDaAPBSYy/cFlG58Lqj3DlExaMtiBUCy1vpR30zKotT/YsQK5Yg4fs+noHvlvx4yjo tGq9gAVhL+aCa/PcaevmWZjsQ0biZjYEpgClORuW0E68yisv7DI5cfEDm6QZ8a+/TG6NUGGZyK7 JZ61GFy7CtovrurFmURzcZEj1moi6//RC8x3TGf6et9QlGWhPC7DBqFJAOYyT3MQ+PAn2kKO8MW MnCU4mXeG6ssWGyCH3A+1uqEAOhsdnIY3CHq0RDmTsRg5wzL5l+jq3veqwKkpg+8lenZ9xqUu8+ 8+Y0U X-Received: by 2002:a05:6000:648:b0:3a6:d967:37d0 with SMTP id ffacd0b85a97d-3a8fdb2aed9mr13224084f8f.11.1751370315344; Tue, 01 Jul 2025 04:45:15 -0700 (PDT) X-Google-Smtp-Source: AGHT+IG1MgKiZ9yhjaYxG7uNg4tWjjVKbP5QUt+zUl1b+rwC82hbYsIIw4vYVXaROS3lWu/1TduaZw== X-Received: by 2002:a05:6000:648:b0:3a6:d967:37d0 with SMTP id ffacd0b85a97d-3a8fdb2aed9mr13224053f8f.11.1751370314804; Tue, 01 Jul 2025 04:45:14 -0700 (PDT) From: Hanna Czenczek To: qemu-block@nongnu.org Cc: qemu-devel@nongnu.org, Hanna Czenczek , Stefan Hajnoczi , Kevin Wolf , Markus Armbruster , Brian Song Subject: [PATCH v3 10/21] fuse: Add halted flag Date: Tue, 1 Jul 2025 13:44:26 +0200 Message-ID: <20250701114437.207419-11-hreitz@redhat.com> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250701114437.207419-1-hreitz@redhat.com> References: <20250701114437.207419-1-hreitz@redhat.com> 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=170.10.129.124; envelope-from=hreitz@redhat.com; helo=us-smtp-delivery-124.mimecast.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, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=unavailable autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1751370451294116600 Content-Type: text/plain; charset="utf-8" This is a flag that we will want when processing FUSE requests ourselves: When the kernel sends us e.g. a truncated request (i.e. we receive less data than the request's indicated length), we cannot rely on subsequent data to be valid. Then, we are going to set this flag, halting all FUSE request processing. We plan to only use this flag in cases that would effectively be kernel bugs. (Right now, the flag is unused because libfuse still does our request processing.) Reviewed-by: Stefan Hajnoczi Signed-off-by: Hanna Czenczek --- block/export/fuse.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/block/export/fuse.c b/block/export/fuse.c index bcbeaf92f4..044fbbf1fe 100644 --- a/block/export/fuse.c +++ b/block/export/fuse.c @@ -53,6 +53,13 @@ typedef struct FuseExport { unsigned int in_flight; /* atomic */ bool mounted, fd_handler_set_up; =20 + /* + * Set when there was an unrecoverable error and no requests should be= read + * from the device anymore (basically only in case of something we wou= ld + * consider a kernel bug) + */ + bool halted; + char *mountpoint; bool writable; bool growable; @@ -69,6 +76,7 @@ static const struct fuse_lowlevel_ops fuse_ops; =20 static void fuse_export_shutdown(BlockExport *exp); static void fuse_export_delete(BlockExport *exp); +static void fuse_export_halt(FuseExport *exp) G_GNUC_UNUSED; =20 static void init_exports_table(void); =20 @@ -99,6 +107,10 @@ static void fuse_dec_in_flight(FuseExport *exp) =20 static void fuse_attach_handlers(FuseExport *exp) { + if (exp->halted) { + return; + } + aio_set_fd_handler(exp->common.ctx, fuse_session_fd(exp->fuse_session), read_from_fuse_export, NULL, NULL, NULL, exp); @@ -316,6 +328,10 @@ static void read_from_fuse_export(void *opaque) FuseExport *exp =3D opaque; int ret; =20 + if (unlikely(exp->halted)) { + return; + } + fuse_inc_in_flight(exp); =20 do { @@ -374,6 +390,20 @@ static void fuse_export_delete(BlockExport *blk_exp) g_free(exp->mountpoint); } =20 +/** + * Halt the export: Detach FD handlers, and set exp->halted to true, preve= nting + * fuse_attach_handlers() from re-attaching them, therefore stopping all f= urther + * request processing. + * + * Call this function when an unrecoverable error happens that makes proce= ssing + * all future requests unreliable. + */ +static void fuse_export_halt(FuseExport *exp) +{ + exp->halted =3D true; + fuse_detach_handlers(exp); +} + /** * Check whether @path points to a regular file. If not, put an * appropriate message into *errp. --=20 2.49.0 From nobody Sat Nov 15 12:14:53 2025 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=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1751370596; cv=none; d=zohomail.com; s=zohoarc; b=Gm2wyxuEl7jBKgmWuQVM+naXOjgG+AM3bETAuM04yfNBIDdGu6C1aqhgNFxsACuFDgsTDg3AO6UmGn708PZk2xzLowGtuza6B4Rdz8RZMS4wzjQN/SJP59s8nI3X0fMTXC8gp7BgTirl6hXqRbKLVqSfcaJBn5M0FFd/fMzFQe4= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1751370596; h=Content-Type: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=RKgwNKq5swcj1deon5pQ3hxXSW/pzxl1K8eAfdwbPRQ=; b=BKK01Nn5+WW+COAFVj9eIzA/X0QYgATYw7lC965q3ata1NdZPmu4ds3V57ybjwC+Vm17yY8wgJswHs6PwXXkVulcJg7MfeVOv6TFLCMEUZD9QiWB2E3hvAbTx/egpAf7a6j3416G8utG2vIR8y+8m4PZOv+33pmp1gQMnQQfefg= 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 lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1751370596658758.5353906533718; Tue, 1 Jul 2025 04:49:56 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1uWZQY-0005S2-37; Tue, 01 Jul 2025 07:45: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 1uWZQU-0005PM-5q for qemu-devel@nongnu.org; Tue, 01 Jul 2025 07:45:26 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uWZQR-0003YB-EL for qemu-devel@nongnu.org; Tue, 01 Jul 2025 07:45:25 -0400 Received: from mail-wm1-f70.google.com (mail-wm1-f70.google.com [209.85.128.70]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-198-rd2BXWNlNtudO8ev5lXdjw-1; Tue, 01 Jul 2025 07:45:20 -0400 Received: by mail-wm1-f70.google.com with SMTP id 5b1f17b1804b1-450df53d461so25881295e9.1 for ; Tue, 01 Jul 2025 04:45:20 -0700 (PDT) Received: from localhost (p200300cfd700f38d3df6a1ca7d40fe1f.dip0.t-ipconnect.de. [2003:cf:d700:f38d:3df6:a1ca:7d40:fe1f]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-3a892e52c23sm13154950f8f.52.2025.07.01.04.45.15 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 01 Jul 2025 04:45:16 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1751370321; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=RKgwNKq5swcj1deon5pQ3hxXSW/pzxl1K8eAfdwbPRQ=; b=FftC9xk4Avu822YnxBxC7OgBQU1wjcGC5KAHAlEa5Z8/oAQQWCU7zt6kPv6fxDSaaA9Gfc SJMTu/iP9YAcNY0IetrMYhD9mizasv90011KoJgC4T9WqXwO1IMVD4Yh7t4EVRjsFZHgei LtOse9fJbRYsj841MsQVXaBV3JbMYrU= X-MC-Unique: rd2BXWNlNtudO8ev5lXdjw-1 X-Mimecast-MFC-AGG-ID: rd2BXWNlNtudO8ev5lXdjw_1751370319 X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1751370319; x=1751975119; 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=RKgwNKq5swcj1deon5pQ3hxXSW/pzxl1K8eAfdwbPRQ=; b=lvhu4C0IafCllEYCBQ59kCkFQRQFG4BoEgRXGDSynKo8uDSYaY6Xw13VEKxoeJWvot +/SgBYu6rd0WIS3QPVcMfoiLgu1vzV/++cGzAZMb2Oame9rH/rfkoigq+MIBTbT2tILP vRS5TFarbJHIsCcAgHNK9d/uFDlI+a06stZlIQ2lf4adrmO0Cfa3IbXGRPrHNsRnZ2y8 VXecG6ejcaWbUxTAidU8lAmVZebJj5v0yLq3gCTJhNnKqpmm5Mk8BqSTobrOq58hhcrb bzACEPj8iAPOgZsmsYXcJ2L+RoDJZ91JrSd8ouzypBrEauDShjwDvNzOxZIWpTdYiYIK Yo7Q== X-Gm-Message-State: AOJu0YzPuqSxH4psKo2Cxd/4J5pS1GNqbVpgPmkxt0+4QKu3JZbdsvLu oY5HBkurP3EzD3STpY4FLeu8IPMRw7Gk2YLPErQr+WPz1Mr03bZOX3HnpUVAG4PTLv1bsur/sRv QWz/vnJt/IknCAPg79QXXW0qYf9wI4sgyojYqGa2A0KOX1I6dDBBaCN5I5SlTMSoC X-Gm-Gg: ASbGncuxHIB3YjVNoLW5fsKoiWvuF69WsH/m+2RnP116vBu2qpZKnK8oiecxdwiLkvi MkDUn5kqBL5KrDQwHV8ukKu/LlaOCtrmfMD09lxkU+Xv2AwzVllQQXyRHPMDigv8HdiEqPMNbvo fTQrpA3wgSUmq07hLi0Bl0e4bWSZ7ZghgAbVIEDGk70j+E8ykEvWKx5OF+HNGSEtF1fNtMcLo7S VYEsBi89zQioIv9h+DkmFykDmTtOOr/TUKbAqprV2TkWCJIkbj4yRru1eD1vXu85pRxoZK1S9Rf ZLsCGZacHRFkprIG3YR9czfBa1qLmqeoPYwFWTCB2xiILSIPVqNAiuJel1grguY+HSrBIF5oxVG UpL+l X-Received: by 2002:a05:600c:4706:b0:453:8bc7:5e53 with SMTP id 5b1f17b1804b1-4538edf9e08mr199742505e9.0.1751370318683; Tue, 01 Jul 2025 04:45:18 -0700 (PDT) X-Google-Smtp-Source: AGHT+IHF4wftffPv/6qtNJJik2Q4NTkD6isOIA22htPfCDaXeTSulgURSVAn8Xkg0bTgVN4xv5l/LQ== X-Received: by 2002:a05:600c:4706:b0:453:8bc7:5e53 with SMTP id 5b1f17b1804b1-4538edf9e08mr199742165e9.0.1751370318233; Tue, 01 Jul 2025 04:45:18 -0700 (PDT) From: Hanna Czenczek To: qemu-block@nongnu.org Cc: qemu-devel@nongnu.org, Hanna Czenczek , Stefan Hajnoczi , Kevin Wolf , Markus Armbruster , Brian Song Subject: [PATCH v3 11/21] fuse: Rename length to blk_len in fuse_write() Date: Tue, 1 Jul 2025 13:44:27 +0200 Message-ID: <20250701114437.207419-12-hreitz@redhat.com> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250701114437.207419-1-hreitz@redhat.com> References: <20250701114437.207419-1-hreitz@redhat.com> 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=170.10.133.124; envelope-from=hreitz@redhat.com; helo=us-smtp-delivery-124.mimecast.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, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=unavailable autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1751370599004124100 Content-Type: text/plain; charset="utf-8" The term "length" is ambiguous, use "blk_len" instead to be clear. Reviewed-by: Stefan Hajnoczi Signed-off-by: Hanna Czenczek --- block/export/fuse.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/block/export/fuse.c b/block/export/fuse.c index 044fbbf1fe..fd7887889c 100644 --- a/block/export/fuse.c +++ b/block/export/fuse.c @@ -679,7 +679,7 @@ static void fuse_write(fuse_req_t req, fuse_ino_t inode= , const char *buf, { FuseExport *exp =3D fuse_req_userdata(req); void *copied; - int64_t length; + int64_t blk_len; int ret; =20 /* Limited by max_write, should not happen */ @@ -705,13 +705,13 @@ static void fuse_write(fuse_req_t req, fuse_ino_t ino= de, const char *buf, * Clients will expect short writes at EOF, so we have to limit * offset+size to the image length. */ - length =3D blk_getlength(exp->common.blk); - if (length < 0) { - fuse_reply_err(req, -length); + blk_len =3D blk_getlength(exp->common.blk); + if (blk_len < 0) { + fuse_reply_err(req, -blk_len); goto free_buffer; } =20 - if (offset + size > length) { + if (offset + size > blk_len) { if (exp->growable) { ret =3D fuse_do_truncate(exp, offset + size, true, PREALLOC_MO= DE_OFF); if (ret < 0) { @@ -719,7 +719,7 @@ static void fuse_write(fuse_req_t req, fuse_ino_t inode= , const char *buf, goto free_buffer; } } else { - size =3D length - offset; + size =3D blk_len - offset; } } =20 --=20 2.49.0 From nobody Sat Nov 15 12:14:53 2025 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=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1751370543; cv=none; d=zohomail.com; s=zohoarc; b=UdHD8MGB7MRKwIvMnMp4FfbCN7JRNJFzsY9Yi4d2eXgarsu4zXUojn25u1Poa6IfQebHOzDTeQLjArTRHlJkQLtopI1llbteggQQVccs6/zOhuPaWC1rGNegGkfJDcZKHX99thg+RxBb1EVKMUQXAtHmojS0lxpIwLWSwg+LNso= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1751370543; h=Content-Type: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=oMe0OVYlTZYOUnzGRhuNbsELyRKdi/6CFqcynNPkjCw=; b=nyPHyT2Q0QzZV1FX8U+MaJDLxswCK0VLVICC3sEcDlB2/Fug0LXEEEExqWrKD/KPzaNg9ZvGkMZe6ohzGKqYzAsYGN/no9rfundFSwIn+ZogABVH4nIvv6W9RXOixPLUaA89tHHe0PoYXfpNcwzGorqKVTcUMs9zTkrx/3x7VOA= 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 lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1751370543324912.4162389372133; Tue, 1 Jul 2025 04:49:03 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1uWZRl-0006Qa-5L; Tue, 01 Jul 2025 07:46:45 -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 1uWZQj-0005Vg-1P for qemu-devel@nongnu.org; Tue, 01 Jul 2025 07:45:41 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uWZQY-0003a2-CH for qemu-devel@nongnu.org; Tue, 01 Jul 2025 07:45:40 -0400 Received: from mail-wr1-f69.google.com (mail-wr1-f69.google.com [209.85.221.69]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-496-q6jaT6KyOtep3jAMtSSolg-1; Tue, 01 Jul 2025 07:45:23 -0400 Received: by mail-wr1-f69.google.com with SMTP id ffacd0b85a97d-3a4edf5bb4dso3657816f8f.0 for ; Tue, 01 Jul 2025 04:45:23 -0700 (PDT) Received: from localhost (p200300cfd700f38d3df6a1ca7d40fe1f.dip0.t-ipconnect.de. [2003:cf:d700:f38d:3df6:a1ca:7d40:fe1f]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-3a88c7e7518sm12850784f8f.2.2025.07.01.04.45.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 01 Jul 2025 04:45:19 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1751370328; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=oMe0OVYlTZYOUnzGRhuNbsELyRKdi/6CFqcynNPkjCw=; b=WJry8N301kh5oO52Ll1zTwkhWBu8rdKJxTfuEIpILVmgPC+OOPoogBvnvQLE3ZZdv6A4bf o833gmFn2KdDBKJnzVtfUWdJMheKz8m3J4ONZ32+FMZaYQ+AB1of1P3a6o5DOK9vIWchqI jXCTddNmQcZIzTlwnIc8A9whgCr8+zc= X-MC-Unique: q6jaT6KyOtep3jAMtSSolg-1 X-Mimecast-MFC-AGG-ID: q6jaT6KyOtep3jAMtSSolg_1751370323 X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1751370322; x=1751975122; 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=oMe0OVYlTZYOUnzGRhuNbsELyRKdi/6CFqcynNPkjCw=; b=EIdTJZnCsMBi2b0npKsZO6ndOMSwL3uhehLQYmtt1dpiParZwpnE59HQIKmwM+Wm/v SAmG6hZ5LFY9Z5yWIPf8xcX51ABO3lagG7IKwBsPmQndBq7xQiDC5m7IC8XFdz4hbKc5 x8MOtNLJaChi2GHVSGvsoDJBhpLOtQpTXiNvMGA7wU+tQQnYagWYO26kjWEqCNBuYijp QpaLRCDQgZzSEaH8aDxom/pLaqvo3mNcT1PZazI+mG2Q9Glo5D1eyKJpbzfU1iRYk8hI zZJLDV2OOiMTQwszdbFjAWuxC4hZlYmKixviv3CPPNL+F0j7bMlmpBpDMkyQwZXTgDIN xdDg== X-Gm-Message-State: AOJu0YxRVMmH4j0sa6x8ge91F4rPAYKiFZgWWNgRdP8aSL+HXQM5+myo /toKx9ooc9qHqRaRTrBVVEAnOZeB2MW2T630Ww7S4mv1HQzI7ntPg1E08XnUFLsDeXhlv3XL3KF sAVrKpE0jI4oZGD9qWWM0TxN57DRT4u/bgGkN9HxK1IHZJ9W4RLYP9TZF X-Gm-Gg: ASbGnctOcvMDdLXEeijavFr9q7bmZkbdBUa8txT1oL02YI36amEKc1AJL9Rcoq0Nqeh UhjRjS0mW23MXa8ZZ266r3+JDFsEiF0aYki1+ohcr+Y1oTKvwaxLBITOgQ8ZH8GOrPpKUF3s5bv Tz2IFa2+zjHVfaINMDoba1TJ/DnznP5Nh+Hq7szzzMv6/qyf8UhEEPsto04/CmuLV9S8TaljpLX c1tdGUp5uWnuC2QGEaYolV+VqcvV+zqHLADygF/eN9dfIN8qrM9yDN8HABPhJ4HjTpBPbHMdqGo 9i3cmSAiZQd7R1L4CyPvunBwX2muJFRN1IKKhjjczx0JZNQBbltkqgAOcO0ppNt+HKmat4FIxEX ktNGb X-Received: by 2002:a05:6000:402a:b0:3a5:300d:5e17 with SMTP id ffacd0b85a97d-3a917603734mr15479243f8f.29.1751370322422; Tue, 01 Jul 2025 04:45:22 -0700 (PDT) X-Google-Smtp-Source: AGHT+IHN2Yw9kikZpOXY+mDEhclFYgRLHty/dbkqGwASlPH8opYztE4LUWpI0gnGzaTZIXorxuUVmQ== X-Received: by 2002:a05:6000:402a:b0:3a5:300d:5e17 with SMTP id ffacd0b85a97d-3a917603734mr15479218f8f.29.1751370321982; Tue, 01 Jul 2025 04:45:21 -0700 (PDT) From: Hanna Czenczek To: qemu-block@nongnu.org Cc: qemu-devel@nongnu.org, Hanna Czenczek , Stefan Hajnoczi , Kevin Wolf , Markus Armbruster , Brian Song Subject: [PATCH v3 12/21] block: Move qemu_fcntl_addfl() into osdep.c Date: Tue, 1 Jul 2025 13:44:28 +0200 Message-ID: <20250701114437.207419-13-hreitz@redhat.com> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250701114437.207419-1-hreitz@redhat.com> References: <20250701114437.207419-1-hreitz@redhat.com> 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=170.10.133.124; envelope-from=hreitz@redhat.com; helo=us-smtp-delivery-124.mimecast.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, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=unavailable autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1751370546545116600 Content-Type: text/plain; charset="utf-8" Move file-posix's helper to add a flag (or a set of flags) to an FD's existing set of flags into osdep.c for other places to use. Suggested-by: Eric Blake Signed-off-by: Hanna Czenczek Reviewed-by: Stefan Hajnoczi --- include/qemu/osdep.h | 1 + block/file-posix.c | 17 +---------------- util/osdep.c | 18 ++++++++++++++++++ 3 files changed, 20 insertions(+), 16 deletions(-) diff --git a/include/qemu/osdep.h b/include/qemu/osdep.h index 96fe51bc39..ff11070c7e 100644 --- a/include/qemu/osdep.h +++ b/include/qemu/osdep.h @@ -619,6 +619,7 @@ int qemu_lock_fd(int fd, int64_t start, int64_t len, bo= ol exclusive); int qemu_unlock_fd(int fd, int64_t start, int64_t len); int qemu_lock_fd_test(int fd, int64_t start, int64_t len, bool exclusive); bool qemu_has_ofd_lock(void); +int qemu_fcntl_addfl(int fd, int flag); #endif =20 bool qemu_has_direct_io(void); diff --git a/block/file-posix.c b/block/file-posix.c index 9b5f08ccb2..045e94d54d 100644 --- a/block/file-posix.c +++ b/block/file-posix.c @@ -1047,21 +1047,6 @@ static int raw_handle_perm_lock(BlockDriverState *bs, return ret; } =20 -/* Sets a specific flag */ -static int fcntl_setfl(int fd, int flag) -{ - int flags; - - flags =3D fcntl(fd, F_GETFL); - if (flags =3D=3D -1) { - return -errno; - } - if (fcntl(fd, F_SETFL, flags | flag) =3D=3D -1) { - return -errno; - } - return 0; -} - static int raw_reconfigure_getfd(BlockDriverState *bs, int flags, int *open_flags, uint64_t perm, Error **e= rrp) { @@ -1100,7 +1085,7 @@ static int raw_reconfigure_getfd(BlockDriverState *bs= , int flags, /* dup the original fd */ fd =3D qemu_dup(s->fd); if (fd >=3D 0) { - ret =3D fcntl_setfl(fd, *open_flags); + ret =3D qemu_fcntl_addfl(fd, *open_flags); if (ret) { qemu_close(fd); fd =3D -1; diff --git a/util/osdep.c b/util/osdep.c index 770369831b..000e7daac8 100644 --- a/util/osdep.c +++ b/util/osdep.c @@ -280,6 +280,24 @@ int qemu_lock_fd_test(int fd, int64_t start, int64_t l= en, bool exclusive) return fl.l_type =3D=3D F_UNLCK ? 0 : -EAGAIN; } } + +/** + * Set the given flag(s) (fcntl GETFL/SETFL) on the given FD, while retain= ing + * other flags. + */ +int qemu_fcntl_addfl(int fd, int flag) +{ + int flags; + + flags =3D fcntl(fd, F_GETFL); + if (flags =3D=3D -1) { + return -errno; + } + if (fcntl(fd, F_SETFL, flags | flag) =3D=3D -1) { + return -errno; + } + return 0; +} #endif =20 bool qemu_has_direct_io(void) --=20 2.49.0 From nobody Sat Nov 15 12:14:53 2025 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=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1751370429; cv=none; d=zohomail.com; s=zohoarc; b=dH26jVMTd4GKTPQX2JeNXJgv0RRiQzmPWOX1JKFBYNi3ApeEiBCascwOuPO98fLkfOVVOlIdDku/sqsr5zLxg11sVAlf5C/0wrCMCm5kozhQvn5ylOvP7pLbH9GOZpTkY4HCxer+a5iptCk4ezE9a9b7dZ+qQnVSuaE04wz2nnQ= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1751370429; h=Content-Type: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=JP8XmZLHNcdiyeyaK+6FJguFZ1bPt6MD8menW4ICUGU=; b=DoQ+j/VjnJ257uSmgNbQMjJZmlDDDpwuqpgkYmh1NHs1O/hIGli8YkH8d5hg9hxJBbNuY/n2Y7wWgak4QTaCQeUblC0wd+HvcLVjA91e0kLudVBaw+W+etvw9nLNPW2V046nBEAvkAmpaIA8l6w4uCDj4H27MBcX2Xxc2e7eZI0= 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 lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1751370429541903.6316463766694; Tue, 1 Jul 2025 04:47:09 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1uWZQl-0005Xq-IF; Tue, 01 Jul 2025 07:45:43 -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 1uWZQf-0005U8-Og for qemu-devel@nongnu.org; Tue, 01 Jul 2025 07:45:39 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uWZQY-0003aA-7B for qemu-devel@nongnu.org; Tue, 01 Jul 2025 07:45:36 -0400 Received: from mail-wm1-f72.google.com (mail-wm1-f72.google.com [209.85.128.72]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-591-Js58WaSWMWGtgrYuwG22ow-1; Tue, 01 Jul 2025 07:45:27 -0400 Received: by mail-wm1-f72.google.com with SMTP id 5b1f17b1804b1-45320bfc18dso27792545e9.1 for ; Tue, 01 Jul 2025 04:45:27 -0700 (PDT) Received: from localhost (p200300cfd700f38d3df6a1ca7d40fe1f.dip0.t-ipconnect.de. [2003:cf:d700:f38d:3df6:a1ca:7d40:fe1f]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-3a892e5b2a7sm13069036f8f.69.2025.07.01.04.45.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 01 Jul 2025 04:45:23 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1751370329; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-type:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=JP8XmZLHNcdiyeyaK+6FJguFZ1bPt6MD8menW4ICUGU=; b=Xhj+BFmRQAI3aCz8rH1n9dvIZwIvI0Gv2NrbslkiS6db9VM0XBjJsN1Unki3DIo5HXcm2i t1AMazSU+0vKCBWABPUdrGHBxd9RCo8cj7vrktpn9tfkt1xNHMheHqarkL6eoB+PhqQ3BP xX3gJbgiRO4bjj0nNOFwxol5rsQgSI0= X-MC-Unique: Js58WaSWMWGtgrYuwG22ow-1 X-Mimecast-MFC-AGG-ID: Js58WaSWMWGtgrYuwG22ow_1751370327 X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1751370327; x=1751975127; 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=JP8XmZLHNcdiyeyaK+6FJguFZ1bPt6MD8menW4ICUGU=; b=h2RvzQ2hJ4CE6yxXYtVRxDQByJccMEH3m8Uhe38R+THB7GmJ3DTcxvs8PO4ryUccS7 JT8ig43Xep039DDdZ48MfdqIlnXWKimeraekRa3EfRn2WnoBe+XR3qriRjrPuQVi294h 3+GKnVk/ekf1c5zsrdZv5zuFlfvEOhocTn7Mlil0whG71NfTIMbbZg8YsJQVX26UD0bx c7TuF+C/A+DyTtHiziGB/9+bUqWK++GHcg5YIJ1VReQx7lkYSZv/364W/Q6K4xA+Qfs8 PNnmzNroN4Dr+y+zhQ7Cy0EbEp5MSuY5k81fVJCu2MkLo7ivEetx8mZKud8GoUFlYAxO QNmw== X-Gm-Message-State: AOJu0YwFGP7mtTWu6kDigOjSg3GnLz7FL8rxFpnhTTHejXba5DgmKdC6 4lMbWbXwI4Nyao/QtRwKyOQsjmzWANt2yyTH12xoY9rYKQas8BjV8lBM5DvFnW0FIM92UE4KF4P Cu2S6LrCmhq/JhFCOcyz4MGl8Xvv8t2wnYVqx+tnU7zfmVicSPY9GfYy0 X-Gm-Gg: ASbGncvqZeHpRqUXVC6vEl7gv+I9aUZK/YmMoyjqAaklBQ6buhDAOJAHkFk/+57pE+9 aXRM4P3ih3R0vR2whmhtwmfx+3yCeeW6+Lk5jajkRYelL26kDln8IY4YPTU6GHCUPaYdHlrsuBF zxlX6aa3xVkOuQN0BzV5GmwK+nfrR9C1TR3w5hyh9XaDVE+8q2vUPly9ENNPtfptr5N+VqD4HwS qX51WYvuhhtHcsgDBTvmCGz11nBSyieV/LQzEeomx+B+VMY21ZjDcD4dvYVMvWatY9w0+IN1jB5 czQQwrFK+eK5aT2R3DsqhjgIyvKt/PoMFXNcx6qErzv1BIEKjE8D+kXQnZuuJ9APZt8e/kt4/h3 EHKwX X-Received: by 2002:a05:600c:3b97:b0:43d:fa5f:7d30 with SMTP id 5b1f17b1804b1-454a0cbb7a8mr7861825e9.16.1751370325709; Tue, 01 Jul 2025 04:45:25 -0700 (PDT) X-Google-Smtp-Source: AGHT+IEF+Kk5V45emhCSh/E3NW+q3LMGjhJuMgaAv9Nr29zpkq+4bd0T8txAjsZUummOFRzYPlgibA== X-Received: by 2002:a05:600c:3b97:b0:43d:fa5f:7d30 with SMTP id 5b1f17b1804b1-454a0cbb7a8mr7861215e9.16.1751370324914; Tue, 01 Jul 2025 04:45:24 -0700 (PDT) From: Hanna Czenczek To: qemu-block@nongnu.org Cc: qemu-devel@nongnu.org, Hanna Czenczek , Stefan Hajnoczi , Kevin Wolf , Markus Armbruster , Brian Song Subject: [PATCH v3 13/21] fuse: Manually process requests (without libfuse) Date: Tue, 1 Jul 2025 13:44:29 +0200 Message-ID: <20250701114437.207419-14-hreitz@redhat.com> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250701114437.207419-1-hreitz@redhat.com> References: <20250701114437.207419-1-hreitz@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Type: text/plain; charset=UTF-8 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=170.10.129.124; envelope-from=hreitz@redhat.com; helo=us-smtp-delivery-124.mimecast.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, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1751370431230116600 Manually read requests from the /dev/fuse FD and process them, without using libfuse. This allows us to safely add parallel request processing in coroutines later, without having to worry about libfuse internals. (Technically, we already have exactly that problem with read_from_fuse_export()/read_from_fuse_fd() nesting.) We will continue to use libfuse for mounting the filesystem; fusermount3 is a effectively a helper program of libfuse, so it should know best how to interact with it. (Doing it manually without libfuse, while doable, is a bit of a pain, and it is not clear to me how stable the "protocol" actually is.) Take this opportunity of quite a major rewrite to update the Copyright line with corrected information that has surfaced in the meantime. Here are some benchmarks from before this patch (4k, iodepth=3D16, libaio; except 'sync', which are iodepth=3D1 and pvsync2): file: read: seq aio: 78.6k =C2=B11.3k IOPS rand aio: 39.3k =C2=B12.9k seq sync: 32.5k =C2=B10.7k rand sync: 9.9k =C2=B10.1k write: seq aio: 61.9k =C2=B10.5k rand aio: 61.2k =C2=B10.6k seq sync: 27.9k =C2=B10.2k rand sync: 27.6k =C2=B10.4k null: read: seq aio: 214.0k =C2=B15.9k rand aio: 212.7k =C2=B14.5k seq sync: 90.3k =C2=B16.5k rand sync: 89.7k =C2=B15.1k write: seq aio: 203.9k =C2=B11.5k rand aio: 201.4k =C2=B13.6k seq sync: 86.1k =C2=B16.2k rand sync: 84.9k =C2=B15.3k And with this patch applied: file: read: seq aio: 76.6k =C2=B11.8k (- 3 %) rand aio: 26.7k =C2=B10.4k (-32 %) seq sync: 47.7k =C2=B11.2k (+47 %) rand sync: 10.1k =C2=B10.2k (+ 2 %) write: seq aio: 58.1k =C2=B10.5k (- 6 %) rand aio: 58.1k =C2=B10.5k (- 5 %) seq sync: 36.3k =C2=B10.3k (+30 %) rand sync: 36.1k =C2=B10.4k (+31 %) null: read: seq aio: 268.4k =C2=B13.4k (+25 %) rand aio: 265.3k =C2=B12.1k (+25 %) seq sync: 134.3k =C2=B12.7k (+49 %) rand sync: 132.4k =C2=B11.4k (+48 %) write: seq aio: 275.3k =C2=B11.7k (+35 %) rand aio: 272.3k =C2=B11.9k (+35 %) seq sync: 130.7k =C2=B11.6k (+52 %) rand sync: 127.4k =C2=B12.4k (+50 %) So clearly the AIO file results are actually not good, and random reads are indeed quite terrible. On the other hand, we can see from the sync and null results that request handling should in theory be quicker. How does this fit together? I believe the bad AIO results are an artifact of the accidental parallel request processing we have due to nested polling: Depending on how the actual request processing is structured and how long request processing takes, more or less requests will be submitted in parallel. So because of the restructuring, I think this patch accidentally changes how many requests end up being submitted in parallel, which decreases performance. (I have seen something like this before: In RSD, without having implemented a polling mode, the debug build tended to have better performance than the more optimized release build, because the debug build, taking longer to submit requests, ended up processing more requests in parallel.) In any case, once we use coroutines throughout the code, performance will improve again across the board. Reviewed-by: Stefan Hajnoczi Signed-off-by: Hanna Czenczek --- block/export/fuse.c | 754 +++++++++++++++++++++++++++++++------------- 1 file changed, 535 insertions(+), 219 deletions(-) diff --git a/block/export/fuse.c b/block/export/fuse.c index fd7887889c..85ebc6bda8 100644 --- a/block/export/fuse.c +++ b/block/export/fuse.c @@ -1,7 +1,7 @@ /* * Present a block device as a raw image through FUSE * - * Copyright (c) 2020 Max Reitz + * Copyright (c) 2020, 2025 Hanna Czenczek * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -27,12 +27,15 @@ #include "block/qapi.h" #include "qapi/error.h" #include "qapi/qapi-commands-block.h" +#include "qemu/error-report.h" #include "qemu/main-loop.h" #include "system/block-backend.h" =20 #include #include =20 +#include "standard-headers/linux/fuse.h" + #if defined(CONFIG_FALLOCATE_ZERO_RANGE) #include #endif @@ -42,17 +45,27 @@ #endif =20 /* Prevent overly long bounce buffer allocations */ -#define FUSE_MAX_BOUNCE_BYTES (MIN(BDRV_REQUEST_MAX_BYTES, 64 * 1024 * 102= 4)) - +#define FUSE_MAX_READ_BYTES (MIN(BDRV_REQUEST_MAX_BYTES, 64 * 1024 * 1024)) +/* Small enough to fit in the request buffer */ +#define FUSE_MAX_WRITE_BYTES (4 * 1024) =20 typedef struct FuseExport { BlockExport common; =20 struct fuse_session *fuse_session; - struct fuse_buf fuse_buf; unsigned int in_flight; /* atomic */ bool mounted, fd_handler_set_up; =20 + /* + * The request buffer must be able to hold a full write, and/or at lea= st + * FUSE_MIN_READ_BUFFER (from linux/fuse.h) bytes + */ + char request_buf[MAX_CONST( + sizeof(struct fuse_in_header) + sizeof(struct fuse_write_in) + + FUSE_MAX_WRITE_BYTES, + FUSE_MIN_READ_BUFFER + )]; + /* * Set when there was an unrecoverable error and no requests should be= read * from the device anymore (basically only in case of something we wou= ld @@ -60,6 +73,8 @@ typedef struct FuseExport { */ bool halted; =20 + int fuse_fd; + char *mountpoint; bool writable; bool growable; @@ -72,19 +87,19 @@ typedef struct FuseExport { } FuseExport; =20 static GHashTable *exports; -static const struct fuse_lowlevel_ops fuse_ops; =20 static void fuse_export_shutdown(BlockExport *exp); static void fuse_export_delete(BlockExport *exp); -static void fuse_export_halt(FuseExport *exp) G_GNUC_UNUSED; +static void fuse_export_halt(FuseExport *exp); =20 static void init_exports_table(void); =20 static int mount_fuse_export(FuseExport *exp, Error **errp); -static void read_from_fuse_export(void *opaque); =20 static bool is_regular_file(const char *path, Error **errp); =20 +static void read_from_fuse_fd(void *opaque); +static void fuse_process_request(FuseExport *exp); =20 static void fuse_inc_in_flight(FuseExport *exp) { @@ -105,22 +120,26 @@ static void fuse_dec_in_flight(FuseExport *exp) } } =20 +/** + * Attach FUSE FD read handler. + */ static void fuse_attach_handlers(FuseExport *exp) { if (exp->halted) { return; } =20 - aio_set_fd_handler(exp->common.ctx, - fuse_session_fd(exp->fuse_session), - read_from_fuse_export, NULL, NULL, NULL, exp); + aio_set_fd_handler(exp->common.ctx, exp->fuse_fd, + read_from_fuse_fd, NULL, NULL, NULL, exp); exp->fd_handler_set_up =3D true; } =20 +/** + * Detach FUSE FD read handler. + */ static void fuse_detach_handlers(FuseExport *exp) { - aio_set_fd_handler(exp->common.ctx, - fuse_session_fd(exp->fuse_session), + aio_set_fd_handler(exp->common.ctx, exp->fuse_fd, NULL, NULL, NULL, NULL, NULL); exp->fd_handler_set_up =3D false; } @@ -247,6 +266,13 @@ static int fuse_export_create(BlockExport *blk_exp, =20 g_hash_table_insert(exports, g_strdup(exp->mountpoint), NULL); =20 + exp->fuse_fd =3D fuse_session_fd(exp->fuse_session); + ret =3D qemu_fcntl_addfl(exp->fuse_fd, O_NONBLOCK); + if (ret < 0) { + error_setg_errno(errp, -ret, "Failed to make FUSE FD non-blocking"= ); + goto fail; + } + fuse_attach_handlers(exp); return 0; =20 @@ -292,7 +318,7 @@ static int mount_fuse_export(FuseExport *exp, Error **e= rrp) mount_opts =3D g_strdup_printf("%s,nosuid,nodev,noatime,max_read=3D%zu= ," "default_permissions%s", exp->writable ? "rw" : "ro", - FUSE_MAX_BOUNCE_BYTES, + FUSE_MAX_READ_BYTES, exp->allow_other ? ",allow_other" : ""); =20 fuse_argv[0] =3D ""; /* Dummy program name */ @@ -301,8 +327,8 @@ static int mount_fuse_export(FuseExport *exp, Error **e= rrp) fuse_argv[3] =3D NULL; fuse_args =3D (struct fuse_args)FUSE_ARGS_INIT(3, (char **)fuse_argv); =20 - exp->fuse_session =3D fuse_session_new(&fuse_args, &fuse_ops, - sizeof(fuse_ops), exp); + /* We just create the session for mounting/unmounting, no need to set = ops */ + exp->fuse_session =3D fuse_session_new(&fuse_args, NULL, 0, NULL); g_free(mount_opts); if (!exp->fuse_session) { error_setg(errp, "Failed to set up FUSE session"); @@ -320,36 +346,54 @@ static int mount_fuse_export(FuseExport *exp, Error *= *errp) } =20 /** - * Callback to be invoked when the FUSE session FD can be read from. - * (This is basically the FUSE event loop.) + * Try to read and process a single request from the FUSE FD. */ -static void read_from_fuse_export(void *opaque) +static void read_from_fuse_fd(void *opaque) { FuseExport *exp =3D opaque; - int ret; + int fuse_fd =3D exp->fuse_fd; + ssize_t ret; + const struct fuse_in_header *in_hdr; + + fuse_inc_in_flight(exp); =20 if (unlikely(exp->halted)) { - return; + goto no_request; } =20 - fuse_inc_in_flight(exp); + ret =3D RETRY_ON_EINTR(read(fuse_fd, exp->request_buf, + sizeof(exp->request_buf))); + if (ret < 0 && errno =3D=3D EAGAIN) { + /* No request available */ + goto no_request; + } else if (unlikely(ret < 0)) { + error_report("Failed to read from FUSE device: %s", strerror(-ret)= ); + goto no_request; + } =20 - do { - ret =3D fuse_session_receive_buf(exp->fuse_session, &exp->fuse_buf= ); - } while (ret =3D=3D -EINTR); - if (ret < 0) { - goto out; + if (unlikely(ret < sizeof(*in_hdr))) { + error_report("Incomplete read from FUSE device, expected at least = %zu " + "bytes, read %zi bytes; cannot trust subsequent " + "requests, halting the export", + sizeof(*in_hdr), ret); + fuse_export_halt(exp); + goto no_request; } =20 - /* - * Note that aio_poll() in any request-processing function can lead to= a - * nested read_from_fuse_export() call, which will overwrite the conte= nts of - * exp->fuse_buf. Anything that takes a buffer needs to take care tha= t the - * content is copied before potentially polling via aio_poll(). - */ - fuse_session_process_buf(exp->fuse_session, &exp->fuse_buf); + in_hdr =3D (const struct fuse_in_header *)exp->request_buf; + if (unlikely(ret !=3D in_hdr->len)) { + error_report("Number of bytes read from FUSE device does not match= " + "request size, expected %" PRIu32 " bytes, read %zi " + "bytes; cannot trust subsequent requests, halting the= " + "export", + in_hdr->len, ret); + fuse_export_halt(exp); + goto no_request; + } + + fuse_process_request(exp); =20 -out: +no_request: fuse_dec_in_flight(exp); } =20 @@ -357,18 +401,14 @@ static void fuse_export_shutdown(BlockExport *blk_exp) { FuseExport *exp =3D container_of(blk_exp, FuseExport, common); =20 - if (exp->fuse_session) { - fuse_session_exit(exp->fuse_session); - - if (exp->fd_handler_set_up) { - fuse_detach_handlers(exp); - } + if (exp->fd_handler_set_up) { + fuse_detach_handlers(exp); } =20 if (exp->mountpoint) { /* - * Safe to drop now, because we will not handle any requests - * for this export anymore anyway. + * Safe to drop now, because we will not handle any requests for t= his + * export anymore anyway (at least not from the main thread). */ g_hash_table_remove(exports, exp->mountpoint); } @@ -386,7 +426,6 @@ static void fuse_export_delete(BlockExport *blk_exp) fuse_session_destroy(exp->fuse_session); } =20 - free(exp->fuse_buf.mem); g_free(exp->mountpoint); } =20 @@ -428,46 +467,57 @@ static bool is_regular_file(const char *path, Error *= *errp) } =20 /** - * A chance to set change some parameters supplied to FUSE_INIT. + * Process FUSE INIT. + * Return the number of bytes written to *out on success, and -errno on er= ror. */ -static void fuse_init(void *userdata, struct fuse_conn_info *conn) +static ssize_t fuse_init(FuseExport *exp, struct fuse_init_out *out, + uint32_t max_readahead, uint32_t flags) { - /* - * MIN_NON_ZERO() would not be wrong here, but what we set here - * must equal what has been passed to fuse_session_new(). - * Therefore, as long as max_read must be passed as a mount option - * (which libfuse claims will be changed at some point), we have - * to set max_read to a fixed value here. - */ - conn->max_read =3D FUSE_MAX_BOUNCE_BYTES; + const uint32_t supported_flags =3D FUSE_ASYNC_READ | FUSE_ASYNC_DIO; =20 - conn->max_write =3D MIN_NON_ZERO(BDRV_REQUEST_MAX_BYTES, conn->max_wri= te); -} + *out =3D (struct fuse_init_out) { + .major =3D FUSE_KERNEL_VERSION, + .minor =3D FUSE_KERNEL_MINOR_VERSION, + .max_readahead =3D max_readahead, + .max_write =3D FUSE_MAX_WRITE_BYTES, + .flags =3D flags & supported_flags, + .flags2 =3D 0, =20 -/** - * Let clients look up files. Always return ENOENT because we only - * care about the mountpoint itself. - */ -static void fuse_lookup(fuse_req_t req, fuse_ino_t parent, const char *nam= e) -{ - fuse_reply_err(req, ENOENT); + /* libfuse maximum: 2^16 - 1 */ + .max_background =3D UINT16_MAX, + + /* libfuse default: max_background * 3 / 4 */ + .congestion_threshold =3D (int)UINT16_MAX * 3 / 4, + + /* libfuse default: 1 */ + .time_gran =3D 1, + + /* + * probably unneeded without FUSE_MAX_PAGES, but this would be the + * libfuse default + */ + .max_pages =3D DIV_ROUND_UP(FUSE_MAX_WRITE_BYTES, + qemu_real_host_page_size()), + + /* Only needed for mappings (i.e. DAX) */ + .map_alignment =3D 0, + }; + + return sizeof(*out); } =20 /** * Let clients get file attributes (i.e., stat() the file). + * Return the number of bytes written to *out on success, and -errno on er= ror. */ -static void fuse_getattr(fuse_req_t req, fuse_ino_t inode, - struct fuse_file_info *fi) +static ssize_t fuse_getattr(FuseExport *exp, struct fuse_attr_out *out) { - struct stat statbuf; int64_t length, allocated_blocks; time_t now =3D time(NULL); - FuseExport *exp =3D fuse_req_userdata(req); =20 length =3D blk_getlength(exp->common.blk); if (length < 0) { - fuse_reply_err(req, -length); - return; + return length; } =20 allocated_blocks =3D bdrv_get_allocated_file_size(blk_bs(exp->common.b= lk)); @@ -477,21 +527,24 @@ static void fuse_getattr(fuse_req_t req, fuse_ino_t i= node, allocated_blocks =3D DIV_ROUND_UP(allocated_blocks, 512); } =20 - statbuf =3D (struct stat) { - .st_ino =3D 1, - .st_mode =3D exp->st_mode, - .st_nlink =3D 1, - .st_uid =3D exp->st_uid, - .st_gid =3D exp->st_gid, - .st_size =3D length, - .st_blksize =3D blk_bs(exp->common.blk)->bl.request_alignment, - .st_blocks =3D allocated_blocks, - .st_atime =3D now, - .st_mtime =3D now, - .st_ctime =3D now, + *out =3D (struct fuse_attr_out) { + .attr_valid =3D 1, + .attr =3D { + .ino =3D 1, + .mode =3D exp->st_mode, + .nlink =3D 1, + .uid =3D exp->st_uid, + .gid =3D exp->st_gid, + .size =3D length, + .blksize =3D blk_bs(exp->common.blk)->bl.request_alignment, + .blocks =3D allocated_blocks, + .atime =3D now, + .mtime =3D now, + .ctime =3D now, + }, }; =20 - fuse_reply_attr(req, &statbuf, 1.); + return sizeof(*out); } =20 static int fuse_do_truncate(const FuseExport *exp, int64_t size, @@ -544,159 +597,151 @@ static int fuse_do_truncate(const FuseExport *exp, = int64_t size, * permit access: Read-only exports cannot be given +w, and exports * without allow_other cannot be given a different UID or GID, and * they cannot be given non-owner access. + * Return the number of bytes written to *out on success, and -errno on er= ror. */ -static void fuse_setattr(fuse_req_t req, fuse_ino_t inode, struct stat *st= atbuf, - int to_set, struct fuse_file_info *fi) +static ssize_t fuse_setattr(FuseExport *exp, struct fuse_attr_out *out, + uint32_t to_set, uint64_t size, uint32_t mode, + uint32_t uid, uint32_t gid) { - FuseExport *exp =3D fuse_req_userdata(req); int supported_attrs; int ret; =20 - supported_attrs =3D FUSE_SET_ATTR_SIZE | FUSE_SET_ATTR_MODE; + /* SIZE and MODE are actually supported, the others can be safely igno= red */ + supported_attrs =3D FATTR_SIZE | FATTR_MODE | + FATTR_FH | FATTR_LOCKOWNER | FATTR_KILL_SUIDGID; if (exp->allow_other) { - supported_attrs |=3D FUSE_SET_ATTR_UID | FUSE_SET_ATTR_GID; + supported_attrs |=3D FATTR_UID | FATTR_GID; } =20 if (to_set & ~supported_attrs) { - fuse_reply_err(req, ENOTSUP); - return; + return -ENOTSUP; } =20 /* Do some argument checks first before committing to anything */ - if (to_set & FUSE_SET_ATTR_MODE) { + if (to_set & FATTR_MODE) { /* * Without allow_other, non-owners can never access the export, so= do * not allow setting permissions for them */ - if (!exp->allow_other && - (statbuf->st_mode & (S_IRWXG | S_IRWXO)) !=3D 0) - { - fuse_reply_err(req, EPERM); - return; + if (!exp->allow_other && (mode & (S_IRWXG | S_IRWXO)) !=3D 0) { + return -EPERM; } =20 /* +w for read-only exports makes no sense, disallow it */ - if (!exp->writable && - (statbuf->st_mode & (S_IWUSR | S_IWGRP | S_IWOTH)) !=3D 0) - { - fuse_reply_err(req, EROFS); - return; + if (!exp->writable && (mode & (S_IWUSR | S_IWGRP | S_IWOTH)) !=3D = 0) { + return -EROFS; } } =20 - if (to_set & FUSE_SET_ATTR_SIZE) { + if (to_set & FATTR_SIZE) { if (!exp->writable) { - fuse_reply_err(req, EACCES); - return; + return -EACCES; } =20 - ret =3D fuse_do_truncate(exp, statbuf->st_size, true, PREALLOC_MOD= E_OFF); + ret =3D fuse_do_truncate(exp, size, true, PREALLOC_MODE_OFF); if (ret < 0) { - fuse_reply_err(req, -ret); - return; + return ret; } } =20 - if (to_set & FUSE_SET_ATTR_MODE) { + if (to_set & FATTR_MODE) { /* Ignore FUSE-supplied file type, only change the mode */ - exp->st_mode =3D (statbuf->st_mode & 07777) | S_IFREG; + exp->st_mode =3D (mode & 07777) | S_IFREG; } =20 - if (to_set & FUSE_SET_ATTR_UID) { - exp->st_uid =3D statbuf->st_uid; + if (to_set & FATTR_UID) { + exp->st_uid =3D uid; } =20 - if (to_set & FUSE_SET_ATTR_GID) { - exp->st_gid =3D statbuf->st_gid; + if (to_set & FATTR_GID) { + exp->st_gid =3D gid; } =20 - fuse_getattr(req, inode, fi); + return fuse_getattr(exp, out); } =20 /** - * Let clients open a file (i.e., the exported image). + * Open an inode. We only have a single inode in our exported filesystem,= so we + * just acknowledge the request. + * Return the number of bytes written to *out on success, and -errno on er= ror. */ -static void fuse_open(fuse_req_t req, fuse_ino_t inode, - struct fuse_file_info *fi) +static ssize_t fuse_open(FuseExport *exp, struct fuse_open_out *out) { - fi->direct_io =3D true; - fi->parallel_direct_writes =3D true; - fuse_reply_open(req, fi); + *out =3D (struct fuse_open_out) { + .open_flags =3D FOPEN_DIRECT_IO | FOPEN_PARALLEL_DIRECT_WRITES, + }; + return sizeof(*out); } =20 /** - * Handle client reads from the exported image. + * Handle client reads from the exported image. Allocates *bufptr and rea= ds + * data from the block device into that buffer. + * Returns the buffer (read) size on success, and -errno on error. + * After use, *bufptr must be freed via qemu_vfree(). */ -static void fuse_read(fuse_req_t req, fuse_ino_t inode, - size_t size, off_t offset, struct fuse_file_info *fi) +static ssize_t fuse_read(FuseExport *exp, void **bufptr, + uint64_t offset, uint32_t size) { - FuseExport *exp =3D fuse_req_userdata(req); - int64_t length; + int64_t blk_len; void *buf; int ret; =20 /* Limited by max_read, should not happen */ - if (size > FUSE_MAX_BOUNCE_BYTES) { - fuse_reply_err(req, EINVAL); - return; + if (size > FUSE_MAX_READ_BYTES) { + return -EINVAL; } =20 /** * Clients will expect short reads at EOF, so we have to limit * offset+size to the image length. */ - length =3D blk_getlength(exp->common.blk); - if (length < 0) { - fuse_reply_err(req, -length); - return; + blk_len =3D blk_getlength(exp->common.blk); + if (blk_len < 0) { + return blk_len; } =20 - if (offset + size > length) { - size =3D length - offset; + if (offset + size > blk_len) { + size =3D blk_len - offset; } =20 buf =3D qemu_try_blockalign(blk_bs(exp->common.blk), size); if (!buf) { - fuse_reply_err(req, ENOMEM); - return; + return -ENOMEM; } =20 ret =3D blk_pread(exp->common.blk, offset, size, buf, 0); - if (ret >=3D 0) { - fuse_reply_buf(req, buf, size); - } else { - fuse_reply_err(req, -ret); + if (ret < 0) { + qemu_vfree(buf); + return ret; } =20 - qemu_vfree(buf); + *bufptr =3D buf; + return size; } =20 /** - * Handle client writes to the exported image. + * Handle client writes to the exported image. @buf has the data to be wr= itten + * and will be copied to a bounce buffer before polling for the first time. + * Return the number of bytes written to *out on success, and -errno on er= ror. */ -static void fuse_write(fuse_req_t req, fuse_ino_t inode, const char *buf, - size_t size, off_t offset, struct fuse_file_info *f= i) +static ssize_t fuse_write(FuseExport *exp, struct fuse_write_out *out, + uint64_t offset, uint32_t size, const void *buf) { - FuseExport *exp =3D fuse_req_userdata(req); void *copied; int64_t blk_len; int ret; =20 /* Limited by max_write, should not happen */ if (size > BDRV_REQUEST_MAX_BYTES) { - fuse_reply_err(req, EINVAL); - return; + return -EINVAL; } =20 if (!exp->writable) { - fuse_reply_err(req, EACCES); - return; + return -EACCES; } =20 /* - * Heed the note on read_from_fuse_export(): If we call aio_poll() (wh= ich - * any blk_*() I/O function may do), read_from_fuse_export() may be ne= sted, - * overwriting the request buffer content. Therefore, we must copy it= here. + * Must copy to bounce buffer before calling aio_poll() (to allow nest= ing) */ copied =3D blk_blockalign(exp->common.blk, size); memcpy(copied, buf, size); @@ -707,16 +752,15 @@ static void fuse_write(fuse_req_t req, fuse_ino_t ino= de, const char *buf, */ blk_len =3D blk_getlength(exp->common.blk); if (blk_len < 0) { - fuse_reply_err(req, -blk_len); - goto free_buffer; + ret =3D blk_len; + goto fail_free_buffer; } =20 if (offset + size > blk_len) { if (exp->growable) { ret =3D fuse_do_truncate(exp, offset + size, true, PREALLOC_MO= DE_OFF); if (ret < 0) { - fuse_reply_err(req, -ret); - goto free_buffer; + goto fail_free_buffer; } } else { size =3D blk_len - offset; @@ -724,36 +768,39 @@ static void fuse_write(fuse_req_t req, fuse_ino_t ino= de, const char *buf, } =20 ret =3D blk_pwrite(exp->common.blk, offset, size, copied, 0); - if (ret >=3D 0) { - fuse_reply_write(req, size); - } else { - fuse_reply_err(req, -ret); + if (ret < 0) { + goto fail_free_buffer; } =20 -free_buffer: qemu_vfree(copied); + + *out =3D (struct fuse_write_out) { + .size =3D size, + }; + return sizeof(*out); + +fail_free_buffer: + qemu_vfree(copied); + return ret; } =20 /** * Let clients perform various fallocate() operations. + * Return 0 on success (no 'out' object), and -errno on error. */ -static void fuse_fallocate(fuse_req_t req, fuse_ino_t inode, int mode, - off_t offset, off_t length, - struct fuse_file_info *fi) +static ssize_t fuse_fallocate(FuseExport *exp, uint64_t offset, uint64_t l= ength, + uint32_t mode) { - FuseExport *exp =3D fuse_req_userdata(req); int64_t blk_len; int ret; =20 if (!exp->writable) { - fuse_reply_err(req, EACCES); - return; + return -EACCES; } =20 blk_len =3D blk_getlength(exp->common.blk); if (blk_len < 0) { - fuse_reply_err(req, -blk_len); - return; + return blk_len; } =20 #ifdef CONFIG_FALLOCATE_PUNCH_HOLE @@ -765,16 +812,14 @@ static void fuse_fallocate(fuse_req_t req, fuse_ino_t= inode, int mode, if (!mode) { /* We can only fallocate at the EOF with a truncate */ if (offset < blk_len) { - fuse_reply_err(req, EOPNOTSUPP); - return; + return -EOPNOTSUPP; } =20 if (offset > blk_len) { /* No preallocation needed here */ ret =3D fuse_do_truncate(exp, offset, true, PREALLOC_MODE_OFF); if (ret < 0) { - fuse_reply_err(req, -ret); - return; + return ret; } } =20 @@ -784,8 +829,7 @@ static void fuse_fallocate(fuse_req_t req, fuse_ino_t i= node, int mode, #ifdef CONFIG_FALLOCATE_PUNCH_HOLE else if (mode & FALLOC_FL_PUNCH_HOLE) { if (!(mode & FALLOC_FL_KEEP_SIZE)) { - fuse_reply_err(req, EINVAL); - return; + return -EINVAL; } =20 do { @@ -813,8 +857,7 @@ static void fuse_fallocate(fuse_req_t req, fuse_ino_t i= node, int mode, ret =3D fuse_do_truncate(exp, offset + length, false, PREALLOC_MODE_OFF); if (ret < 0) { - fuse_reply_err(req, -ret); - return; + return ret; } } =20 @@ -832,44 +875,38 @@ static void fuse_fallocate(fuse_req_t req, fuse_ino_t= inode, int mode, ret =3D -EOPNOTSUPP; } =20 - fuse_reply_err(req, ret < 0 ? -ret : 0); + return ret < 0 ? ret : 0; } =20 /** * Let clients fsync the exported image. + * Return 0 on success (no 'out' object), and -errno on error. */ -static void fuse_fsync(fuse_req_t req, fuse_ino_t inode, int datasync, - struct fuse_file_info *fi) +static ssize_t fuse_fsync(FuseExport *exp) { - FuseExport *exp =3D fuse_req_userdata(req); - int ret; - - ret =3D blk_flush(exp->common.blk); - fuse_reply_err(req, ret < 0 ? -ret : 0); + return blk_flush(exp->common.blk); } =20 /** * Called before an FD to the exported image is closed. (libfuse * notes this to be a way to return last-minute errors.) + * Return 0 on success (no 'out' object), and -errno on error. */ -static void fuse_flush(fuse_req_t req, fuse_ino_t inode, - struct fuse_file_info *fi) +static ssize_t fuse_flush(FuseExport *exp) { - fuse_fsync(req, inode, 1, fi); + return blk_flush(exp->common.blk); } =20 #ifdef CONFIG_FUSE_LSEEK /** * Let clients inquire allocation status. + * Return the number of bytes written to *out on success, and -errno on er= ror. */ -static void fuse_lseek(fuse_req_t req, fuse_ino_t inode, off_t offset, - int whence, struct fuse_file_info *fi) +static ssize_t fuse_lseek(FuseExport *exp, struct fuse_lseek_out *out, + uint64_t offset, uint32_t whence) { - FuseExport *exp =3D fuse_req_userdata(req); - if (whence !=3D SEEK_HOLE && whence !=3D SEEK_DATA) { - fuse_reply_err(req, EINVAL); - return; + return -EINVAL; } =20 while (true) { @@ -879,8 +916,7 @@ static void fuse_lseek(fuse_req_t req, fuse_ino_t inode= , off_t offset, ret =3D bdrv_block_status_above(blk_bs(exp->common.blk), NULL, offset, INT64_MAX, &pnum, NULL, NULL= ); if (ret < 0) { - fuse_reply_err(req, -ret); - return; + return ret; } =20 if (!pnum && (ret & BDRV_BLOCK_EOF)) { @@ -897,34 +933,38 @@ static void fuse_lseek(fuse_req_t req, fuse_ino_t ino= de, off_t offset, =20 blk_len =3D blk_getlength(exp->common.blk); if (blk_len < 0) { - fuse_reply_err(req, -blk_len); - return; + return blk_len; } =20 if (offset > blk_len || whence =3D=3D SEEK_DATA) { - fuse_reply_err(req, ENXIO); - } else { - fuse_reply_lseek(req, offset); + return -ENXIO; } - return; + + *out =3D (struct fuse_lseek_out) { + .offset =3D offset, + }; + return sizeof(*out); } =20 if (ret & BDRV_BLOCK_DATA) { if (whence =3D=3D SEEK_DATA) { - fuse_reply_lseek(req, offset); - return; + *out =3D (struct fuse_lseek_out) { + .offset =3D offset, + }; + return sizeof(*out); } } else { if (whence =3D=3D SEEK_HOLE) { - fuse_reply_lseek(req, offset); - return; + *out =3D (struct fuse_lseek_out) { + .offset =3D offset, + }; + return sizeof(*out); } } =20 /* Safety check against infinite loops */ if (!pnum) { - fuse_reply_err(req, ENXIO); - return; + return -ENXIO; } =20 offset +=3D pnum; @@ -932,21 +972,297 @@ static void fuse_lseek(fuse_req_t req, fuse_ino_t in= ode, off_t offset, } #endif =20 -static const struct fuse_lowlevel_ops fuse_ops =3D { - .init =3D fuse_init, - .lookup =3D fuse_lookup, - .getattr =3D fuse_getattr, - .setattr =3D fuse_setattr, - .open =3D fuse_open, - .read =3D fuse_read, - .write =3D fuse_write, - .fallocate =3D fuse_fallocate, - .flush =3D fuse_flush, - .fsync =3D fuse_fsync, +/** + * Write a FUSE response to the given @fd, using a single buffer consecuti= vely + * containing both the response header and data: Initialize *out_hdr, and = write + * it plus @response_data_length consecutive bytes to @fd. + * + * @fd: FUSE file descriptor + * @req_id: Corresponding request ID + * @out_hdr: Pointer to buffer that will hold the output header, and + * additionally already contains @response_data_length data bytes + * starting at *out_hdr + 1. + * @err: Error code (-errno, or 0 in case of success) + * @response_data_length: Length of data to return (following *out_hdr) + */ +static int fuse_write_response(int fd, uint32_t req_id, + struct fuse_out_header *out_hdr, int err, + size_t response_data_length) +{ + void *write_ptr =3D out_hdr; + size_t to_write =3D sizeof(*out_hdr) + response_data_length; + ssize_t ret; + + *out_hdr =3D (struct fuse_out_header) { + .len =3D to_write, + .error =3D err, + .unique =3D req_id, + }; + + while (true) { + ret =3D RETRY_ON_EINTR(write(fd, write_ptr, to_write)); + if (ret < 0) { + ret =3D -errno; + error_report("Failed to write to FUSE device: %s", strerror(-r= et)); + return ret; + } else { + to_write -=3D ret; + if (to_write > 0) { + write_ptr +=3D ret; + } else { + return 0; /* success */ + } + } + } +} + +/** + * Write a FUSE response to the given @fd, using separate buffers for the + * response header and data: Initialize *out_hdr, and write it plus the da= ta in + * *buf to @fd. + * + * In contrast to fuse_write_response(), this function cannot return error= s, and + * will always return success (error code 0). + * + * @fd: FUSE file descriptor + * @req_id: Corresponding request ID + * @out_hdr: Pointer to buffer that will hold the output header + * @buf: Pointer to response data + * @buflen: Length of response data + */ +static int fuse_write_buf_response(int fd, uint32_t req_id, + struct fuse_out_header *out_hdr, + const void *buf, size_t buflen) +{ + struct iovec iov[2] =3D { + { out_hdr, sizeof(*out_hdr) }, + { (void *)buf, buflen }, + }; + struct iovec *iovp =3D iov; + unsigned iov_count =3D ARRAY_SIZE(iov); + size_t to_write =3D sizeof(*out_hdr) + buflen; + ssize_t ret; + + *out_hdr =3D (struct fuse_out_header) { + .len =3D to_write, + .unique =3D req_id, + }; + + while (true) { + ret =3D RETRY_ON_EINTR(writev(fd, iovp, iov_count)); + if (ret < 0) { + ret =3D -errno; + error_report("Failed to write to FUSE device: %s", strerror(-r= et)); + return ret; + } else { + to_write -=3D ret; + if (to_write > 0) { + iov_discard_front(&iovp, &iov_count, ret); + } else { + return 0; /* success */ + } + } + } +} + +/* + * For use in fuse_process_request(): + * Returns a pointer to the parameter object for the given operation (insi= de of + * export->request_buf, which is assumed to hold a fuse_in_header first). + * Verifies that the object is complete (export->request_buf is large enou= gh to + * hold it in one piece, and the request length includes the whole object). + * + * Note that export->request_buf may be overwritten after polling, so the + * returned pointer must not be used across a function that may poll! + */ +#define FUSE_IN_OP_STRUCT(op_name, export) \ + ({ \ + const struct fuse_in_header *__in_hdr =3D \ + (const struct fuse_in_header *)(export)->request_buf; \ + const struct fuse_##op_name##_in *__in =3D \ + (const struct fuse_##op_name##_in *)(__in_hdr + 1); \ + const size_t __param_len =3D sizeof(*__in_hdr) + sizeof(*__in); \ + uint32_t __req_len; \ + \ + QEMU_BUILD_BUG_ON(sizeof((export)->request_buf) < __param_len); \ + \ + __req_len =3D __in_hdr->len; \ + if (__req_len < __param_len) { \ + warn_report("FUSE request truncated (%" PRIu32 " < %zu)", \ + __req_len, __param_len); \ + ret =3D -EINVAL; \ + break; \ + } \ + __in; \ + }) + +/* + * For use in fuse_process_request(): + * Returns a pointer to the return object for the given operation (inside = of + * out_buf, which is assumed to hold a fuse_out_header first). + * Verifies that out_buf is large enough to hold the whole object. + * + * (out_buf should be a char[] array.) + */ +#define FUSE_OUT_OP_STRUCT(op_name, out_buf) \ + ({ \ + struct fuse_out_header *__out_hdr =3D \ + (struct fuse_out_header *)(out_buf); \ + struct fuse_##op_name##_out *__out =3D \ + (struct fuse_##op_name##_out *)(__out_hdr + 1); \ + \ + QEMU_BUILD_BUG_ON(sizeof(*__out_hdr) + sizeof(*__out) > \ + sizeof(out_buf)); \ + \ + __out; \ + }) + +/** + * Process a FUSE request, incl. writing the response. + * + * Note that polling in any request-processing function can lead to a nest= ed + * read_from_fuse_fd() call, which will overwrite the contents of + * exp->request_buf. Anything that takes a buffer needs to take care that= the + * content is copied before potentially polling. + */ +static void fuse_process_request(FuseExport *exp) +{ + uint32_t opcode; + uint64_t req_id; + /* + * Return buffer. Must be large enough to hold all return headers, bu= t does + * not include space for data returned by read requests. + * (FUSE_IN_OP_STRUCT() verifies at compile time that out_buf is indeed + * large enough.) + */ + char out_buf[sizeof(struct fuse_out_header) + + MAX_CONST(sizeof(struct fuse_init_out), + MAX_CONST(sizeof(struct fuse_open_out), + MAX_CONST(sizeof(struct fuse_attr_out), + MAX_CONST(sizeof(struct fuse_write_out), + sizeof(struct fuse_lseek_out)))))]; + struct fuse_out_header *out_hdr =3D (struct fuse_out_header *)out_buf; + /* For read requests: Data to be returned */ + void *out_data_buffer =3D NULL; + ssize_t ret; + + /* Limit scope to ensure pointer is no longer used after polling */ + { + const struct fuse_in_header *in_hdr =3D + (const struct fuse_in_header *)exp->request_buf; + + opcode =3D in_hdr->opcode; + req_id =3D in_hdr->unique; + } + + switch (opcode) { + case FUSE_INIT: { + const struct fuse_init_in *in =3D FUSE_IN_OP_STRUCT(init, exp); + ret =3D fuse_init(exp, FUSE_OUT_OP_STRUCT(init, out_buf), + in->max_readahead, in->flags); + break; + } + + case FUSE_OPEN: + ret =3D fuse_open(exp, FUSE_OUT_OP_STRUCT(open, out_buf)); + break; + + case FUSE_RELEASE: + ret =3D 0; + break; + + case FUSE_LOOKUP: + ret =3D -ENOENT; /* There is no node but the root node */ + break; + + case FUSE_GETATTR: + ret =3D fuse_getattr(exp, FUSE_OUT_OP_STRUCT(attr, out_buf)); + break; + + case FUSE_SETATTR: { + const struct fuse_setattr_in *in =3D FUSE_IN_OP_STRUCT(setattr, ex= p); + ret =3D fuse_setattr(exp, FUSE_OUT_OP_STRUCT(attr, out_buf), + in->valid, in->size, in->mode, in->uid, in->gid= ); + break; + } + + case FUSE_READ: { + const struct fuse_read_in *in =3D FUSE_IN_OP_STRUCT(read, exp); + ret =3D fuse_read(exp, &out_data_buffer, in->offset, in->size); + break; + } + + case FUSE_WRITE: { + const struct fuse_write_in *in =3D FUSE_IN_OP_STRUCT(write, exp); + uint32_t req_len; + + req_len =3D ((const struct fuse_in_header *)exp->request_buf)->len; + if (unlikely(req_len < sizeof(struct fuse_in_header) + sizeof(*in)= + + in->size)) { + warn_report("FUSE WRITE truncated; received %zu bytes of %" PR= Iu32, + req_len - sizeof(struct fuse_in_header) - sizeof(*= in), + in->size); + ret =3D -EINVAL; + break; + } + + /* + * poll_fuse_fd() has checked that in_hdr->len matches the number = of + * bytes read, which cannot exceed the max_write value we set + * (FUSE_MAX_WRITE_BYTES). So we know that FUSE_MAX_WRITE_BYTES >= =3D + * in_hdr->len >=3D in->size + X, so this assertion must hold. + */ + assert(in->size <=3D FUSE_MAX_WRITE_BYTES); + + /* + * Passing a pointer to `in` (i.e. the request buffer) is fine bec= ause + * fuse_write() takes care to copy its contents before potentially + * polling. + */ + ret =3D fuse_write(exp, FUSE_OUT_OP_STRUCT(write, out_buf), + in->offset, in->size, in + 1); + break; + } + + case FUSE_FALLOCATE: { + const struct fuse_fallocate_in *in =3D FUSE_IN_OP_STRUCT(fallocate= , exp); + ret =3D fuse_fallocate(exp, in->offset, in->length, in->mode); + break; + } + + case FUSE_FSYNC: + ret =3D fuse_fsync(exp); + break; + + case FUSE_FLUSH: + ret =3D fuse_flush(exp); + break; + #ifdef CONFIG_FUSE_LSEEK - .lseek =3D fuse_lseek, + case FUSE_LSEEK: { + const struct fuse_lseek_in *in =3D FUSE_IN_OP_STRUCT(lseek, exp); + ret =3D fuse_lseek(exp, FUSE_OUT_OP_STRUCT(lseek, out_buf), + in->offset, in->whence); + break; + } #endif -}; + + default: + ret =3D -ENOSYS; + } + + /* Ignore errors from fuse_write*(), nothing we can do anyway */ + if (out_data_buffer) { + assert(ret >=3D 0); + fuse_write_buf_response(exp->fuse_fd, req_id, out_hdr, + out_data_buffer, ret); + qemu_vfree(out_data_buffer); + } else { + fuse_write_response(exp->fuse_fd, req_id, out_hdr, + ret < 0 ? ret : 0, + ret < 0 ? 0 : ret); + } +} =20 const BlockExportDriver blk_exp_fuse =3D { .type =3D BLOCK_EXPORT_TYPE_FUSE, --=20 2.49.0 From nobody Sat Nov 15 12:14:53 2025 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=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1751370604; cv=none; d=zohomail.com; s=zohoarc; b=YRivxqSupGcqrLgtUBqRNlsOIgESfSphOCkxtQ86DYtByW10BKtnOh6yj1Bl1jBzrEl98NWCFtrFEjRZ6N5O8Hx2upo74SGekN62sRQnm647j0WRbSeTOupEF7e5j/H0Rzo6SBai5Q/w/lM4mQwUp5dGyQCJd3OnQkDXdtYpBGc= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1751370604; h=Content-Type: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=/8UsRrHLeCoAGqBtD2jv+/jE3kcOvs7fn80vwhdcsKY=; b=GzzyedYaydiqktwSG5EVyIGBh6ebx/rkUzQxUVvkdvqtSLctVzHxL8Xi2B7Y9TsB4pVcPETULo6xFKaHyO/CUWSa6oPFaaVP8Pqa7VKl/+mp6Jj1MSZKOrspF4NkTg05s3u0tu6IewU+WDyGX0JIAevVheEyFEbDtCFRDSXaOXc= 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 lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 175137060406681.56335655927933; Tue, 1 Jul 2025 04:50:04 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1uWZQn-0005YQ-2v; Tue, 01 Jul 2025 07:45:45 -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 1uWZQd-0005Tu-7V for qemu-devel@nongnu.org; Tue, 01 Jul 2025 07:45:39 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uWZQa-0003ap-M6 for qemu-devel@nongnu.org; Tue, 01 Jul 2025 07:45:34 -0400 Received: from mail-wm1-f70.google.com (mail-wm1-f70.google.com [209.85.128.70]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-110-iBbAUlEfOMas6X4NH-adSQ-1; Tue, 01 Jul 2025 07:45:28 -0400 Received: by mail-wm1-f70.google.com with SMTP id 5b1f17b1804b1-453a190819bso13758255e9.1 for ; Tue, 01 Jul 2025 04:45:28 -0700 (PDT) Received: from localhost (p200300cfd700f38d3df6a1ca7d40fe1f.dip0.t-ipconnect.de. [2003:cf:d700:f38d:3df6:a1ca:7d40:fe1f]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-3a88c7facf9sm12913901f8f.22.2025.07.01.04.45.25 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 01 Jul 2025 04:45:26 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1751370332; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=/8UsRrHLeCoAGqBtD2jv+/jE3kcOvs7fn80vwhdcsKY=; b=fCoXsd9kdIyQ+Lt4N8/M7dqsxzYwD1hmudwx59fLOzXuCOmCRQbnPeFZBEVItzqBX/HMV7 vx68ury9XkCMOM5GRQXgThvtCD9OC9xhKW5BxADzmUQ0NO++7n173x6mTDoMW0mbNIbtNK QozDHUdZoNm1O6LC0aMGi+hjIx7cedg= X-MC-Unique: iBbAUlEfOMas6X4NH-adSQ-1 X-Mimecast-MFC-AGG-ID: iBbAUlEfOMas6X4NH-adSQ_1751370328 X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1751370327; x=1751975127; 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=/8UsRrHLeCoAGqBtD2jv+/jE3kcOvs7fn80vwhdcsKY=; b=E5lCQK5cb9T6+V0ESxnPBeBtCOrTovfoamwDB5izCFv4F8XgFnkVPtH3573ZzBCQ/O fzHjQtXJD+c3Karh1Lm+z8O3j/oF35twHq5H+4ruuoQdPnt5mxSURuQ/oUPuYoYkzaSN O0W/ZBsWzrIRd50ocxydSuXimzUp4capcpz/9rGOQo6I+aAF6cE0gQEPUMvby1cAzM8d DwuuM/h+PJLyYWfEIqueoprP//jkYQ8eJC62uRZzTlIweM9caoLFr5S+HaxZwCVV88vE FbhRH27kZz3zfrLe71hPd2uDqg5JIUGXu+2umKwcmCezmfq6tYpF+2fRjHMP4Bl2bQwp LyIA== X-Gm-Message-State: AOJu0YzBzP1bFPlLCxwHO1Da2ZIbWNIC1wS74OVt98VPbWhEUDtz3DxC pRzTGhkHmYb52Tc5qcbEO0u4iOZd1kn+uAj2OfH3P0/NN2m1SNTVpUs9hT/fAlCe+k3UEU3wev3 KloNYHSOcMvpDlsKQ2Y4uStAwC9TYoj5rNv9UY+U7wWeBf8fVhJsaLf3X X-Gm-Gg: ASbGncuDN/F40xAQl/7tjB3bkXqUVvE1b2KjRf8Cw96AwpkcBiukrJKDfGomxfJ7A3p ft+l87077ZrH2U1MK74BPpO6IsHZ8i9SNZozth0Tt2gf3OMcoYmryZroluuK8KsUqAEOD4XwNWf SQ0/9wnq3C0NhMnNiasYwOu152vFNxIacVO+I5WBCWySs+wYhwYxGzJ0m5hM0BrorzfQF0Rc8LY o/x98Qv+QDV8thvZNqEyaJP0LIP7ipm6vrScfuCTDh3Y9gAdUVpfKjrWhVBHZidLLbP3iaBTWBD vK+Tw2VGipyqE9cLD86uQDQDR97aO+Gj5/qniRy4x60SfjoNVhr8eNCGffQPxHn348Guh020n37 p+QE5 X-Received: by 2002:a05:600c:c11b:b0:450:cfa7:5ea1 with SMTP id 5b1f17b1804b1-4538ee55a30mr159988435e9.16.1751370327397; Tue, 01 Jul 2025 04:45:27 -0700 (PDT) X-Google-Smtp-Source: AGHT+IF2KNQLfO/I2YRGw6uIVq7Qc1sCLdTSb0Zn2ydNII6jbq967DweV4cVUYr6ZYEx1I+pwCSCAg== X-Received: by 2002:a05:600c:c11b:b0:450:cfa7:5ea1 with SMTP id 5b1f17b1804b1-4538ee55a30mr159988065e9.16.1751370326919; Tue, 01 Jul 2025 04:45:26 -0700 (PDT) From: Hanna Czenczek To: qemu-block@nongnu.org Cc: qemu-devel@nongnu.org, Hanna Czenczek , Stefan Hajnoczi , Kevin Wolf , Markus Armbruster , Brian Song Subject: [PATCH v3 14/21] fuse: Reduce max read size Date: Tue, 1 Jul 2025 13:44:30 +0200 Message-ID: <20250701114437.207419-15-hreitz@redhat.com> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250701114437.207419-1-hreitz@redhat.com> References: <20250701114437.207419-1-hreitz@redhat.com> 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=170.10.133.124; envelope-from=hreitz@redhat.com; helo=us-smtp-delivery-124.mimecast.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, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1751370607039124100 Content-Type: text/plain; charset="utf-8" We are going to introduce parallel processing via coroutines, a maximum read size of 64 MB may be problematic, allowing users of the export to force us to allocate quite large amounts of memory with just a few requests. At least tone it down to 1 MB, which is still probably far more than enough. (Larger requests are split automatically by the FUSE kernel driver anyway.) (Yes, we inadvertently already had parallel request processing due to nested polling before. Better to fix this late than never.) Reviewed-by: Stefan Hajnoczi Signed-off-by: Hanna Czenczek --- block/export/fuse.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/block/export/fuse.c b/block/export/fuse.c index 85ebc6bda8..8ea590ba67 100644 --- a/block/export/fuse.c +++ b/block/export/fuse.c @@ -45,7 +45,7 @@ #endif =20 /* Prevent overly long bounce buffer allocations */ -#define FUSE_MAX_READ_BYTES (MIN(BDRV_REQUEST_MAX_BYTES, 64 * 1024 * 1024)) +#define FUSE_MAX_READ_BYTES (MIN(BDRV_REQUEST_MAX_BYTES, 1 * 1024 * 1024)) /* Small enough to fit in the request buffer */ #define FUSE_MAX_WRITE_BYTES (4 * 1024) =20 --=20 2.49.0 From nobody Sat Nov 15 12:14:53 2025 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=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1751370404; cv=none; d=zohomail.com; s=zohoarc; b=d5rtIxMo/BkSUZHgJly7coHbOMkNYaOHdsnmjIhwJAT0evZ1f4GTK+U/ZkKcSOJ5G/Dyxk43vkGaAIr4KY/mENdcz7SouEsUPj1o2nTwEqciqcy+JmVGtXs+r/4rOOAP3XbsT+jy0UlTLsvp2H3gnRzPkBFpLjOG7Didd8Can9A= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1751370404; h=Content-Type: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=DQOyHi5Vq8SmPuJYcbMf4L5+TZHDp+p28dU/TErUBxQ=; b=PURY8H2V+ZsvUP0/F7MbcunVepj1Se7rmhec7QPhcSE1TLr6pav1R5cZU5HlHAp3DSPRaOjFOoQTM8fua6fzMRhfhLkXQK+BZpUUwgZARylOUBslCtBwHutB+ABCbkDT53tcWY/hwob7qyLK7UgMYq8C+rOyK7bKTUCe+nywhkg= 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 lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1751370404127874.0966085275547; Tue, 1 Jul 2025 04:46:44 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1uWZQo-0005Zp-LU; Tue, 01 Jul 2025 07:45:46 -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 1uWZQj-0005Vf-1H for qemu-devel@nongnu.org; Tue, 01 Jul 2025 07:45:41 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uWZQe-0003bO-FK for qemu-devel@nongnu.org; Tue, 01 Jul 2025 07:45:40 -0400 Received: from mail-wm1-f72.google.com (mail-wm1-f72.google.com [209.85.128.72]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-649-v4nBZoC5MMWyzuxceid2Lw-1; Tue, 01 Jul 2025 07:45:33 -0400 Received: by mail-wm1-f72.google.com with SMTP id 5b1f17b1804b1-451d2037f1eso18744805e9.0 for ; Tue, 01 Jul 2025 04:45:33 -0700 (PDT) Received: from localhost (p200300cfd700f38d3df6a1ca7d40fe1f.dip0.t-ipconnect.de. [2003:cf:d700:f38d:3df6:a1ca:7d40:fe1f]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-453823c3c7csm192762955e9.36.2025.07.01.04.45.27 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 01 Jul 2025 04:45:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1751370335; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-type:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=DQOyHi5Vq8SmPuJYcbMf4L5+TZHDp+p28dU/TErUBxQ=; b=Im0F/fj5FkxCjzGj2l7ZJr0bHyxd1dtMKr2uljlJhLsr3iztRNxk+YdYd9NOQIoKgegZmO 4dU754js74hYpm0baboqIGPXuqNcK84FX38Hac6ItDmXQvDdFjPdylr4McqS5bYLNBYM// QcbGUu2REXnXnpNkH7rBhjXgtiBCeik= X-MC-Unique: v4nBZoC5MMWyzuxceid2Lw-1 X-Mimecast-MFC-AGG-ID: v4nBZoC5MMWyzuxceid2Lw_1751370332 X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1751370332; x=1751975132; 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=DQOyHi5Vq8SmPuJYcbMf4L5+TZHDp+p28dU/TErUBxQ=; b=SuLqJ1PakYiHrTQKzLOaug3OEOBUET3ubARCnBwdbCtUYsXpzW4iK9exaso8vaBXMn UKFYlfkiUpt7U7wp8dFKnoGzfa8WbPd1qBOqBj+u/6WGV+rRL451UWfxQA3M58Qht9xO 4hV7ZTp3lGHCJ51RfryWuFKEQAUZPu1orNngl0HKZwIJUyfPSG63RjtqSq6O1y7BbDIh bsxnJcKHbbouCNUmorKPQwAxVx/LJblTTLq171YExzumwbMziF8cFh0xq+zju5L0M4N9 lPXPMjkONJLAt7JjZFi5bMZfmt/w0s1yHtj+LQtwnq2rwcVI3GuvrES73gn14FHCRaLQ Bq0Q== X-Gm-Message-State: AOJu0YxiCLebdf+RVZOkLyz9CCmT+1bOR7OIvQ8vfrGz0+9SLiMjGP9e y98OKLG3XyjfW/xiq/a+2Mgy03zYGzLAWuUDH33yKD/wyAnYQZNhrb+RcRcqi/02BYBgy19hVME A1NhllmG2Mzx5JQo2gwCc98BrjQ6B1pUysXb64CykKA05VISom2WmvP7Y X-Gm-Gg: ASbGncukFXYXlPhV06/P0TPetk95a2btYyv9Tf4tBjIMRpk25gO6GU6z9os0KP2zJWx wfEqa54UE4XbPKVq4s7hmJHnANHz0V6twa7gDNaAgAXIlOsIfeGuXuDg0v3tECURj5SJAW4tZ23 Eqwk8WwvBF+DosblMKaDzqro6DXGrStEIZmV+WuCeX4Rts7h17U2rricFFYeFCsfCpYljNdENn4 zNcDGAtUH37u/0wqlts54VMAwICewwTQrTdwNi1SP+D2dDWoTJJWl3T10+WPdmGDi7tFcxSgPiV IlL3mdhMMXcqFkaapiRNBt5CIFaXGTOoAzd4BcB75Sz8lH9h1f/ZFRM9oVxixPqln50EGhqUh43 liRVd X-Received: by 2002:a05:600c:8b01:b0:450:d30e:ff96 with SMTP id 5b1f17b1804b1-4538ee5dc58mr172757515e9.0.1751370331832; Tue, 01 Jul 2025 04:45:31 -0700 (PDT) X-Google-Smtp-Source: AGHT+IG+6tbve2VIfHNx7nqaMbBY58aXjlMozczZcU//mSONAp9Hn4r8sA3uzwOTXZm8N1jHVuaXrg== X-Received: by 2002:a05:600c:8b01:b0:450:d30e:ff96 with SMTP id 5b1f17b1804b1-4538ee5dc58mr172757035e9.0.1751370331155; Tue, 01 Jul 2025 04:45:31 -0700 (PDT) From: Hanna Czenczek To: qemu-block@nongnu.org Cc: qemu-devel@nongnu.org, Hanna Czenczek , Stefan Hajnoczi , Kevin Wolf , Markus Armbruster , Brian Song Subject: [PATCH v3 15/21] fuse: Process requests in coroutines Date: Tue, 1 Jul 2025 13:44:31 +0200 Message-ID: <20250701114437.207419-16-hreitz@redhat.com> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250701114437.207419-1-hreitz@redhat.com> References: <20250701114437.207419-1-hreitz@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Type: text/plain; charset=UTF-8 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=170.10.129.124; envelope-from=hreitz@redhat.com; helo=us-smtp-delivery-124.mimecast.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, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1751370406991116600 Make fuse_process_request() a coroutine_fn (fuse_co_process_request()) and have read_from_fuse_fd() launch it inside of a newly created coroutine instead of running it synchronously. This way, we can process requests in parallel. These are the benchmark results, compared to (a) the original results with libfuse, and (b) the results after switching away from libfuse (i.e. before this patch): file: (vs. libfuse / vs. no libfuse) read: seq aio: 120.6k =C2=B11.1k (+ 53 % / + 58 %) rand aio: 113.3k =C2=B15.9k (+188 % / +325 %) seq sync: 52.4k =C2=B10.4k (+ 61 % / + 10 %) rand sync: 10.4k =C2=B10.4k (+ 6 % / + 3 %) write: seq aio: 79.8k =C2=B10.8k (+ 29 % / + 37 %) rand aio: 79.0k =C2=B10.6k (+ 29 % / + 36 %) seq sync: 41.5k =C2=B10.3k (+ 49 % / + 15 %) rand sync: 41.4k =C2=B10.2k (+ 50 % / + 15 %) null: read: seq aio: 266.1k =C2=B11.5k (+ 24 % / - 1 %) rand aio: 264.1k =C2=B12.5k (+ 24 % / =C2=B1 0 %) seq sync: 135.6k =C2=B13.2k (+ 50 % / + 1 %) rand sync: 134.7k =C2=B13.0k (+ 50 % / + 2 %) write: seq aio: 281.0k =C2=B11.8k (+ 38 % / + 2 %) rand aio: 288.1k =C2=B16.1k (+ 43 % / + 6 %) seq sync: 142.2k =C2=B13.1k (+ 65 % / + 9 %) rand sync: 141.1k =C2=B12.9k (+ 66 % / + 11 %) So for non-AIO cases (and the null driver, which does not yield), there is little change; but for file AIO, results greatly improve, resolving the performance issue we saw before (when switching away from libfuse). Reviewed-by: Stefan Hajnoczi Signed-off-by: Hanna Czenczek --- block/export/fuse.c | 194 ++++++++++++++++++++++++++------------------ 1 file changed, 113 insertions(+), 81 deletions(-) diff --git a/block/export/fuse.c b/block/export/fuse.c index 8ea590ba67..0648b5bc7d 100644 --- a/block/export/fuse.c +++ b/block/export/fuse.c @@ -27,6 +27,7 @@ #include "block/qapi.h" #include "qapi/error.h" #include "qapi/qapi-commands-block.h" +#include "qemu/coroutine.h" #include "qemu/error-report.h" #include "qemu/main-loop.h" #include "system/block-backend.h" @@ -86,6 +87,12 @@ typedef struct FuseExport { gid_t st_gid; } FuseExport; =20 +/* Parameters to the request processing coroutine */ +typedef struct FuseRequestCoParam { + FuseExport *exp; + int got_request; +} FuseRequestCoParam; + static GHashTable *exports; =20 static void fuse_export_shutdown(BlockExport *exp); @@ -99,7 +106,7 @@ static int mount_fuse_export(FuseExport *exp, Error **er= rp); static bool is_regular_file(const char *path, Error **errp); =20 static void read_from_fuse_fd(void *opaque); -static void fuse_process_request(FuseExport *exp); +static void coroutine_fn fuse_co_process_request(FuseExport *exp); =20 static void fuse_inc_in_flight(FuseExport *exp) { @@ -346,17 +353,20 @@ static int mount_fuse_export(FuseExport *exp, Error *= *errp) } =20 /** - * Try to read and process a single request from the FUSE FD. + * Try to read a single request from the FUSE FD. + * Takes a FuseExport pointer in `opaque`. + * + * Assumes the export's in-flight counter has already been incremented. + * + * If a request is available, process it. */ -static void read_from_fuse_fd(void *opaque) +static void coroutine_fn co_read_from_fuse_fd(void *opaque) { FuseExport *exp =3D opaque; int fuse_fd =3D exp->fuse_fd; ssize_t ret; const struct fuse_in_header *in_hdr; =20 - fuse_inc_in_flight(exp); - if (unlikely(exp->halted)) { goto no_request; } @@ -391,12 +401,28 @@ static void read_from_fuse_fd(void *opaque) goto no_request; } =20 - fuse_process_request(exp); + fuse_co_process_request(exp); =20 no_request: fuse_dec_in_flight(exp); } =20 +/** + * Try to read and process a single request from the FUSE FD. + * (To be used as a handler for when the FUSE FD becomes readable.) + * Takes a FuseExport pointer in `opaque`. + */ +static void read_from_fuse_fd(void *opaque) +{ + FuseExport *exp =3D opaque; + Coroutine *co; + + co =3D qemu_coroutine_create(co_read_from_fuse_fd, exp); + /* Decremented by co_read_from_fuse_fd() */ + fuse_inc_in_flight(exp); + qemu_coroutine_enter(co); +} + static void fuse_export_shutdown(BlockExport *blk_exp) { FuseExport *exp =3D container_of(blk_exp, FuseExport, common); @@ -470,8 +496,9 @@ static bool is_regular_file(const char *path, Error **e= rrp) * Process FUSE INIT. * Return the number of bytes written to *out on success, and -errno on er= ror. */ -static ssize_t fuse_init(FuseExport *exp, struct fuse_init_out *out, - uint32_t max_readahead, uint32_t flags) +static ssize_t coroutine_fn +fuse_co_init(FuseExport *exp, struct fuse_init_out *out, + uint32_t max_readahead, uint32_t flags) { const uint32_t supported_flags =3D FUSE_ASYNC_READ | FUSE_ASYNC_DIO; =20 @@ -510,17 +537,18 @@ static ssize_t fuse_init(FuseExport *exp, struct fuse= _init_out *out, * Let clients get file attributes (i.e., stat() the file). * Return the number of bytes written to *out on success, and -errno on er= ror. */ -static ssize_t fuse_getattr(FuseExport *exp, struct fuse_attr_out *out) +static ssize_t coroutine_fn +fuse_co_getattr(FuseExport *exp, struct fuse_attr_out *out) { int64_t length, allocated_blocks; time_t now =3D time(NULL); =20 - length =3D blk_getlength(exp->common.blk); + length =3D blk_co_getlength(exp->common.blk); if (length < 0) { return length; } =20 - allocated_blocks =3D bdrv_get_allocated_file_size(blk_bs(exp->common.b= lk)); + allocated_blocks =3D bdrv_co_get_allocated_file_size(blk_bs(exp->commo= n.blk)); if (allocated_blocks <=3D 0) { allocated_blocks =3D DIV_ROUND_UP(length, 512); } else { @@ -547,8 +575,9 @@ static ssize_t fuse_getattr(FuseExport *exp, struct fus= e_attr_out *out) return sizeof(*out); } =20 -static int fuse_do_truncate(const FuseExport *exp, int64_t size, - bool req_zero_write, PreallocMode prealloc) +static int coroutine_fn +fuse_co_do_truncate(const FuseExport *exp, int64_t size, bool req_zero_wri= te, + PreallocMode prealloc) { uint64_t blk_perm, blk_shared_perm; BdrvRequestFlags truncate_flags =3D 0; @@ -577,8 +606,8 @@ static int fuse_do_truncate(const FuseExport *exp, int6= 4_t size, } } =20 - ret =3D blk_truncate(exp->common.blk, size, true, prealloc, - truncate_flags, NULL); + ret =3D blk_co_truncate(exp->common.blk, size, true, prealloc, + truncate_flags, NULL); =20 if (add_resize_perm) { /* Must succeed, because we are only giving up the RESIZE permissi= on */ @@ -599,9 +628,9 @@ static int fuse_do_truncate(const FuseExport *exp, int6= 4_t size, * they cannot be given non-owner access. * Return the number of bytes written to *out on success, and -errno on er= ror. */ -static ssize_t fuse_setattr(FuseExport *exp, struct fuse_attr_out *out, - uint32_t to_set, uint64_t size, uint32_t mode, - uint32_t uid, uint32_t gid) +static ssize_t coroutine_fn +fuse_co_setattr(FuseExport *exp, struct fuse_attr_out *out, uint32_t to_se= t, + uint64_t size, uint32_t mode, uint32_t uid, uint32_t gid) { int supported_attrs; int ret; @@ -638,7 +667,7 @@ static ssize_t fuse_setattr(FuseExport *exp, struct fus= e_attr_out *out, return -EACCES; } =20 - ret =3D fuse_do_truncate(exp, size, true, PREALLOC_MODE_OFF); + ret =3D fuse_co_do_truncate(exp, size, true, PREALLOC_MODE_OFF); if (ret < 0) { return ret; } @@ -657,7 +686,7 @@ static ssize_t fuse_setattr(FuseExport *exp, struct fus= e_attr_out *out, exp->st_gid =3D gid; } =20 - return fuse_getattr(exp, out); + return fuse_co_getattr(exp, out); } =20 /** @@ -665,7 +694,8 @@ static ssize_t fuse_setattr(FuseExport *exp, struct fus= e_attr_out *out, * just acknowledge the request. * Return the number of bytes written to *out on success, and -errno on er= ror. */ -static ssize_t fuse_open(FuseExport *exp, struct fuse_open_out *out) +static ssize_t coroutine_fn +fuse_co_open(FuseExport *exp, struct fuse_open_out *out) { *out =3D (struct fuse_open_out) { .open_flags =3D FOPEN_DIRECT_IO | FOPEN_PARALLEL_DIRECT_WRITES, @@ -679,8 +709,8 @@ static ssize_t fuse_open(FuseExport *exp, struct fuse_o= pen_out *out) * Returns the buffer (read) size on success, and -errno on error. * After use, *bufptr must be freed via qemu_vfree(). */ -static ssize_t fuse_read(FuseExport *exp, void **bufptr, - uint64_t offset, uint32_t size) +static ssize_t coroutine_fn +fuse_co_read(FuseExport *exp, void **bufptr, uint64_t offset, uint32_t siz= e) { int64_t blk_len; void *buf; @@ -695,7 +725,7 @@ static ssize_t fuse_read(FuseExport *exp, void **bufptr, * Clients will expect short reads at EOF, so we have to limit * offset+size to the image length. */ - blk_len =3D blk_getlength(exp->common.blk); + blk_len =3D blk_co_getlength(exp->common.blk); if (blk_len < 0) { return blk_len; } @@ -709,7 +739,7 @@ static ssize_t fuse_read(FuseExport *exp, void **bufptr, return -ENOMEM; } =20 - ret =3D blk_pread(exp->common.blk, offset, size, buf, 0); + ret =3D blk_co_pread(exp->common.blk, offset, size, buf, 0); if (ret < 0) { qemu_vfree(buf); return ret; @@ -721,11 +751,12 @@ static ssize_t fuse_read(FuseExport *exp, void **bufp= tr, =20 /** * Handle client writes to the exported image. @buf has the data to be wr= itten - * and will be copied to a bounce buffer before polling for the first time. + * and will be copied to a bounce buffer before yielding for the first tim= e. * Return the number of bytes written to *out on success, and -errno on er= ror. */ -static ssize_t fuse_write(FuseExport *exp, struct fuse_write_out *out, - uint64_t offset, uint32_t size, const void *buf) +static ssize_t coroutine_fn +fuse_co_write(FuseExport *exp, struct fuse_write_out *out, + uint64_t offset, uint32_t size, const void *buf) { void *copied; int64_t blk_len; @@ -740,9 +771,7 @@ static ssize_t fuse_write(FuseExport *exp, struct fuse_= write_out *out, return -EACCES; } =20 - /* - * Must copy to bounce buffer before calling aio_poll() (to allow nest= ing) - */ + /* Must copy to bounce buffer before potentially yielding */ copied =3D blk_blockalign(exp->common.blk, size); memcpy(copied, buf, size); =20 @@ -750,7 +779,7 @@ static ssize_t fuse_write(FuseExport *exp, struct fuse_= write_out *out, * Clients will expect short writes at EOF, so we have to limit * offset+size to the image length. */ - blk_len =3D blk_getlength(exp->common.blk); + blk_len =3D blk_co_getlength(exp->common.blk); if (blk_len < 0) { ret =3D blk_len; goto fail_free_buffer; @@ -758,7 +787,8 @@ static ssize_t fuse_write(FuseExport *exp, struct fuse_= write_out *out, =20 if (offset + size > blk_len) { if (exp->growable) { - ret =3D fuse_do_truncate(exp, offset + size, true, PREALLOC_MO= DE_OFF); + ret =3D fuse_co_do_truncate(exp, offset + size, true, + PREALLOC_MODE_OFF); if (ret < 0) { goto fail_free_buffer; } @@ -767,7 +797,7 @@ static ssize_t fuse_write(FuseExport *exp, struct fuse_= write_out *out, } } =20 - ret =3D blk_pwrite(exp->common.blk, offset, size, copied, 0); + ret =3D blk_co_pwrite(exp->common.blk, offset, size, copied, 0); if (ret < 0) { goto fail_free_buffer; } @@ -788,8 +818,9 @@ fail_free_buffer: * Let clients perform various fallocate() operations. * Return 0 on success (no 'out' object), and -errno on error. */ -static ssize_t fuse_fallocate(FuseExport *exp, uint64_t offset, uint64_t l= ength, - uint32_t mode) +static ssize_t coroutine_fn +fuse_co_fallocate(FuseExport *exp, + uint64_t offset, uint64_t length, uint32_t mode) { int64_t blk_len; int ret; @@ -798,7 +829,7 @@ static ssize_t fuse_fallocate(FuseExport *exp, uint64_t= offset, uint64_t length, return -EACCES; } =20 - blk_len =3D blk_getlength(exp->common.blk); + blk_len =3D blk_co_getlength(exp->common.blk); if (blk_len < 0) { return blk_len; } @@ -817,14 +848,14 @@ static ssize_t fuse_fallocate(FuseExport *exp, uint64= _t offset, uint64_t length, =20 if (offset > blk_len) { /* No preallocation needed here */ - ret =3D fuse_do_truncate(exp, offset, true, PREALLOC_MODE_OFF); + ret =3D fuse_co_do_truncate(exp, offset, true, PREALLOC_MODE_O= FF); if (ret < 0) { return ret; } } =20 - ret =3D fuse_do_truncate(exp, offset + length, true, - PREALLOC_MODE_FALLOC); + ret =3D fuse_co_do_truncate(exp, offset + length, true, + PREALLOC_MODE_FALLOC); } #ifdef CONFIG_FALLOCATE_PUNCH_HOLE else if (mode & FALLOC_FL_PUNCH_HOLE) { @@ -835,8 +866,9 @@ static ssize_t fuse_fallocate(FuseExport *exp, uint64_t= offset, uint64_t length, do { int size =3D MIN(length, BDRV_REQUEST_MAX_BYTES); =20 - ret =3D blk_pwrite_zeroes(exp->common.blk, offset, size, - BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLB= ACK); + ret =3D blk_co_pwrite_zeroes(exp->common.blk, offset, size, + BDRV_REQ_MAY_UNMAP | + BDRV_REQ_NO_FALLBACK); if (ret =3D=3D -ENOTSUP) { /* * fallocate() specifies to return EOPNOTSUPP for unsuppor= ted @@ -854,8 +886,8 @@ static ssize_t fuse_fallocate(FuseExport *exp, uint64_t= offset, uint64_t length, else if (mode & FALLOC_FL_ZERO_RANGE) { if (!(mode & FALLOC_FL_KEEP_SIZE) && offset + length > blk_len) { /* No need for zeroes, we are going to write them ourselves */ - ret =3D fuse_do_truncate(exp, offset + length, false, - PREALLOC_MODE_OFF); + ret =3D fuse_co_do_truncate(exp, offset + length, false, + PREALLOC_MODE_OFF); if (ret < 0) { return ret; } @@ -864,8 +896,8 @@ static ssize_t fuse_fallocate(FuseExport *exp, uint64_t= offset, uint64_t length, do { int size =3D MIN(length, BDRV_REQUEST_MAX_BYTES); =20 - ret =3D blk_pwrite_zeroes(exp->common.blk, - offset, size, 0); + ret =3D blk_co_pwrite_zeroes(exp->common.blk, + offset, size, 0); offset +=3D size; length -=3D size; } while (ret =3D=3D 0 && length > 0); @@ -882,9 +914,9 @@ static ssize_t fuse_fallocate(FuseExport *exp, uint64_t= offset, uint64_t length, * Let clients fsync the exported image. * Return 0 on success (no 'out' object), and -errno on error. */ -static ssize_t fuse_fsync(FuseExport *exp) +static ssize_t coroutine_fn fuse_co_fsync(FuseExport *exp) { - return blk_flush(exp->common.blk); + return blk_co_flush(exp->common.blk); } =20 /** @@ -892,9 +924,9 @@ static ssize_t fuse_fsync(FuseExport *exp) * notes this to be a way to return last-minute errors.) * Return 0 on success (no 'out' object), and -errno on error. */ -static ssize_t fuse_flush(FuseExport *exp) +static ssize_t coroutine_fn fuse_co_flush(FuseExport *exp) { - return blk_flush(exp->common.blk); + return blk_co_flush(exp->common.blk); } =20 #ifdef CONFIG_FUSE_LSEEK @@ -902,8 +934,9 @@ static ssize_t fuse_flush(FuseExport *exp) * Let clients inquire allocation status. * Return the number of bytes written to *out on success, and -errno on er= ror. */ -static ssize_t fuse_lseek(FuseExport *exp, struct fuse_lseek_out *out, - uint64_t offset, uint32_t whence) +static ssize_t coroutine_fn +fuse_co_lseek(FuseExport *exp, struct fuse_lseek_out *out, + uint64_t offset, uint32_t whence) { if (whence !=3D SEEK_HOLE && whence !=3D SEEK_DATA) { return -EINVAL; @@ -913,8 +946,8 @@ static ssize_t fuse_lseek(FuseExport *exp, struct fuse_= lseek_out *out, int64_t pnum; int ret; =20 - ret =3D bdrv_block_status_above(blk_bs(exp->common.blk), NULL, - offset, INT64_MAX, &pnum, NULL, NULL= ); + ret =3D bdrv_co_block_status_above(blk_bs(exp->common.blk), NULL, + offset, INT64_MAX, &pnum, NULL, N= ULL); if (ret < 0) { return ret; } @@ -931,7 +964,7 @@ static ssize_t fuse_lseek(FuseExport *exp, struct fuse_= lseek_out *out, * and @blk_len (the client-visible EOF). */ =20 - blk_len =3D blk_getlength(exp->common.blk); + blk_len =3D blk_co_getlength(exp->common.blk); if (blk_len < 0) { return blk_len; } @@ -1066,14 +1099,14 @@ static int fuse_write_buf_response(int fd, uint32_t= req_id, } =20 /* - * For use in fuse_process_request(): + * For use in fuse_co_process_request(): * Returns a pointer to the parameter object for the given operation (insi= de of * export->request_buf, which is assumed to hold a fuse_in_header first). * Verifies that the object is complete (export->request_buf is large enou= gh to * hold it in one piece, and the request length includes the whole object). * - * Note that export->request_buf may be overwritten after polling, so the - * returned pointer must not be used across a function that may poll! + * Note that export->request_buf may be overwritten after yielding, so the + * returned pointer must not be used across a function that may yield! */ #define FUSE_IN_OP_STRUCT(op_name, export) \ ({ \ @@ -1097,7 +1130,7 @@ static int fuse_write_buf_response(int fd, uint32_t r= eq_id, }) =20 /* - * For use in fuse_process_request(): + * For use in fuse_co_process_request(): * Returns a pointer to the return object for the given operation (inside = of * out_buf, which is assumed to hold a fuse_out_header first). * Verifies that out_buf is large enough to hold the whole object. @@ -1120,12 +1153,11 @@ static int fuse_write_buf_response(int fd, uint32_t= req_id, /** * Process a FUSE request, incl. writing the response. * - * Note that polling in any request-processing function can lead to a nest= ed - * read_from_fuse_fd() call, which will overwrite the contents of - * exp->request_buf. Anything that takes a buffer needs to take care that= the - * content is copied before potentially polling. + * Note that yielding in any request-processing function can overwrite the + * contents of exp->request_buf. Anything that takes a buffer needs to ta= ke + * care that the content is copied before yielding. */ -static void fuse_process_request(FuseExport *exp) +static void coroutine_fn fuse_co_process_request(FuseExport *exp) { uint32_t opcode; uint64_t req_id; @@ -1146,7 +1178,7 @@ static void fuse_process_request(FuseExport *exp) void *out_data_buffer =3D NULL; ssize_t ret; =20 - /* Limit scope to ensure pointer is no longer used after polling */ + /* Limit scope to ensure pointer is no longer used after yielding */ { const struct fuse_in_header *in_hdr =3D (const struct fuse_in_header *)exp->request_buf; @@ -1158,13 +1190,13 @@ static void fuse_process_request(FuseExport *exp) switch (opcode) { case FUSE_INIT: { const struct fuse_init_in *in =3D FUSE_IN_OP_STRUCT(init, exp); - ret =3D fuse_init(exp, FUSE_OUT_OP_STRUCT(init, out_buf), - in->max_readahead, in->flags); + ret =3D fuse_co_init(exp, FUSE_OUT_OP_STRUCT(init, out_buf), + in->max_readahead, in->flags); break; } =20 case FUSE_OPEN: - ret =3D fuse_open(exp, FUSE_OUT_OP_STRUCT(open, out_buf)); + ret =3D fuse_co_open(exp, FUSE_OUT_OP_STRUCT(open, out_buf)); break; =20 case FUSE_RELEASE: @@ -1176,19 +1208,19 @@ static void fuse_process_request(FuseExport *exp) break; =20 case FUSE_GETATTR: - ret =3D fuse_getattr(exp, FUSE_OUT_OP_STRUCT(attr, out_buf)); + ret =3D fuse_co_getattr(exp, FUSE_OUT_OP_STRUCT(attr, out_buf)); break; =20 case FUSE_SETATTR: { const struct fuse_setattr_in *in =3D FUSE_IN_OP_STRUCT(setattr, ex= p); - ret =3D fuse_setattr(exp, FUSE_OUT_OP_STRUCT(attr, out_buf), - in->valid, in->size, in->mode, in->uid, in->gid= ); + ret =3D fuse_co_setattr(exp, FUSE_OUT_OP_STRUCT(attr, out_buf), + in->valid, in->size, in->mode, in->uid, in->= gid); break; } =20 case FUSE_READ: { const struct fuse_read_in *in =3D FUSE_IN_OP_STRUCT(read, exp); - ret =3D fuse_read(exp, &out_data_buffer, in->offset, in->size); + ret =3D fuse_co_read(exp, &out_data_buffer, in->offset, in->size); break; } =20 @@ -1216,33 +1248,33 @@ static void fuse_process_request(FuseExport *exp) =20 /* * Passing a pointer to `in` (i.e. the request buffer) is fine bec= ause - * fuse_write() takes care to copy its contents before potentially - * polling. + * fuse_co_write() takes care to copy its contents before potentia= lly + * yielding. */ - ret =3D fuse_write(exp, FUSE_OUT_OP_STRUCT(write, out_buf), - in->offset, in->size, in + 1); + ret =3D fuse_co_write(exp, FUSE_OUT_OP_STRUCT(write, out_buf), + in->offset, in->size, in + 1); break; } =20 case FUSE_FALLOCATE: { const struct fuse_fallocate_in *in =3D FUSE_IN_OP_STRUCT(fallocate= , exp); - ret =3D fuse_fallocate(exp, in->offset, in->length, in->mode); + ret =3D fuse_co_fallocate(exp, in->offset, in->length, in->mode); break; } =20 case FUSE_FSYNC: - ret =3D fuse_fsync(exp); + ret =3D fuse_co_fsync(exp); break; =20 case FUSE_FLUSH: - ret =3D fuse_flush(exp); + ret =3D fuse_co_flush(exp); break; =20 #ifdef CONFIG_FUSE_LSEEK case FUSE_LSEEK: { const struct fuse_lseek_in *in =3D FUSE_IN_OP_STRUCT(lseek, exp); - ret =3D fuse_lseek(exp, FUSE_OUT_OP_STRUCT(lseek, out_buf), - in->offset, in->whence); + ret =3D fuse_co_lseek(exp, FUSE_OUT_OP_STRUCT(lseek, out_buf), + in->offset, in->whence); break; } #endif --=20 2.49.0 From nobody Sat Nov 15 12:14:53 2025 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=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1751370557; cv=none; d=zohomail.com; s=zohoarc; b=WAEcsJwpaJNDw894mJqa65aLPNHpotAa643l02cQIShdHpGM2qZtB6k0MTD7XBVQLCPBXhJWTjo/MfKTfferdVuPhuXS3/n5cYT8ZdgsCJ5+Dx75S55SVCgCc4IXMUE6VEjXbcjnYAU5huyxyeQp6U+Ue9x/VIgJ7MmMcHOmYaQ= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1751370557; h=Content-Type: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=Qihe+exxIN+/4sefM9Iuz6plsiYQc/e5rgGK1PReb6U=; b=D0Vi4YXae0boB/v4XJXYJUqRArSqZxMHSUXcHrpKWobiyBSZgRcRhFQHoHGDd/Bufw6I4qBvZiAF6YIfjiJjOG/o97TB+HyFIvVmhFUqq2Oj8Mw2ZOKPE7LzsQaA1Zals6+fiY8uJPaPKHXI2O9pvwH/neUHtnw/oF99XX0BQLw= 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 lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1751370557052622.6329077899032; Tue, 1 Jul 2025 04:49:17 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1uWZRx-00070j-Lf; Tue, 01 Jul 2025 07:46:57 -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 1uWZQr-0005bZ-2H for qemu-devel@nongnu.org; Tue, 01 Jul 2025 07:45:49 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uWZQk-0003cc-9f for qemu-devel@nongnu.org; Tue, 01 Jul 2025 07:45:48 -0400 Received: from mail-wr1-f69.google.com (mail-wr1-f69.google.com [209.85.221.69]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-260-_iMP0aBTPl-UL_TyA7mXiA-1; Tue, 01 Jul 2025 07:45:37 -0400 Received: by mail-wr1-f69.google.com with SMTP id ffacd0b85a97d-3a52bfda108so2620067f8f.3 for ; Tue, 01 Jul 2025 04:45:36 -0700 (PDT) Received: from localhost (p200300cfd700f38d3df6a1ca7d40fe1f.dip0.t-ipconnect.de. [2003:cf:d700:f38d:3df6:a1ca:7d40:fe1f]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-3a892e6214fsm13186326f8f.98.2025.07.01.04.45.32 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 01 Jul 2025 04:45:32 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1751370338; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=Qihe+exxIN+/4sefM9Iuz6plsiYQc/e5rgGK1PReb6U=; b=Dtvnll0i890g1lzgj57HsxhzYOqvqP4EZNkLJqn5ZsOMyYZlRhB9HfaijGkaQddmzWcSeL SWmlcIZu8IU6rBi18H+xyMciEKPl96ogSESf+tg3tVnNXx1VyaHXBax9v1TOu9kMeHjBJb L0RV5V3AA9Sz/CWn1X4Kb4rzO3wblyg= X-MC-Unique: _iMP0aBTPl-UL_TyA7mXiA-1 X-Mimecast-MFC-AGG-ID: _iMP0aBTPl-UL_TyA7mXiA_1751370336 X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1751370336; x=1751975136; 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=Qihe+exxIN+/4sefM9Iuz6plsiYQc/e5rgGK1PReb6U=; b=v3EIvOj9MmadhWyWiAri0n5A/vmGFlRUOd/XL4ibnOwhJnLLQE6y49nGXmw2UvEV9k K/TfRRvxmSO5yq3h5gY0dZCfcN9oxUzseery3otXXfnkjpfYmxwJWrsVOIkHLoI2XKOw fNNnnV+zvpnquEUWNN6XgueXFxL3irCxIZ6WdENtW1HpdH/+/OhLRqPtEcfumMluwH9+ 8PpDoQLfWtW8l90HlNO/XBuBZr0aKkMuY2GGWMU+NvsOROd2xctY2DtlV9g9PsrByIO9 ApnGR54R5CbI4YwbPOYKeDaKofBaWVIm5fvraXiinKESEaJVk/rhGfO30Ph1TPezuGno 8xoA== X-Gm-Message-State: AOJu0YwhAOlrBpeQ+Le2XeY2WVuqDbz2aGuhGkqK5A/kpeM+lqGe69YC a9jnELNI5uJZ40f79wIa57qVgTp7ExEpntRhaLPr9TrITam2GMMNXtE/KXEBlOyKlMFPotVXuLF SxibJcB2nI8mimTj11sw124/EI41rY4tLIDhF+bjpTLVDHGKbn5ydivdx X-Gm-Gg: ASbGncvWDcyoNaSbK09f+n0oUVf0z9Is9jtx6um6av4F/P0hb2Y6+4Rc6jx6Ila3Jxk WJWXgKosyGReFvoBqFs8u4eWoNjlIo2gqzIkJYaMkSDnW5PlU1mfrpGoodP8mePGW0IQvvMElL4 hpqOdg1K2SO/53n9o3j/HmsbzgEfIdqqT7ZHkGyi0BhNFgMGyFhGnnjV9MzRTUcv2CpX6B+NWPN PL3ljN2/7neQH7HcMpT4naSGXKBAzqb/8cGnOq0iwbKvs1tPpEwS4t2mJTdYtN6e5NTNL7wrtXI oo0GcW5SH+U0C6BSjDOedjrsLOsyw/5LR1xORDvvCz5w6U+NxTTIPBy/BgmfOc8KkJsGLuiE7kx Moxm6 X-Received: by 2002:a05:6000:3102:b0:3a5:2ed2:118e with SMTP id ffacd0b85a97d-3a8fda35a0cmr15236785f8f.9.1751370335402; Tue, 01 Jul 2025 04:45:35 -0700 (PDT) X-Google-Smtp-Source: AGHT+IF7Rvg3VL280xjrGK6ZBw7bgc022kxnR0eScCCGF8fL1IpRKAmmP+CoSUIRydib35SX4lJgBQ== X-Received: by 2002:a05:6000:3102:b0:3a5:2ed2:118e with SMTP id ffacd0b85a97d-3a8fda35a0cmr15236746f8f.9.1751370334754; Tue, 01 Jul 2025 04:45:34 -0700 (PDT) From: Hanna Czenczek To: qemu-block@nongnu.org Cc: qemu-devel@nongnu.org, Hanna Czenczek , Stefan Hajnoczi , Kevin Wolf , Markus Armbruster , Brian Song Subject: [PATCH v3 16/21] block/export: Add multi-threading interface Date: Tue, 1 Jul 2025 13:44:32 +0200 Message-ID: <20250701114437.207419-17-hreitz@redhat.com> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250701114437.207419-1-hreitz@redhat.com> References: <20250701114437.207419-1-hreitz@redhat.com> 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=170.10.133.124; envelope-from=hreitz@redhat.com; helo=us-smtp-delivery-124.mimecast.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, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=unavailable autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1751370558867124100 Content-Type: text/plain; charset="utf-8" Make BlockExportType.iothread an alternate between a single-thread variant 'str' and a multi-threading variant '[str]'. In contrast to the single-thread setting, the multi-threading setting will not change the BDS's context (and so is incompatible with the fixed-iothread setting), but instead just pass a list to the export driver, with which it can do whatever it wants. Currently no export driver supports multi-threading, so they all return an error when receiving such a list. Suggested-by: Kevin Wolf Acked-by: Markus Armbruster Reviewed-by: Stefan Hajnoczi Signed-off-by: Hanna Czenczek --- qapi/block-export.json | 34 +++++++++++++++++--- include/block/export.h | 12 +++++-- block/export/export.c | 48 +++++++++++++++++++++++++--- block/export/fuse.c | 7 ++++ block/export/vduse-blk.c | 7 ++++ block/export/vhost-user-blk-server.c | 8 +++++ nbd/server.c | 6 ++++ 7 files changed, 111 insertions(+), 11 deletions(-) diff --git a/qapi/block-export.json b/qapi/block-export.json index ed4deb54db..ee30606680 100644 --- a/qapi/block-export.json +++ b/qapi/block-export.json @@ -362,14 +362,16 @@ # to the export before completion is signalled. (since: 5.2; # default: false) # -# @iothread: The name of the iothread object where the export will -# run. The default is to use the thread currently associated with -# the block node. (since: 5.2) +# @iothread: The name(s) of one or more iothread object(s) where the +# export will run. The default is to use the thread currently +# associated with the block node. (since: 5.2; multi-threading +# since 10.1) # # @fixed-iothread: True prevents the block node from being moved to # another thread while the export is active. If true and # @iothread is given, export creation fails if the block node -# cannot be moved to the iothread. The default is false. +# cannot be moved to the iothread. Must not be true when giving +# multiple iothreads for @iothread. The default is false. # (since: 5.2) # # @allow-inactive: If true, the export allows the exported node to be inac= tive. @@ -385,7 +387,7 @@ 'base': { 'type': 'BlockExportType', 'id': 'str', '*fixed-iothread': 'bool', - '*iothread': 'str', + '*iothread': 'BlockExportIothreads', 'node-name': 'str', '*writable': 'bool', '*writethrough': 'bool', @@ -401,6 +403,28 @@ 'if': 'CONFIG_VDUSE_BLK_EXPORT' } } } =20 +## +# @BlockExportIothreads: +# +# Specify a single or multiple I/O threads in which to run a block export'= s I/O. +# +# @single: Run the export's I/O in the given single I/O thread. +# +# @multi: Use multi-threading across the given set of I/O threads, which m= ust +# must not be empty. Note: Passing a single I/O thread via this varia= nt is +# still treated as multi-threading, which is different from using the +# @single variant. In particular, even if there only is a single I/O = thread +# in the set, export types that do not support multi-threading will +# generally reject this variant, and BlockExportOptions.fixed-iothread= is +# always incompatible with it. +# +# Since: 10.1 +## +{ 'alternate': 'BlockExportIothreads', + 'data': { + 'single': 'str', + 'multi': ['str'] } } + ## # @block-export-add: # diff --git a/include/block/export.h b/include/block/export.h index 4bd9531d4d..ca45da928c 100644 --- a/include/block/export.h +++ b/include/block/export.h @@ -32,8 +32,16 @@ typedef struct BlockExportDriver { /* True if the export type supports running on an inactive node */ bool supports_inactive; =20 - /* Creates and starts a new block export */ - int (*create)(BlockExport *, BlockExportOptions *, Error **); + /* + * Creates and starts a new block export. + * + * If the user passed a set of I/O threads for multi-threading, @multi= thread + * is a list of the @multithread_count corresponding contexts (freed b= y the + * caller). Note that @exp->ctx has no relation to that list. + */ + int (*create)(BlockExport *exp, BlockExportOptions *opts, + AioContext *const *multithread, size_t multithread_count, + Error **errp); =20 /* * Frees a removed block export. This function is only called after all diff --git a/block/export/export.c b/block/export/export.c index f3bbf11070..b733f269f3 100644 --- a/block/export/export.c +++ b/block/export/export.c @@ -76,16 +76,26 @@ BlockExport *blk_exp_add(BlockExportOptions *export, Er= ror **errp) { bool fixed_iothread =3D export->has_fixed_iothread && export->fixed_io= thread; bool allow_inactive =3D export->has_allow_inactive && export->allow_in= active; + bool multithread =3D export->iothread && + export->iothread->type =3D=3D QTYPE_QLIST; const BlockExportDriver *drv; BlockExport *exp =3D NULL; BlockDriverState *bs; BlockBackend *blk =3D NULL; AioContext *ctx; + AioContext **multithread_ctxs =3D NULL; + size_t multithread_count =3D 0; uint64_t perm; int ret; =20 GLOBAL_STATE_CODE(); =20 + if (fixed_iothread && multithread) { + error_setg(errp, + "Cannot use fixed-iothread for a multi-threaded export"= ); + return NULL; + } + if (!id_wellformed(export->id)) { error_setg(errp, "Invalid block export id"); return NULL; @@ -116,14 +126,16 @@ BlockExport *blk_exp_add(BlockExportOptions *export, = Error **errp) =20 ctx =3D bdrv_get_aio_context(bs); =20 - if (export->iothread) { + /* Move the BDS to the target I/O thread, if it is a single one */ + if (export->iothread && !multithread) { + const char *iothread_id =3D export->iothread->u.single; IOThread *iothread; AioContext *new_ctx; Error **set_context_errp; =20 - iothread =3D iothread_by_id(export->iothread); + iothread =3D iothread_by_id(iothread_id); if (!iothread) { - error_setg(errp, "iothread \"%s\" not found", export->iothread= ); + error_setg(errp, "iothread \"%s\" not found", iothread_id); goto fail; } =20 @@ -137,6 +149,32 @@ BlockExport *blk_exp_add(BlockExportOptions *export, E= rror **errp) } else if (fixed_iothread) { goto fail; } + } else if (multithread) { + strList *iothread_list =3D export->iothread->u.multi; + size_t i; + + multithread_count =3D 0; + for (strList *e =3D iothread_list; e; e =3D e->next) { + multithread_count++; + } + + if (multithread_count =3D=3D 0) { + error_setg(errp, "The set of I/O threads must not be empty"); + return NULL; + } + + multithread_ctxs =3D g_new(AioContext *, multithread_count); + i =3D 0; + for (strList *e =3D iothread_list; e; e =3D e->next) { + IOThread *iothread =3D iothread_by_id(e->value); + + if (!iothread) { + error_setg(errp, "iothread \"%s\" not found", e->value); + goto fail; + } + multithread_ctxs[i++] =3D iothread_get_aio_context(iothread); + } + assert(i =3D=3D multithread_count); } =20 bdrv_graph_rdlock_main_loop(); @@ -195,7 +233,7 @@ BlockExport *blk_exp_add(BlockExportOptions *export, Er= ror **errp) .blk =3D blk, }; =20 - ret =3D drv->create(exp, export, errp); + ret =3D drv->create(exp, export, multithread_ctxs, multithread_count, = errp); if (ret < 0) { goto fail; } @@ -203,6 +241,7 @@ BlockExport *blk_exp_add(BlockExportOptions *export, Er= ror **errp) assert(exp->blk !=3D NULL); =20 QLIST_INSERT_HEAD(&block_exports, exp, next); + g_free(multithread_ctxs); return exp; =20 fail: @@ -214,6 +253,7 @@ fail: g_free(exp->id); g_free(exp); } + g_free(multithread_ctxs); return NULL; } =20 diff --git a/block/export/fuse.c b/block/export/fuse.c index 0648b5bc7d..0e3fa028d3 100644 --- a/block/export/fuse.c +++ b/block/export/fuse.c @@ -180,6 +180,8 @@ static const BlockDevOps fuse_export_blk_dev_ops =3D { =20 static int fuse_export_create(BlockExport *blk_exp, BlockExportOptions *blk_exp_args, + AioContext *const *multithread, + size_t mt_count, Error **errp) { ERRP_GUARD(); /* ensure clean-up even with error_fatal */ @@ -189,6 +191,11 @@ static int fuse_export_create(BlockExport *blk_exp, =20 assert(blk_exp_args->type =3D=3D BLOCK_EXPORT_TYPE_FUSE); =20 + if (multithread) { + error_setg(errp, "FUSE export does not support multi-threading"); + return -EINVAL; + } + /* For growable and writable exports, take the RESIZE permission */ if (args->growable || blk_exp_args->writable) { uint64_t blk_perm, blk_shared_perm; diff --git a/block/export/vduse-blk.c b/block/export/vduse-blk.c index bd852e538d..bf70c98dd6 100644 --- a/block/export/vduse-blk.c +++ b/block/export/vduse-blk.c @@ -266,6 +266,7 @@ static const BlockDevOps vduse_block_ops =3D { }; =20 static int vduse_blk_exp_create(BlockExport *exp, BlockExportOptions *opts, + AioContext *const *multithread, size_t mt_= count, Error **errp) { VduseBlkExport *vblk_exp =3D container_of(exp, VduseBlkExport, export); @@ -301,6 +302,12 @@ static int vduse_blk_exp_create(BlockExport *exp, Bloc= kExportOptions *opts, return -EINVAL; } } + + if (multithread) { + error_setg(errp, "vduse-blk export does not support multi-threadin= g"); + return -EINVAL; + } + vblk_exp->num_queues =3D num_queues; vblk_exp->handler.blk =3D exp->blk; vblk_exp->handler.serial =3D g_strdup(vblk_opts->serial ?: ""); diff --git a/block/export/vhost-user-blk-server.c b/block/export/vhost-user= -blk-server.c index d9d2014d9b..481d4b7441 100644 --- a/block/export/vhost-user-blk-server.c +++ b/block/export/vhost-user-blk-server.c @@ -315,6 +315,7 @@ static const BlockDevOps vu_blk_dev_ops =3D { }; =20 static int vu_blk_exp_create(BlockExport *exp, BlockExportOptions *opts, + AioContext *const *multithread, size_t mt_cou= nt, Error **errp) { VuBlkExport *vexp =3D container_of(exp, VuBlkExport, export); @@ -340,6 +341,13 @@ static int vu_blk_exp_create(BlockExport *exp, BlockEx= portOptions *opts, error_setg(errp, "num-queues must be greater than 0"); return -EINVAL; } + + if (multithread) { + error_setg(errp, + "vhost-user-blk export does not support multi-threading= "); + return -EINVAL; + } + vexp->handler.blk =3D exp->blk; vexp->handler.serial =3D g_strdup("vhost_user_blk"); vexp->handler.logical_block_size =3D logical_block_size; diff --git a/nbd/server.c b/nbd/server.c index d242be9811..a1736a5a24 100644 --- a/nbd/server.c +++ b/nbd/server.c @@ -1793,6 +1793,7 @@ static const BlockDevOps nbd_block_ops =3D { }; =20 static int nbd_export_create(BlockExport *blk_exp, BlockExportOptions *exp= _args, + AioContext *const *multithread, size_t mt_cou= nt, Error **errp) { NBDExport *exp =3D container_of(blk_exp, NBDExport, common); @@ -1829,6 +1830,11 @@ static int nbd_export_create(BlockExport *blk_exp, B= lockExportOptions *exp_args, return -EEXIST; } =20 + if (multithread) { + error_setg(errp, "NBD export does not support multi-threading"); + return -EINVAL; + } + size =3D blk_getlength(blk); if (size < 0) { error_setg_errno(errp, -size, --=20 2.49.0 From nobody Sat Nov 15 12:14:53 2025 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=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1751370440; cv=none; d=zohomail.com; s=zohoarc; b=AL8Qx5CuAymaEcMEvzarGgy/eiOyRUyj+fsoUJGoLVvvOUO0tfXMh1Jt5GfRM11iEqgIKEYyDXD15rh0hjiMWjhVqFSZLPUHUqaKjOfz8XrbWYezBkXvuU7sFidso5VCB6sipOAJwY9huY6Co3tTujdnoQ7qv8ez8Pl2dIkJv/U= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1751370440; h=Content-Type: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=4miDEcFeoLMzpknUkidzUiT3tY62ZBbQkI2NJpJaCbA=; b=WPoCVlkYdA8CML06hZvNTZssE2wQuqhn4uppheVF1RMSbs5TA6ZlzppQPbRzojAYtfwgznvYesOs5IHTs34q8sWOgT6hu8oSqOe239xxehWVKsiMQtNk2pMHkSqWmQKM9zRUkBfX/o7tyDrM+B08LvCqhyKKKsYCBXVqk9yM3M0= 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 lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1751370440126937.3635929282632; Tue, 1 Jul 2025 04:47:20 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1uWZQo-0005Zb-5O; Tue, 01 Jul 2025 07:45:46 -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 1uWZQm-0005YL-NE for qemu-devel@nongnu.org; Tue, 01 Jul 2025 07:45:44 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uWZQk-0003dC-TB for qemu-devel@nongnu.org; Tue, 01 Jul 2025 07:45:44 -0400 Received: from mail-wr1-f71.google.com (mail-wr1-f71.google.com [209.85.221.71]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-12-sqi_68arMOGFrf7IZRz2zg-1; Tue, 01 Jul 2025 07:45:39 -0400 Received: by mail-wr1-f71.google.com with SMTP id ffacd0b85a97d-3a4f65a705dso1918926f8f.2 for ; Tue, 01 Jul 2025 04:45:39 -0700 (PDT) Received: from localhost (p200300cfd700f38d3df6a1ca7d40fe1f.dip0.t-ipconnect.de. [2003:cf:d700:f38d:3df6:a1ca:7d40:fe1f]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-3a892e52a35sm13228925f8f.57.2025.07.01.04.45.35 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 01 Jul 2025 04:45:36 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1751370340; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=4miDEcFeoLMzpknUkidzUiT3tY62ZBbQkI2NJpJaCbA=; b=Y1iSDwbnbJUoPV72i9CphkP486nnsKnt7MmY0W+soGk8NR1psWylnKR88/YstUrZvIZEbm V4TwYdbxEwkKdl+qyLxD/au3LYvv6dfHo12Qf9+7+eD03NSTEu0FWEFl4d3/yjI3M+I6Gg R0jM7bnMPypd0bP2qaoyI4Xe8O5zm04= X-MC-Unique: sqi_68arMOGFrf7IZRz2zg-1 X-Mimecast-MFC-AGG-ID: sqi_68arMOGFrf7IZRz2zg_1751370338 X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1751370338; x=1751975138; 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=4miDEcFeoLMzpknUkidzUiT3tY62ZBbQkI2NJpJaCbA=; b=rtN6LSHgADriw7x4uJd4athL75XKh9mCMMqYH8Ts4X/Rm8PPZjQH6hV2wqUgC8ynaM d1Ap58hoE+w8egN3idWfDPOsVZU3MUp2cN1R7VRpw8jEixKafl2P4KBkFEk5dPXSJDG4 EFSdAfV/ivLb4xs4PWKDxYlWS6sKVbgPsVybSUWrRF+6EX6Wd5meY+4FKgFym5g3OPls cMBGUO6OVFz2n7q/bOnWg+jmvNHt428anZfCUW3xVq45UMHFspSubalD9uQfMvFPaBeA SwGNV9UXKhtcjXvTd1MOjoMPu0HpGgc+VCuIn7wbQfEzB0Cj/74hz6nrmKxSB/EMG7fs aR+Q== X-Gm-Message-State: AOJu0YzmnD6EvvO/7KWka0lrHNS49td+4i/7iqpZW1mRHKSU0Kts907t QLQiDpI8qMHwd1IwFqfDgc/oNMSlEdgUMRB+bAl1vydAsVwFdSBDNTgVFoHrlRVcbJDoIifuY8i NGs4GurgLxRkroF/ZVimrJZodUkGo7tmNHSSYbEv4Y31DQhuO4MSBJqda X-Gm-Gg: ASbGncsXDrdInQZgb2/XWDl05CV7DXT2usgdbqAen4CTRh8oseTpE7+/DuaKSL7bXXa 7w/93M/7hTF7yAH3mKlhGHq/0NdVfat9praXaK+zAuIrYI/WGnQQsdHLzFC9/BdWoxMBz8LcL+X 4A9VoRfT3sD3tjWYhoa3oZBxoCRkbPXZ7OO7isHIGqI5ELTrnff/1ku0jfApSy0PbntzzOJpvR/ nHJX8jwY0ZIVYc0lKQLToJrGy7O02HMNWK97AZ+mHG1iS4/X1REKBRNjDsZM8dY+pdyrg9otzNL 148ozM3hTmOWaD4pbUuw0Cs6uDEtlFe/wA36/TkSo5v4Y0yZHZbymg0WAuwPksIy6qrKaknkS9Y ba9pW X-Received: by 2002:a05:6000:1a8f:b0:3a5:541c:b40f with SMTP id ffacd0b85a97d-3a8f435e1c6mr14693127f8f.9.1751370338426; Tue, 01 Jul 2025 04:45:38 -0700 (PDT) X-Google-Smtp-Source: AGHT+IGdyOJrCwa0ubmb30ykhye4/88RrVgFLz2TEVMayQUNJdMxh5VJ8LZYxRvx6LgwKJmvq68epA== X-Received: by 2002:a05:6000:1a8f:b0:3a5:541c:b40f with SMTP id ffacd0b85a97d-3a8f435e1c6mr14693091f8f.9.1751370337938; Tue, 01 Jul 2025 04:45:37 -0700 (PDT) From: Hanna Czenczek To: qemu-block@nongnu.org Cc: qemu-devel@nongnu.org, Hanna Czenczek , Stefan Hajnoczi , Kevin Wolf , Markus Armbruster , Brian Song Subject: [PATCH v3 17/21] iotests/307: Test multi-thread export interface Date: Tue, 1 Jul 2025 13:44:33 +0200 Message-ID: <20250701114437.207419-18-hreitz@redhat.com> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250701114437.207419-1-hreitz@redhat.com> References: <20250701114437.207419-1-hreitz@redhat.com> 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=170.10.133.124; envelope-from=hreitz@redhat.com; helo=us-smtp-delivery-124.mimecast.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, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1751370441405116600 Content-Type: text/plain; charset="utf-8" Test the QAPI interface for multi-threaded exports. None of our exports currently support multi-threading, so it's always an error in the end, but we can still test the specific errors. Signed-off-by: Hanna Czenczek Reviewed-by: Stefan Hajnoczi --- tests/qemu-iotests/307 | 47 ++++++++++++++++++++++++++++++++++++++ tests/qemu-iotests/307.out | 18 +++++++++++++++ 2 files changed, 65 insertions(+) diff --git a/tests/qemu-iotests/307 b/tests/qemu-iotests/307 index b429b5aa50..f6ee3ebec0 100755 --- a/tests/qemu-iotests/307 +++ b/tests/qemu-iotests/307 @@ -142,5 +142,52 @@ with iotests.FilePath('image') as img, \ vm.qmp_log('query-block-exports') iotests.qemu_nbd_list_log('-k', socket) =20 + iotests.log('\n=3D=3D=3D Using multi-thread with NBD =3D=3D=3D') + + # Actual multi-threading; (currently) not supported by NBD + vm.qmp_log('block-export-add', + id=3D'export0', + type=3D'nbd', + node_name=3D'fmt', + iothread=3D['iothread0', 'iothread1']) + + # Should be treated the same way as actual multi-threading, even if th= ere's + # only a single thread + vm.qmp_log('block-export-add', + id=3D'export0', + type=3D'nbd', + node_name=3D'fmt', + iothread=3D['iothread0']) + + iotests.log('\n=3D=3D=3D Empty thread list') + + # Simply not allowed + vm.qmp_log('block-export-add', + id=3D'export0', + type=3D'nbd', + node_name=3D'fmt', + iothread=3D[]) + + iotests.log('\n=3D=3D=3D Non-existent thread name in list') + + # Expect an error, even if NBD does not support multi-threading, becau= se the + # list is parsed before being passed to NBD + vm.qmp_log('block-export-add', + id=3D'export0', + type=3D'nbd', + node_name=3D'fmt', + iothread=3D['iothread0', 'nothread', 'iothread1']) + + iotests.log('\n=3D=3D=3D Multi-thread with fixed-iothread') + + # With multi-threading, there is no single context to give the BDS, so= it is + # just left where it is. fixed-iothread does not make sense then. + vm.qmp_log('block-export-add', + id=3D'export0', + type=3D'nbd', + node_name=3D'fmt', + iothread=3D['iothread0', 'iothread1'], + fixed_iothread=3DTrue) + iotests.log('\n=3D=3D=3D Shut down QEMU =3D=3D=3D') vm.shutdown() diff --git a/tests/qemu-iotests/307.out b/tests/qemu-iotests/307.out index f645f3315f..a9b37d3ac1 100644 --- a/tests/qemu-iotests/307.out +++ b/tests/qemu-iotests/307.out @@ -134,4 +134,22 @@ read failed: Input/output error exports available: 0 =20 =20 +=3D=3D=3D Using multi-thread with NBD =3D=3D=3D +{"execute": "block-export-add", "arguments": {"id": "export0", "iothread":= ["iothread0", "iothread1"], "node-name": "fmt", "type": "nbd"}} +{"error": {"class": "GenericError", "desc": "NBD export does not support m= ulti-threading"}} +{"execute": "block-export-add", "arguments": {"id": "export0", "iothread":= ["iothread0"], "node-name": "fmt", "type": "nbd"}} +{"error": {"class": "GenericError", "desc": "NBD export does not support m= ulti-threading"}} + +=3D=3D=3D Empty thread list +{"execute": "block-export-add", "arguments": {"id": "export0", "iothread":= [], "node-name": "fmt", "type": "nbd"}} +{"error": {"class": "GenericError", "desc": "The set of I/O threads must n= ot be empty"}} + +=3D=3D=3D Non-existent thread name in list +{"execute": "block-export-add", "arguments": {"id": "export0", "iothread":= ["iothread0", "nothread", "iothread1"], "node-name": "fmt", "type": "nbd"}} +{"error": {"class": "GenericError", "desc": "iothread \"nothread\" not fou= nd"}} + +=3D=3D=3D Multi-thread with fixed-iothread +{"execute": "block-export-add", "arguments": {"fixed-iothread": true, "id"= : "export0", "iothread": ["iothread0", "iothread1"], "node-name": "fmt", "t= ype": "nbd"}} +{"error": {"class": "GenericError", "desc": "Cannot use fixed-iothread for= a multi-threaded export"}} + =3D=3D=3D Shut down QEMU =3D=3D=3D --=20 2.49.0 From nobody Sat Nov 15 12:14:53 2025 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=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1751370458; cv=none; d=zohomail.com; s=zohoarc; b=bax7bwGJOLduoE8+P1OPm4dV7a9ahu1Ah/lwixQIp15uD1rgS6LVINhn+TkzFhVjYowuywcksb2r+H4kNc2tTVoJS7uyuhaRXlTZk7+M3GRuCHZRqayiAUBaTvN/Lo/eWZdkvzNNNaNe3mNipnKImD2ndv5OWQxUKh3a9/LyZYY= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1751370458; h=Content-Type: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=acljPY5jE8NaIoOEBBfWfxcfowfW4u2TZybdI7SjzQk=; b=fPQ81ljvi9qhEX8qAEu4YlHxQELkrbr/IqA2YfpBkNFfOsNvkAJGzfhSmpFqpy/uTpStf8HVPgEmjp4wdGQWOtln9tqQHsWYSj5ix10QoiQVIwoJpoaFzqcFz+W49y9ca8sko1gkfZxo9+2Ibimd+gQFieuQmslxORD76KZJ0r8= 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 lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1751370458173579.6960659212189; Tue, 1 Jul 2025 04:47:38 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1uWZRd-0005xJ-10; Tue, 01 Jul 2025 07:46:38 -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 1uWZQr-0005bb-B7 for qemu-devel@nongnu.org; Tue, 01 Jul 2025 07:45:49 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uWZQo-0003e1-BY for qemu-devel@nongnu.org; Tue, 01 Jul 2025 07:45:48 -0400 Received: from mail-wr1-f69.google.com (mail-wr1-f69.google.com [209.85.221.69]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-15-rIGS4-ZiPhyA7EDY41A7jQ-1; Tue, 01 Jul 2025 07:45:44 -0400 Received: by mail-wr1-f69.google.com with SMTP id ffacd0b85a97d-3a4f6ba526eso2024471f8f.1 for ; Tue, 01 Jul 2025 04:45:44 -0700 (PDT) Received: from localhost (p200300cfd700f38d3df6a1ca7d40fe1f.dip0.t-ipconnect.de. [2003:cf:d700:f38d:3df6:a1ca:7d40:fe1f]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-3a88c7fadf3sm13256625f8f.34.2025.07.01.04.45.38 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 01 Jul 2025 04:45:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1751370345; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-type:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=acljPY5jE8NaIoOEBBfWfxcfowfW4u2TZybdI7SjzQk=; b=KGpV9V2zThj0x59r2ujTbAp6vE5YBZ9TxwvdihxuQnHnUqBAekwQuKJiXF2l6PUIynb+hR 6HwBN/PqYhLPttlqgnX5DVyOSXFd65bsHaBSkg+1vnl2W8P6tJ+CizR3zBpFZ+xPTrljNK eolA/Yq5USQzqYL+Msbb9FNHq8rvx80= X-MC-Unique: rIGS4-ZiPhyA7EDY41A7jQ-1 X-Mimecast-MFC-AGG-ID: rIGS4-ZiPhyA7EDY41A7jQ_1751370343 X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1751370342; x=1751975142; 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=acljPY5jE8NaIoOEBBfWfxcfowfW4u2TZybdI7SjzQk=; b=uu1OxSya/+jnWnt1mkO+RyYWJ/jiuooKAdWlbFoSPata4kd8f7l1lcBiafl0OFjXP0 ImPnudj/cid+tp4Rzac4raeoAQ2zLzp2HDmlAjHqBjUn9CzwKvA2sws+wSvwWR7fRibT y9MS28PNLc8ppven2jcVRiXiBV+oaOgCQIsl56FWWukNBRGX0EKx+ixsZHEJjj5o++fW qhnpBdPLF/Pl6zL9cH3NnXFP8K0BgxsCrhg5nSgtGxjuGrztH8gTRynuz52RKkZZapXd JBtvMllpz4zqhbR457X8L6SBPlFaNbNXXK1fz16KXZg1QNgbM8ouaK2xyTRmk0wLWIYv /4wg== X-Gm-Message-State: AOJu0YxOcih6E1n1EHkFKc5Qipe+D9hTcK0lLhe21HG0S8cD4k4F73pt AkTmGd+ODxGuX5jSouYwapWnqCnpFXxe9zSPtncRHL+NPIpT29pgpm6YA8/QZMjDIYLoQ0JAXAK H0PEHUguKf/9pyDvvMqu4k41GXA4rqZ7bUd8GIdggcBX6D8CMWAAAn4my7r1FaXWF X-Gm-Gg: ASbGncs8HlXONFeHOZ9aYiatO9M87txmx8xujTovfbgEQjsi/ZcC9aENTQUQFduqpMT 1tp7RGmK3jiI9emWa5OXRNc7WkDeZovWtDekJcOgm7jOjYUsoItRLK6IhL1UsYxIrNoNquNipX7 qyD0XaD4dmuBaA1gMsQc1G2jzT52YCvdX+6EhZEsaYu/OyJFv0oiJ2HsBTioHOQieIaIieEljbT PDOealPWgUkVDawxouY3jHNd6ITR8sk07FIRSoMEcEQf5DEG0U69R+FwagznfzmO2M+lB8P2PJh 1hstLXdTFKNFjZIcLl0Jvhgn/AJPRqqoooDM5qgo5qpDhEKzpRJzknuvDso3savLbS4UnoQ+Qrg 9GfJd X-Received: by 2002:a05:6000:2082:b0:3a5:2875:f985 with SMTP id ffacd0b85a97d-3a90066afb5mr15342907f8f.59.1751370341879; Tue, 01 Jul 2025 04:45:41 -0700 (PDT) X-Google-Smtp-Source: AGHT+IEgV6NbBG7RkeUHZCua1hWta0uG/lP3mR2xcBuXtMzAa0rG3dRcGlDTO+5mHlI8iL14ldrtnA== X-Received: by 2002:a05:6000:2082:b0:3a5:2875:f985 with SMTP id ffacd0b85a97d-3a90066afb5mr15342871f8f.59.1751370341237; Tue, 01 Jul 2025 04:45:41 -0700 (PDT) From: Hanna Czenczek To: qemu-block@nongnu.org Cc: qemu-devel@nongnu.org, Hanna Czenczek , Stefan Hajnoczi , Kevin Wolf , Markus Armbruster , Brian Song Subject: [PATCH v3 18/21] fuse: Implement multi-threading Date: Tue, 1 Jul 2025 13:44:34 +0200 Message-ID: <20250701114437.207419-19-hreitz@redhat.com> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250701114437.207419-1-hreitz@redhat.com> References: <20250701114437.207419-1-hreitz@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Type: text/plain; charset=UTF-8 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=170.10.129.124; envelope-from=hreitz@redhat.com; helo=us-smtp-delivery-124.mimecast.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, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1751370459528116600 FUSE allows creating multiple request queues by "cloning" /dev/fuse FDs (via open("/dev/fuse") + ioctl(FUSE_DEV_IOC_CLONE)). We can use this to implement multi-threading. For configuration, we don't need any more information beyond the simple array provided by the core block export interface: The FUSE kernel driver feeds these FDs in a round-robin fashion, so all of them are equivalent and we want to have exactly one per thread. These are the benchmark results when using four threads (compared to a single thread); note that fio still only uses a single job, but performance can still be improved because of said round-robin usage for the queues. (Not in the sync case, though, in which case I guess it just adds overhead.) file: read: seq aio: 264.8k =C2=B10.8k (+120 %) rand aio: 143.8k =C2=B10.4k (+ 27 %) seq sync: 49.9k =C2=B10.5k (- 5 %) rand sync: 10.3k =C2=B10.1k (- 1 %) write: seq aio: 226.6k =C2=B12.1k (+184 %) rand aio: 225.9k =C2=B11.8k (+186 %) seq sync: 36.9k =C2=B10.6k (- 11 %) rand sync: 36.9k =C2=B10.2k (- 11 %) null: read: seq aio: 315.2k =C2=B111.0k (+18 %) rand aio: 300.5k =C2=B110.8k (+14 %) seq sync: 114.2k =C2=B1 3.6k (-16 %) rand sync: 112.5k =C2=B1 2.8k (-16 %) write: seq aio: 222.6k =C2=B16.8k (-21 %) rand aio: 220.5k =C2=B16.8k (-23 %) seq sync: 117.2k =C2=B13.7k (-18 %) rand sync: 116.3k =C2=B14.4k (-18 %) (I don't know what's going on in the null-write AIO case, sorry.) Here's results for numjobs=3D4: "Before", i.e. without multithreading in QSD/FUSE (results compared to numjobs=3D1): file: read: seq aio: 104.7k =C2=B1 0.4k (- 13 %) rand aio: 111.5k =C2=B1 0.4k (- 2 %) seq sync: 71.0k =C2=B113.8k (+ 36 %) rand sync: 41.4k =C2=B1 0.1k (+297 %) write: seq aio: 79.4k =C2=B10.1k (- 1 %) rand aio: 78.6k =C2=B10.1k (=C2=B1 0 %) seq sync: 83.3k =C2=B10.1k (+101 %) rand sync: 82.0k =C2=B10.2k (+ 98 %) null: read: seq aio: 260.5k =C2=B11.5k (- 2 %) rand aio: 260.1k =C2=B11.4k (- 2 %) seq sync: 291.8k =C2=B11.3k (+115 %) rand sync: 280.1k =C2=B11.7k (+115 %) write: seq aio: 280.1k =C2=B11.7k (=C2=B1 0 %) rand aio: 279.5k =C2=B11.4k (- 3 %) seq sync: 306.7k =C2=B12.2k (+116 %) rand sync: 305.9k =C2=B11.8k (+117 %) (As probably expected, little difference in the AIO case, but great improvements in the sync case because it kind of gives it an artificial iodepth of 4.) "After", i.e. with four threads in QSD/FUSE (now results compared to the above): file: read: seq aio: 193.3k =C2=B1 1.8k (+ 85 %) rand aio: 329.3k =C2=B1 0.3k (+195 %) seq sync: 66.2k =C2=B113.0k (- 7 %) rand sync: 40.1k =C2=B1 0.0k (- 3 %) write: seq aio: 219.7k =C2=B10.8k (+177 %) rand aio: 217.2k =C2=B11.5k (+176 %) seq sync: 92.5k =C2=B10.2k (+ 11 %) rand sync: 91.9k =C2=B10.2k (+ 12 %) null: read: seq aio: 706.7k =C2=B12.1k (+171 %) rand aio: 714.7k =C2=B13.2k (+175 %) seq sync: 431.7k =C2=B13.0k (+ 48 %) rand sync: 435.4k =C2=B12.8k (+ 50 %) write: seq aio: 746.9k =C2=B12.8k (+167 %) rand aio: 749.0k =C2=B14.9k (+168 %) seq sync: 420.7k =C2=B13.1k (+ 37 %) rand sync: 419.1k =C2=B12.5k (+ 37 %) So this helps mainly for the AIO cases, but also in the null sync cases, because null is always CPU-bound, so more threads help. Signed-off-by: Hanna Czenczek Reviewed-by: Stefan Hajnoczi --- block/export/fuse.c | 205 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 159 insertions(+), 46 deletions(-) diff --git a/block/export/fuse.c b/block/export/fuse.c index 0e3fa028d3..4ae448bc14 100644 --- a/block/export/fuse.c +++ b/block/export/fuse.c @@ -31,11 +31,14 @@ #include "qemu/error-report.h" #include "qemu/main-loop.h" #include "system/block-backend.h" +#include "system/block-backend.h" +#include "system/iothread.h" =20 #include #include =20 #include "standard-headers/linux/fuse.h" +#include =20 #if defined(CONFIG_FALLOCATE_ZERO_RANGE) #include @@ -50,12 +53,17 @@ /* Small enough to fit in the request buffer */ #define FUSE_MAX_WRITE_BYTES (4 * 1024) =20 -typedef struct FuseExport { - BlockExport common; +typedef struct FuseExport FuseExport; =20 - struct fuse_session *fuse_session; - unsigned int in_flight; /* atomic */ - bool mounted, fd_handler_set_up; +/* + * One FUSE "queue", representing one FUSE FD from which requests are fetc= hed + * and processed. Each queue is tied to an AioContext. + */ +typedef struct FuseQueue { + FuseExport *exp; + + AioContext *ctx; + int fuse_fd; =20 /* * The request buffer must be able to hold a full write, and/or at lea= st @@ -66,6 +74,14 @@ typedef struct FuseExport { FUSE_MAX_WRITE_BYTES, FUSE_MIN_READ_BUFFER )]; +} FuseQueue; + +struct FuseExport { + BlockExport common; + + struct fuse_session *fuse_session; + unsigned int in_flight; /* atomic */ + bool mounted, fd_handler_set_up; =20 /* * Set when there was an unrecoverable error and no requests should be= read @@ -74,7 +90,15 @@ typedef struct FuseExport { */ bool halted; =20 - int fuse_fd; + int num_queues; + FuseQueue *queues; + /* + * True if this export should follow the generic export's AioContext. + * Will be false if the queues' AioContexts have been explicitly set b= y the + * user, i.e. are expected to stay in those contexts. + * (I.e. is always false if there is more than one queue.) + */ + bool follow_aio_context; =20 char *mountpoint; bool writable; @@ -85,11 +109,11 @@ typedef struct FuseExport { mode_t st_mode; uid_t st_uid; gid_t st_gid; -} FuseExport; +}; =20 /* Parameters to the request processing coroutine */ typedef struct FuseRequestCoParam { - FuseExport *exp; + FuseQueue *q; int got_request; } FuseRequestCoParam; =20 @@ -102,11 +126,12 @@ static void fuse_export_halt(FuseExport *exp); static void init_exports_table(void); =20 static int mount_fuse_export(FuseExport *exp, Error **errp); +static int clone_fuse_fd(int fd, Error **errp); =20 static bool is_regular_file(const char *path, Error **errp); =20 static void read_from_fuse_fd(void *opaque); -static void coroutine_fn fuse_co_process_request(FuseExport *exp); +static void coroutine_fn fuse_co_process_request(FuseQueue *q); =20 static void fuse_inc_in_flight(FuseExport *exp) { @@ -136,8 +161,11 @@ static void fuse_attach_handlers(FuseExport *exp) return; } =20 - aio_set_fd_handler(exp->common.ctx, exp->fuse_fd, - read_from_fuse_fd, NULL, NULL, NULL, exp); + for (int i =3D 0; i < exp->num_queues; i++) { + aio_set_fd_handler(exp->queues[i].ctx, exp->queues[i].fuse_fd, + read_from_fuse_fd, NULL, NULL, NULL, + &exp->queues[i]); + } exp->fd_handler_set_up =3D true; } =20 @@ -146,8 +174,10 @@ static void fuse_attach_handlers(FuseExport *exp) */ static void fuse_detach_handlers(FuseExport *exp) { - aio_set_fd_handler(exp->common.ctx, exp->fuse_fd, - NULL, NULL, NULL, NULL, NULL); + for (int i =3D 0; i < exp->num_queues; i++) { + aio_set_fd_handler(exp->queues[i].ctx, exp->queues[i].fuse_fd, + NULL, NULL, NULL, NULL, NULL); + } exp->fd_handler_set_up =3D false; } =20 @@ -162,6 +192,11 @@ static void fuse_export_drained_end(void *opaque) =20 /* Refresh AioContext in case it changed */ exp->common.ctx =3D blk_get_aio_context(exp->common.blk); + if (exp->follow_aio_context) { + assert(exp->num_queues =3D=3D 1); + exp->queues[0].ctx =3D exp->common.ctx; + } + fuse_attach_handlers(exp); } =20 @@ -192,8 +227,32 @@ static int fuse_export_create(BlockExport *blk_exp, assert(blk_exp_args->type =3D=3D BLOCK_EXPORT_TYPE_FUSE); =20 if (multithread) { - error_setg(errp, "FUSE export does not support multi-threading"); - return -EINVAL; + /* Guaranteed by common export code */ + assert(mt_count >=3D 1); + + exp->follow_aio_context =3D false; + exp->num_queues =3D mt_count; + exp->queues =3D g_new(FuseQueue, mt_count); + + for (size_t i =3D 0; i < mt_count; i++) { + exp->queues[i] =3D (FuseQueue) { + .exp =3D exp, + .ctx =3D multithread[i], + .fuse_fd =3D -1, + }; + } + } else { + /* Guaranteed by common export code */ + assert(mt_count =3D=3D 0); + + exp->follow_aio_context =3D true; + exp->num_queues =3D 1; + exp->queues =3D g_new(FuseQueue, 1); + exp->queues[0] =3D (FuseQueue) { + .exp =3D exp, + .ctx =3D exp->common.ctx, + .fuse_fd =3D -1, + }; } =20 /* For growable and writable exports, take the RESIZE permission */ @@ -280,13 +339,23 @@ static int fuse_export_create(BlockExport *blk_exp, =20 g_hash_table_insert(exports, g_strdup(exp->mountpoint), NULL); =20 - exp->fuse_fd =3D fuse_session_fd(exp->fuse_session); - ret =3D qemu_fcntl_addfl(exp->fuse_fd, O_NONBLOCK); + assert(exp->num_queues >=3D 1); + exp->queues[0].fuse_fd =3D fuse_session_fd(exp->fuse_session); + ret =3D qemu_fcntl_addfl(exp->queues[0].fuse_fd, O_NONBLOCK); if (ret < 0) { error_setg_errno(errp, -ret, "Failed to make FUSE FD non-blocking"= ); goto fail; } =20 + for (int i =3D 1; i < exp->num_queues; i++) { + int fd =3D clone_fuse_fd(exp->queues[0].fuse_fd, errp); + if (fd < 0) { + ret =3D fd; + goto fail; + } + exp->queues[i].fuse_fd =3D fd; + } + fuse_attach_handlers(exp); return 0; =20 @@ -359,9 +428,42 @@ static int mount_fuse_export(FuseExport *exp, Error **= errp) return 0; } =20 +/** + * Clone the given /dev/fuse file descriptor, yielding a second FD from wh= ich + * requests can be pulled for the associated filesystem. Returns an FD on + * success, and -errno on error. + */ +static int clone_fuse_fd(int fd, Error **errp) +{ + uint32_t src_fd =3D fd; + int new_fd; + int ret; + + /* + * The name "/dev/fuse" is fixed, see libfuse's lib/fuse_loop_mt.c + * (fuse_clone_chan()). + */ + new_fd =3D open("/dev/fuse", O_RDWR | O_CLOEXEC | O_NONBLOCK); + if (new_fd < 0) { + ret =3D -errno; + error_setg_errno(errp, errno, "Failed to open /dev/fuse"); + return ret; + } + + ret =3D ioctl(new_fd, FUSE_DEV_IOC_CLONE, &src_fd); + if (ret < 0) { + ret =3D -errno; + error_setg_errno(errp, errno, "Failed to clone FUSE FD"); + close(new_fd); + return ret; + } + + return new_fd; +} + /** * Try to read a single request from the FUSE FD. - * Takes a FuseExport pointer in `opaque`. + * Takes a FuseQueue pointer in `opaque`. * * Assumes the export's in-flight counter has already been incremented. * @@ -369,8 +471,9 @@ static int mount_fuse_export(FuseExport *exp, Error **e= rrp) */ static void coroutine_fn co_read_from_fuse_fd(void *opaque) { - FuseExport *exp =3D opaque; - int fuse_fd =3D exp->fuse_fd; + FuseQueue *q =3D opaque; + int fuse_fd =3D q->fuse_fd; + FuseExport *exp =3D q->exp; ssize_t ret; const struct fuse_in_header *in_hdr; =20 @@ -378,8 +481,7 @@ static void coroutine_fn co_read_from_fuse_fd(void *opa= que) goto no_request; } =20 - ret =3D RETRY_ON_EINTR(read(fuse_fd, exp->request_buf, - sizeof(exp->request_buf))); + ret =3D RETRY_ON_EINTR(read(fuse_fd, q->request_buf, sizeof(q->request= _buf))); if (ret < 0 && errno =3D=3D EAGAIN) { /* No request available */ goto no_request; @@ -397,7 +499,7 @@ static void coroutine_fn co_read_from_fuse_fd(void *opa= que) goto no_request; } =20 - in_hdr =3D (const struct fuse_in_header *)exp->request_buf; + in_hdr =3D (const struct fuse_in_header *)q->request_buf; if (unlikely(ret !=3D in_hdr->len)) { error_report("Number of bytes read from FUSE device does not match= " "request size, expected %" PRIu32 " bytes, read %zi " @@ -408,7 +510,7 @@ static void coroutine_fn co_read_from_fuse_fd(void *opa= que) goto no_request; } =20 - fuse_co_process_request(exp); + fuse_co_process_request(q); =20 no_request: fuse_dec_in_flight(exp); @@ -417,16 +519,16 @@ no_request: /** * Try to read and process a single request from the FUSE FD. * (To be used as a handler for when the FUSE FD becomes readable.) - * Takes a FuseExport pointer in `opaque`. + * Takes a FuseQueue pointer in `opaque`. */ static void read_from_fuse_fd(void *opaque) { - FuseExport *exp =3D opaque; + FuseQueue *q =3D opaque; Coroutine *co; =20 - co =3D qemu_coroutine_create(co_read_from_fuse_fd, exp); + co =3D qemu_coroutine_create(co_read_from_fuse_fd, q); /* Decremented by co_read_from_fuse_fd() */ - fuse_inc_in_flight(exp); + fuse_inc_in_flight(q->exp); qemu_coroutine_enter(co); } =20 @@ -451,6 +553,16 @@ static void fuse_export_delete(BlockExport *blk_exp) { FuseExport *exp =3D container_of(blk_exp, FuseExport, common); =20 + for (int i =3D 0; i < exp->num_queues; i++) { + FuseQueue *q =3D &exp->queues[i]; + + /* Queue 0's FD belongs to the FUSE session */ + if (i > 0 && q->fuse_fd >=3D 0) { + close(q->fuse_fd); + } + } + g_free(exp->queues); + if (exp->fuse_session) { if (exp->mounted) { fuse_session_unmount(exp->fuse_session); @@ -1108,23 +1220,23 @@ static int fuse_write_buf_response(int fd, uint32_t= req_id, /* * For use in fuse_co_process_request(): * Returns a pointer to the parameter object for the given operation (insi= de of - * export->request_buf, which is assumed to hold a fuse_in_header first). - * Verifies that the object is complete (export->request_buf is large enou= gh to + * queue->request_buf, which is assumed to hold a fuse_in_header first). + * Verifies that the object is complete (queue->request_buf is large enoug= h to * hold it in one piece, and the request length includes the whole object). * - * Note that export->request_buf may be overwritten after yielding, so the + * Note that queue->request_buf may be overwritten after yielding, so the * returned pointer must not be used across a function that may yield! */ -#define FUSE_IN_OP_STRUCT(op_name, export) \ +#define FUSE_IN_OP_STRUCT(op_name, queue) \ ({ \ const struct fuse_in_header *__in_hdr =3D \ - (const struct fuse_in_header *)(export)->request_buf; \ + (const struct fuse_in_header *)(queue)->request_buf; \ const struct fuse_##op_name##_in *__in =3D \ (const struct fuse_##op_name##_in *)(__in_hdr + 1); \ const size_t __param_len =3D sizeof(*__in_hdr) + sizeof(*__in); \ uint32_t __req_len; \ \ - QEMU_BUILD_BUG_ON(sizeof((export)->request_buf) < __param_len); \ + QEMU_BUILD_BUG_ON(sizeof((queue)->request_buf) < __param_len); \ \ __req_len =3D __in_hdr->len; \ if (__req_len < __param_len) { \ @@ -1161,11 +1273,12 @@ static int fuse_write_buf_response(int fd, uint32_t= req_id, * Process a FUSE request, incl. writing the response. * * Note that yielding in any request-processing function can overwrite the - * contents of exp->request_buf. Anything that takes a buffer needs to ta= ke + * contents of q->request_buf. Anything that takes a buffer needs to take * care that the content is copied before yielding. */ -static void coroutine_fn fuse_co_process_request(FuseExport *exp) +static void coroutine_fn fuse_co_process_request(FuseQueue *q) { + FuseExport *exp =3D q->exp; uint32_t opcode; uint64_t req_id; /* @@ -1188,7 +1301,7 @@ static void coroutine_fn fuse_co_process_request(Fuse= Export *exp) /* Limit scope to ensure pointer is no longer used after yielding */ { const struct fuse_in_header *in_hdr =3D - (const struct fuse_in_header *)exp->request_buf; + (const struct fuse_in_header *)q->request_buf; =20 opcode =3D in_hdr->opcode; req_id =3D in_hdr->unique; @@ -1196,7 +1309,7 @@ static void coroutine_fn fuse_co_process_request(Fuse= Export *exp) =20 switch (opcode) { case FUSE_INIT: { - const struct fuse_init_in *in =3D FUSE_IN_OP_STRUCT(init, exp); + const struct fuse_init_in *in =3D FUSE_IN_OP_STRUCT(init, q); ret =3D fuse_co_init(exp, FUSE_OUT_OP_STRUCT(init, out_buf), in->max_readahead, in->flags); break; @@ -1219,23 +1332,23 @@ static void coroutine_fn fuse_co_process_request(Fu= seExport *exp) break; =20 case FUSE_SETATTR: { - const struct fuse_setattr_in *in =3D FUSE_IN_OP_STRUCT(setattr, ex= p); + const struct fuse_setattr_in *in =3D FUSE_IN_OP_STRUCT(setattr, q); ret =3D fuse_co_setattr(exp, FUSE_OUT_OP_STRUCT(attr, out_buf), in->valid, in->size, in->mode, in->uid, in->= gid); break; } =20 case FUSE_READ: { - const struct fuse_read_in *in =3D FUSE_IN_OP_STRUCT(read, exp); + const struct fuse_read_in *in =3D FUSE_IN_OP_STRUCT(read, q); ret =3D fuse_co_read(exp, &out_data_buffer, in->offset, in->size); break; } =20 case FUSE_WRITE: { - const struct fuse_write_in *in =3D FUSE_IN_OP_STRUCT(write, exp); + const struct fuse_write_in *in =3D FUSE_IN_OP_STRUCT(write, q); uint32_t req_len; =20 - req_len =3D ((const struct fuse_in_header *)exp->request_buf)->len; + req_len =3D ((const struct fuse_in_header *)q->request_buf)->len; if (unlikely(req_len < sizeof(struct fuse_in_header) + sizeof(*in)= + in->size)) { warn_report("FUSE WRITE truncated; received %zu bytes of %" PR= Iu32, @@ -1264,7 +1377,7 @@ static void coroutine_fn fuse_co_process_request(Fuse= Export *exp) } =20 case FUSE_FALLOCATE: { - const struct fuse_fallocate_in *in =3D FUSE_IN_OP_STRUCT(fallocate= , exp); + const struct fuse_fallocate_in *in =3D FUSE_IN_OP_STRUCT(fallocate= , q); ret =3D fuse_co_fallocate(exp, in->offset, in->length, in->mode); break; } @@ -1279,7 +1392,7 @@ static void coroutine_fn fuse_co_process_request(Fuse= Export *exp) =20 #ifdef CONFIG_FUSE_LSEEK case FUSE_LSEEK: { - const struct fuse_lseek_in *in =3D FUSE_IN_OP_STRUCT(lseek, exp); + const struct fuse_lseek_in *in =3D FUSE_IN_OP_STRUCT(lseek, q); ret =3D fuse_co_lseek(exp, FUSE_OUT_OP_STRUCT(lseek, out_buf), in->offset, in->whence); break; @@ -1293,11 +1406,11 @@ static void coroutine_fn fuse_co_process_request(Fu= seExport *exp) /* Ignore errors from fuse_write*(), nothing we can do anyway */ if (out_data_buffer) { assert(ret >=3D 0); - fuse_write_buf_response(exp->fuse_fd, req_id, out_hdr, + fuse_write_buf_response(q->fuse_fd, req_id, out_hdr, out_data_buffer, ret); qemu_vfree(out_data_buffer); } else { - fuse_write_response(exp->fuse_fd, req_id, out_hdr, + fuse_write_response(q->fuse_fd, req_id, out_hdr, ret < 0 ? ret : 0, ret < 0 ? 0 : ret); } --=20 2.49.0 From nobody Sat Nov 15 12:14:53 2025 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=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1751370706; cv=none; d=zohomail.com; s=zohoarc; b=IFrwv3mL3TDX4lz3p+xyQMQNEo2gvua009Y589hrUPhHxz17LR4sicPOev6K465AOwoYVbMzddC6zf+rLCPMxWD4ZKkMHd1HL+U6X00svSUYHCw+9/zhSDejQbp+Gb7eK61WwGgjOMDoJiy09P+ohVQ4DqCY02357mEOWSGfZfs= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1751370706; h=Content-Type: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=3rxoquqbsAfv2DglEJ+FeqUFKqD3/UIqhsvayd1Gi3Q=; b=EphrLoTfpQU0F06lzSZgE3TSbr97sxHBV9xIGaPP5HgIgeEVeX0GBcaWp8ZLk6czjznD0wqrUg481c+4PuTtHknl9Xytwlg9prIk/BmC/rCJBVhfs+2aYGwGN70/+RBovtfhC3PL/xtlh41rhbXrCNFnGS7aFMWH4KaltCOKr5w= 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 lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1751370706265885.1051586657836; Tue, 1 Jul 2025 04:51:46 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1uWZRp-0006hp-3G; Tue, 01 Jul 2025 07:46:49 -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 1uWZQz-0005fi-H1 for qemu-devel@nongnu.org; Tue, 01 Jul 2025 07:46:10 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uWZQt-0003eP-94 for qemu-devel@nongnu.org; Tue, 01 Jul 2025 07:45:56 -0400 Received: from mail-wr1-f70.google.com (mail-wr1-f70.google.com [209.85.221.70]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-33-m88-_0UiMO-YUjA2xe1hWg-1; Tue, 01 Jul 2025 07:45:46 -0400 Received: by mail-wr1-f70.google.com with SMTP id ffacd0b85a97d-3a52bfda108so2620197f8f.3 for ; Tue, 01 Jul 2025 04:45:45 -0700 (PDT) Received: from localhost (p200300cfd700f38d3df6a1ca7d40fe1f.dip0.t-ipconnect.de. [2003:cf:d700:f38d:3df6:a1ca:7d40:fe1f]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4538a306a01sm171978155e9.0.2025.07.01.04.45.42 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 01 Jul 2025 04:45:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1751370347; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=3rxoquqbsAfv2DglEJ+FeqUFKqD3/UIqhsvayd1Gi3Q=; b=YarJuQjXoKEY8fb7RilPVRw1hB/NsDddiOELNL4nJrmA+r4rYcmGK44crTPA9AJK7zj93F R0KDRfgFvIDS3UDTtx87PESM/NMcExpp8qIBEou24z/rNfbWK7tb93QKdIfr0oHhBxEGM4 9OruUAM/5ErQIUGMethOoC1dF1Hp+/0= X-MC-Unique: m88-_0UiMO-YUjA2xe1hWg-1 X-Mimecast-MFC-AGG-ID: m88-_0UiMO-YUjA2xe1hWg_1751370345 X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1751370345; x=1751975145; 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=3rxoquqbsAfv2DglEJ+FeqUFKqD3/UIqhsvayd1Gi3Q=; b=Ns/5teczRnu1e1n7q8l0kQoxc54SwJMc/f++uNUJOf7STVSV6nz3upM1f5j/+vCxC3 d4R9s10BLMGvgjkUZRS0w0jAJNRfNQv1cSu+591N4UKNrHtx98KPTxckyVcKZCeRrgx6 RTXHgMBDUJWjruLKc0Qp/uGefQQFyPxV95Bs9ukhz2A1Yw7+kKjbr/oi0Ig1tVgXS0aQ UOA3Qb3HdIsNy0K07FcSZwexg+yJGNzjD47OYsgenDd2b57dclM0hoWWOZCxDXvQlLqk T/MmXxso0a4rx0I+ngTmdpNbJYeMN84a4axHg/Tt64QB2Z+tlAOJ/ofW2uvG2kL8EYuM CI5g== X-Gm-Message-State: AOJu0Yx1D5IE43b4EqovK8cvgnuZiDHnNyivhJINIHUYJfJdcHYlNf3Y U8fmUyzn2gidNB6OgljxO8Dn49BvcWyxNHlVJ+IIkECnFDevOWRlvJQv4L+gObOiAIKNarxB5hQ j2V1hEV8M78j2KDGqOrWbm7qywJIB7gult35RqyOwuF74SngHYKp1PW9V X-Gm-Gg: ASbGncuMiQqE0QQ1ypw7yDeZ4CTUgp+ovOqOUenLkeiZSTLKDjAN97AlWBej+n3G48N ZEGEfiuJ9tYiuIFJeTNc8/sGB4KgRpSc/GexEJp3/2pyyyY7WFmVbzP7Uz1ocnCrC8t8gSB+viR aUBlPA8FbFpkxjWOOZjkdIKBxXvr3gyIkNn7Nijaruw5tgE4nMPb5VD8okRbYRYKvXqeJlowdtj H495il9DmCiG6g4KGW9GmVrOyaopOr2VzreWKj/PGG3nyZSaLx/WMeXLf+M9MfYcVTdNRNS8f1Z BWjEHCKWzrnkOJ4GbVt1uaXEUj3r+RemPjKU3YbFzjzEy7CsDV1bHO1Bf6uCTAlZwdKgxl7kytI Vzub0 X-Received: by 2002:a05:6000:65c:b0:3a4:cf10:28f with SMTP id ffacd0b85a97d-3a8ffdbf0b1mr14234523f8f.31.1751370344849; Tue, 01 Jul 2025 04:45:44 -0700 (PDT) X-Google-Smtp-Source: AGHT+IFSW9bEUOXnOKFHKpkrkm3rildAF2jAmF6FtAz4xLYpXhOgQUw/4Vr59an2+e5eas35ixxLKw== X-Received: by 2002:a05:6000:65c:b0:3a4:cf10:28f with SMTP id ffacd0b85a97d-3a8ffdbf0b1mr14234504f8f.31.1751370344423; Tue, 01 Jul 2025 04:45:44 -0700 (PDT) From: Hanna Czenczek To: qemu-block@nongnu.org Cc: qemu-devel@nongnu.org, Hanna Czenczek , Stefan Hajnoczi , Kevin Wolf , Markus Armbruster , Brian Song Subject: [PATCH v3 19/21] qapi/block-export: Document FUSE's multi-threading Date: Tue, 1 Jul 2025 13:44:35 +0200 Message-ID: <20250701114437.207419-20-hreitz@redhat.com> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250701114437.207419-1-hreitz@redhat.com> References: <20250701114437.207419-1-hreitz@redhat.com> 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=170.10.129.124; envelope-from=hreitz@redhat.com; helo=us-smtp-delivery-124.mimecast.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, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=unavailable autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1751370708152124100 Content-Type: text/plain; charset="utf-8" Document for users that FUSE's multi-threading implementation distributes requests in a round-robin manner, regardless of where they originate from. As noted by Stefan, this will probably change with a FUSE-over-io_uring implementation (which is supposed to have CPU affinity), but documenting that is left for once that is done. Suggested-by: Stefan Hajnoczi Acked-by: Markus Armbruster Signed-off-by: Hanna Czenczek Reviewed-by: Stefan Hajnoczi --- qapi/block-export.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/qapi/block-export.json b/qapi/block-export.json index ee30606680..9ae703ad01 100644 --- a/qapi/block-export.json +++ b/qapi/block-export.json @@ -163,6 +163,11 @@ # Options for exporting a block graph node on some (file) mountpoint # as a raw image. # +# Multi-threading note: The FUSE export supports multi-threading. +# Currently, requests are distributed across these threads in a +# round-robin fashion, i.e. independently of the CPU core from which a +# request originates. +# # @mountpoint: Path on which to export the block device via FUSE. # This must point to an existing regular file. # --=20 2.49.0 From nobody Sat Nov 15 12:14:53 2025 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=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1751370446; cv=none; d=zohomail.com; s=zohoarc; b=XDbCk9HijrTz7txdCOXBTAY4vBMxvsiAMjEblX3XHaTrEH7CgHePD5qg1oJ+q2rKqIjOmQZOhhmCCUbUooLDaK2hYZUhEoP6o5+mIAgEhh7Un6/ZaVLCGoiCAwNo0tquL60hZWEE1lumzY1cYxJasy8e+c7czbs2lGJ9hsqVb04= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1751370446; h=Content-Type: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=Wmi5I5WHYt2gr3ayuHReWJBs0mW0tBonN0/WuhY6EsA=; b=Q665DXcIHOexGBr5tVJuK2DMTxOot0DlkprQBgHo+qbzhBP3iKDX2mcaNLgsPybVfNLw79/2bVQ/xbCg9h2uxApUi/nvP2rOsycsm5Hoh6m7fmxJZYuIXuTFaTavWhymjq3VafiWiM+i+8Hgtaudlb679C7uWLvL6cG7lwTkh8M= 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 lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1751370446423336.6162581065082; Tue, 1 Jul 2025 04:47:26 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1uWZRu-0006qA-1A; Tue, 01 Jul 2025 07:46:54 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uWZR3-0005m0-9Y for qemu-devel@nongnu.org; Tue, 01 Jul 2025 07:46:23 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uWZQu-0003fJ-92 for qemu-devel@nongnu.org; Tue, 01 Jul 2025 07:45:58 -0400 Received: from mail-wm1-f71.google.com (mail-wm1-f71.google.com [209.85.128.71]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-605-AByYE_STNyCoIaApVAB5Pg-1; Tue, 01 Jul 2025 07:45:49 -0400 Received: by mail-wm1-f71.google.com with SMTP id 5b1f17b1804b1-451dda846a0so21553825e9.2 for ; Tue, 01 Jul 2025 04:45:49 -0700 (PDT) Received: from localhost (p200300cfd700f38d3df6a1ca7d40fe1f.dip0.t-ipconnect.de. [2003:cf:d700:f38d:3df6:a1ca:7d40:fe1f]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-453a1914d10sm53734025e9.4.2025.07.01.04.45.45 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 01 Jul 2025 04:45:45 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1751370350; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=Wmi5I5WHYt2gr3ayuHReWJBs0mW0tBonN0/WuhY6EsA=; b=SyXhT8BW/5ZiNALaCGkuCc7gP5XpWIiERs4TLUU8Fmls+xmWjD3kNK8GQCtgoRytP9JgDX AD39A3lst4J8uXmDqoelOBBYWtwIXxw5qciI6ZV++RKpcYbUfjeFv4dddXuyqg4IfjDZuE nRAtBPdogvRL2biUA8QWfTQiPIVEsrU= X-MC-Unique: AByYE_STNyCoIaApVAB5Pg-1 X-Mimecast-MFC-AGG-ID: AByYE_STNyCoIaApVAB5Pg_1751370348 X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1751370348; x=1751975148; 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=Wmi5I5WHYt2gr3ayuHReWJBs0mW0tBonN0/WuhY6EsA=; b=s7cQd3T9Hn4YoTtcDVrQzloPTSVMFijrSKkEmAoZm13pUq2sEIZWZArxzYmCXBC4e0 AOqH77L2O3jEY7CIr1/TVWkq9mJORC813Tki0aqBq0KjFwsW68BbBSZSDe/C+NXLiMZI sLrZGy4QfC/JVFUuIWCCWPtfRE/qTiQ+9/bjqn8Oo6+9keqWVoWqPo6i8YEPKh/VccKO IUln393kmSOA7m6Hg4DIUcoV8WafPhLnYk2D8IF91+gcL/YzqyZxHUS61jAC4FEZy0WH PkAVMrS/mvYXbeT+W7wwahGGlovCFD20W5OG+nQFuSFPYc/OAlU2krGpET41vcggiF3Z Jaiw== X-Gm-Message-State: AOJu0YyKZ1w8xOR6WphcpAAV2MJM9lwivSzjJ5M+1BlovnApXNz/IEao k+PBwEnscCcNSQ1IUfChE2DkLMG8RVgStOEYkL4+5pRgGoblfBJr63BGEMERAkhR+kH+3sp9M8W o/WDanBieIRzetH5e2whAvWZXpbrlFXgyYkbNYvFE4SbkktYbhB6kJ+Hw X-Gm-Gg: ASbGncsqfwKbTSE7verK+8lVv+1MnwMRhci9QkQzOQjOQB1EaVmo72pNbqJ4SVZQdCq JvDCGIv9i3HOtk27o8ULWdzUAydaJPFZ58BPgZje/zaRYgEMFcQrpdtOZ2ABYMVzIKOlNc0lie9 7tlccvWSU0/KcGSlgBnuRWsCwj5TasO8gfEhxKsR80i4+pjUyNZVYPhhkrxkcon1JB6U4zJxD9G rfwvr/VjkU3mSsWBSWyj7z6xSL3n2un0SphMvcGHgIAKNqkuoXn37RUbbjhUYyVcoWeK8m/p4S3 enfSmoqM8iwZQDShnNKdCR6s/gSphlzPsqMJngJPzIMqJBFNDPUfBQzI+4W9ptEkdIGUwMiezhB jXB7/ X-Received: by 2002:a05:600c:3b0a:b0:453:9bf:6f7c with SMTP id 5b1f17b1804b1-4538ee5d0b8mr188520015e9.9.1751370348279; Tue, 01 Jul 2025 04:45:48 -0700 (PDT) X-Google-Smtp-Source: AGHT+IHT+GObbK6oNCknbIHIqRpvMqUDBTM25FlbyxEDP54tbNEMOOgubqChNq1ebJqXelLH5Zx1Ew== X-Received: by 2002:a05:600c:3b0a:b0:453:9bf:6f7c with SMTP id 5b1f17b1804b1-4538ee5d0b8mr188519695e9.9.1751370347798; Tue, 01 Jul 2025 04:45:47 -0700 (PDT) From: Hanna Czenczek To: qemu-block@nongnu.org Cc: qemu-devel@nongnu.org, Hanna Czenczek , Stefan Hajnoczi , Kevin Wolf , Markus Armbruster , Brian Song Subject: [PATCH v3 20/21] iotests/308: Add multi-threading sanity test Date: Tue, 1 Jul 2025 13:44:36 +0200 Message-ID: <20250701114437.207419-21-hreitz@redhat.com> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250701114437.207419-1-hreitz@redhat.com> References: <20250701114437.207419-1-hreitz@redhat.com> 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=170.10.129.124; envelope-from=hreitz@redhat.com; helo=us-smtp-delivery-124.mimecast.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, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=unavailable autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1751370447337116600 Content-Type: text/plain; charset="utf-8" Run qemu-img bench on a simple multi-threaded FUSE export to test that it works. Reviewed-by: Stefan Hajnoczi Signed-off-by: Hanna Czenczek --- tests/qemu-iotests/308 | 51 ++++++++++++++++++++++++++++++++++ tests/qemu-iotests/308.out | 56 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 107 insertions(+) diff --git a/tests/qemu-iotests/308 b/tests/qemu-iotests/308 index 033d5cbe22..2960412285 100755 --- a/tests/qemu-iotests/308 +++ b/tests/qemu-iotests/308 @@ -415,6 +415,57 @@ $QEMU_IO -c 'read -P 0 0 64M' "$TEST_IMG" | _filter_qe= mu_io =20 _cleanup_test_img =20 +echo +echo '=3D=3D=3D Multi-threading =3D=3D=3D' + +# Just set up a null block device, export it (with multi-threading), and r= un +# qemu-img bench on it (to get parallel requests) + +_launch_qemu +_send_qemu_cmd $QEMU_HANDLE \ + "{'execute': 'qmp_capabilities'}" \ + 'return' + +_send_qemu_cmd $QEMU_HANDLE \ + "{'execute': 'blockdev-add', + 'arguments': { + 'driver': 'null-co', + 'node-name': 'null' + } }" \ + 'return' + +for id in iothread{0,1,2,3}; do + _send_qemu_cmd $QEMU_HANDLE \ + "{'execute': 'object-add', + 'arguments': { + 'qom-type': 'iothread', + 'id': '$id' + } }" \ + 'return' +done + +echo + +iothreads=3D"['iothread0', 'iothread1', 'iothread2', 'iothread3']" +fuse_export_add \ + 'export' \ + "'mountpoint': '$EXT_MP', 'iothread': $iothreads" \ + 'return' \ + 'null' + +echo +$QEMU_IMG bench -f raw "$EXT_MP" | + sed -e 's/[0-9.]\+ seconds/X.XXX seconds/' +echo + +fuse_export_del 'export' + +_send_qemu_cmd $QEMU_HANDLE \ + "{'execute': 'quit'}" \ + 'return' + +wait=3Dyes _cleanup_qemu + # success, all done echo "*** done" rm -f $seq.full diff --git a/tests/qemu-iotests/308.out b/tests/qemu-iotests/308.out index 2d7a38d63d..04e6913c5c 100644 --- a/tests/qemu-iotests/308.out +++ b/tests/qemu-iotests/308.out @@ -207,4 +207,60 @@ read 67108864/67108864 bytes at offset 0 {"return": {}} read 67108864/67108864 bytes at offset 0 64 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +=3D=3D=3D Multi-threading =3D=3D=3D +{'execute': 'qmp_capabilities'} +{"return": {}} +{'execute': 'blockdev-add', + 'arguments': { + 'driver': 'null-co', + 'node-name': 'null' + } } +{"return": {}} +{'execute': 'object-add', + 'arguments': { + 'qom-type': 'iothread', + 'id': 'iothread0' + } } +{"return": {}} +{'execute': 'object-add', + 'arguments': { + 'qom-type': 'iothread', + 'id': 'iothread1' + } } +{"return": {}} +{'execute': 'object-add', + 'arguments': { + 'qom-type': 'iothread', + 'id': 'iothread2' + } } +{"return": {}} +{'execute': 'object-add', + 'arguments': { + 'qom-type': 'iothread', + 'id': 'iothread3' + } } +{"return": {}} + +{'execute': 'block-export-add', + 'arguments': { + 'type': 'fuse', + 'id': 'export', + 'node-name': 'null', + 'mountpoint': 'TEST_DIR/t.IMGFMT.fuse', 'iothread': ['iothre= ad0', 'iothread1', 'iothread2', 'iothread3'] + } } +{"return": {}} + +Sending 75000 read requests, 4096 bytes each, 64 in parallel (starting at = offset 0, step size 4096) +Run completed in X.XXX seconds. + +{'execute': 'block-export-del', + 'arguments': { + 'id': 'export' + } } +{"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "BLOCK_EXPORT_DELETED", "data": {"id": "export"}} +{'execute': 'quit'} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event"= : "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}} +{"return": {}} *** done --=20 2.49.0 From nobody Sat Nov 15 12:14:53 2025 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=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1751370586; cv=none; d=zohomail.com; s=zohoarc; b=ZuNkWznihbRkAQoZJ6QUBr+Ae6FniVnMHELDVV1dtw3nshxc2GL8cOZjMyWVMlqNdkR0sVnBQAwdy4AyC1sOxL9aziKD3tJz7D7Dhk22SGhpLCSwB5YN+0qedDJqxHHu5Py05WEivpDHa6EDSWXvAECpPSQJvIxC4ldyekKLvzA= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1751370586; h=Content-Type: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=apTE44HrBCLaFuuQZm7HtEFEO/u09gbTpH+Q+H5z9eQ=; b=el5UKbODXzmamvX4839Q4EIqdCCGlyQYTG7GkwT7MYKKlKGpbkXzxa4lHqgPVjNEtC1G0GVNWQ9nAt/HTairrQ8paRhPnaoujsUKuhqF5G6DR40GOayV1HrfK4LhrsZkPViI2684poq231iRejsxB/YrsOJ4SZdNqpo6QogSAmk= 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 lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1751370586919557.4968375253488; Tue, 1 Jul 2025 04:49:46 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1uWZRo-0006gR-Ui; Tue, 01 Jul 2025 07:46:49 -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 1uWZR4-0005m1-AN for qemu-devel@nongnu.org; Tue, 01 Jul 2025 07:46:15 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uWZQx-0003fo-9e for qemu-devel@nongnu.org; Tue, 01 Jul 2025 07:45:59 -0400 Received: from mail-wm1-f72.google.com (mail-wm1-f72.google.com [209.85.128.72]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-461-Fo5K_tIcMWeqMNp7B19CQw-1; Tue, 01 Jul 2025 07:45:53 -0400 Received: by mail-wm1-f72.google.com with SMTP id 5b1f17b1804b1-4538f375e86so29202295e9.3 for ; Tue, 01 Jul 2025 04:45:53 -0700 (PDT) Received: from localhost (p200300cfd700f38d3df6a1ca7d40fe1f.dip0.t-ipconnect.de. [2003:cf:d700:f38d:3df6:a1ca:7d40:fe1f]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-453823c463asm192863615e9.39.2025.07.01.04.45.48 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 01 Jul 2025 04:45:49 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1751370354; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=apTE44HrBCLaFuuQZm7HtEFEO/u09gbTpH+Q+H5z9eQ=; b=RraMnKL3q4MHWH6+dDLTGaMtcSpc/sXsTOiZukhXM3qFpBwuPzRk4dVrsuTjBFBl7Vi7dl LajaMZRD8/VRGJzkteFHiCNwgVs2R/9PXOz63dKag7aa0pdUB0jNUw7QxSVXQjy2MxsIjO WoyMs7IJmKDZRFsA6BV9lGIlqSgbxPA= X-MC-Unique: Fo5K_tIcMWeqMNp7B19CQw-1 X-Mimecast-MFC-AGG-ID: Fo5K_tIcMWeqMNp7B19CQw_1751370352 X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1751370351; x=1751975151; 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=apTE44HrBCLaFuuQZm7HtEFEO/u09gbTpH+Q+H5z9eQ=; b=FrAn1V0/+ix8mLL49yYTwJn5L0YRPTC+uo1QG79K/JZajWl8dbAEi/8MudvWHTCWL/ baQV+MZYVNzzBxytXqkAQ412S2bd9GS6P9K4UEjG2jlysjjvDTnbXSH1X0+eQDKzXiFY Rjy3jRPPbpsQpPZrYSrR4GbaNA4dKhgygntNLxlJ4PQwRNdmMKA9DvRNXHEHIAd7VK1M 2s7E8/1p4mvsa3GT8nUuQRHYxAB3k/U5LMAcErZFKrbLxjMbc9WfFJhrBxNCeeXeeHEx T767xHnQq3acKQ5mLZWYoLvqhcGPO2+bQzM3EAfpuoxaG82pTDmER8+aI+VeYXa/niV4 iC4g== X-Gm-Message-State: AOJu0YyC0W4xB4MBOfKDWeExtZmZZY6KgxFhrEmFzU/UVQj9W1xlReEZ SoY2w4YmyhA9C6JonUvyvw6zkt6g/UMgRHtCVqCldhGnK7gubBZymbUwdgSQXXNT/5tE0gjJjcI Ytq9lSEdLOQhcdplnfxsN4HQDnorYZEbux+CQasecIgw4KIO8nNw5uPXQ7+gQL9M3 X-Gm-Gg: ASbGncus/nt4FG7n59eEaxq7MtEi5bqYRRcF8QSBGe4nqk85eR98GdnbK6jUxevmkre 4XUBbvZijnG0IjrrthXePU1n+A73ZuNTTM6rRAYA0raCjKR7ap/ukZL0pehWwtlUo5SrOLQ/8Vt DGFnm+UQ1ypYIxVDlNruB+uRybnEOAmIoyef3QLcqJRohGwv8Xfa5O2tdSQGWNF1AhzXKuzUn2Q odXvxFUDlL4THvantLT94k0qc344AHLZN75d936bueC7eQCbUNQHNgfIPrz0oRCLDHLZD/E5xgc 1CkCTvHg3csJHC9UK8FvVaKh5+1nmqlM5Bahbk1HPehpwb+7udSE2gaqob+Gj31YZdBGtlh1YdK G7qj4 X-Received: by 2002:a05:600c:3b86:b0:441:b00d:e9d1 with SMTP id 5b1f17b1804b1-454a06a497bmr11468685e9.2.1751370351057; Tue, 01 Jul 2025 04:45:51 -0700 (PDT) X-Google-Smtp-Source: AGHT+IFpFSF/XW67UQPnhg2EidQc4NBbXVWYD3M0WmuTG8ymS/RlumP3MZOEMaLLR7efZLxafugscw== X-Received: by 2002:a05:600c:3b86:b0:441:b00d:e9d1 with SMTP id 5b1f17b1804b1-454a06a497bmr11468155e9.2.1751370350514; Tue, 01 Jul 2025 04:45:50 -0700 (PDT) From: Hanna Czenczek To: qemu-block@nongnu.org Cc: qemu-devel@nongnu.org, Hanna Czenczek , Stefan Hajnoczi , Kevin Wolf , Markus Armbruster , Brian Song Subject: [PATCH v3 21/21] fuse: Increase MAX_WRITE_SIZE with a second buffer Date: Tue, 1 Jul 2025 13:44:37 +0200 Message-ID: <20250701114437.207419-22-hreitz@redhat.com> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250701114437.207419-1-hreitz@redhat.com> References: <20250701114437.207419-1-hreitz@redhat.com> 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=170.10.129.124; envelope-from=hreitz@redhat.com; helo=us-smtp-delivery-124.mimecast.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, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1751370589090124100 Content-Type: text/plain; charset="utf-8" We probably want to support larger write sizes than just 4k; 64k seems nice. However, we cannot read partial requests from the FUSE FD, we always have to read requests in full; so our read buffer must be large enough to accommodate potential 64k writes if we want to support that. Always allocating FuseRequest objects with 64k buffers in them seems wasteful, though. But we can get around the issue by splitting the buffer into two and using readv(): One part will hold all normal (up to 4k) write requests and all other requests, and a second part (the "spill-over buffer") will be used only for larger write requests. Each FuseQueue has its own spill-over buffer, and only if we find it used when reading a request will we move its ownership into the FuseRequest object and allocate a new spill-over buffer for the queue. This way, we get to support "large" write sizes without having to allocate big buffers when they aren't used. Also, this even reduces the size of the FuseRequest objects because the read buffer has to have at least FUSE_MIN_READ_BUFFER (8192) bytes; but the requests we support are not quite so large (except for >4k writes), so until now, we basically had to have useless padding in there. With the spill-over buffer added, the FUSE_MIN_READ_BUFFER requirement is easily met and we can decrease the size of the buffer portion that is right inside of FuseRequest. As for benchmarks, the benefit of this patch can be shown easily by writing a 4G image (with qemu-img convert) to a FUSE export: - Before this patch: Takes 25.6 s (14.4 s with -t none) - After this patch: Takes 4.5 s (5.5 s with -t none) Reviewed-by: Stefan Hajnoczi Signed-off-by: Hanna Czenczek --- block/export/fuse.c | 137 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 118 insertions(+), 19 deletions(-) diff --git a/block/export/fuse.c b/block/export/fuse.c index 4ae448bc14..c0ad4696ce 100644 --- a/block/export/fuse.c +++ b/block/export/fuse.c @@ -50,8 +50,17 @@ =20 /* Prevent overly long bounce buffer allocations */ #define FUSE_MAX_READ_BYTES (MIN(BDRV_REQUEST_MAX_BYTES, 1 * 1024 * 1024)) -/* Small enough to fit in the request buffer */ -#define FUSE_MAX_WRITE_BYTES (4 * 1024) +/* + * FUSE_MAX_WRITE_BYTES determines the maximum number of bytes we support = in a + * write request; FUSE_IN_PLACE_WRITE_BYTES and FUSE_SPILLOVER_BUF_SIZE + * determine the split between the size of the in-place buffer in FuseRequ= est + * and the spill-over buffer in FuseQueue. See FuseQueue.spillover_buf fo= r a + * detailed explanation. + */ +#define FUSE_IN_PLACE_WRITE_BYTES (4 * 1024) +#define FUSE_MAX_WRITE_BYTES (64 * 1024) +#define FUSE_SPILLOVER_BUF_SIZE \ + (FUSE_MAX_WRITE_BYTES - FUSE_IN_PLACE_WRITE_BYTES) =20 typedef struct FuseExport FuseExport; =20 @@ -67,15 +76,49 @@ typedef struct FuseQueue { =20 /* * The request buffer must be able to hold a full write, and/or at lea= st - * FUSE_MIN_READ_BUFFER (from linux/fuse.h) bytes + * FUSE_MIN_READ_BUFFER (from linux/fuse.h) bytes. + * This however is just the first part of the buffer; every read is gi= ven + * a vector of this buffer (which should be enough for all normal requ= ests, + * which we check via the static assertion in FUSE_IN_OP_STRUCT()) and= the + * spill-over buffer below. + * Therefore, the size of this buffer plus FUSE_SPILLOVER_BUF_SIZE mus= t be + * FUSE_MIN_READ_BUFFER or more (checked via static assertion below). + */ + char request_buf[sizeof(struct fuse_in_header) + + sizeof(struct fuse_write_in) + + FUSE_IN_PLACE_WRITE_BYTES]; + + /* + * When retrieving a FUSE request, the destination buffer must always = be + * sufficiently large for the whole request, i.e. with max_write=3D64k= , we + * must provide a buffer that fits the WRITE header and 64 kB of space= for + * data. + * We do want to support 64k write requests without requiring them to = be + * split up, but at the same time, do not want to do such a large allo= cation + * for every single request. + * Therefore, the FuseRequest object provides an in-line buffer that is + * enough for write requests up to 4k (and all other requests), and for + * every request that is bigger, we provide a spill-over buffer here (= for + * the remaining 64k - 4k =3D 60k). + * When poll_fuse_fd() reads a FUSE request, it passes these buffers a= s an + * I/O vector, and then checks the return value (number of bytes read)= to + * find out whether the spill-over buffer was used. If so, it will mo= ve the + * buffer to the request, and will allocate a new spill-over buffer fo= r the + * next request. + * + * Free this buffer with qemu_vfree(). */ - char request_buf[MAX_CONST( - sizeof(struct fuse_in_header) + sizeof(struct fuse_write_in) + - FUSE_MAX_WRITE_BYTES, - FUSE_MIN_READ_BUFFER - )]; + void *spillover_buf; } FuseQueue; =20 +/* + * Verify that FuseQueue.request_buf plus the spill-over buffer together + * are big enough to be accepted by the FUSE kernel driver. + */ +QEMU_BUILD_BUG_ON(sizeof(((FuseQueue *)0)->request_buf) + + FUSE_SPILLOVER_BUF_SIZE < + FUSE_MIN_READ_BUFFER); + struct FuseExport { BlockExport common; =20 @@ -131,7 +174,8 @@ static int clone_fuse_fd(int fd, Error **errp); static bool is_regular_file(const char *path, Error **errp); =20 static void read_from_fuse_fd(void *opaque); -static void coroutine_fn fuse_co_process_request(FuseQueue *q); +static void coroutine_fn +fuse_co_process_request(FuseQueue *q, void *spillover_buf); =20 static void fuse_inc_in_flight(FuseExport *exp) { @@ -476,12 +520,27 @@ static void coroutine_fn co_read_from_fuse_fd(void *o= paque) FuseExport *exp =3D q->exp; ssize_t ret; const struct fuse_in_header *in_hdr; + struct iovec iov[2]; + void *spillover_buf =3D NULL; =20 if (unlikely(exp->halted)) { goto no_request; } =20 - ret =3D RETRY_ON_EINTR(read(fuse_fd, q->request_buf, sizeof(q->request= _buf))); + /* + * If handling the last request consumed the spill-over buffer, alloca= te a + * new one. Align it to the block device's alignment, which admittedl= y is + * only useful if FUSE_IN_PLACE_WRITE_BYTES is aligned, too. + */ + if (unlikely(!q->spillover_buf)) { + q->spillover_buf =3D blk_blockalign(exp->common.blk, + FUSE_SPILLOVER_BUF_SIZE); + } + /* Construct the I/O vector to hold the FUSE request */ + iov[0] =3D (struct iovec) { q->request_buf, sizeof(q->request_buf) }; + iov[1] =3D (struct iovec) { q->spillover_buf, FUSE_SPILLOVER_BUF_SIZE = }; + + ret =3D RETRY_ON_EINTR(readv(fuse_fd, iov, ARRAY_SIZE(iov))); if (ret < 0 && errno =3D=3D EAGAIN) { /* No request available */ goto no_request; @@ -510,7 +569,13 @@ static void coroutine_fn co_read_from_fuse_fd(void *op= aque) goto no_request; } =20 - fuse_co_process_request(q); + if (unlikely(ret > sizeof(q->request_buf))) { + /* Spillover buffer used, take ownership */ + spillover_buf =3D q->spillover_buf; + q->spillover_buf =3D NULL; + } + + fuse_co_process_request(q, spillover_buf); =20 no_request: fuse_dec_in_flight(exp); @@ -560,6 +625,9 @@ static void fuse_export_delete(BlockExport *blk_exp) if (i > 0 && q->fuse_fd >=3D 0) { close(q->fuse_fd); } + if (q->spillover_buf) { + qemu_vfree(q->spillover_buf); + } } g_free(exp->queues); =20 @@ -869,17 +937,25 @@ fuse_co_read(FuseExport *exp, void **bufptr, uint64_t= offset, uint32_t size) } =20 /** - * Handle client writes to the exported image. @buf has the data to be wr= itten - * and will be copied to a bounce buffer before yielding for the first tim= e. + * Handle client writes to the exported image. @in_place_buf has the first + * FUSE_IN_PLACE_WRITE_BYTES bytes of the data to be written, @spillover_b= uf + * contains the rest (if any; NULL otherwise). + * Data in @in_place_buf is assumed to be overwritten after yielding, so w= ill + * be copied to a bounce buffer beforehand. @spillover_buf in contrast is + * assumed to be exclusively owned and will be used as-is. * Return the number of bytes written to *out on success, and -errno on er= ror. */ static ssize_t coroutine_fn fuse_co_write(FuseExport *exp, struct fuse_write_out *out, - uint64_t offset, uint32_t size, const void *buf) + uint64_t offset, uint32_t size, + const void *in_place_buf, const void *spillover_buf) { + size_t in_place_size; void *copied; int64_t blk_len; int ret; + struct iovec iov[2]; + QEMUIOVector qiov; =20 /* Limited by max_write, should not happen */ if (size > BDRV_REQUEST_MAX_BYTES) { @@ -891,8 +967,9 @@ fuse_co_write(FuseExport *exp, struct fuse_write_out *o= ut, } =20 /* Must copy to bounce buffer before potentially yielding */ - copied =3D blk_blockalign(exp->common.blk, size); - memcpy(copied, buf, size); + in_place_size =3D MIN(size, FUSE_IN_PLACE_WRITE_BYTES); + copied =3D blk_blockalign(exp->common.blk, in_place_size); + memcpy(copied, in_place_buf, in_place_size); =20 /** * Clients will expect short writes at EOF, so we have to limit @@ -916,7 +993,21 @@ fuse_co_write(FuseExport *exp, struct fuse_write_out *= out, } } =20 - ret =3D blk_co_pwrite(exp->common.blk, offset, size, copied, 0); + iov[0] =3D (struct iovec) { + .iov_base =3D copied, + .iov_len =3D in_place_size, + }; + if (size > FUSE_IN_PLACE_WRITE_BYTES) { + assert(size - FUSE_IN_PLACE_WRITE_BYTES <=3D FUSE_SPILLOVER_BUF_SI= ZE); + iov[1] =3D (struct iovec) { + .iov_base =3D (void *)spillover_buf, + .iov_len =3D size - FUSE_IN_PLACE_WRITE_BYTES, + }; + qemu_iovec_init_external(&qiov, iov, 2); + } else { + qemu_iovec_init_external(&qiov, iov, 1); + } + ret =3D blk_co_pwritev(exp->common.blk, offset, size, &qiov, 0); if (ret < 0) { goto fail_free_buffer; } @@ -1275,8 +1366,14 @@ static int fuse_write_buf_response(int fd, uint32_t = req_id, * Note that yielding in any request-processing function can overwrite the * contents of q->request_buf. Anything that takes a buffer needs to take * care that the content is copied before yielding. + * + * @spillover_buf can contain the tail of a write request too large to fit= into + * q->request_buf. This function takes ownership of it (i.e. will free it= ), + * which assumes that its contents will not be overwritten by concurrent + * requests (as opposed to q->request_buf). */ -static void coroutine_fn fuse_co_process_request(FuseQueue *q) +static void coroutine_fn +fuse_co_process_request(FuseQueue *q, void *spillover_buf) { FuseExport *exp =3D q->exp; uint32_t opcode; @@ -1372,7 +1469,7 @@ static void coroutine_fn fuse_co_process_request(Fuse= Queue *q) * yielding. */ ret =3D fuse_co_write(exp, FUSE_OUT_OP_STRUCT(write, out_buf), - in->offset, in->size, in + 1); + in->offset, in->size, in + 1, spillover_buf); break; } =20 @@ -1414,6 +1511,8 @@ static void coroutine_fn fuse_co_process_request(Fuse= Queue *q) ret < 0 ? ret : 0, ret < 0 ? 0 : ret); } + + qemu_vfree(spillover_buf); } =20 const BlockExportDriver blk_exp_fuse =3D { --=20 2.49.0