golang / go

The Go programming language
https://go.dev
BSD 3-Clause "New" or "Revised" License
123.3k stars 17.58k forks source link

all: announce end of support for old Linux versions #60792

Open dmitshur opened 1 year ago

dmitshur commented 1 year ago

New Linux versions get released over time, and old ones cannot be supported indefinitely. This is the tracking recurring issue for announcing end of support for very old versions that we decide to drop support for. (The corresponding tracking issues for macOS and Windows, the other two OSes that have first class ports, are #23011 and #52188.)

The most recent change was applied in Go 1.18, where proposal #45964 increased the minimum Linux kernel version requirement from 2.6.23 to 2.6.32. See https://go.dev/doc/go1.18#linux.

CC @golang/release.

ianlancetaylor commented 1 year ago

Just a note that the case for Linux is a bit different than that for macOS and Windows, as Linux does not have a sole vendor. We need to identify organizations that distribute older versions of Linux that are supported and used. For example, I believe that we should continue to support all versions of Linux that are actively supported by commercial organizations, such as RHEL or Suse Linux Enterprise Server, and also all versions of Linux that are actively supported by communities supporting stable versions, such as Rocky Linux. Of course the nature of Linux is such that the set of active organizations changes over time.

baryluk commented 11 months ago

3.10 could be a reasonable target.

For reference some facts about distros, and the kernel changes tangential to Go and userland.

Centos 7 - Linux 3.10 Centos 7: Released: 2014-07-07 , Full updates ended: 2020-08-06, Maintenance updates EOL: 2024-06-30 (Centos 8 is in maintenance for about a year now, and Centos 9 is current version)

Debian 9 - Linux 4.9 Debian 9.0 (codename Stretch) was initially released on June 17th, 2017. Last major update was Debian 9.13 was released [July 18th, 2020. Stretch had Long Term Support (LTS) until the end of June 2022.

Current stable Debian is version 12.2. So Debian 9.x is really ancient actually.

Debian 8 (Jessie), from 2015, had Linux 3.16.7-ckt9 in the 8.0

Ubuntu 16.04.7 LTS (initial relase of 16.04 - 2016-04-21; with latest minor bump 16.04.7 - August 13, 2020) - End of standard support: April 2021, EOL: April 2026

OpenSUSE 13.1, released 2013-11-19, end of life 2016-01, Linux 3.11.6

Oracle Linux 7 - initial release, Jul 2014, about same time as RHEL 7/ Centos. Extended support, Jun 2026. But if you pay, they will support you indefinitively (even on older version than 7), and it is likely there are people having such support in various industries. It is unlikely they run Go programs, and if they do, they will likely run older Go version for this anyway.

Also of note is that Oracle Linux 6.x, latest release, 6.10 from July 2018, has updated kernels, including 4.1.12, 2.6.39, and not just 2.6.32 (as RHEL 6).

These are the major ones that might be running and be sometimes hard to upgrade. Other distributions are more desktop and normal user focused, and update way faster, and earlier, and do not have LTS often. So it is close to 0% they would use old system or kernel.

For example, 3.10 would be like 20 major releases ago in world of Fedora, or Ubuntu.

The biggest risk would be probably various mobile and embedded arm devices, like Android, SBCs, routers, etc.

Linux 3.10 was release 30 June 2013, and was 10th LTS release. EOLed November 2017. Red Hat was maintaining own version of 3.10 (with backports from newer kernels, including some syscalls that were not originally in any upstream 3.10 release) until very recently.

Personally, I do not use any of these ancient systems. (Where I work, we migrated from Centos 7, about 2.5 years ago, and almost migrated from Centos 8 to Centos 9 to, already on some parts of our infra, but migrate on demand slowly instead). In other places, I run Debian 12, and still few Debian 11 systems, that could be updated anytime, but just wait their time.

Notable features added between 2.6.32 and 3.10, that might be semi related to userland go runtime

3.10:

3.9

3.8 (2012)

3.7

3.6

3.5

3.4

3.3

3.2

3.1

3.0

2.6.32 - 2.6.39 - Various / A lot / Not listed here.

I also looked at some man pages, and found few bits, for Linux above 2.6.32:

vdso:

   aarch64 functions
       The table below lists the symbols exported by the vDSO.
       symbol                   version
       ──────────────────────────────────────
       __kernel_rt_sigreturn    LINUX_2.6.39
       __kernel_gettimeofday    LINUX_2.6.39
       __kernel_clock_gettime   LINUX_2.6.39
       __kernel_clock_getres    LINUX_2.6.39

syscalls:

       bpf(2)                      3.18
       clone3(2)                   5.3
       close_range(2)              5.9
       copy_file_range(2)          4.5
       epoll_pwait2(2)             5.11
       execveat(2)                 3.19
       faccessat2(2)               5.8
       finit_module(2)             3.8             ireelavant (this is mostly for Android for loading kernel modules)
       fsconfig(2)                 5.2
       fsmount(2)                  5.2
       fsopen(2)                   5.2
       fspick(2)                   5.2
       get_tls(2)                  4.15          ARM OABI only, has __ARM_NR prefix
       getrandom(2)                3.17
       io_pgetevents(2)            4.18
       io_uring_enter(2)           5.1
       io_uring_register(2)        5.1
       io_uring_setup(2)           5.1
       kcmp(2)                     3.5
       kern_features(2)            3.7           SPARC64 only
       kexec_file_load(2)          3.17       irrelevant
       landlock_add_rule(2)        5.13    irrelevant
       landlock_create_ruleset(2)  5.13    irrelevant
       landlock_restrict_self(2)   5.13    irrelevant
       membarrier(2)               3.17
       memfd_create(2)             3.17
       memfd_secret(2)             5.14
       move_mount(2)               5.2
       name_to_handle_at(2)        2.6.39
       open_by_handle_at(2)        2.6.39
       open_tree(2)                5.2
       openat2(2)                  5.6
       or1k_atomic(2)              3.1           OpenRISC 1000 only
       pidfd_getfd(2)              5.6
       pidfd_send_signal(2)        5.1
       pidfd_open(2)               5.3
       pkey_alloc(2)               4.8
       pkey_free(2)                4.8
       pkey_mprotect(2)            4.8
       preadv2(2)                  4.6
       prlimit64(2)                2.6.36
       process_madvise(2)          5.10
       process_vm_readv(2)         3.2
       process_vm_writev(2)        3.2
       pwritev2(2)                 4.6
       quotactl_fd(2)              5.14
       recvmmsg(2)                 2.6.33
       riscv_flush_icache(2)       4.15          RISC-V only
       rseq(2)                     4.18
       s390_runtime_instr(2)       3.7           s390 only
       s390_pci_mmio_read(2)       3.19          s390 only
       s390_pci_mmio_write(2)      3.19          s390 only
       s390_sthyi(2)               4.15          s390 only
       s390_guarded_storage(2)     4.12          s390 only
       sched_getattr(2)            3.14
       sched_setattr(2)            3.14
       seccomp(2)                  3.17
       sendmmsg(2)                 3.0
       setns(2)                    3.0
       statx(2)                    4.11
       switch_endian(2)            4.1           PowerPC64 only
       syncfs(2)                   2.6.39
       userfaultfd(2)              4.3

Extra syscall options:

mmap

       MAP_SHARED_VALIDATE (since Linux 4.15)
       MAP_FIXED_NOREPLACE (since Linux 4.17)
       MAP_HUGE_2MB, MAP_HUGE_1GB (since Linux 3.8)
       MAP_SYNC (since Linux 4.15)
       MAP_UNINITIALIZED (since Linux 2.6.33)            irrelevant, requires special kernel config, for embeded single-user devices
open

       O_PATH (since Linux 2.6.39)
       O_TMPFILE (since Linux 3.11)

Since  Linux  2.6.33,  proper  O_SYNC support is provided.  

Since Linux 6.1, O_DIRECT support and alignment restrictions for a file can be queried using statx(2), using the STATX_DIOALIGN flag.
linkat

       AT_EMPTY_PATH (since Linux 2.6.39)
execve

can no longer fail with EAGAIN error (i.e. due to switching to a different user, and exhausting max number of processes limits).
clone3 options

               u64 set_tid;      /* Pointer to a pid_t array
                                    (since Linux 5.5) */
               u64 set_tid_size; /* Number of elements in set_tid
                                    (since Linux 5.5) */
               u64 cgroup;       /* File descriptor for target cgroup
                                    of child (since Linux 5.7) */

flag masks

       CLONE_CLEAR_SIGHAND (since Linux 5.5)
       CLONE_INTO_CGROUP (since Linux 5.7)
       CLONE_NEWCGROUP (since Linux 4.6)
       CLONE_NEWUSER  semantic fianlized between 2.6.23 and 3.5
       CLONE_PIDFD (since Linux 5.2)

returns:

EINVAL and and some other could be returned, some in relation to new flags, or to previously unhandled wrong combinations of flags.
       epoll_pwait2() was added in Linux 5.11.

epoll_ctl

       EPOLLWAKEUP (since Linux 3.5)
       EPOLLEXCLUSIVE (since Linux 4.5)
epoll_wait

       Before Linux 2.6.37, a timeout value larger than approximately
       LONG_MAX / HZ milliseconds is treated as -1 (i.e., infinity).
       Thus, for example, on a system where sizeof(long) is 4 and the
       kernel HZ value is 1000, this means that timeouts greater than
       35.79 minutes are treated as infinity.
clock_gettime

       CLOCK_REALTIME_ALARM (since Linux 3.0; Linux-specific)
       CLOCK_TAI (since Linux 3.10; Linux-specific)
       CLOCK_BOOTTIME (since Linux 2.6.39; Linux-specific)
       CLOCK_BOOTTIME_ALARM (since Linux 3.0; Linux-specific)
   preadv2() and pwritev2()  # preadv2() and pwritev2() first appeared in Linux 4.6.
       RWF_DSYNC (since Linux 4.7)
       RWF_HIPRI (since Linux 4.6)
       RWF_SYNC (since Linux 4.7)
       RWF_NOWAIT (since Linux 4.14)
       RWF_APPEND (since Linux 4.16)
sendmsg

       MSG_FASTOPEN (since Linux 3.7)
recvfrom

      MSG_TRUNC (since Linux 2.2)
              For raw (AF_PACKET), Internet datagram (since Linux 2.4.27/2.6.8), netlink (since Linux 2.6.22), and UNIX datagram (since Linux 3.4) sockets: return the real length of the packet or datagram, even when it was longer than the passed buffer.
setsockopt

       TCP_USER_TIMEOUT (since Linux 2.6.37)
       TCP_FASTOPEN (since Linux 3.6)
       TCP_FASTOPEN_CONNECT (since Linux 4.11)

       SO_ATTACH_FILTER (since Linux 2.2), SO_ATTACH_BPF (since Linux 3.19)
       SO_BINDTODEVICE  (can do getsockopt since Linux 3.8)
       SO_DETACH_FILTER (since Linux 2.2), SO_DETACH_BPF (since Linux 3.19)
       SO_ATTACH_REUSEPORT_CBPF, SO_ATTACH_REUSEPORT_EBPF
       SO_INCOMING_NAPI_ID (gettable since Linux 4.12)
       SO_PEEK_OFF (since Linux 3.4)
       SO_REUSEPORT (since Linux 3.9)
       SO_RXQ_OVFL (since Linux 2.6.33)
       SO_SELECT_ERR_QUEUE (since Linux 3.10)
       SO_BUSY_POLL (since Linux 3.11)

       IP_BIND_ADDRESS_NO_PORT (since Linux 4.2)
       IP_NODEFRAG (since Linux 2.6.36)
The prlimit() system call is available since Linux 2.6.36.
mlock2() is available since Linux 4.4

MCL_ONFAULT (since Linux 4.4)

Some limit account bugs fixed in 4.9
pkey_mprotect() first appeared in Linux 4.9
futex

       FUTEX_LOCK_PI2 (since Linux 5.14)
timerfd_create

can use boottime and realtime alarm / clocks

              TFD_IOC_SET_TICKS (since Linux 3.17)
sendfile

       Before Linux 2.6.33, out_fd must refer to a socket.  Since Linux 2.6.33 it can be any file.  If it is a regular file, then sendfile() changes the file offset appropriately.  (Just like in 2.4.x and earlier).
copy_file_range

Since 5.19, can use for cross-filesystems copy, if src and dst file systems are the same and support it

Significantly improved error return codes in 5.3 and 5.19
pipe2

       O_DIRECT (since Linux 3.4)

O_NOTIFICATION_PIPE
              Since Linux 5.8,
fcntl

       F_SETPIPE_SZ (int; since Linux 2.6.35)
       F_GETPIPE_SZ (void; since Linux 2.6.35)

       F_ADD_SEALS (int; since Linux 3.17)
       F_GET_SEALS (void; since Linux 3.17)
       F_SEAL_FUTURE_WRITE (since Linux 5.1)

       F_GET_RW_HINT (uint64_t *; since Linux 4.13)
       F_SET_RW_HINT (uint64_t *; since Linux 4.13)
       F_GET_FILE_RW_HINT (uint64_t *; since Linux 4.13)
       F_SET_FILE_RW_HINT (uint64_t *; since Linux 4.13)
       RWH_WRITE_LIFE_NOT_SET
       RWH_WRITE_LIFE_NONE
       RWH_WRITE_LIFE_SHORT
       RWH_WRITE_LIFE_MEDIUM
       RWH_WRITE_LIFE_LONG
       RWH_WRITE_LIFE_EXTREME

Lost locks on NFSv4 mounts, are correctly detected in 3.12 in all cases, when using default nfs kernel module params.
statfs

       ST_NOSYMFOLLOW (since Linux 5.10)

       From Linux 2.6.38 up to and including Linux 3.1, fstatfs() failed with the error ENOSYS for file descriptors created by pipe(2).
dmitshur commented 10 months ago

Thanks for the suggestion above.

We've entered the release freeze for 1.22 and there aren't announcements to make for this release, moving to the next for now.

mdempsky commented 10 months ago

FWIW, it looks like Rust bumped their minimum Linux version to 3.2 last year, to align with glibc:

The new baseline requirements were picked as the least common denominator among long-term-support distributions that still have active support. This is currently RHEL 7 with glibc 2.17 and kernel 3.10. The kernel requirement is picked as 3.2 instead, because this is the minimum requirement of glibc itself, and there is little relevant API difference between these versions.

https://blog.rust-lang.org/2022/08/01/Increasing-glibc-kernel-requirements.html

rsc commented 5 months ago

Filed https://github.com/golang/go/issues/67001 for Linux 3.2.

dmitshur commented 4 months ago

CL 589015 added a pre-announcement to Go 1.23 release notes. Moving to the next milestone.