diff --git a/libs/native/src/main/java/org/elasticsearch/nativeaccess/FreebsdNativeAccess.java b/libs/native/src/main/java/org/elasticsearch/nativeaccess/FreebsdNativeAccess.java new file mode 100644 index 0000000000000..d24bba0b3a736 --- /dev/null +++ b/libs/native/src/main/java/org/elasticsearch/nativeaccess/FreebsdNativeAccess.java @@ -0,0 +1,83 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +package org.elasticsearch.nativeaccess; + +import org.elasticsearch.nativeaccess.lib.BsdCLibrary; +import org.elasticsearch.nativeaccess.lib.NativeLibraryProvider; +import org.elasticsearch.nativeaccess.lib.PosixCLibrary; + +public class FreebsdNativeAccess extends PosixNativeAccess { + + private final BsdCLibrary bsdLibc; + static final int RLIMIT_NPROC = 7; + + // https://github.com/freebsd/freebsd-src/blob/release/14.2.0/sys/sys/resource.h#L123 + // https://man.freebsd.org/cgi/man.cgi?stat(2) + // https://github.com/freebsd/freebsd-src/blob/release/14.2.0/sys/sys/stat.h#L159 + // Offset of st_size: 112 bytes + // Offset of st_blocks: 120 bytes + FreebsdNativeAccess(NativeLibraryProvider libraryProvider) { + super("FreeBSD", libraryProvider, + new PosixConstants( + -1L, + 10, + 1, + 6, + 512, + 144, + 112, + 120 + ) + ); + + this.bsdLibc = libraryProvider.getLibrary(BsdCLibrary.class); + } + + // https://github.com/freebsd/freebsd-src/blob/release/14.2.0/sys/sys/resource.h#L110 + @Override + protected long getMaxThreads() { + return getRLimit(RLIMIT_NPROC, "max number of threads"); + } + + @Override + protected void logMemoryLimitInstructions() { + logger.warn("You can allow ElasticSearch to lock large amounts of RAM by setting the following in /etc/sysctl.conf:"); + logger.warn("security.bsd.unprivileged_mlock=1\n"); + logger.warn("You can also run the following command to modify the value immediately:"); + logger.warn("sysctl security.bsd.unprivileged_mlock=1\n"); + logger.warn("When running within a Jail, it's highly advisable to set:"); + logger.warn("enforce_statfs = 1"); + } + + @Override + protected boolean nativePreallocate(int fd, long currentSize, long newSize) { + final int rc = bsdLibc.posix_fallocate(fd, currentSize, newSize - currentSize); + if (rc != 0) { + logger.warn("posix_fallocate failed: " + libc.strerror(libc.errno())); + return false; + } + return true; + } + + // https://github.com/elastic/elasticsearch/blob/v8.15.5/server/src/main/java/org/elasticsearch/bootstrap/SystemCallFilter.java#L556 + @Override + public void tryInstallExecSandbox() { + PosixCLibrary.RLimit limit = libc.newRLimit(); + limit.rlim_cur(0); + limit.rlim_max(0); + if (libc.setrlimit(RLIMIT_NPROC, limit) != 0) { + throw new UnsupportedOperationException("RLIMIT_NPROC unavailable: " + libc.strerror(libc.errno())); + } + + logger.debug("FreeBSD RLIMIT_NPROC initialization successful"); + + execSandboxState = ExecSandboxState.ALL_THREADS; + } +} diff --git a/libs/native/src/main/java/org/elasticsearch/nativeaccess/NativeAccessHolder.java b/libs/native/src/main/java/org/elasticsearch/nativeaccess/NativeAccessHolder.java index e1c2b4c4cd8e3..c9f9db8daae7a 100644 --- a/libs/native/src/main/java/org/elasticsearch/nativeaccess/NativeAccessHolder.java +++ b/libs/native/src/main/java/org/elasticsearch/nativeaccess/NativeAccessHolder.java @@ -31,6 +31,8 @@ class NativeAccessHolder { inst = new MacNativeAccess(libProvider); } else if (os.startsWith("Windows")) { inst = new WindowsNativeAccess(libProvider); + } else if (os.startsWith("FreeBSD")) { + inst = new FreebsdNativeAccess(libProvider); } else { logger.warn("Unsupported OS [" + os + "]. Native methods will be disabled."); } diff --git a/libs/native/src/main/java/org/elasticsearch/nativeaccess/PosixNativeAccess.java b/libs/native/src/main/java/org/elasticsearch/nativeaccess/PosixNativeAccess.java index a2188d0685c3b..03ac3e5459cb3 100644 --- a/libs/native/src/main/java/org/elasticsearch/nativeaccess/PosixNativeAccess.java +++ b/libs/native/src/main/java/org/elasticsearch/nativeaccess/PosixNativeAccess.java @@ -200,7 +200,8 @@ String rlimitToString(long value) { } static boolean isNativeVectorLibSupported() { - return Runtime.version().feature() >= 21 && (isMacOrLinuxAarch64() || isLinuxAmd64()) && checkEnableSystemProperty(); + return Runtime.version().feature() >= 21 && (isMacOrLinuxAarch64() || isLinuxAmd64() || isFreebsdAmd64()) && + checkEnableSystemProperty(); } /** @@ -217,6 +218,12 @@ static boolean isMacOrLinuxAarch64() { return (name.startsWith("Mac") || name.startsWith("Linux")) && System.getProperty("os.arch").equals("aarch64"); } + /** Returns true if the OS is FreeBSD, and the architecture is x64. */ + static boolean isFreebsdAmd64() { + String name = System.getProperty("os.name"); + return (name.startsWith("FreeBSD")) && System.getProperty("os.arch").equals("amd64"); + } + /** -Dorg.elasticsearch.nativeaccess.enableVectorLibrary=false to disable.*/ static final String ENABLE_JDK_VECTOR_LIBRARY = "org.elasticsearch.nativeaccess.enableVectorLibrary"; diff --git a/libs/native/src/main/java/org/elasticsearch/nativeaccess/lib/BsdCLibrary.java b/libs/native/src/main/java/org/elasticsearch/nativeaccess/lib/BsdCLibrary.java new file mode 100644 index 0000000000000..f173c5e8b066a --- /dev/null +++ b/libs/native/src/main/java/org/elasticsearch/nativeaccess/lib/BsdCLibrary.java @@ -0,0 +1,15 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +package org.elasticsearch.nativeaccess.lib; + +public non-sealed interface BsdCLibrary extends NativeLibrary { + + int posix_fallocate(int fd, long offset, long length); +} diff --git a/libs/native/src/main/java/org/elasticsearch/nativeaccess/lib/LoaderHelper.java b/libs/native/src/main/java/org/elasticsearch/nativeaccess/lib/LoaderHelper.java index d9c725f5a8d3b..6167f18c7664a 100644 --- a/libs/native/src/main/java/org/elasticsearch/nativeaccess/lib/LoaderHelper.java +++ b/libs/native/src/main/java/org/elasticsearch/nativeaccess/lib/LoaderHelper.java @@ -36,6 +36,8 @@ private static Path findPlatformLibDir() { os = "linux"; } else if (osname.startsWith("Mac OS")) { os = "darwin"; + } else if (osname.startsWith("FreeBSD")) { + os = "freebsd"; } else { os = "unsupported_os[" + osname + "]"; } diff --git a/libs/native/src/main/java/org/elasticsearch/nativeaccess/lib/NativeLibrary.java b/libs/native/src/main/java/org/elasticsearch/nativeaccess/lib/NativeLibrary.java index 943d8565f0897..4c9fa6b0a1505 100644 --- a/libs/native/src/main/java/org/elasticsearch/nativeaccess/lib/NativeLibrary.java +++ b/libs/native/src/main/java/org/elasticsearch/nativeaccess/lib/NativeLibrary.java @@ -11,4 +11,4 @@ /** A marker interface for libraries that can be loaded by {@link org.elasticsearch.nativeaccess.lib.NativeLibraryProvider} */ public sealed interface NativeLibrary permits JavaLibrary, PosixCLibrary, LinuxCLibrary, MacCLibrary, Kernel32Library, VectorLibrary, - ZstdLibrary {} + ZstdLibrary, BsdCLibrary {} diff --git a/libs/native/src/main21/java/org/elasticsearch/nativeaccess/jdk/JdkFreebsdCLibrary.java b/libs/native/src/main21/java/org/elasticsearch/nativeaccess/jdk/JdkFreebsdCLibrary.java new file mode 100644 index 0000000000000..7d1250f4def15 --- /dev/null +++ b/libs/native/src/main21/java/org/elasticsearch/nativeaccess/jdk/JdkFreebsdCLibrary.java @@ -0,0 +1,39 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +package org.elasticsearch.nativeaccess.jdk; + +import org.elasticsearch.nativeaccess.lib.BsdCLibrary; + +import java.lang.foreign.FunctionDescriptor; +import java.lang.invoke.MethodHandle; + +import static java.lang.foreign.ValueLayout.JAVA_INT; +import static java.lang.foreign.ValueLayout.JAVA_LONG; +import static org.elasticsearch.nativeaccess.jdk.JdkPosixCLibrary.downcallHandleWithErrno; +import static org.elasticsearch.nativeaccess.jdk.JdkPosixCLibrary.errnoState; + +public class JdkFreebsdCLibrary implements BsdCLibrary { + + private static final MethodHandle posix_allocate$mh = downcallHandleWithErrno( + "posix_fallocate", + FunctionDescriptor.of(JAVA_INT, JAVA_INT, JAVA_LONG, JAVA_LONG) + ); + + // https://man.freebsd.org/cgi/man.cgi?query=posix_fallocate + // https://github.com/freebsd/freebsd-src/blob/release/14.2.0/sys/sys/fcntl.h#L390 + @Override + public int posix_fallocate(int fd, long offset, long length) { + try { + return (int) posix_allocate$mh.invokeExact(errnoState, fd, offset, length); + } catch (Throwable t) { + throw new AssertionError(t); + } + } +} diff --git a/libs/native/src/main21/java/org/elasticsearch/nativeaccess/jdk/JdkNativeLibraryProvider.java b/libs/native/src/main21/java/org/elasticsearch/nativeaccess/jdk/JdkNativeLibraryProvider.java index 1ac0780fcc460..e6e79ac5828bd 100644 --- a/libs/native/src/main21/java/org/elasticsearch/nativeaccess/jdk/JdkNativeLibraryProvider.java +++ b/libs/native/src/main21/java/org/elasticsearch/nativeaccess/jdk/JdkNativeLibraryProvider.java @@ -9,6 +9,7 @@ package org.elasticsearch.nativeaccess.jdk; +import org.elasticsearch.nativeaccess.lib.BsdCLibrary; import org.elasticsearch.nativeaccess.lib.JavaLibrary; import org.elasticsearch.nativeaccess.lib.Kernel32Library; import org.elasticsearch.nativeaccess.lib.LinuxCLibrary; @@ -39,7 +40,9 @@ public JdkNativeLibraryProvider() { ZstdLibrary.class, JdkZstdLibrary::new, VectorLibrary.class, - JdkVectorLibrary::new + JdkVectorLibrary::new, + BsdCLibrary.class, + JdkFreebsdCLibrary::new ) ); } diff --git a/libs/native/src/main21/java/org/elasticsearch/nativeaccess/jdk/JdkPosixCLibrary.java b/libs/native/src/main21/java/org/elasticsearch/nativeaccess/jdk/JdkPosixCLibrary.java index 727f271d3a0c0..ef63d6b668004 100644 --- a/libs/native/src/main21/java/org/elasticsearch/nativeaccess/jdk/JdkPosixCLibrary.java +++ b/libs/native/src/main21/java/org/elasticsearch/nativeaccess/jdk/JdkPosixCLibrary.java @@ -79,8 +79,12 @@ class JdkPosixCLibrary implements PosixCLibrary { private static final MethodHandle fstat$mh; static { MethodHandle fstat; + String fstatFunc = "fstat64"; try { - fstat = downcallHandleWithErrno("fstat64", FunctionDescriptor.of(JAVA_INT, JAVA_INT, ADDRESS)); + if (System.getProperty("os.name").equals("FreeBSD")) { + fstatFunc = "fstat"; + } + fstat = downcallHandleWithErrno(fstatFunc, FunctionDescriptor.of(JAVA_INT, JAVA_INT, ADDRESS)); } catch (LinkageError e) { // Due to different sizes of the stat structure for 32 vs 64 bit machines, on some systems fstat actually points to // an internal symbol. So we fall back to looking for that symbol.