From nobody Mon Sep 16 19:13:29 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass(p=quarantine dis=none) header.from=suse.com ARC-Seal: i=1; a=rsa-sha256; t=1707411394; cv=none; d=zohomail.com; s=zohoarc; b=hBTvLIvaPEPeOh6CHYPnytUK7UQ85rQu9hyBghYsSmPm3jO0ZCKehrxI5b6NCk9e+vcgNC5sl199ZB0578waxPjxrhtfUvUHThb7P4U2GGr0Aneo1DFzrHbRGPVGuzQKxevPsX9YKGeNm2VTgW6WDV1ojyK/rGw64AnG5ROLgcc= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1707411394; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=O73f+E3GNfH4W5rlXCuJYVhh6QCuB0n/PfhAGghm1+4=; b=LWjce3myjrYeTG1RIp0Tt3Rkup52n6FyI2jmFR4XJNUpgjMtGTaMDe4Xz5MMZ+3uoucCO1YAo+LqClJOuQawuwOe6QSu90yc6D6Q7YVLijMLVvhIyEV9PKQgH4epRHMtA8+Lra/wHxTWQNhK2eSk/P6VskP9QmdT0vhIrNCaW0g= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1707411394599580.8478408581617; Thu, 8 Feb 2024 08:56:34 -0800 (PST) Received: from list by lists.xenproject.org with outflank-mailman.678356.1055570 (Exim 4.92) (envelope-from ) id 1rY7hE-0007RT-RD; Thu, 08 Feb 2024 16:56:20 +0000 Received: by outflank-mailman (output) from mailman id 678356.1055570; Thu, 08 Feb 2024 16:56:20 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1rY7hE-0007Qb-NC; Thu, 08 Feb 2024 16:56:20 +0000 Received: by outflank-mailman (input) for mailman id 678356; Thu, 08 Feb 2024 16:56:19 +0000 Received: from se1-gles-flk1-in.inumbo.com ([94.247.172.50] helo=se1-gles-flk1.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1rY7hD-0005q0-Nu for xen-devel@lists.xenproject.org; Thu, 08 Feb 2024 16:56:19 +0000 Received: from smtp-out2.suse.de (smtp-out2.suse.de [2a07:de40:b251:101:10:150:64:2]) by se1-gles-flk1.inumbo.com (Halon) with ESMTPS id f9ff0e2f-c6a2-11ee-98f5-efadbce2ee36; Thu, 08 Feb 2024 17:56:17 +0100 (CET) Received: from imap1.dmz-prg2.suse.org (imap1.dmz-prg2.suse.org [10.150.64.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by smtp-out2.suse.de (Postfix) with ESMTPS id 52F4C1FCF6; Thu, 8 Feb 2024 16:56:17 +0000 (UTC) Received: from imap1.dmz-prg2.suse.org (localhost [127.0.0.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by imap1.dmz-prg2.suse.org (Postfix) with ESMTPS id 2596E1326D; Thu, 8 Feb 2024 16:56:17 +0000 (UTC) Received: from dovecot-director2.suse.de ([2a07:de40:b281:106:10:150:64:167]) by imap1.dmz-prg2.suse.org with ESMTPSA id 2hjGB7EHxWXPEwAAD6G6ig (envelope-from ); Thu, 08 Feb 2024 16:56:17 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" X-Inumbo-ID: f9ff0e2f-c6a2-11ee-98f5-efadbce2ee36 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=susede1; t=1707411377; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=O73f+E3GNfH4W5rlXCuJYVhh6QCuB0n/PfhAGghm1+4=; b=nkZm9m8QVWUfkfUTsQw6NwlKpn2n5Cn6EF90D/G1d6w4ct6KfLbLI4jYOPxlo8ZiTw6ANU nA5DJjE84Mlnt0o2CkMZZzE61hvvBPxD3clbGzYEyi4+Cv/VHEZrb0Hj/71urEOPkHhyiB hN+fMPzkeZQvTPYQ2XjxXu/7rCDM4RI= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=susede1; t=1707411377; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=O73f+E3GNfH4W5rlXCuJYVhh6QCuB0n/PfhAGghm1+4=; b=nkZm9m8QVWUfkfUTsQw6NwlKpn2n5Cn6EF90D/G1d6w4ct6KfLbLI4jYOPxlo8ZiTw6ANU nA5DJjE84Mlnt0o2CkMZZzE61hvvBPxD3clbGzYEyi4+Cv/VHEZrb0Hj/71urEOPkHhyiB hN+fMPzkeZQvTPYQ2XjxXu/7rCDM4RI= From: Juergen Gross To: xen-devel@lists.xenproject.org Cc: Juergen Gross , Wei Liu , Anthony PERARD , Jason Andryuk Subject: [PATCH v5 05/22] tools/9pfsd: add 9pfs response generation support Date: Thu, 8 Feb 2024 17:55:29 +0100 Message-Id: <20240208165546.5715-6-jgross@suse.com> X-Mailer: git-send-email 2.35.3 In-Reply-To: <20240208165546.5715-1-jgross@suse.com> References: <20240208165546.5715-1-jgross@suse.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Authentication-Results: smtp-out2.suse.de; none X-Spam-Level: X-Spam-Score: -3.30 X-Spamd-Result: default: False [-3.30 / 50.00]; ARC_NA(0.00)[]; RCVD_VIA_SMTP_AUTH(0.00)[]; FROM_HAS_DN(0.00)[]; TO_DN_SOME(0.00)[]; R_MISSING_CHARSET(2.50)[]; FREEMAIL_ENVRCPT(0.00)[gmail.com]; MIME_GOOD(-0.10)[text/plain]; TO_MATCH_ENVRCPT_ALL(0.00)[]; REPLY(-4.00)[]; BROKEN_CONTENT_TYPE(1.50)[]; RCPT_COUNT_FIVE(0.00)[5]; NEURAL_HAM_LONG(-1.00)[-1.000]; RCVD_COUNT_THREE(0.00)[3]; DKIM_SIGNED(0.00)[suse.com:s=susede1]; NEURAL_HAM_SHORT(-0.20)[-1.000]; MID_CONTAINS_FROM(1.00)[]; DBL_BLOCKED_OPENRESOLVER(0.00)[suse.com:email]; FUZZY_BLOCKED(0.00)[rspamd.com]; FROM_EQ_ENVFROM(0.00)[]; MIME_TRACE(0.00)[0:+]; FREEMAIL_CC(0.00)[suse.com,xen.org,citrix.com,gmail.com]; RCVD_TLS_ALL(0.00)[]; BAYES_HAM(-3.00)[100.00%] X-Spam-Flag: NO X-ZohoMail-DKIM: pass (identity @suse.com) X-ZM-MESSAGEID: 1707411395016100001 Content-Type: text/plain; charset="utf-8" Add support for generation a 9pfs protocol response via a format based approach. Strings are stored in a per device string buffer and they are referenced via their offset in this buffer. This allows to avoid having to dynamically allocate memory for each single string. As a first user of the response handling add a generic p9_error() function which will be used to return any error to the client. Add all format parsing variants in order to avoid additional code churn later when adding the users of those variants. Prepare a special case for the "read" case already (format character 'D'): in order to avoid adding another buffer for read data support doing the read I/O directly into the response buffer. Signed-off-by: Juergen Gross Acked-by: Anthony PERARD Reviewed-by: Jason Andryuk --- V2: - check parameter size limits (Jason Andryuk) V3: - use new unaligned access macros (Jason Andryuk) V4: - use recursion in fill_buffer() as a preparation for reading dirs --- tools/9pfsd/io.c | 217 +++++++++++++++++++++++++++++++++++++++- tools/9pfsd/xen-9pfsd.h | 3 + 2 files changed, 219 insertions(+), 1 deletion(-) diff --git a/tools/9pfsd/io.c b/tools/9pfsd/io.c index 4312a62dfe..4a44c70c4d 100644 --- a/tools/9pfsd/io.c +++ b/tools/9pfsd/io.c @@ -11,6 +11,7 @@ * before looking for the next request. */ =20 +#include #include #include #include @@ -20,6 +21,16 @@ =20 #include "xen-9pfsd.h" =20 +/* P9 protocol commands (response is either cmd+1 or P9_CMD_ERROR). */ +#define P9_CMD_ERROR 107 + +struct p9_qid { + uint8_t type; +#define QID_TYPE_DIR 0x80 + uint32_t version; + uint64_t path; +}; + /* * Note that the ring names "in" and "out" are from the frontend's * perspective, so the "in" ring will be used for responses to the fronten= d, @@ -100,6 +111,200 @@ static bool io_work_pending(struct ring *ring) return ring->handle_response ? ring_in_free(ring) : ring_out_data(ring= ); } =20 +static void fmt_err(const char *fmt) +{ + syslog(LOG_CRIT, "illegal format %s passed to fill_buffer()", fmt); + exit(1); +} + +/* + * Fill buffer with response data. + * fmt is a sequence of format characters. Supported characters are: + * a: an array (2 bytes number of elements + the following format as eleme= nts) + * The number of elements is passed in the first unsigned int parameter= , the + * next parameter is a pointer to an array of elements as denoted by th= e next + * format character. + * b: 1 byte unsigned integer + * u: 2 byte unsigned integer + * The parameter is a pointer to a uint16_t value + * D: Data blob (4 byte length + bytes) + * 2 parameters are consumed, first an unsigned int for the length, the= n a + * pointer to the first uint8_t value. + * No array support. + * L: 8 byte unsigned integer + * The parameter is a pointer to a uint64_t value + * Q: Qid (struct p9_qid) + * S: String (2 byte length + characters) + * The length is obtained via strlen() of the parameter, being a pointer + * to the first character of the string + * U: 4 byte unsigned integer + * The parameter is a pointer to a uint32_t value + */ +static void fill_buffer_at(void **data, const char *fmt, ...); +static void vfill_buffer_at(void **data, const char *fmt, va_list ap) +{ + const char *f; + const void *par; + const char *str_val; + const struct p9_qid *qid; + unsigned int len; + unsigned int array_sz =3D 0; + unsigned int elem_sz =3D 0; + + for ( f =3D fmt; *f; f++ ) + { + if ( !array_sz ) + par =3D va_arg(ap, const void *); + else + { + par +=3D elem_sz; + array_sz--; + } + + switch ( *f ) + { + case 'a': + f++; + if ( !*f || array_sz ) + fmt_err(fmt); + array_sz =3D *(const unsigned int *)par; + if ( array_sz > 0xffff ) + { + syslog(LOG_CRIT, "array size %u in fill_buffer()", array_s= z); + exit(1); + } + put_unaligned(array_sz, (uint16_t *)*data); + *data +=3D sizeof(uint16_t); + par =3D va_arg(ap, const void *); + elem_sz =3D 0; + break; + + case 'b': + put_unaligned(*(const uint8_t *)par, (uint8_t *)*data); + elem_sz =3D sizeof(uint8_t); + *data +=3D sizeof(uint8_t); + break; + + case 'u': + put_unaligned(*(const uint16_t *)par, (uint16_t *)*data); + elem_sz =3D sizeof(uint16_t); + *data +=3D sizeof(uint16_t); + break; + + case 'D': + if ( array_sz ) + fmt_err(fmt); + len =3D *(const unsigned int *)par; + put_unaligned(len, (uint32_t *)*data); + *data +=3D sizeof(uint32_t); + par =3D va_arg(ap, const void *); + if ( *data !=3D par ) + memcpy(*data, par, len); + *data +=3D len; + break; + + case 'L': + put_unaligned(*(const uint64_t *)par, (uint64_t *)*data); + elem_sz =3D sizeof(uint64_t); + *data +=3D sizeof(uint64_t); + break; + + case 'Q': + qid =3D par; + elem_sz =3D sizeof(*qid); + fill_buffer_at(data, "bUL", &qid->type, &qid->version, &qid->p= ath); + break; + + case 'S': + str_val =3D par; + elem_sz =3D sizeof(str_val); + len =3D strlen(str_val); + if ( len > 0xffff ) + { + syslog(LOG_CRIT, "string length %u in fill_buffer()", len); + exit(1); + } + put_unaligned(len, (uint16_t *)*data); + *data +=3D sizeof(uint16_t); + memcpy(*data, str_val, len); + *data +=3D len; + break; + + case 'U': + put_unaligned(*(const uint32_t *)par, (uint32_t *)*data); + elem_sz =3D sizeof(uint32_t); + *data +=3D sizeof(uint32_t); + break; + + default: + fmt_err(fmt); + } + + if ( array_sz ) + f--; + } +} + +static void fill_buffer_at(void **data, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + vfill_buffer_at(data, fmt, ap); + va_end(ap); +} + +static void fill_buffer(struct ring *ring, uint8_t cmd, uint16_t tag, + const char *fmt, ...) +{ + struct p9_header *hdr =3D ring->buffer; + void *data =3D hdr + 1; + va_list ap; + + hdr->cmd =3D cmd; + hdr->tag =3D tag; + + va_start(ap, fmt); + vfill_buffer_at(&data, fmt, ap); + va_end(ap); + + hdr->size =3D data - ring->buffer; +} + +static unsigned int add_string(struct ring *ring, const char *str, + unsigned int len) +{ + char *tmp; + unsigned int ret; + + if ( ring->str_used + len + 1 > ring->str_size ) + { + tmp =3D realloc(ring->str, ring->str_used + len + 1); + if ( !tmp ) + return ~0; + ring->str =3D tmp; + ring->str_size =3D ring->str_used + len + 1; + } + + ret =3D ring->str_used; + memcpy(ring->str + ret, str, len); + ring->str_used +=3D len; + ring->str[ring->str_used++] =3D 0; + + return ret; +} + +static void p9_error(struct ring *ring, uint16_t tag, uint32_t err) +{ + unsigned int erroff; + + strerror_r(err, ring->buffer, ring->ring_size); + erroff =3D add_string(ring, ring->buffer, strlen(ring->buffer)); + fill_buffer(ring, P9_CMD_ERROR, tag, "SU", + erroff !=3D ~0 ? ring->str + erroff : "cannot allocate mem= ory", + &err); +} + void *io_thread(void *arg) { struct ring *ring =3D arg; @@ -151,7 +356,16 @@ void *io_thread(void *arg) if ( count < hdr.size ) continue; =20 - /* TODO: handle request (will rewrite hdr.size). */ + ring->str_used =3D 0; + + switch ( hdr.cmd ) + { + default: + syslog(LOG_DEBUG, "%u.%u sent unhandled command %u\n", + ring->device->domid, ring->device->devid, hdr.cmd); + p9_error(ring, hdr.tag, EOPNOTSUPP); + break; + } =20 ring->handle_response =3D true; hdr.size =3D ((struct p9_header *)ring->buffer)->size; @@ -174,6 +388,7 @@ void *io_thread(void *arg) } } =20 + free(ring->str); free(ring->buffer); =20 ring->thread_active =3D false; diff --git a/tools/9pfsd/xen-9pfsd.h b/tools/9pfsd/xen-9pfsd.h index d587f59a32..0cde0d2bb8 100644 --- a/tools/9pfsd/xen-9pfsd.h +++ b/tools/9pfsd/xen-9pfsd.h @@ -46,6 +46,9 @@ struct ring { bool error; /* Protocol error - stop processing. */ bool handle_response; /* Main loop now handling response. */ void *buffer; /* Request/response buffer. */ + char *str; /* String work space. */ + unsigned int str_size; /* Size of *str. */ + unsigned int str_used; /* Currently used size of *str. */ }; =20 struct device { --=20 2.35.3