[PATCH v2 4/6] Add GPIO v2 ioctl decoding

Dmitry V. Levin ldv at altlinux.org
Wed Jan 20 10:43:15 UTC 2021


On Wed, Jan 20, 2021 at 03:34:34PM +0800, Kent Gibson wrote:
> On Tue, Jan 19, 2021 at 11:14:32PM +0300, Dmitry V. Levin wrote:
> > On Mon, Jan 11, 2021 at 11:09:10PM +0800, Kent Gibson wrote:
> > > Add decoding of GPIO uAPI v2 ioctls added in Linux v5.10.
> > > 
> > > Signed-off-by: Kent Gibson <warthog618 at gmail.com>
> > > ---
> [snip]
> 
> > > +
> > > +static void
> > > +print_gpio_v2_line_attribute(struct tcb *const tcp,
> > > +			     struct gpio_v2_line_attribute *attr)
> > > +{
> > > +	switch (attr->id) {
> > > +	case GPIO_V2_LINE_ATTR_ID_FLAGS:
> > > +		PRINT_FIELD_FLAGS("", *attr, flags, gpio_v2_line_flags,
> > > +				  "GPIO_V2_LINE_FLAG_???");
> > > +		break;
> > > +	case GPIO_V2_LINE_ATTR_ID_OUTPUT_VALUES:
> > > +		PRINT_FIELD_X("", *attr, values);
> > > +		break;
> > > +	case GPIO_V2_LINE_ATTR_ID_DEBOUNCE:
> > > +		PRINT_FIELD_U("", *attr, debounce_period_us);
> > > +		break;

[...]
> > > +	default:
> > > +		tprintf("(id=%u)=%#" PRIx64, attr->id, (uint64_t)attr->values);
> > > +		break;
> > 
> > We already discussed this before, but I'm still not quite happy with the
> > output because (id=%u)=%#x is very odd looking thing indeed, it doesn't
> > look similar to any valid C construct I'm aware of, and we strive to
> > produce a C-like output.
> > 
> > What if we invent a non-exiting field and print it instead?  For example,
> > 
> > 	PRINT_FIELD_U("", *attr, id);
> > #define unknown_data values
> > 	PRINT_FIELD_X("", *attr, unknown_data);
> > #undef unknown_data
> > 
> 
> I'm ok with effectively decoding it raw, e.g. 
> "{id=42, data=0x1234567812345678}", but I'm uncomfortable with the #define
> and #undef, particularly if I were to call the field "data".
> So I would lean towards a tprintf for this one:
> 
> 		PRINT_FIELD_U("{", *attr, id);
> 		tprintf(", data=%#" PRIx64 "}", attr->values);
> 
> unless there is some other helper function that could do the same
> without requiring preprocessor gymnastics.
> 
> Or are you trying to replace all instances of tprintf with a PRINT_xxx
> variant?

Yes, we are trying to replace all tprintf instances, but we don't have to
replace all of them right now, so let it remain tprintf here for a while.

You can add a short comment in the code telling why the field is printed
with a different name.

[...]
> > > +static bool
> > > +print_gpio_v2_line_attr_array_member(struct tcb *tcp, void *elem_buf,
> > > +				     size_t elem_size, void *data)
> > > +{
> > > +	struct gpio_v2_line_attribute *la;
> > > +
> > > +	la = (struct gpio_v2_line_attribute *)elem_buf;
> > > +	if (la->padding) {
> > > +		PRINT_FIELD_X("{", *la, padding);
> > > +		tprints(", ");
> > > +	}
> > > +	print_gpio_v2_line_attribute(tcp, la);
> > > +	if (la->padding)
> > > +		tprints("}");
> > > +
> > > +	return true;
> > > +}
> > 
> > If struct gpio_v2_line_attribute is a structure regardless of the value
> > stored in la->padding, then I suggest to print "{" and "}"
> > unconditionally.
> 
> Logically, the array of line attributes is equivalent to a struct.
> Each element in the array corresponds to one field in the logical struct.
> The uAPI is written that way to allow the line configuration to be
> flexible - only the fields of interest need to be passed, and new fields
> can be defined in the future without breaking the ABI. 
> Each struct gpio_v2_line_attribute is decoded as a single field=value,
> based on the id field.  It is only decoded as a struct if the id is
> unknown to the decoder - see the comment above.
> 
> The padding should be zeroed.  If not then it probably means the
> protocol has been extended with fields this decoder doesn't understand,
> and so how about we also fallback to raw decoding in this case, so
> something like "{id=42, padding=0x12345678, data=0x8765432112345678}"?
> 
> The padding being non-zero may also mean the user doesn't understand
> the protocol - which requires the padding to be zero or the request will
> be rejected by the kernel - and I'm ok with decoding to a raw struct in
> that case as well.

If this is the case, then I suggest turning
print_gpio_v2_line_attr_array_member into a trivial wrapper around
print_gpio_v2_line_attribute, similar to its neighbour
print_gpio_v2_line_config_attr_array_member being a trivial wrapper around
print_gpio_v2_line_config_attribute.

I suppose it's still worth printing the structure in
print_gpio_v2_line_attribute even if the padding is non-zero, this would
be consistent with print_gpio_v2_line_config, print_gpio_v2_line_info,
and print_gpio_v2_line_request.


-- 
ldv


More information about the Strace-devel mailing list