diff --git a/map.go b/map.go index 78fc99575..ad2745578 100644 --- a/map.go +++ b/map.go @@ -673,7 +673,7 @@ func handleMapCreateError(attr sys.MapCreateAttr, spec *MapSpec, err error) erro return fmt.Errorf("map create: %w (MEMLOCK may be too low, consider rlimit.RemoveMemlock)", err) } if errors.Is(err, unix.EINVAL) { - if spec.MaxEntries == 0 { + if spec.MaxEntries == 0 && !spec.Type.requiresZeroMaxEntries() { return fmt.Errorf("map create: %w (MaxEntries may be incorrectly set to zero)", err) } if spec.Type == UnspecifiedMap { diff --git a/map_test.go b/map_test.go index 17ed6cdb1..4a470bcce 100644 --- a/map_test.go +++ b/map_test.go @@ -2323,3 +2323,67 @@ func ExampleMap_Iterate_nestedMapsAndProgramArrays() { panic(fmt.Sprint("Iterator encountered an error:", err)) } } + +func TestMapCreateStorageMisleadingError(t *testing.T) { + tests := []struct { + name string + mapType MapType + version string + }{ + {"SkStorage", SkStorage, "5.2"}, + {"InodeStorage", InodeStorage, "5.10"}, + {"TaskStorage", TaskStorage, "5.11"}, + {"CgroupStorage", CgroupStorage, "6.2"}, + {"CGroupStorage", CGroupStorage, "4.19"}, + {"PerCPUCGroupStorage", PerCPUCGroupStorage, "4.20"}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + testutils.SkipOnOldKernel(t, tt.version, tt.name+" map") + + spec := &MapSpec{ + Type: tt.mapType, + KeySize: 4, + ValueSize: 4, + MaxEntries: 0, + Flags: sys.BPF_F_NO_PREALLOC, + } + + _, err := NewMap(spec) + qt.Assert(t, qt.IsNotNil(err), qt.Commentf("Expected map creation to fail")) + + if errors.Is(err, unix.EINVAL) { + qt.Assert(t, qt.Not(qt.StringContains(err.Error(), "MaxEntries may be incorrectly set to zero"))) + } + }) + } +} + +func TestMapCreateZeroMaxEntriesError(t *testing.T) { + tests := []struct { + name string + mapType MapType + }{ + {"Hash", Hash}, + {"Array", Array}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + spec := &MapSpec{ + Type: tt.mapType, + KeySize: 4, + ValueSize: 4, + MaxEntries: 0, // Invalid zero value + } + + _, err := NewMap(spec) + qt.Assert(t, qt.IsNotNil(err), qt.Commentf("Expected map creation to fail")) + + if errors.Is(err, unix.EINVAL) { + qt.Assert(t, qt.StringContains(err.Error(), "MaxEntries may be incorrectly set to zero")) + } + }) + } +} diff --git a/types.go b/types.go index 52ff75b5c..66b009b7f 100644 --- a/types.go +++ b/types.go @@ -188,6 +188,16 @@ func (mt MapType) mustHaveNoPrealloc() bool { return false } +// requiresZeroMaxEntries returns true if the map type requires MaxEntries to be zero. +func (mt MapType) requiresZeroMaxEntries() bool { + switch mt { + case CgroupStorage, CGroupStorage, PerCPUCGroupStorage, InodeStorage, TaskStorage, SkStorage: + return true + } + + return false +} + // ProgramType of the eBPF program type ProgramType uint32