|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH 05/29] tools/xenlogd: add 9pfs response generation support
On Wed, Nov 1, 2023 at 6:56 AM Juergen Gross <jgross@xxxxxxxx> wrote:
>
> 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 <jgross@xxxxxxxx>
> ---
> diff --git a/tools/xenlogd/io.c b/tools/xenlogd/io.c
> index 590d06e906..5a06f72338 100644
> --- a/tools/xenlogd/io.c
> +++ b/tools/xenlogd/io.c
> @@ -101,6 +112,172 @@ static bool io_work_pending(device *device)
> : ring_out_data(device);
> }
>
> +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
> elements)
> + * 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 the
> next
> + * format character.
> + * b: 2 byte unsigned integer
> + * The parameter is a pointer to a uint16_t value
> + * D: Data blob (4 byte length + <length> bytes)
> + * 2 parameters are consumed, first an unsigned int for the length, then 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 + <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(device *device, uint8_t cmd, uint16_t tag,
> + const char *fmt, ...)
> +{
> + struct p9_header *hdr = device->buffer;
> + void *data = hdr + 1;
> + const char *f;
> + const void *par;
> + const char *str_val;
> + const struct p9_qid *qid;
> + unsigned int len;
> + va_list ap;
> + unsigned int array_sz = 0;
> + unsigned int elem_sz = 0;
> +
> + hdr->cmd = cmd;
> + hdr->tag = tag;
> +
> + va_start(ap, fmt);
> +
> + for ( f = fmt; *f; f++ )
> + {
> + if ( !array_sz )
> + par = va_arg(ap, const void *);
> + else
> + {
> + par += elem_sz;
> + array_sz--;
> + }
> +
> + switch ( *f )
> + {
> + case 'a':
> + f++;
> + if ( !*f || array_sz )
> + fmt_err(fmt);
> + array_sz = *(const unsigned int *)par;
> + *(__packed uint16_t *)data = array_sz;
Is it worth checking that array_sz doesn't exceed 0xffff?
> + data += sizeof(uint16_t);
> + par = va_arg(ap, const void *);
> + elem_sz = 0;
> + break;
> +
> + case 'u':
> + *(__packed uint16_t *)data = *(const uint16_t *)par;
> + elem_sz = sizeof(uint16_t);
> + data += sizeof(uint16_t);
> + break;
> +
> + case 'D':
> + if ( array_sz )
> + fmt_err(fmt);
> + len = *(const unsigned int *)par;
> + *(__packed uint32_t *)data = len;
> + data += sizeof(uint32_t);
> + par = va_arg(ap, const void *);
> + if ( data != par )
> + memcpy(data, par, len);
> + data += len;
> + break;
> +
> + case 'L':
> + *(__packed uint64_t *)data = *(const uint64_t *)par;
> + elem_sz = sizeof(uint64_t);
> + data += sizeof(uint64_t);
> + break;
> +
> + case 'Q':
> + qid = par;
> + elem_sz = sizeof(*qid);
> + *(uint8_t *)data = qid->type;
> + data += sizeof(uint8_t);
> + *(__packed uint32_t *)data = qid->version;
> + data += sizeof(uint32_t);
> + *(__packed uint64_t *)data = qid->path;
> + data += sizeof(uint64_t);
> + break;
> +
> + case 'S':
> + str_val = par;
> + elem_sz = sizeof(str_val);
> + len = strlen(str_val);
Should len be checked to ensure it doesn't exceed 0xffff?
Regards,
Jason
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |