2
0
mirror of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git synced 2025-09-04 20:19:47 +08:00

tools: ynl-gen: print setters for multi-val attrs

For basic types we "flatten" setters. If a request "a" has a simple
nest "b" with value "val" we print helpers like:

 req_set_a_b(struct a *req, int val)
 {
   req->_present.a = 1;
   req->b._present.val = 1;
   req->b.val = ...
 }

This is not possible for multi-attr because they have to be allocated
dynamically by the user. Print "object level" setters so that user
preparing the object doesn't have to futz with the presence bits
and other YNL internals.

Add the ability to pass in the variable name to generated setters.
Using "req" here doesn't feel right, while the attr is part of a request
it's not the request itself, so it seems cleaner to call it "obj".

Example:

 static inline void
 netdev_queue_id_set_id(struct netdev_queue_id *obj, __u32 id)
 {
	obj->_present.id = 1;
	obj->id = id;
 }

Reviewed-by: Donald Hunter <donald.hunter@gmail.com>
Acked-by: Stanislav Fomichev <sdf@fomichev.me>
Link: https://patch.msgid.link/20250723171046.4027470-5-kuba@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Jakub Kicinski 2025-07-23 10:10:45 -07:00
parent 2c222dde61
commit 8553fb7c55

View File

@ -275,9 +275,8 @@ class Type(SpecAttr):
def _setter_lines(self, ri, member, presence):
raise Exception(f"Setter not implemented for class type {self.type}")
def setter(self, ri, space, direction, deref=False, ref=None):
def setter(self, ri, space, direction, deref=False, ref=None, var="req"):
ref = (ref if ref else []) + [self.c_name]
var = "req"
member = f"{var}->{'.'.join(ref)}"
local_vars = []
@ -332,7 +331,7 @@ class TypeUnused(Type):
def attr_get(self, ri, var, first):
pass
def setter(self, ri, space, direction, deref=False, ref=None):
def setter(self, ri, space, direction, deref=False, ref=None, var=None):
pass
@ -355,7 +354,7 @@ class TypePad(Type):
def attr_policy(self, cw):
pass
def setter(self, ri, space, direction, deref=False, ref=None):
def setter(self, ri, space, direction, deref=False, ref=None, var=None):
pass
@ -695,13 +694,14 @@ class TypeNest(Type):
f"parg.data = &{var}->{self.c_name};"]
return get_lines, init_lines, None
def setter(self, ri, space, direction, deref=False, ref=None):
def setter(self, ri, space, direction, deref=False, ref=None, var="req"):
ref = (ref if ref else []) + [self.c_name]
for _, attr in ri.family.pure_nested_structs[self.nested_attrs].member_list():
if attr.is_recursive():
continue
attr.setter(ri, self.nested_attrs, direction, deref=deref, ref=ref)
attr.setter(ri, self.nested_attrs, direction, deref=deref, ref=ref,
var=var)
class TypeMultiAttr(Type):
@ -2563,6 +2563,13 @@ def print_type_full(ri, struct):
free_rsp_nested_prototype(ri)
ri.cw.nl()
# Name conflicts are too hard to deal with with the current code base,
# they are very rare so don't bother printing setters in that case.
if ri.ku_space == 'user' and not ri.type_name_conflict:
for _, attr in struct.member_list():
attr.setter(ri, ri.attr_set, "", var="obj")
ri.cw.nl()
def print_type_helpers(ri, direction, deref=False):
print_free_prototype(ri, direction)