@@ -554,42 +554,61 @@ func (spec *MapSpec) createMap(inner *sys.FD, c *btf.Cache) (_ *Map, err error)
554554 defer handle .Close ()
555555
556556 if spec .Type == StructOpsMap {
557+ if handle == nil {
558+ return nil , fmt .Errorf ("struct_ops: BTF handle is not resolved" )
559+ }
560+
557561 if spec .Value == nil {
558562 return nil , fmt .Errorf ("struct_ops map: missing value type information" )
559563 }
560564
561- valueType , ok := btf.As [* btf.Struct ](spec .Value )
565+ if spec .Key == nil {
566+ return nil , fmt .Errorf ("struct_ops map: Key must be specified" )
567+ }
568+
569+ keyType , ok := btf.As [* btf.Int ](spec .Key )
562570 if ! ok {
563- return nil , fmt .Errorf ("value must be Struct type" )
571+ return nil , fmt .Errorf ("key must be Int type" )
564572 }
565573
566- if spec .KeySize != 4 {
567- return nil , fmt .Errorf ("struct_ops: KeySize must be 4" )
574+ // The key size of StructOps is always 4
575+ if keyType .Size != 4 {
576+ return nil , fmt .Errorf ("key size must be 4" )
577+ }
578+
579+ valueType , ok := btf.As [* btf.Struct ](spec .Value )
580+ if ! ok {
581+ return nil , fmt .Errorf ("value must be Struct type" )
568582 }
569583
570584 // struct_ops: resolve value type ("bpf_struct_ops_<name>") and
571585 // record kernel-specific BTF IDs / FDs needed for map creation.
572- target := btf .Type ((* btf .Struct )(nil ))
573- s , module , err := findTargetInKernel (valueType .Name , & target , c )
586+ vTarget := btf .Type ((* btf .Struct )(nil ))
587+ s , module , err := findTargetInKernel (valueType .Name , & vTarget , c )
574588 if err != nil {
575589 return nil , fmt .Errorf ("lookup value type %q: %w" , valueType .Name , err )
576590 }
577591 defer module .Close ()
578592
579- vType := target .(* btf.Struct )
580-
593+ vType := vTarget .(* btf.Struct )
581594 btfValueTypeId , err := s .TypeID (vType )
582595 if err != nil {
583596 return nil , fmt .Errorf ("lookup type_id: %w" , err )
584597 }
585598
586- attr .ValueSize = spec . ValueSize
599+ attr .BtfFd = uint32 ( handle . FD ())
587600 attr .BtfVmlinuxValueTypeId = btfValueTypeId
588-
589- if handle == nil {
590- return nil , fmt .Errorf ("struct_ops: BTF handle is not resolved" )
601+ attr .KeySize , spec .KeySize = keyType .Size , keyType .Size
602+
603+ if spec .ValueSize == 0 {
604+ attr .ValueSize , spec .ValueSize = vType .Size , vType .Size
605+ } else {
606+ // If spec.ValueSize is non-zero but does not match vtype.size, it should fail.
607+ if spec .ValueSize != vType .Size {
608+ return nil , fmt .Errorf ("struct_ops: ValueSize (%d) mismatches vtype size (%d)" , spec .ValueSize , vType .Size )
609+ }
610+ attr .ValueSize = spec .ValueSize
591611 }
592- attr .BtfFd = uint32 (handle .FD ())
593612
594613 if module != nil {
595614 // BPF_F_VTYPE_BTF_OBJ_FD is required if the type comes from a module
0 commit comments