From a047abb1f633867a593b8490173d03743bbcebbf Mon Sep 17 00:00:00 2001 From: Wei Chen Date: Fri, 29 Sep 2017 16:36:12 +0800 Subject: [PATCH] ctr: Identify the platform.variant for ARM platforms In the commit "26329b2b8d7fd4e290b2b0f0163547f2d79bb817", dmcgowan/fix-pull-multi-arch, PR#1535. The containerd has enabled the pull multi-arch image support. But the platform.variant field of OCI for ARM hadn't been ready at that time, so all ARM images could not pull successfully. " docker.io/library/hello-world:latest: resolved |++++++++++++++++++++++++++++++++++++++| index-sha256:3644c0788e3d3823f9e97f757f01d2ddc6eb5458df9d801: done |++++++++++++++++++++++++++++++++++++++| elapsed: 5.1 s total: 2.7 Ki (533.0 B/s) unpacking sha256:3d3823f9e97f757f01d2ddc6eb5458df9d801... ctr: : manifest not found: not found " In this patch we'll detect the ARM variants from /proc/cpuinfo. Because Linux kernel has already detected the ABI, ISA and Features for us. We don't need to parse them from registers again. Change-Id: I479b34bf3f52df9f7a6b3c77718b7d316dbf7f69 Signed-off-by: Wei Chen Signed-off-by: Penny Zheng --- platforms/cpuinfo.go | 85 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 platforms/cpuinfo.go diff --git a/platforms/cpuinfo.go b/platforms/cpuinfo.go new file mode 100644 index 000000000..b7c23cc19 --- /dev/null +++ b/platforms/cpuinfo.go @@ -0,0 +1,85 @@ +package platforms + +import ( + "bufio" + "os" + "runtime" + "strings" + + "github.com/containerd/containerd/errdefs" + "github.com/containerd/containerd/log" + "github.com/pkg/errors" +) + +// Present the ARM instruction set architecture, eg: v7, v8 +var cpuVariant string + +func init() { + if isArmArch(runtime.GOARCH) { + cpuVariant = getCPUVariant() + } else { + cpuVariant = "" + } +} + +// For Linux, the kernel has already detected the ABI, ISA and Features. +// So we don't need to access the ARM registers to detect platform information +// by ourselves. We can just parse these information from /proc/cpuinfo +func getCPUInfo(pattern string) (info string, err error) { + if !isLinuxOS(runtime.GOOS) { + return "", errors.Wrapf(errdefs.ErrNotImplemented, "getCPUInfo for OS %s", runtime.GOOS) + } + + cpuinfo, err := os.Open("/proc/cpuinfo") + if err != nil { + return "", err + } + defer cpuinfo.Close() + + // Start to Parse the Cpuinfo line by line. For SMP SoC, we parse + // the first core is enough. + scanner := bufio.NewScanner(cpuinfo) + for scanner.Scan() { + newline := scanner.Text() + list := strings.Split(newline, ":") + + if len(list) > 1 && strings.EqualFold(strings.TrimSpace(list[0]), pattern) { + return strings.TrimSpace(list[1]), nil + } + } + + // Check whether the scanner encountered errors + err = scanner.Err() + if err != nil { + return "", err + } + + return "", errors.Wrapf(errdefs.ErrNotFound, "getCPUInfo for pattern: %s", pattern) +} + +func getCPUVariant() string { + variant, err := getCPUInfo("Cpu architecture") + if err != nil { + log.L.WithError(err).Error("failure getting variant") + return "" + } + + switch variant { + case "8": + variant = "v8" + case "7", "7M", "?(12)", "?(13)", "?(14)", "?(15)", "?(16)", "?(17)": + variant = "v7" + case "6", "6TEJ": + variant = "v6" + case "5", "5T", "5TE", "5TEJ": + variant = "v5" + case "4", "4T": + variant = "v4" + case "3": + variant = "v3" + default: + variant = "unknown" + } + + return variant +}