From patchwork Mon Jan 13 22:20:37 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christian Schoenebeck X-Patchwork-Id: 11331135 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 3E177139A for ; Tue, 14 Jan 2020 00:40:12 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 136B0207FD for ; Tue, 14 Jan 2020 00:40:12 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=crudebyte.com header.i=@crudebyte.com header.b="UQFid1OV" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 136B0207FD Authentication-Results: mail.kernel.org; dmarc=fail (p=quarantine dis=none) header.from=crudebyte.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Received: from localhost ([::1]:57536 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1irAFe-0007ie-RA for patchwork-qemu-devel@patchwork.kernel.org; Mon, 13 Jan 2020 19:40:10 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:35185) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from <8d86288c6b169461812b2c5838c35df51396d5ff@lizzy.crudebyte.com>) id 1irAES-0006mo-84 for qemu-devel@nongnu.org; Mon, 13 Jan 2020 19:38:57 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from <8d86288c6b169461812b2c5838c35df51396d5ff@lizzy.crudebyte.com>) id 1irAEQ-0003lN-WC for qemu-devel@nongnu.org; Mon, 13 Jan 2020 19:38:56 -0500 Received: from lizzy.crudebyte.com ([91.194.90.13]:53853) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from <8d86288c6b169461812b2c5838c35df51396d5ff@lizzy.crudebyte.com>) id 1irAEQ-0002iH-PL for qemu-devel@nongnu.org; Mon, 13 Jan 2020 19:38:54 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=crudebyte.com; s=lizzy; h=Cc:To:Subject:Date:From:References:In-Reply-To: Message-Id:Content-Type:Content-Transfer-Encoding:MIME-Version:Content-ID: Content-Description; bh=ueZKXtIfpbKoSzdo2zVCHwkMKgcaOQPLVmaUXXmHksI=; b=UQFid 1OVALJC5mm/sFuVDn3sDHFBZHf3PfpFYZDZLoTeCgM693wS3Q0CWIl4QHt/XEnSgAKLpGnWKdJfcI NvTRO27/5b3KoyQAQgYdzA/Z7Rpra+FghakP+bzwWJB+cHoeSS2FfofsIVprHGQwTSpj9B3KTg5Gm 4GfkM1K/PYTYd9rdnNenSYmOYhLxmJp6feMfHT6LR64tzJqKV8nky6VTM5HeFWx9OPaCB6wKthhiH IDw116umci3imzJdFqd9TiSlSQcpEkgtYAWlev3NTzZ6KBvo1FfMg/XGXmsQFk9b5dE2bsQR2hm1B dJhaQqo5PCWY1rkuQKaesvL8T0OTQ==; Message-Id: <8d86288c6b169461812b2c5838c35df51396d5ff.1578957500.git.qemu_oss@crudebyte.com> In-Reply-To: References: From: Christian Schoenebeck Date: Mon, 13 Jan 2020 23:20:37 +0100 Subject: [PATCH v3 01/11] tests/virtio-9p: add terminating null in v9fs_string_read() To: qemu-devel@nongnu.org Cc: Greg Kurz X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 91.194.90.13 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" The 9p protocol sends strings in general without null termination over the wire. However for future use of this functions it is beneficial for the delivered string to be null terminated though for being able to use the string with standard C functions which often rely on strings being null terminated. Signed-off-by: Christian Schoenebeck Reviewed-by: Greg Kurz --- tests/virtio-9p-test.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/virtio-9p-test.c b/tests/virtio-9p-test.c index e7b58e3a0c..06263edb53 100644 --- a/tests/virtio-9p-test.c +++ b/tests/virtio-9p-test.c @@ -130,8 +130,9 @@ static void v9fs_string_read(P9Req *req, uint16_t *len, char **string) *len = local_len; } if (string) { - *string = g_malloc(local_len); + *string = g_malloc(local_len + 1); v9fs_memread(req, *string, local_len); + (*string)[local_len] = 0; } else { v9fs_memskip(req, local_len); } From patchwork Mon Jan 13 22:21:04 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christian Schoenebeck X-Patchwork-Id: 11331137 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 6E34013A0 for ; Tue, 14 Jan 2020 00:40:58 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 44C1C2084D for ; Tue, 14 Jan 2020 00:40:58 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=crudebyte.com header.i=@crudebyte.com header.b="R8Jv4Gqn" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 44C1C2084D Authentication-Results: mail.kernel.org; dmarc=fail (p=quarantine dis=none) header.from=crudebyte.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Received: from localhost ([::1]:57554 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1irAGP-0000q3-C5 for patchwork-qemu-devel@patchwork.kernel.org; Mon, 13 Jan 2020 19:40:57 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:35389) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from <49ff399635ccfd21858b15417a398df362ff0b90@lizzy.crudebyte.com>) id 1irAFS-0007Qf-7r for qemu-devel@nongnu.org; Mon, 13 Jan 2020 19:39:59 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from <49ff399635ccfd21858b15417a398df362ff0b90@lizzy.crudebyte.com>) id 1irAFR-0004ax-4B for qemu-devel@nongnu.org; Mon, 13 Jan 2020 19:39:58 -0500 Received: from lizzy.crudebyte.com ([91.194.90.13]:58501) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from <49ff399635ccfd21858b15417a398df362ff0b90@lizzy.crudebyte.com>) id 1irAFQ-0003nl-UA for qemu-devel@nongnu.org; Mon, 13 Jan 2020 19:39:57 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=crudebyte.com; s=lizzy; h=Cc:To:Subject:Date:From:References:In-Reply-To: Message-Id:Content-Type:Content-Transfer-Encoding:MIME-Version:Content-ID: Content-Description; bh=+Myfkq98Clr2ORtfWNQein9mN5wHBp4bIQMl85shDKw=; b=R8Jv4 GqnRIHxyFLv+BjMrQnD054U+toPSm2aqHP0bgsO2m7C8QVmy4XErA80rxYZxAgoZuyVrgFpz8oMY+ Y67fxwEdKIXjJSERfAmNyamAQjdIL1vuwr63psK2togayyCoJXBO1arm53nzGUHo4INxT+afglLMK f4kYYDeAGafaW6FNofxkPOU6ZfWzj9kLZfLBJEwLBVPxCszkjSvLP0z9nHoHxrtGn6hHVXmRLBARu PD7VNHmte081vFOi/OK60ixiHQVbv1lXXnDQuf+FcA0VScCL862ky5NWr5a7yGoCiGoFjNxwke0rt iAPwRiC2LgkVg4jhXCR1vCfT5/pCw==; Message-Id: <49ff399635ccfd21858b15417a398df362ff0b90.1578957500.git.qemu_oss@crudebyte.com> In-Reply-To: References: From: Christian Schoenebeck Date: Mon, 13 Jan 2020 23:21:04 +0100 Subject: [PATCH v3 02/11] 9pfs: require msize >= 4096 To: qemu-devel@nongnu.org Cc: Greg Kurz X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 91.194.90.13 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" A client establishes a session by sending a Tversion request along with a 'msize' parameter which client uses to suggest server a maximum message size ever to be used for communication (for both requests and replies) between client and server during that session. If client suggests a 'msize' smaller than 4096 then deny session by server immediately with an error response (Rlerror for "9P2000.L" clients or Rerror for "9P2000.u" clients) instead of replying with Rversion. Introduction of a minimum msize is required to prevent issues in responses to numerous individual request types. For instance with a msize of < P9_IOHDRSZ no useful operations would be possible at all. Furthermore there are some responses which are not allowed by the 9p protocol to be truncated like e.g. Rreadlink which may yield up to a size of PATH_MAX which is usually 4096. Hence this size was chosen as min. msize for server, which is already the minimum msize of the Linux kernel's 9pfs client. By forcing a min. msize already at session start (when handling Tversion) we don't have to check for a minimum msize on a per request type basis later on during session, which would be much harder and more error prone to maintain. This is a user visible change which should be documented as such (i.e. in public QEMU release changelog). Signed-off-by: Christian Schoenebeck Reviewed-by: Greg Kurz --- hw/9pfs/9p.c | 12 ++++++++++++ hw/9pfs/9p.h | 11 +++++++++++ 2 files changed, 23 insertions(+) diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c index 520177f40c..a5fbe821d4 100644 --- a/hw/9pfs/9p.c +++ b/hw/9pfs/9p.c @@ -1363,8 +1363,20 @@ static void coroutine_fn v9fs_version(void *opaque) s->proto_version = V9FS_PROTO_2000L; } else { v9fs_string_sprintf(&version, "unknown"); + /* skip min. msize check, reporting invalid version has priority */ + goto marshal; } + if (s->msize < P9_MIN_MSIZE) { + err = -EMSGSIZE; + error_report( + "9pfs: Client requested msize < minimum msize (" + stringify(P9_MIN_MSIZE) ") supported by this server." + ); + goto out; + } + +marshal: err = pdu_marshal(pdu, offset, "ds", s->msize, &version); if (err < 0) { goto out; diff --git a/hw/9pfs/9p.h b/hw/9pfs/9p.h index 3904f82901..6fffe44f5a 100644 --- a/hw/9pfs/9p.h +++ b/hw/9pfs/9p.h @@ -100,6 +100,17 @@ typedef enum P9ProtoVersion { V9FS_PROTO_2000L = 0x02, } P9ProtoVersion; +/** + * @brief Minimum message size supported by this 9pfs server. + * + * A client establishes a session by sending a Tversion request along with a + * 'msize' parameter which suggests the server a maximum message size ever to be + * used for communication (for both requests and replies) between client and + * server during that session. If client suggests a 'msize' smaller than this + * value then session is denied by server with an error response. + */ +#define P9_MIN_MSIZE 4096 + #define P9_NOTAG UINT16_MAX #define P9_NOFID UINT32_MAX #define P9_MAXWELEM 16 From patchwork Mon Jan 13 22:22:08 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christian Schoenebeck X-Patchwork-Id: 11331129 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 05A6E109A for ; Tue, 14 Jan 2020 00:36:38 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id D02F0207FD for ; Tue, 14 Jan 2020 00:36:37 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=crudebyte.com header.i=@crudebyte.com header.b="d5svA8GG" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org D02F0207FD Authentication-Results: mail.kernel.org; dmarc=fail (p=quarantine dis=none) header.from=crudebyte.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Received: from localhost ([::1]:57478 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1irACC-0004Fm-TZ for patchwork-qemu-devel@patchwork.kernel.org; Mon, 13 Jan 2020 19:36:36 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:34509) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from <0edf21d2cb2a6cf22ba1065bf451b44ad5962cbd@lizzy.crudebyte.com>) id 1irABT-00034W-3y for qemu-devel@nongnu.org; Mon, 13 Jan 2020 19:35:52 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from <0edf21d2cb2a6cf22ba1065bf451b44ad5962cbd@lizzy.crudebyte.com>) id 1irABS-0001Q7-44 for qemu-devel@nongnu.org; Mon, 13 Jan 2020 19:35:51 -0500 Received: from lizzy.crudebyte.com ([91.194.90.13]:49893) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from <0edf21d2cb2a6cf22ba1065bf451b44ad5962cbd@lizzy.crudebyte.com>) id 1irABQ-0000gb-Cn for qemu-devel@nongnu.org; Mon, 13 Jan 2020 19:35:50 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=crudebyte.com; s=lizzy; h=Cc:To:Subject:Date:From:References:In-Reply-To: Message-Id:Content-Type:Content-Transfer-Encoding:MIME-Version:Content-ID: Content-Description; bh=DaJOrz3IZpnkejwrW0e8xc6WCAlOTLpMiIkJfiSMCLg=; b=d5svA 8GGIzqQYlpHqWKvvVolpdWh5F8qt0v09+uqz616hdIBH8B9AslcRZa7mxk1+iBlO0ZLEQyEZkjOrL cXfN8TbWAiPlNY7eadiE4z7XjsJSpYS3bWuuYydjJKUxJYFZCvfw1KzLk+t8krCTWX60dD3FOv53j JYDWGuvhqZeKOHrY1SDjzh2ccC3jg+WxQTygkd0ANnimYANAUsPszEQUtor+XTAZYDgTYmaVL4uk1 qiDyTrnT8xnqBfTUceKb/j1euu1AFQg+WdlNU1KxSZCiKIjKi2aUCaG0IqZbDZKkGLemT/L/tIhzd o/Bf14Vyj7mNxALn99uZoHpcB1r+Q==; Message-Id: <0edf21d2cb2a6cf22ba1065bf451b44ad5962cbd.1578957500.git.qemu_oss@crudebyte.com> In-Reply-To: References: From: Christian Schoenebeck Date: Mon, 13 Jan 2020 23:22:08 +0100 Subject: [PATCH v3 03/11] 9pfs: validate count sent by client with T_readdir To: qemu-devel@nongnu.org Cc: Greg Kurz X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 91.194.90.13 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" A good 9p client sends T_readdir with "count" parameter that's sufficiently smaller than client's initially negotiated msize (maximum message size). We perform a check for that though to avoid the server to be interrupted with a "Failed to encode VirtFS reply type 41" error message by bad clients. Signed-off-by: Christian Schoenebeck --- hw/9pfs/9p.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c index a5fbe821d4..30da2fedf3 100644 --- a/hw/9pfs/9p.c +++ b/hw/9pfs/9p.c @@ -2426,6 +2426,7 @@ static void coroutine_fn v9fs_readdir(void *opaque) int32_t count; uint32_t max_count; V9fsPDU *pdu = opaque; + V9fsState *s = pdu->s; retval = pdu_unmarshal(pdu, offset, "dqd", &fid, &initial_offset, &max_count); @@ -2434,6 +2435,13 @@ static void coroutine_fn v9fs_readdir(void *opaque) } trace_v9fs_readdir(pdu->tag, pdu->id, fid, initial_offset, max_count); + if (max_count > s->msize - P9_IOHDRSZ) { + max_count = s->msize - P9_IOHDRSZ; + warn_report_once( + "9p: bad client: T_readdir with count > msize - P9_IOHDRSZ" + ); + } + fidp = get_fid(pdu, fid); if (fidp == NULL) { retval = -EINVAL; From patchwork Mon Jan 13 22:23:03 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christian Schoenebeck X-Patchwork-Id: 11331147 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id F1E2613A0 for ; Tue, 14 Jan 2020 00:42:37 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id C804D207FD for ; Tue, 14 Jan 2020 00:42:37 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=crudebyte.com header.i=@crudebyte.com header.b="gXzzmN8a" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org C804D207FD Authentication-Results: mail.kernel.org; dmarc=fail (p=quarantine dis=none) header.from=crudebyte.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Received: from localhost ([::1]:57596 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1irAI0-0003W9-Tx for patchwork-qemu-devel@patchwork.kernel.org; Mon, 13 Jan 2020 19:42:36 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:35680) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from <14b8f74a5cd10d5cb0cdbe82f1dddb0242cdb285@lizzy.crudebyte.com>) id 1irAHQ-0002EH-Gn for qemu-devel@nongnu.org; Mon, 13 Jan 2020 19:42:01 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from <14b8f74a5cd10d5cb0cdbe82f1dddb0242cdb285@lizzy.crudebyte.com>) id 1irAHP-0005xt-Ef for qemu-devel@nongnu.org; Mon, 13 Jan 2020 19:42:00 -0500 Received: from lizzy.crudebyte.com ([91.194.90.13]:51357) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from <14b8f74a5cd10d5cb0cdbe82f1dddb0242cdb285@lizzy.crudebyte.com>) id 1irAHP-0005HU-81 for qemu-devel@nongnu.org; Mon, 13 Jan 2020 19:41:59 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=crudebyte.com; s=lizzy; h=Cc:To:Subject:Date:From:References:In-Reply-To: Message-Id:Content-Type:Content-Transfer-Encoding:MIME-Version:Content-ID: Content-Description; bh=fb6OOVIO1AGu0rbOOglAJ88WjD1vPGjm74d52ypJseM=; b=gXzzm N8aNr9Grj6Fbi4qBhIoRGIDoMimlkrfVu9CmiFzcnjp2e13HoF3rbyVyr866waGMY1e0zxR8jXRiU LKMKxqde7L69scguQbc7lzE/k/k9M4/jDr/lz1G9TSiSaKfedAyiBrjjAvVKMtb6Uf9WdsbBm9mAv DyMB7zmFRcAiwTJbxiQNExTsO9sfS5ryj/iAGCwLvLBdqiW7AKYLgz7MKuoroZkAglU0ncLyEt5cK 1ucEJysTyMk5YMmQs6CWjWsqqwPrp/DpOUoiTsvKHrT/XPiM11QxiRr7zYQr3xmb4gYUxe1hlhm8H Auz1rkAuGAugreelaqgDXiUEMMIWw==; Message-Id: <14b8f74a5cd10d5cb0cdbe82f1dddb0242cdb285.1578957500.git.qemu_oss@crudebyte.com> In-Reply-To: References: From: Christian Schoenebeck Date: Mon, 13 Jan 2020 23:23:03 +0100 Subject: [PATCH v3 04/11] hw/9pfs/9p-synth: added directory for readdir test To: qemu-devel@nongnu.org Cc: Greg Kurz X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 91.194.90.13 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" This will provide the following virtual files by the 9pfs synth driver: - /ReadDirDir/ReadDirFile99 - /ReadDirDir/ReadDirFile98 ... - /ReadDirDir/ReadDirFile1 - /ReadDirDir/ReadDirFile0 This virtual directory and its virtual 100 files will be used by the upcoming 9pfs readdir tests. Signed-off-by: Christian Schoenebeck Reviewed-by: Greg Kurz --- hw/9pfs/9p-synth.c | 19 +++++++++++++++++++ hw/9pfs/9p-synth.h | 5 +++++ 2 files changed, 24 insertions(+) diff --git a/hw/9pfs/9p-synth.c b/hw/9pfs/9p-synth.c index 54239c9bbf..7eb210ffa8 100644 --- a/hw/9pfs/9p-synth.c +++ b/hw/9pfs/9p-synth.c @@ -578,6 +578,25 @@ static int synth_init(FsContext *ctx, Error **errp) NULL, v9fs_synth_qtest_flush_write, ctx); assert(!ret); + + /* Directory for READDIR test */ + { + V9fsSynthNode *dir = NULL; + ret = qemu_v9fs_synth_mkdir( + NULL, 0700, QTEST_V9FS_SYNTH_READDIR_DIR, &dir + ); + assert(!ret); + for (i = 0; i < QTEST_V9FS_SYNTH_READDIR_NFILES; ++i) { + char *name = g_strdup_printf( + QTEST_V9FS_SYNTH_READDIR_FILE, i + ); + ret = qemu_v9fs_synth_add_file( + dir, 0, name, NULL, NULL, ctx + ); + assert(!ret); + g_free(name); + } + } } return 0; diff --git a/hw/9pfs/9p-synth.h b/hw/9pfs/9p-synth.h index af7a993a1e..036d7e4a5b 100644 --- a/hw/9pfs/9p-synth.h +++ b/hw/9pfs/9p-synth.h @@ -55,6 +55,11 @@ int qemu_v9fs_synth_add_file(V9fsSynthNode *parent, int mode, #define QTEST_V9FS_SYNTH_LOPEN_FILE "LOPEN" #define QTEST_V9FS_SYNTH_WRITE_FILE "WRITE" +/* for READDIR test */ +#define QTEST_V9FS_SYNTH_READDIR_DIR "ReadDirDir" +#define QTEST_V9FS_SYNTH_READDIR_FILE "ReadDirFile%d" +#define QTEST_V9FS_SYNTH_READDIR_NFILES 100 + /* Any write to the "FLUSH" file is handled one byte at a time by the * backend. If the byte is zero, the backend returns success (ie, 1), * otherwise it forces the server to try again forever. Thus allowing From patchwork Mon Jan 13 23:08:51 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christian Schoenebeck X-Patchwork-Id: 11331131 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 5DAD1139A for ; Tue, 14 Jan 2020 00:37:47 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 33430207FD for ; Tue, 14 Jan 2020 00:37:47 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=crudebyte.com header.i=@crudebyte.com header.b="J6s7sCgn" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 33430207FD Authentication-Results: mail.kernel.org; dmarc=fail (p=quarantine dis=none) header.from=crudebyte.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Received: from localhost ([::1]:57496 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1irADK-0005al-Be for patchwork-qemu-devel@patchwork.kernel.org; Mon, 13 Jan 2020 19:37:46 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:34711) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1irACS-0004fj-Ob for qemu-devel@nongnu.org; Mon, 13 Jan 2020 19:36:54 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1irACR-000276-9s for qemu-devel@nongnu.org; Mon, 13 Jan 2020 19:36:52 -0500 Received: from lizzy.crudebyte.com ([91.194.90.13]:45099) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1irACR-0001QF-3P for qemu-devel@nongnu.org; Mon, 13 Jan 2020 19:36:51 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=crudebyte.com; s=lizzy; h=Cc:To:Subject:Date:From:References:In-Reply-To: Message-Id:Content-Type:Content-Transfer-Encoding:MIME-Version:Content-ID: Content-Description; bh=5SRLsmRYeTgLc6a5gUFa2LRmbfUrHubdGrgNCIVhYMs=; b=J6s7s Cgnn+tS+iFxHpl+2AM0R3cda1fyeMq+472W/4Fs1jHwPSdBsWEmwrB8/ZVj+zw9x0mZlohz92XBK5 HP81cXbfyTwAN9/yai5QGOtJZN3WHCuK4d9c6rasrNzoVKssu3ZB7H5P0kcVYUjQpcLhAOzxhW6+g UKsyFVOjpIUXnLVan3L0nSkM6by9+0wzylp8vNpWaqdY5CRjf13wSSPAJiXwTuuItpl1KScizvSsY fx1Gxr/ZPodEWT9N+1Js5AaVGf+SD+y6S2VOT4QCS4En2mrYI9uHiIKYpU0sw5blyfaE9iVktjCbm FawVspuzCtX/+9bCguQsaori2O0oQ==; Message-Id: In-Reply-To: References: From: Christian Schoenebeck Date: Tue, 14 Jan 2020 00:08:51 +0100 Subject: [PATCH v3 05/11] tests/virtio-9p: added readdir test To: qemu-devel@nongnu.org Cc: Greg Kurz X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 91.194.90.13 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" The first readdir test simply checks the amount of directory entries returned by 9pfs server, according to the created amount of virtual files on 9pfs synth driver side. Then the subsequent readdir test also checks whether all directory entries have the expected file names (as created on 9pfs synth driver side), ignoring their precise order in result list though. Signed-off-by: Christian Schoenebeck --- tests/virtio-9p-test.c | 149 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 149 insertions(+) diff --git a/tests/virtio-9p-test.c b/tests/virtio-9p-test.c index 06263edb53..721f13c1fb 100644 --- a/tests/virtio-9p-test.c +++ b/tests/virtio-9p-test.c @@ -68,6 +68,11 @@ static void v9fs_memread(P9Req *req, void *addr, size_t len) req->r_off += len; } +static void v9fs_uint8_read(P9Req *req, uint8_t *val) +{ + v9fs_memread(req, val, 1); +} + static void v9fs_uint16_write(P9Req *req, uint16_t val) { uint16_t le_val = cpu_to_le16(val); @@ -101,6 +106,12 @@ static void v9fs_uint32_read(P9Req *req, uint32_t *val) le32_to_cpus(val); } +static void v9fs_uint64_read(P9Req *req, uint64_t *val) +{ + v9fs_memread(req, val, 8); + le64_to_cpus(val); +} + /* len[2] string[len] */ static uint16_t v9fs_string_size(const char *string) { @@ -191,6 +202,7 @@ static const char *rmessage_name(uint8_t id) id == P9_RLOPEN ? "RLOPEN" : id == P9_RWRITE ? "RWRITE" : id == P9_RFLUSH ? "RFLUSH" : + id == P9_RREADDIR ? "READDIR" : ""; } @@ -348,6 +360,82 @@ static void v9fs_rwalk(P9Req *req, uint16_t *nwqid, v9fs_qid **wqid) v9fs_req_free(req); } +/* size[4] Treaddir tag[2] fid[4] offset[8] count[4] */ +static P9Req *v9fs_treaddir(QVirtio9P *v9p, uint32_t fid, uint64_t offset, + uint32_t count, uint16_t tag) +{ + P9Req *req; + + req = v9fs_req_init(v9p, 4 + 8 + 4, P9_TREADDIR, tag); + v9fs_uint32_write(req, fid); + v9fs_uint64_write(req, offset); + v9fs_uint32_write(req, count); + v9fs_req_send(req); + return req; +} + +struct V9fsDirent { + v9fs_qid qid; + uint64_t offset; + uint8_t type; + char *name; + struct V9fsDirent *next; +}; + +/* size[4] Rreaddir tag[2] count[4] data[count] */ +static void v9fs_rreaddir(P9Req *req, uint32_t *count, uint32_t *nentries, + struct V9fsDirent **entries) +{ + uint32_t local_count; + struct V9fsDirent *e = NULL; + uint16_t slen; + uint32_t n = 0; + + v9fs_req_recv(req, P9_RREADDIR); + v9fs_uint32_read(req, &local_count); + + if (count) { + *count = local_count; + } + + for (int32_t togo = (int32_t)local_count; + togo >= 13 + 8 + 1 + 2; + togo -= 13 + 8 + 1 + 2 + slen, ++n) + { + if (!e) { + e = g_malloc(sizeof(struct V9fsDirent)); + if (entries) { + *entries = e; + } + } else { + e = e->next = g_malloc(sizeof(struct V9fsDirent)); + } + e->next = NULL; + /* qid[13] offset[8] type[1] name[s] */ + v9fs_memread(req, &e->qid, 13); + v9fs_uint64_read(req, &e->offset); + v9fs_uint8_read(req, &e->type); + v9fs_string_read(req, &slen, &e->name); + } + + if (nentries) { + *nentries = n; + } + + v9fs_req_free(req); +} + +static void v9fs_free_dirents(struct V9fsDirent *e) +{ + struct V9fsDirent *next = NULL; + + for (; e; e = next) { + next = e->next; + g_free(e->name); + g_free(e); + } +} + /* size[4] Tlopen tag[2] fid[4] flags[4] */ static P9Req *v9fs_tlopen(QVirtio9P *v9p, uint32_t fid, uint32_t flags, uint16_t tag) @@ -480,6 +568,66 @@ static void fs_walk(void *obj, void *data, QGuestAllocator *t_alloc) g_free(wqid); } +static bool fs_dirents_contain_name(struct V9fsDirent *e, const char* name) +{ + for (; e; e = e->next) { + if (!strcmp(e->name, name)) { + return true; + } + } + return false; +} + +static void fs_readdir(void *obj, void *data, QGuestAllocator *t_alloc) +{ + QVirtio9P *v9p = obj; + alloc = t_alloc; + char *const wnames[] = { g_strdup(QTEST_V9FS_SYNTH_READDIR_DIR) }; + uint16_t nqid; + v9fs_qid qid; + uint32_t count, nentries; + struct V9fsDirent *entries = NULL; + P9Req *req; + + fs_attach(v9p, NULL, t_alloc); + req = v9fs_twalk(v9p, 0, 1, 1, wnames, 0); + v9fs_req_wait_for_reply(req, NULL); + v9fs_rwalk(req, &nqid, NULL); + g_assert_cmpint(nqid, ==, 1); + + req = v9fs_tlopen(v9p, 1, O_DIRECTORY, 0); + v9fs_req_wait_for_reply(req, NULL); + v9fs_rlopen(req, &qid, NULL); + + req = v9fs_treaddir(v9p, 1, 0, P9_MAX_SIZE - P9_IOHDRSZ, 0); + v9fs_req_wait_for_reply(req, NULL); + v9fs_rreaddir(req, &count, &nentries, &entries); + + /* + * Assuming msize (P9_MAX_SIZE) is large enough so we can retrieve all + * dir entries with only one readdir request. + */ + g_assert_cmpint( + nentries, ==, + QTEST_V9FS_SYNTH_READDIR_NFILES + 2 /* "." and ".." */ + ); + + /* + * Check all file names exist in returned entries, ignore their order + * though. + */ + g_assert_cmpint(fs_dirents_contain_name(entries, "."), ==, true); + g_assert_cmpint(fs_dirents_contain_name(entries, ".."), ==, true); + for (int i = 0; i < QTEST_V9FS_SYNTH_READDIR_NFILES; ++i) { + char *name = g_strdup_printf(QTEST_V9FS_SYNTH_READDIR_FILE, i); + g_assert_cmpint(fs_dirents_contain_name(entries, name), ==, true); + g_free(name); + } + + v9fs_free_dirents(entries); + g_free(wnames[0]); +} + static void fs_walk_no_slash(void *obj, void *data, QGuestAllocator *t_alloc) { QVirtio9P *v9p = obj; @@ -658,6 +806,7 @@ static void register_virtio_9p_test(void) NULL); qos_add_test("fs/flush/ignored", "virtio-9p", fs_flush_ignored, NULL); + qos_add_test("fs/readdir/basic", "virtio-9p", fs_readdir, NULL); } libqos_init(register_virtio_9p_test); From patchwork Mon Jan 13 23:11:08 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christian Schoenebeck X-Patchwork-Id: 11331149 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id B974613A0 for ; Tue, 14 Jan 2020 00:44:08 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 8E23B207FD for ; Tue, 14 Jan 2020 00:44:08 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=crudebyte.com header.i=@crudebyte.com header.b="nbaiZAgz" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 8E23B207FD Authentication-Results: mail.kernel.org; dmarc=fail (p=quarantine dis=none) header.from=crudebyte.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Received: from localhost ([::1]:57616 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1irAJT-0005Np-KO for patchwork-qemu-devel@patchwork.kernel.org; Mon, 13 Jan 2020 19:44:07 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:35877) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1irAIR-0004NN-Fm for qemu-devel@nongnu.org; Mon, 13 Jan 2020 19:43:04 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1irAIQ-0006mN-5u for qemu-devel@nongnu.org; Mon, 13 Jan 2020 19:43:03 -0500 Received: from lizzy.crudebyte.com ([91.194.90.13]:50147) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1irAIO-0005yJ-TQ for qemu-devel@nongnu.org; Mon, 13 Jan 2020 19:43:02 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=crudebyte.com; s=lizzy; h=Cc:To:Subject:Date:From:References:In-Reply-To: Message-Id:Content-Type:Content-Transfer-Encoding:MIME-Version:Content-ID: Content-Description; bh=SnTKgxtm8KmUuX3BQOZ3np4LjvhrN0t+xCNcOwfTQIA=; b=nbaiZ AgzDoowlhpeixAKc6oacENig/yRE3YgC6Ds0cU+R6nQmaZ0aSVFLAARfn7NIu9PvyLCoG9eG/kn0u au8x3tPkrP+7IaI2cM1h+8HBQ0g5L8831ujbtp/CBubeW6IpPoJB5i9CunogAmiOxW5gI5eM7jI95 JL2QIf3TtIct7yhoV8f/0bIqphDHet0mi+6NrDZzCIkbO8rDqmEDM1Ik/mU6HjtosoB4ZFN3tD17H /hFzjo0yGM9ghyIUPZu+lQTnx6PaazRTAV172zMugerZSAHNJoj6ZvaI9aef2wvpfxBmwy/XqUYSQ RC8P4BnQ6QkqfrSyIhBS9Y+hjXAZw==; Message-Id: In-Reply-To: References: From: Christian Schoenebeck Date: Tue, 14 Jan 2020 00:11:08 +0100 Subject: [PATCH v3 06/11] tests/virtio-9p: added splitted readdir test To: qemu-devel@nongnu.org Cc: Greg Kurz X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 91.194.90.13 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" The previous, already existing readdir test simply used a 'count' parameter big enough to retrieve all directory entries with a single Treaddir request. In this new 'splitted' readdir test, directory entries are retrieved, splitted over several Treaddir requests by picking small 'count' parameters which force the server to truncate the response. So the test client sends as many Treaddir requests as necessary to get all directory entries. Currently this test covers actually two tests: a sequence of Treaddir requests with count=512 and then a subsequent test with a sequence of Treaddir requests with count=256. Signed-off-by: Christian Schoenebeck --- tests/virtio-9p-test.c | 91 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) diff --git a/tests/virtio-9p-test.c b/tests/virtio-9p-test.c index 721f13c1fb..55bfe41dfd 100644 --- a/tests/virtio-9p-test.c +++ b/tests/virtio-9p-test.c @@ -578,6 +578,7 @@ static bool fs_dirents_contain_name(struct V9fsDirent *e, const char* name) return false; } +/* basic readdir test where reply fits into a single response message */ static void fs_readdir(void *obj, void *data, QGuestAllocator *t_alloc) { QVirtio9P *v9p = obj; @@ -628,6 +629,95 @@ static void fs_readdir(void *obj, void *data, QGuestAllocator *t_alloc) g_free(wnames[0]); } +/* readdir test where overall request is splitted over several messages */ +static void fs_readdir_split(void *obj, void *data, QGuestAllocator *t_alloc) +{ + QVirtio9P *v9p = obj; + alloc = t_alloc; + char *const wnames[] = { g_strdup(QTEST_V9FS_SYNTH_READDIR_DIR) }; + uint16_t nqid; + v9fs_qid qid; + uint32_t count, nentries, npartialentries; + struct V9fsDirent *entries, *tail, *partialentries; + P9Req *req; + int subtest; + int fid; + uint64_t offset; + /* the Treaddir 'count' parameter values to be tested */ + const uint32_t vcount[] = { 512, 256 }; + const int nvcount = sizeof(vcount) / sizeof(uint32_t); + + fs_attach(v9p, NULL, t_alloc); + + /* iterate over all 'count' parameter values to be tested with Treaddir */ + for (subtest = 0; subtest < nvcount; ++subtest) { + fid = subtest + 1; + offset = 0; + entries = NULL; + nentries = 0; + tail = NULL; + + req = v9fs_twalk(v9p, 0, fid, 1, wnames, 0); + v9fs_req_wait_for_reply(req, NULL); + v9fs_rwalk(req, &nqid, NULL); + g_assert_cmpint(nqid, ==, 1); + + req = v9fs_tlopen(v9p, fid, O_DIRECTORY, 0); + v9fs_req_wait_for_reply(req, NULL); + v9fs_rlopen(req, &qid, NULL); + + /* + * send as many Treaddir requests as required to get all directory + * entries + */ + while (true) { + npartialentries = 0; + partialentries = NULL; + + req = v9fs_treaddir(v9p, fid, offset, vcount[subtest], 0); + v9fs_req_wait_for_reply(req, NULL); + v9fs_rreaddir(req, &count, &npartialentries, &partialentries); + if (npartialentries > 0 && partialentries) { + if (!entries) { + entries = partialentries; + nentries = npartialentries; + tail = partialentries; + } else { + tail->next = partialentries; + nentries += npartialentries; + } + while (tail->next) { + tail = tail->next; + } + offset = tail->offset; + } else { + break; + } + } + + g_assert_cmpint( + nentries, ==, + QTEST_V9FS_SYNTH_READDIR_NFILES + 2 /* "." and ".." */ + ); + + /* + * Check all file names exist in returned entries, ignore their order + * though. + */ + g_assert_cmpint(fs_dirents_contain_name(entries, "."), ==, true); + g_assert_cmpint(fs_dirents_contain_name(entries, ".."), ==, true); + for (int i = 0; i < QTEST_V9FS_SYNTH_READDIR_NFILES; ++i) { + char *name = g_strdup_printf(QTEST_V9FS_SYNTH_READDIR_FILE, i); + g_assert_cmpint(fs_dirents_contain_name(entries, name), ==, true); + g_free(name); + } + + v9fs_free_dirents(entries); + } + + g_free(wnames[0]); +} + static void fs_walk_no_slash(void *obj, void *data, QGuestAllocator *t_alloc) { QVirtio9P *v9p = obj; @@ -807,6 +897,7 @@ static void register_virtio_9p_test(void) qos_add_test("fs/flush/ignored", "virtio-9p", fs_flush_ignored, NULL); qos_add_test("fs/readdir/basic", "virtio-9p", fs_readdir, NULL); + qos_add_test("fs/readdir/split", "virtio-9p", fs_readdir_split, NULL); } libqos_init(register_virtio_9p_test); From patchwork Mon Jan 13 23:13:55 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christian Schoenebeck X-Patchwork-Id: 11331125 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 7B36F109A for ; Tue, 14 Jan 2020 00:34:56 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 50DC0207FF for ; Tue, 14 Jan 2020 00:34:56 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=crudebyte.com header.i=@crudebyte.com header.b="UWQQmmjo" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 50DC0207FF Authentication-Results: mail.kernel.org; dmarc=fail (p=quarantine dis=none) header.from=crudebyte.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Received: from localhost ([::1]:57438 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1irAAZ-0008Fr-8f for patchwork-qemu-devel@patchwork.kernel.org; Mon, 13 Jan 2020 19:34:55 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:33964) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from <178b9a7187b004998ffb313ef750851cdbfbcf6c@lizzy.crudebyte.com>) id 1irA9T-00069V-BY for qemu-devel@nongnu.org; Mon, 13 Jan 2020 19:33:48 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from <178b9a7187b004998ffb313ef750851cdbfbcf6c@lizzy.crudebyte.com>) id 1irA9S-00083m-Ar for qemu-devel@nongnu.org; Mon, 13 Jan 2020 19:33:47 -0500 Received: from lizzy.crudebyte.com ([91.194.90.13]:51305) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from <178b9a7187b004998ffb313ef750851cdbfbcf6c@lizzy.crudebyte.com>) id 1irA9S-0007Cq-4E for qemu-devel@nongnu.org; Mon, 13 Jan 2020 19:33:46 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=crudebyte.com; s=lizzy; h=Cc:To:Subject:Date:From:References:In-Reply-To: Message-Id:Content-Type:Content-Transfer-Encoding:MIME-Version:Content-ID: Content-Description; bh=gSrLBSeXST+abK1XbYVkGJqXNFTw0aCRskxx7cYuZSs=; b=UWQQm mjoTPNdhEHqMVk6AY9QFdwIvpFrjR6euqqw0XF3mP57PS36ct8ibrN6TtIJJJiTH7WtSEWXecX3r4 PtdTDSmjcAADDTSBybOShpbjINELO3+O83XW67RJCxPt6FZ98APrKX2wDVsz/T/uw4MxE1Q6vk8qL t8kfA9kfOaY6/6SGlsAhkKWGEFyL8ZEjX+wUjQABro4UWjuYxJGT/Z5ZtLfGFmNPZR/4pPUrPh2ge jYNSlCwSA2BD3KEkU1TfyGPE591Xq1GTmFDlqggDgjb89G8VGFpNlxrVxMrf5i0CES/thd4oIIS1C s8HNp8gDqyxKelTp+i1fzHbYbjagQ==; Message-Id: <178b9a7187b004998ffb313ef750851cdbfbcf6c.1578957500.git.qemu_oss@crudebyte.com> In-Reply-To: References: From: Christian Schoenebeck Date: Tue, 14 Jan 2020 00:13:55 +0100 Subject: [PATCH v3 07/11] tests/virtio-9p: failing splitted readdir test To: qemu-devel@nongnu.org Cc: Greg Kurz X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 91.194.90.13 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" This patch is not intended to be merged. It resembles an issue (with debug messages) where the splitted readdir test fails because server is interrupted with transport error "Failed to decode VirtFS request type 40", which BTW fails both with the unoptimized and with the optimized 9p readdir code. Signed-off-by: Christian Schoenebeck --- tests/virtio-9p-test.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tests/virtio-9p-test.c b/tests/virtio-9p-test.c index 55bfe41dfd..f5a8a192b5 100644 --- a/tests/virtio-9p-test.c +++ b/tests/virtio-9p-test.c @@ -644,13 +644,14 @@ static void fs_readdir_split(void *obj, void *data, QGuestAllocator *t_alloc) int fid; uint64_t offset; /* the Treaddir 'count' parameter values to be tested */ - const uint32_t vcount[] = { 512, 256 }; + const uint32_t vcount[] = { 512, 256, 128 }; const int nvcount = sizeof(vcount) / sizeof(uint32_t); fs_attach(v9p, NULL, t_alloc); /* iterate over all 'count' parameter values to be tested with Treaddir */ for (subtest = 0; subtest < nvcount; ++subtest) { + printf("\nsubtest[%d] with count=%d\n", subtest, vcount[subtest]); fid = subtest + 1; offset = 0; entries = NULL; @@ -671,12 +672,16 @@ static void fs_readdir_split(void *obj, void *data, QGuestAllocator *t_alloc) * entries */ while (true) { + printf("\toffset=%ld\n", offset); npartialentries = 0; partialentries = NULL; + printf("Treaddir fid=%d offset=%ld count=%d\n", + fid, offset, vcount[subtest]); req = v9fs_treaddir(v9p, fid, offset, vcount[subtest], 0); v9fs_req_wait_for_reply(req, NULL); v9fs_rreaddir(req, &count, &npartialentries, &partialentries); + printf("\t\tnpartial=%d nentries=%d\n", npartialentries, nentries); if (npartialentries > 0 && partialentries) { if (!entries) { entries = partialentries; @@ -713,6 +718,8 @@ static void fs_readdir_split(void *obj, void *data, QGuestAllocator *t_alloc) } v9fs_free_dirents(entries); + + printf("PASSED subtest[%d]\n", subtest); } g_free(wnames[0]); From patchwork Mon Jan 13 23:16:08 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christian Schoenebeck X-Patchwork-Id: 11331133 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 50F6C109A for ; Tue, 14 Jan 2020 00:38:36 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 262B4207FD for ; Tue, 14 Jan 2020 00:38:36 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=crudebyte.com header.i=@crudebyte.com header.b="GDlibERt" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 262B4207FD Authentication-Results: mail.kernel.org; dmarc=fail (p=quarantine dis=none) header.from=crudebyte.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Received: from localhost ([::1]:57510 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1irAE7-0006Z9-8N for patchwork-qemu-devel@patchwork.kernel.org; Mon, 13 Jan 2020 19:38:35 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:34872) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1irADS-0005n6-Bj for qemu-devel@nongnu.org; Mon, 13 Jan 2020 19:37:55 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1irADR-0002hN-0n for qemu-devel@nongnu.org; Mon, 13 Jan 2020 19:37:54 -0500 Received: from lizzy.crudebyte.com ([91.194.90.13]:60229) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1irADQ-00027d-Py for qemu-devel@nongnu.org; Mon, 13 Jan 2020 19:37:52 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=crudebyte.com; s=lizzy; h=Cc:To:Subject:Date:From:References:In-Reply-To: Message-Id:Content-Type:Content-Transfer-Encoding:MIME-Version:Content-ID: Content-Description; bh=bheWyEwG6Ump4Gvq4e39z2Jp7rLOXGOYm+28PsL3IXk=; b=GDlib ERt/jldARcl/oZ6y+78etZJcTkjd4gBBfNjAITKxuTouN3BBprchG12zH1J72rKo9OeVl1pMYHiRl U984H2h+i6+N4ICFuT/r7XcwW18Cm0xuyc2Jq1ybokrn0DEI2dmgyLZ0SYA6PLXS5O4A5Zwox/Kla PaoJguXe7kc55vu4DTX+RucmiJrHX4Y+VXg7GdZBF6jLqyiAXT0xc6LVjfjRoAcAMlYRhhkotuUSC kaVqR0kXu1vDAG4dsEIYm0qrqGNIXcNXZiqntFIRnmMIyYkp1f2TyFWQJjYSfQS7DzS2jwk7OcxCK +KPef8N0w6FDkuA/mPiWtnWPhsgWA==; Message-Id: In-Reply-To: References: From: Christian Schoenebeck Date: Tue, 14 Jan 2020 00:16:08 +0100 Subject: [PATCH v3 08/11] 9pfs: readdir benchmark To: qemu-devel@nongnu.org Cc: Greg Kurz X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 91.194.90.13 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" This patch is not intended to be merged. It just provides a temporary benchmark foundation for coneniently A/B comparison of the subsequent 9p readdir optimization patches: * hw/9pfs/9p-synth: increase amount of simulated files for readdir test to 2000 files. * tests/virtio-9p: measure wall time that elapsed between sending T_readdir request and arrival of R_readdir response and print out that measured duration, as well as amount of directory entries received, and the amount of bytes of the response message. * tests/virtio-9p: increased msize to 256kiB to allow retrieving all 2000 files (simulated by 9pfs synth driver) with only one T_readdir request. Running this benchmark is fairly quick & simple and does not require any guest OS installation or other prerequisites: cd build make && make tests/qos-test export QTEST_QEMU_BINARY=x86_64-softmmu/qemu-system-x86_64 tests/qos-test -p $(tests/qos-test -l | grep readdir/basic) Since this benchmark uses the 9pfs synth driver, the host machine's I/O hardware (SSDs/HDDs) is not relevant for the benchmark result, because the synth backend's readdir implementation returns immediately (without any blocking I/O that would incur with a real-life fs driver) and just returns already prepared, simulated directory entries directly from RAM. So this benchmark focuses on the efficiency of the 9pfs controller code (or top half) for readdir request handling. Signed-off-by: Christian Schoenebeck --- hw/9pfs/9p-synth.h | 2 +- tests/virtio-9p-test.c | 37 ++++++++++++++++++++++++++++++++++++- 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/hw/9pfs/9p-synth.h b/hw/9pfs/9p-synth.h index 036d7e4a5b..7d6cedcdac 100644 --- a/hw/9pfs/9p-synth.h +++ b/hw/9pfs/9p-synth.h @@ -58,7 +58,7 @@ int qemu_v9fs_synth_add_file(V9fsSynthNode *parent, int mode, /* for READDIR test */ #define QTEST_V9FS_SYNTH_READDIR_DIR "ReadDirDir" #define QTEST_V9FS_SYNTH_READDIR_FILE "ReadDirFile%d" -#define QTEST_V9FS_SYNTH_READDIR_NFILES 100 +#define QTEST_V9FS_SYNTH_READDIR_NFILES 2000 /* Any write to the "FLUSH" file is handled one byte at a time by the * backend. If the byte is zero, the backend returns success (ie, 1), diff --git a/tests/virtio-9p-test.c b/tests/virtio-9p-test.c index f5a8a192b5..1c901c889f 100644 --- a/tests/virtio-9p-test.c +++ b/tests/virtio-9p-test.c @@ -15,6 +15,18 @@ #include "libqos/virtio-9p.h" #include "libqos/qgraph.h" +/* + * to benchmark the real time (not CPU time) that elapsed between start of + * a request and arrival of its response + */ +static double wall_time(void) +{ + struct timeval t; + struct timezone tz; + gettimeofday(&t, &tz); + return t.tv_sec + t.tv_usec * 0.000001; +} + #define QVIRTIO_9P_TIMEOUT_US (10 * 1000 * 1000) static QGuestAllocator *alloc; @@ -36,7 +48,7 @@ static void pci_config(void *obj, void *data, QGuestAllocator *t_alloc) g_free(tag); } -#define P9_MAX_SIZE 4096 /* Max size of a T-message or R-message */ +#define P9_MAX_SIZE (256 * 1024) /* Max size of a T-message or R-message */ typedef struct { QTestState *qts; @@ -600,9 +612,32 @@ static void fs_readdir(void *obj, void *data, QGuestAllocator *t_alloc) v9fs_req_wait_for_reply(req, NULL); v9fs_rlopen(req, &qid, NULL); + const double start = wall_time(); + req = v9fs_treaddir(v9p, 1, 0, P9_MAX_SIZE - P9_IOHDRSZ, 0); + const double treaddir = wall_time(); v9fs_req_wait_for_reply(req, NULL); + const double waitforreply = wall_time(); v9fs_rreaddir(req, &count, &nentries, &entries); + const double end = wall_time(); + + printf("\nTime client spent on sending T_readdir: %fs\n\n", + treaddir - start); + + printf("Time client spent for waiting for reply from server: %fs " + "[MOST IMPORTANT]\n", waitforreply - start); + printf("(This is the most important value, because it reflects the time\n" + "the 9p server required to process and return the result of the\n" + "T_readdir request.)\n\n"); + + printf("Total client time: %fs\n", end - start); + printf("(NOTE: this time is not relevant; this huge time comes from\n" + "inefficient qtest_memread() calls. So you can discard this\n" + "value as a problem of this test client implementation while\n" + "processing the received server T_readdir reply.)\n\n"); + + printf("Details of response message data: R_readddir nentries=%d " + "rbytes=%d\n", nentries, count); /* * Assuming msize (P9_MAX_SIZE) is large enough so we can retrieve all From patchwork Mon Jan 13 23:16:41 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christian Schoenebeck X-Patchwork-Id: 11331127 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 41B2B109A for ; Tue, 14 Jan 2020 00:36:36 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 17186207FD for ; Tue, 14 Jan 2020 00:36:36 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=crudebyte.com header.i=@crudebyte.com header.b="DpIKMuCV" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 17186207FD Authentication-Results: mail.kernel.org; dmarc=fail (p=quarantine dis=none) header.from=crudebyte.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Received: from localhost ([::1]:57475 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1irACB-0004Eb-7z for patchwork-qemu-devel@patchwork.kernel.org; Mon, 13 Jan 2020 19:36:35 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:34363) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from <8351c098c0bd0ff63a57587e0e6bbe09d4efb760@lizzy.crudebyte.com>) id 1irAAS-00081k-K6 for qemu-devel@nongnu.org; Mon, 13 Jan 2020 19:34:49 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from <8351c098c0bd0ff63a57587e0e6bbe09d4efb760@lizzy.crudebyte.com>) id 1irAAR-0000gN-FG for qemu-devel@nongnu.org; Mon, 13 Jan 2020 19:34:48 -0500 Received: from lizzy.crudebyte.com ([91.194.90.13]:45835) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from <8351c098c0bd0ff63a57587e0e6bbe09d4efb760@lizzy.crudebyte.com>) id 1irAAR-00083u-8a for qemu-devel@nongnu.org; Mon, 13 Jan 2020 19:34:47 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=crudebyte.com; s=lizzy; h=Cc:To:Subject:Date:From:References:In-Reply-To: Message-Id:Content-Type:Content-Transfer-Encoding:MIME-Version:Content-ID: Content-Description; bh=d8arDOv455rogF2dRq1K5W98O1g4hMO9yNUA10vG7Sk=; b=DpIKM uCVI8zRpoZ/n8I0P6zJMhODbkjgXYPRQ75/YPf+XPN82ILj+LKjwz29zxvrWk+3frssEZDfkniHse gzsacxTwpSaBErVxZ//J1kU8Ay3genkKBh4R1i3fmweT70jJvVHm3WGebPH6ssgBQ4e5jsXQRx1ox A/ITRrPAtYYcDRZ3R46qS6GhfFZ1frLPyeuKspkKy+fntZeZGmWVgXWqYmEC3aq8XBwR2fu3wfPFB M3mBEPzjTYYyJIVNNJsphYvlvqHecmzIv/3uGuiEBRfZ/bcmyttw8VlSp3Lsd54jAs2Woxs12cjBx QIjb4zr6MqqVsjwwW/e+9PgCXsfoA==; Message-Id: <8351c098c0bd0ff63a57587e0e6bbe09d4efb760.1578957500.git.qemu_oss@crudebyte.com> In-Reply-To: References: From: Christian Schoenebeck Date: Tue, 14 Jan 2020 00:16:41 +0100 Subject: [PATCH v3 09/11] hw/9pfs/9p-synth: avoid n-square issue in synth_readdir() To: qemu-devel@nongnu.org Cc: Greg Kurz X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 91.194.90.13 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" This patch is just a temporary benchmark hack, not intended to be merged! 9pfs synth driver's readdir() implementation has a severe n-square performance problem. This patch is a quick and dirty hack to prevent that performance problem from tainting the readdir() benchmark results. In its current form, this patch is not useful for anything else than for an isolated readdir benchmark. NOTE: This patch would break the new readdir/split test, because it would alter the behaviour of seekdir() required for retrieving directory entries splitted over several requests. Signed-off-by: Christian Schoenebeck --- hw/9pfs/9p-synth.c | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/hw/9pfs/9p-synth.c b/hw/9pfs/9p-synth.c index 7eb210ffa8..54dc30f37b 100644 --- a/hw/9pfs/9p-synth.c +++ b/hw/9pfs/9p-synth.c @@ -225,7 +225,8 @@ static void synth_direntry(V9fsSynthNode *node, } static struct dirent *synth_get_dentry(V9fsSynthNode *dir, - struct dirent *entry, off_t off) + struct dirent *entry, off_t off, + V9fsSynthNode **hack) { int i = 0; V9fsSynthNode *node; @@ -243,16 +244,38 @@ static struct dirent *synth_get_dentry(V9fsSynthNode *dir, /* end of directory */ return NULL; } + *hack = node; synth_direntry(node, entry, off); return entry; } static struct dirent *synth_readdir(FsContext *ctx, V9fsFidOpenState *fs) { - struct dirent *entry; + struct dirent *entry = NULL; V9fsSynthOpenState *synth_open = fs->private; V9fsSynthNode *node = synth_open->node; - entry = synth_get_dentry(node, &synth_open->dent, synth_open->offset); + + /* + * HACK: This is just intended for benchmark, to avoid severe n-square + * performance problem of synth driver's readdir implementation here which + * would otherwise unncessarily taint the benchmark results. By simply + * caching (globally) the previous node (of the previous synth_readdir() + * call) we can simply proceed to next node in chained list efficiently. + * + * not a good idea for any production code ;-) + */ + static struct V9fsSynthNode *cachedNode; + + if (!cachedNode) { + entry = synth_get_dentry(node, &synth_open->dent, synth_open->offset, + &cachedNode); + } else { + cachedNode = cachedNode->sibling.le_next; + if (cachedNode) { + entry = &synth_open->dent; + synth_direntry(cachedNode, entry, synth_open->offset + 1); + } + } if (entry) { synth_open->offset++; } From patchwork Mon Jan 13 23:17:08 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christian Schoenebeck X-Patchwork-Id: 11331141 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 3EB496C1 for ; Tue, 14 Jan 2020 00:41:50 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 04689207FD for ; Tue, 14 Jan 2020 00:41:50 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=crudebyte.com header.i=@crudebyte.com header.b="dBGLkjqe" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 04689207FD Authentication-Results: mail.kernel.org; dmarc=fail (p=quarantine dis=none) header.from=crudebyte.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Received: from localhost ([::1]:57576 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1irAHF-0001rz-8p for patchwork-qemu-devel@patchwork.kernel.org; Mon, 13 Jan 2020 19:41:49 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:35503) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from <7bf0ae4aefac46dad62489bb4665a4447e6fd1ee@lizzy.crudebyte.com>) id 1irAGS-0000xc-Hz for qemu-devel@nongnu.org; Mon, 13 Jan 2020 19:41:02 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from <7bf0ae4aefac46dad62489bb4665a4447e6fd1ee@lizzy.crudebyte.com>) id 1irAGQ-0005HF-Au for qemu-devel@nongnu.org; Mon, 13 Jan 2020 19:41:00 -0500 Received: from lizzy.crudebyte.com ([91.194.90.13]:44957) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from <7bf0ae4aefac46dad62489bb4665a4447e6fd1ee@lizzy.crudebyte.com>) id 1irAGQ-0004b5-0Z for qemu-devel@nongnu.org; Mon, 13 Jan 2020 19:40:58 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=crudebyte.com; s=lizzy; h=Cc:To:Subject:Date:From:References:In-Reply-To: Message-Id:Content-Type:Content-Transfer-Encoding:MIME-Version:Content-ID: Content-Description; bh=dNj5ouyYd7esI/4a7QGrKVpvwDKLZz/uuwtWvsHCgC8=; b=dBGLk jqethvzWy3BdwnwYQ+LTAj+JURUvYL85IEzkXKvjYryn4Gv6anjn7MrFEGT/a1U3kPFR6QgogAspa P5TUuKsU9PIdte7+N/TLNZD0J99oNbmk5P/bfyxiv0UNODHj3wkMI3Gog5lGH6WTXFAB+7RwzBV9w PbdATXffMPhV2hTIq+hxAOaYeKwFwucKLKP/FVfKr2Ca21j/8476DrBMECpxt66MSiAm63Pd3SlLd zydWpazcR7G5NHjC7AoQj8lRvV50YkDnUBiaaj+rOTYO7zLgK+6NZgnQBi29h08t/jMdscWcGbbkT lL+v7MCYKA0jl01uTxvTfCvp42GwQ==; Message-Id: <7bf0ae4aefac46dad62489bb4665a4447e6fd1ee.1578957500.git.qemu_oss@crudebyte.com> In-Reply-To: References: From: Christian Schoenebeck Date: Tue, 14 Jan 2020 00:17:08 +0100 Subject: [PATCH v3 10/11] 9pfs: T_readdir latency optimization To: qemu-devel@nongnu.org Cc: Greg Kurz X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 91.194.90.13 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" Make top half really top half and bottom half really bottom half: Each T_readdir request handling is hopping between threads (main I/O thread and background I/O driver threads) several times for every individual directory entry, which sums up to huge latencies for handling just a single T_readdir request. Instead of doing that, collect now all required directory entries (including all potentially required stat buffers for each entry) in one rush on a background I/O thread from fs driver, then assemble the entire resulting network response message for the readdir request on main I/O thread. The fs driver is still aborting the directory entry retrieval loop (on the background I/O thread) as soon as it would exceed the client's requested maximum R_readdir response size. So we should not have any performance penalty by doing this. Signed-off-by: Christian Schoenebeck --- hw/9pfs/9p.c | 124 +++++++++++++++----------------- hw/9pfs/9p.h | 23 ++++++ hw/9pfs/codir.c | 183 +++++++++++++++++++++++++++++++++++++++++++++--- hw/9pfs/coth.h | 3 + 4 files changed, 254 insertions(+), 79 deletions(-) diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c index 30da2fedf3..5ebd424af9 100644 --- a/hw/9pfs/9p.c +++ b/hw/9pfs/9p.c @@ -971,30 +971,6 @@ static int coroutine_fn fid_to_qid(V9fsPDU *pdu, V9fsFidState *fidp, return 0; } -static int coroutine_fn dirent_to_qid(V9fsPDU *pdu, V9fsFidState *fidp, - struct dirent *dent, V9fsQID *qidp) -{ - struct stat stbuf; - V9fsPath path; - int err; - - v9fs_path_init(&path); - - err = v9fs_co_name_to_path(pdu, &fidp->path, dent->d_name, &path); - if (err < 0) { - goto out; - } - err = v9fs_co_lstat(pdu, &path, &stbuf); - if (err < 0) { - goto out; - } - err = stat_to_qid(pdu, &stbuf, qidp); - -out: - v9fs_path_free(&path); - return err; -} - V9fsPDU *pdu_alloc(V9fsState *s) { V9fsPDU *pdu = NULL; @@ -2314,7 +2290,7 @@ out_nofid: pdu_complete(pdu, err); } -static size_t v9fs_readdir_data_size(V9fsString *name) +size_t v9fs_readdir_response_size(V9fsString *name) { /* * Size of each dirent on the wire: size of qid (13) + size of offset (8) @@ -2323,6 +2299,18 @@ static size_t v9fs_readdir_data_size(V9fsString *name) return 24 + v9fs_string_size(name); } +static void v9fs_free_dirents(struct V9fsDirEnt *e) +{ + struct V9fsDirEnt *next = NULL; + + for (; e; e = next) { + next = e->next; + g_free(e->dent); + g_free(e->st); + g_free(e); + } +} + static int coroutine_fn v9fs_do_readdir(V9fsPDU *pdu, V9fsFidState *fidp, int32_t max_count) { @@ -2331,54 +2319,53 @@ static int coroutine_fn v9fs_do_readdir(V9fsPDU *pdu, V9fsFidState *fidp, V9fsString name; int len, err = 0; int32_t count = 0; - off_t saved_dir_pos; struct dirent *dent; + struct stat *st; + struct V9fsDirEnt *entries = NULL; - /* save the directory position */ - saved_dir_pos = v9fs_co_telldir(pdu, fidp); - if (saved_dir_pos < 0) { - return saved_dir_pos; - } - - while (1) { - v9fs_readdir_lock(&fidp->fs.dir); + /* + * inode remapping requires the device id, which in turn might be + * different for different directory entries, so if inode remapping is + * enabled we have to make a full stat for each directory entry + */ + const bool dostat = pdu->s->ctx.export_flags & V9FS_REMAP_INODES; - err = v9fs_co_readdir(pdu, fidp, &dent); - if (err || !dent) { - break; - } - v9fs_string_init(&name); - v9fs_string_sprintf(&name, "%s", dent->d_name); - if ((count + v9fs_readdir_data_size(&name)) > max_count) { - v9fs_readdir_unlock(&fidp->fs.dir); + /* + * Fetch all required directory entries altogether on a background IO + * thread from fs driver. We don't want to do that for each entry + * individually, because hopping between threads (this main IO thread + * and background IO driver thread) would sum up to huge latencies. + */ + count = v9fs_co_readdir_lowlat(pdu, fidp, &entries, max_count, dostat); + if (count < 0) { + err = count; + count = 0; + goto out; + } + count = 0; - /* Ran out of buffer. Set dir back to old position and return */ - v9fs_co_seekdir(pdu, fidp, saved_dir_pos); - v9fs_string_free(&name); - return count; - } + for (struct V9fsDirEnt *e = entries; e; e = e->next) { + dent = e->dent; if (pdu->s->ctx.export_flags & V9FS_REMAP_INODES) { - /* - * dirent_to_qid() implies expensive stat call for each entry, - * we must do that here though since inode remapping requires - * the device id, which in turn might be different for - * different entries; we cannot make any assumption to avoid - * that here. - */ - err = dirent_to_qid(pdu, fidp, dent, &qid); + st = e->st; + /* e->st should never be NULL, but just to be sure */ + if (!st) { + err = -1; + break; + } + + /* remap inode */ + err = stat_to_qid(pdu, st, &qid); if (err < 0) { - v9fs_readdir_unlock(&fidp->fs.dir); - v9fs_co_seekdir(pdu, fidp, saved_dir_pos); - v9fs_string_free(&name); - return err; + break; } } else { /* * Fill up just the path field of qid because the client uses * only that. To fill the entire qid structure we will have * to stat each dirent found, which is expensive. For the - * latter reason we don't call dirent_to_qid() here. Only drawback + * latter reason we don't call stat_to_qid() here. Only drawback * is that no multi-device export detection of stat_to_qid() * would be done and provided as error to the user here. But * user would get that error anyway when accessing those @@ -2391,25 +2378,26 @@ static int coroutine_fn v9fs_do_readdir(V9fsPDU *pdu, V9fsFidState *fidp, qid.version = 0; } + v9fs_string_init(&name); + v9fs_string_sprintf(&name, "%s", dent->d_name); + /* 11 = 7 + 4 (7 = start offset, 4 = space for storing count) */ len = pdu_marshal(pdu, 11 + count, "Qqbs", &qid, dent->d_off, dent->d_type, &name); - v9fs_readdir_unlock(&fidp->fs.dir); + v9fs_string_free(&name); if (len < 0) { - v9fs_co_seekdir(pdu, fidp, saved_dir_pos); - v9fs_string_free(&name); - return len; + err = len; + break; } + count += len; - v9fs_string_free(&name); - saved_dir_pos = dent->d_off; } - v9fs_readdir_unlock(&fidp->fs.dir); - +out: + v9fs_free_dirents(entries); if (err < 0) { return err; } diff --git a/hw/9pfs/9p.h b/hw/9pfs/9p.h index 6fffe44f5a..1dbb0ad189 100644 --- a/hw/9pfs/9p.h +++ b/hw/9pfs/9p.h @@ -215,6 +215,28 @@ static inline void v9fs_readdir_init(V9fsDir *dir) qemu_mutex_init(&dir->readdir_mutex); } +/* + * Type for 9p fs drivers' (a.k.a. 9p backends) result of readdir requests, + * which is a chained list of directory entries. + */ +typedef struct V9fsDirEnt { + /* mandatory (must not be NULL) information for all readdir requests */ + struct dirent *dent; + /* + * optional (may be NULL): A full stat of each directory entry is just + * done if explicitly told to fs driver. + */ + struct stat *st; + /* + * instead of an array, directory entries are always returned as + * chained list, that's because the amount of entries retrieved by fs + * drivers is dependent on the individual entries' name (since response + * messages are size limited), so the final amount cannot be estimated + * before hand + */ + struct V9fsDirEnt *next; +} V9fsDirEnt; + /* * Filled by fs driver on open and other * calls. @@ -419,6 +441,7 @@ void v9fs_path_init(V9fsPath *path); void v9fs_path_free(V9fsPath *path); void v9fs_path_sprintf(V9fsPath *path, const char *fmt, ...); void v9fs_path_copy(V9fsPath *dst, const V9fsPath *src); +size_t v9fs_readdir_response_size(V9fsString *name); int v9fs_name_to_path(V9fsState *s, V9fsPath *dirpath, const char *name, V9fsPath *path); int v9fs_device_realize_common(V9fsState *s, const V9fsTransport *t, diff --git a/hw/9pfs/codir.c b/hw/9pfs/codir.c index 73f9a751e1..6ce7dc8cde 100644 --- a/hw/9pfs/codir.c +++ b/hw/9pfs/codir.c @@ -18,28 +18,189 @@ #include "qemu/main-loop.h" #include "coth.h" +/* + * This is solely executed on a background IO thread. + */ +static int do_readdir(V9fsPDU *pdu, V9fsFidState *fidp, struct dirent **dent) +{ + int err = 0; + V9fsState *s = pdu->s; + struct dirent *entry; + + errno = 0; + entry = s->ops->readdir(&s->ctx, &fidp->fs); + if (!entry && errno) { + *dent = NULL; + err = -errno; + } else { + *dent = entry; + } + return err; +} + +/* + * TODO: This will be removed for performance reasons. + * Use v9fs_co_readdir_lowlat() instead. + */ int coroutine_fn v9fs_co_readdir(V9fsPDU *pdu, V9fsFidState *fidp, struct dirent **dent) { int err; - V9fsState *s = pdu->s; if (v9fs_request_cancelled(pdu)) { return -EINTR; } - v9fs_co_run_in_worker( - { - struct dirent *entry; + v9fs_co_run_in_worker({ + err = do_readdir(pdu, fidp, dent); + }); + return err; +} + +/* + * This is solely executed on a background IO thread. + * + * See v9fs_co_readdir_lowlat() (as its only user) below for details. + */ +static int do_readdir_lowlat(V9fsPDU *pdu, V9fsFidState *fidp, + struct V9fsDirEnt **entries, + int32_t maxsize, bool dostat) +{ + V9fsState *s = pdu->s; + V9fsString name; + int len, err = 0; + int32_t size = 0; + off_t saved_dir_pos; + struct dirent *dent; + struct V9fsDirEnt *e = NULL; + V9fsPath path; + struct stat stbuf; + + *entries = NULL; + v9fs_path_init(&path); + + /* + * TODO: Here should be a warn_report_once() if lock failed. + * + * With a good 9p client we should not get into concurrency here, + * because a good client would not use the same fid for concurrent + * requests. We do the lock here for safety reasons though. However + * the client would then suffer performance issues, so better log that + * issue here. + */ + v9fs_readdir_lock(&fidp->fs.dir); + + /* save the directory position */ + saved_dir_pos = s->ops->telldir(&s->ctx, &fidp->fs); + if (saved_dir_pos < 0) { + err = saved_dir_pos; + goto out; + } + + while (true) { + /* get directory entry from fs driver */ + err = do_readdir(pdu, fidp, &dent); + if (err || !dent) { + break; + } + + /* + * stop this loop as soon as it would exceed the allowed maximum + * response message size for the directory entries collected so far, + * because anything beyond that size would need to be discarded by + * 9p controller (main thread / top half) anyway + */ + v9fs_string_init(&name); + v9fs_string_sprintf(&name, "%s", dent->d_name); + len = v9fs_readdir_response_size(&name); + v9fs_string_free(&name); + if (size + len > maxsize) { + /* this is not an error case actually */ + break; + } + + /* append next node to result chain */ + if (!e) { + *entries = e = g_malloc0(sizeof(V9fsDirEnt)); + } else { + e = e->next = g_malloc0(sizeof(V9fsDirEnt)); + } + e->dent = g_malloc0(sizeof(struct dirent)); + memcpy(e->dent, dent, sizeof(struct dirent)); - errno = 0; - entry = s->ops->readdir(&s->ctx, &fidp->fs); - if (!entry && errno) { + /* perform a full stat() for directory entry if requested by caller */ + if (dostat) { + err = s->ops->name_to_path( + &s->ctx, &fidp->path, dent->d_name, &path + ); + if (err < 0) { err = -errno; - } else { - *dent = entry; - err = 0; + break; } - }); + + err = s->ops->lstat(&s->ctx, &path, &stbuf); + if (err < 0) { + err = -errno; + break; + } + + e->st = g_malloc0(sizeof(struct stat)); + memcpy(e->st, &stbuf, sizeof(struct stat)); + } + + size += len; + saved_dir_pos = dent->d_off; + } + + /* restore (last) saved position */ + s->ops->seekdir(&s->ctx, &fidp->fs, saved_dir_pos); + +out: + v9fs_readdir_unlock(&fidp->fs.dir); + v9fs_path_free(&path); + if (err < 0) { + return err; + } + return size; +} + +/** + * @brief Low latency variant of fs driver readdir handling. + * + * Retrieves the requested (max. amount of) directory entries from the fs + * driver. This function must only be called by the main IO thread (top half). + * Internally this function call will be dispatched to a background IO thread + * (bottom half) where it is eventually executed by the fs driver. + * + * The old readdir implementation above just retrieves always one dir entry + * per call. The problem of that implementation above is that latency is + * added for (retrieval of) each directory entry, which in practice lead to + * latencies of several hundred ms for readdir of only one directory. + * + * This is avoided in this function by letting the fs driver retrieve all + * required directory entries with only call of this function and hence with + * only a single fs driver request. + * + * @param pdu - the causing 9p (T_readdir) client request + * @param fidp - already opened directory where readdir shall be performed on + * @param entries - output for directory entries (must not be NULL) + * @param maxsize - maximum result message body size (in bytes) + * @param dostat - whether a stat() should be performed and returned for + * each directory entry + * @returns resulting response message body size (in bytes) on success, + * negative error code otherwise + */ +int coroutine_fn v9fs_co_readdir_lowlat(V9fsPDU *pdu, V9fsFidState *fidp, + struct V9fsDirEnt **entries, + int32_t maxsize, bool dostat) +{ + int err = 0; + + if (v9fs_request_cancelled(pdu)) { + return -EINTR; + } + v9fs_co_run_in_worker({ + err = do_readdir_lowlat(pdu, fidp, entries, maxsize, dostat); + }); return err; } diff --git a/hw/9pfs/coth.h b/hw/9pfs/coth.h index c2cdc7a9ea..1249dbe6df 100644 --- a/hw/9pfs/coth.h +++ b/hw/9pfs/coth.h @@ -49,6 +49,9 @@ void co_run_in_worker_bh(void *); int coroutine_fn v9fs_co_readlink(V9fsPDU *, V9fsPath *, V9fsString *); int coroutine_fn v9fs_co_readdir(V9fsPDU *, V9fsFidState *, struct dirent **); +int coroutine_fn v9fs_co_readdir_lowlat(V9fsPDU *, V9fsFidState *, + struct V9fsDirEnt **, + int32_t, bool); off_t coroutine_fn v9fs_co_telldir(V9fsPDU *, V9fsFidState *); void coroutine_fn v9fs_co_seekdir(V9fsPDU *, V9fsFidState *, off_t); void coroutine_fn v9fs_co_rewinddir(V9fsPDU *, V9fsFidState *); From patchwork Mon Jan 13 23:17:26 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christian Schoenebeck X-Patchwork-Id: 11331123 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id E3AFC139A for ; Tue, 14 Jan 2020 00:33:31 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 7BD8E207FF for ; Tue, 14 Jan 2020 00:33:31 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=crudebyte.com header.i=@crudebyte.com header.b="ESqToqjy" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 7BD8E207FF Authentication-Results: mail.kernel.org; dmarc=fail (p=quarantine dis=none) header.from=crudebyte.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Received: from localhost ([::1]:57418 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1irA9C-00061t-LS for patchwork-qemu-devel@patchwork.kernel.org; Mon, 13 Jan 2020 19:33:30 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:33724) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1irA8T-0005Kt-T6 for qemu-devel@nongnu.org; Mon, 13 Jan 2020 19:32:47 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1irA8S-0007CY-PL for qemu-devel@nongnu.org; Mon, 13 Jan 2020 19:32:45 -0500 Received: from lizzy.crudebyte.com ([91.194.90.13]:52331) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1irA8S-0006M1-Ae for qemu-devel@nongnu.org; Mon, 13 Jan 2020 19:32:44 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=crudebyte.com; s=lizzy; h=Cc:To:Subject:Date:From:References:In-Reply-To: Message-Id:Content-Type:Content-Transfer-Encoding:MIME-Version:Content-ID: Content-Description; bh=+KvNmyLG6kAE2TZaj6MEGe1C+5iebgEtjpC5n6Htklk=; b=ESqTo qjy6pN/gGpJVw4FuqOimXOp7oSNInl/joGmmsVQouZu1a1Q8gChPSJ6orn19a+VJx7DCZ3lnnl/8L Db9oxb7x/SiE9jC9W7l2dThxcGxMAAkL7tM5LTXbHPRTZoylALNnwepEtojtalcymMDWkY9mjmWY8 RTFZL/CEr3m+Sxx5Vty/TD++XcNJn44Ocot6Cj05E8flhQrSW3MErz3BJ37cHQ5m2P37tBg4F4tfH 96Fx/Q9VPhJVLofA4A4ufU9k3Gz+D7PB/gwsT7tApsm0pwFJvp8bPrlvDmdcT5LgH+FAWO1M7FblM 6/oCjFmxLGJ6wSJjOs7P6k8MR/WNg==; Message-Id: In-Reply-To: References: From: Christian Schoenebeck Date: Tue, 14 Jan 2020 00:17:26 +0100 Subject: [PATCH v3 11/11] hw/9pfs/9p.c: benchmark time on T_readdir request To: qemu-devel@nongnu.org Cc: Greg Kurz X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 91.194.90.13 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" This patch is not intended to be merged, it measures and prints the time the 9p server spends on handling a T_readdir request. It prints the total time it spent on handling the request, and also the time it spent on I/O (fs driver) only. Signed-off-by: Christian Schoenebeck --- hw/9pfs/9p.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c index 5ebd424af9..7cdf18080f 100644 --- a/hw/9pfs/9p.c +++ b/hw/9pfs/9p.c @@ -2311,6 +2311,15 @@ static void v9fs_free_dirents(struct V9fsDirEnt *e) } } +static double wall_time(void) +{ + struct timeval t; + struct timezone tz; + gettimeofday(&t, &tz); + return t.tv_sec + t.tv_usec * 0.000001; +} + + static int coroutine_fn v9fs_do_readdir(V9fsPDU *pdu, V9fsFidState *fidp, int32_t max_count) { @@ -2330,6 +2339,8 @@ static int coroutine_fn v9fs_do_readdir(V9fsPDU *pdu, V9fsFidState *fidp, */ const bool dostat = pdu->s->ctx.export_flags & V9FS_REMAP_INODES; + const double start = wall_time(); + /* * Fetch all required directory entries altogether on a background IO * thread from fs driver. We don't want to do that for each entry @@ -2344,6 +2355,10 @@ static int coroutine_fn v9fs_do_readdir(V9fsPDU *pdu, V9fsFidState *fidp, } count = 0; + const double end = wall_time(); + printf("\n\nTime 9p server spent on synth_readdir() I/O only (synth " + "driver): %fs\n", end - start); + for (struct V9fsDirEnt *e = entries; e; e = e->next) { dent = e->dent; @@ -2416,6 +2431,8 @@ static void coroutine_fn v9fs_readdir(void *opaque) V9fsPDU *pdu = opaque; V9fsState *s = pdu->s; + const double start = wall_time(); + retval = pdu_unmarshal(pdu, offset, "dqd", &fid, &initial_offset, &max_count); if (retval < 0) { @@ -2459,6 +2476,10 @@ out: put_fid(pdu, fidp); out_nofid: pdu_complete(pdu, retval); + + const double end = wall_time(); + printf("Time 9p server spent on entire T_readdir request: %fs " + "[IMPORTANT]\n", end - start); } static int v9fs_xattr_write(V9fsState *s, V9fsPDU *pdu, V9fsFidState *fidp,