createMap validates the spec's properties and creates the map in the kernel using the given opts. It does not populate or freeze the map.
(inner *sys.FD, c *btf.Cache)
| 549 | // createMap validates the spec's properties and creates the map in the kernel |
| 550 | // using the given opts. It does not populate or freeze the map. |
| 551 | func (spec *MapSpec) createMap(inner *sys.FD, c *btf.Cache) (_ *Map, err error) { |
| 552 | closeOnError := func(closer io.Closer) { |
| 553 | if err != nil { |
| 554 | closer.Close() |
| 555 | } |
| 556 | } |
| 557 | |
| 558 | // Kernels 4.13 through 5.4 used a struct bpf_map_def that contained |
| 559 | // additional 'inner_map_idx' and later 'numa_node' fields. |
| 560 | // In order to support loading these definitions, tolerate the presence of |
| 561 | // extra bytes, but require them to be zeroes. |
| 562 | if spec.Extra != nil { |
| 563 | if _, err := io.Copy(internal.DiscardZeroes{}, spec.Extra); err != nil { |
| 564 | return nil, errors.New("extra contains unhandled non-zero bytes, drain before creating map") |
| 565 | } |
| 566 | } |
| 567 | |
| 568 | spec, err = spec.fixupMagicFields() |
| 569 | if err != nil { |
| 570 | return nil, err |
| 571 | } |
| 572 | |
| 573 | p, sysMapType := platform.DecodeConstant(spec.Type) |
| 574 | if p != platform.Native { |
| 575 | return nil, fmt.Errorf("map type %s (%s): %w", spec.Type, p, internal.ErrNotSupportedOnOS) |
| 576 | } |
| 577 | |
| 578 | attr := sys.MapCreateAttr{ |
| 579 | MapName: maybeFillObjName(spec.Name), |
| 580 | MapType: sys.MapType(sysMapType), |
| 581 | KeySize: spec.KeySize, |
| 582 | ValueSize: spec.ValueSize, |
| 583 | MaxEntries: spec.MaxEntries, |
| 584 | MapFlags: spec.Flags, |
| 585 | NumaNode: spec.NumaNode, |
| 586 | MapExtra: spec.MapExtra, |
| 587 | } |
| 588 | |
| 589 | if inner != nil { |
| 590 | attr.InnerMapFd = inner.Uint() |
| 591 | } |
| 592 | |
| 593 | if spec.Key != nil || spec.Value != nil { |
| 594 | handle, keyTypeID, valueTypeID, err := btf.MarshalMapKV(spec.Key, spec.Value) |
| 595 | if err != nil && !errors.Is(err, btf.ErrNotSupported) { |
| 596 | return nil, fmt.Errorf("load BTF: %w", err) |
| 597 | } |
| 598 | |
| 599 | if handle != nil { |
| 600 | defer handle.Close() |
| 601 | |
| 602 | // Use BTF k/v during map creation. |
| 603 | attr.BtfFd = uint32(handle.FD()) |
| 604 | attr.BtfKeyTypeId = keyTypeID |
| 605 | attr.BtfValueTypeId = valueTypeID |
| 606 | } |
| 607 | |
| 608 | if spec.Type == StructOpsMap { |
no test coverage detected