Skip to content

Commit 0f461a2

Browse files
rjernstalbertzaharovits
authored andcommitted
Move preallocate functionality to native access (#110678)
This commit moves the file preallocation functionality into NativeAccess. The code is basically the same. One small tweak is that instead of breaking Java access boundaries in order to get an open file handle, the new code uses posix open directly. relates #104876
1 parent eb7a5f0 commit 0f461a2

File tree

47 files changed

+492
-1171
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+492
-1171
lines changed

build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/InternalDistributionModuleCheckTaskProvider.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,6 @@ public class InternalDistributionModuleCheckTaskProvider {
5959
"org.elasticsearch.plugin",
6060
"org.elasticsearch.plugin.analysis",
6161
"org.elasticsearch.pluginclassloader",
62-
"org.elasticsearch.preallocate",
6362
"org.elasticsearch.securesm",
6463
"org.elasticsearch.server",
6564
"org.elasticsearch.simdvec",

distribution/build.gradle

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -280,8 +280,6 @@ configure(subprojects.findAll { ['archives', 'packages'].contains(it.name) }) {
280280

281281
dependencies {
282282
libs project(':server')
283-
// this is a special circumstance of a jar that is not a dependency of server, but needs to be in the module path
284-
libs project(':libs:elasticsearch-preallocate')
285283

286284
libsVersionChecker project(':distribution:tools:java-version-checker')
287285
libsCliLauncher project(':distribution:tools:cli-launcher')

distribution/tools/server-cli/src/main/java/org/elasticsearch/server/cli/SystemJvmOptions.java

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -69,11 +69,6 @@ static List<String> systemJvmOptions(Settings nodeSettings, final Map<String, St
6969
* parsing will break in an incompatible way for some date patterns and locales.
7070
*/
7171
"-Djava.locale.providers=SPI,COMPAT",
72-
/*
73-
* Temporarily suppress illegal reflective access in searchable snapshots shared cache preallocation; this is temporary
74-
* while we explore alternatives. See org.elasticsearch.xpack.searchablesnapshots.preallocate.Preallocate.
75-
*/
76-
"--add-opens=java.base/java.io=org.elasticsearch.preallocate",
7772
maybeEnableNativeAccess(),
7873
maybeOverrideDockerCgroup(distroType),
7974
maybeSetActiveProcessorCount(nodeSettings),

libs/native/jna/src/main/java/module-info.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
requires org.elasticsearch.nativeaccess;
1515
requires org.elasticsearch.logging;
1616
requires com.sun.jna;
17+
requires java.desktop;
1718

1819
exports org.elasticsearch.nativeaccess.jna to com.sun.jna;
1920

libs/native/jna/src/main/java/org/elasticsearch/nativeaccess/jna/JnaKernel32Library.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,14 @@
1515
import com.sun.jna.Structure;
1616
import com.sun.jna.Structure.ByReference;
1717
import com.sun.jna.WString;
18+
import com.sun.jna.ptr.IntByReference;
1819
import com.sun.jna.win32.StdCallLibrary;
1920

2021
import org.elasticsearch.nativeaccess.WindowsFunctions.ConsoleCtrlHandler;
2122
import org.elasticsearch.nativeaccess.lib.Kernel32Library;
2223

2324
import java.util.List;
25+
import java.util.function.IntConsumer;
2426

2527
class JnaKernel32Library implements Kernel32Library {
2628
private static class JnaHandle implements Handle {
@@ -158,6 +160,8 @@ private interface NativeFunctions extends StdCallLibrary {
158160

159161
boolean SetProcessWorkingSetSize(Pointer handle, SizeT minSize, SizeT maxSize);
160162

163+
int GetCompressedFileSizeW(WString lpFileName, IntByReference lpFileSizeHigh);
164+
161165
int GetShortPathNameW(WString lpszLongPath, char[] lpszShortPath, int cchBuffer);
162166

163167
boolean SetConsoleCtrlHandler(StdCallLibrary.StdCallCallback handler, boolean add);
@@ -232,6 +236,15 @@ public boolean SetProcessWorkingSetSize(Handle handle, long minSize, long maxSiz
232236
return functions.SetProcessWorkingSetSize(jnaHandle.pointer, new SizeT(minSize), new SizeT(maxSize));
233237
}
234238

239+
@Override
240+
public int GetCompressedFileSizeW(String lpFileName, IntConsumer lpFileSizeHigh) {
241+
var wideFileName = new WString(lpFileName);
242+
var fileSizeHigh = new IntByReference();
243+
int ret = functions.GetCompressedFileSizeW(wideFileName, fileSizeHigh);
244+
lpFileSizeHigh.accept(fileSizeHigh.getValue());
245+
return ret;
246+
}
247+
235248
@Override
236249
public int GetShortPathNameW(String lpszLongPath, char[] lpszShortPath, int cchBuffer) {
237250
var wideFileName = new WString(lpszLongPath);

libs/native/jna/src/main/java/org/elasticsearch/nativeaccess/jna/JnaLinuxCLibrary.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ private interface NativeFunctions extends Library {
6060
* this is the only way, DON'T use it on some other architecture unless you know wtf you are doing
6161
*/
6262
NativeLong syscall(NativeLong number, Object... args);
63+
64+
int fallocate(int fd, int mode, long offset, long length);
6365
}
6466

6567
private final NativeFunctions functions;
@@ -91,4 +93,9 @@ public int prctl(int option, long arg2, long arg3, long arg4, long arg5) {
9193
public long syscall(long number, int operation, int flags, long address) {
9294
return functions.syscall(new NativeLong(number), operation, flags, address).longValue();
9395
}
96+
97+
@Override
98+
public int fallocate(int fd, int mode, long offset, long length) {
99+
return functions.fallocate(fd, mode, offset, length);
100+
}
94101
}

libs/native/jna/src/main/java/org/elasticsearch/nativeaccess/jna/JnaPosixCLibrary.java

Lines changed: 93 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,10 @@
99
package org.elasticsearch.nativeaccess.jna;
1010

1111
import com.sun.jna.Library;
12+
import com.sun.jna.Memory;
1213
import com.sun.jna.Native;
1314
import com.sun.jna.NativeLong;
15+
import com.sun.jna.Pointer;
1416
import com.sun.jna.Structure;
1517

1618
import org.elasticsearch.nativeaccess.lib.PosixCLibrary;
@@ -51,37 +53,58 @@ public void rlim_max(long v) {
5153
}
5254
}
5355

54-
public static class JnaFStore extends Structure implements Structure.ByReference, FStore {
56+
public static final class JnaStat64 implements Stat64 {
57+
final Memory memory;
58+
private final int stSizeOffset;
59+
private final int stBlocksOffset;
5560

56-
public int fst_flags = 0;
57-
public int fst_posmode = 0;
58-
public NativeLong fst_offset = new NativeLong(0);
59-
public NativeLong fst_length = new NativeLong(0);
60-
public NativeLong fst_bytesalloc = new NativeLong(0);
61+
JnaStat64(int sizeof, int stSizeOffset, int stBlocksOffset) {
62+
this.memory = new Memory(sizeof);
63+
this.stSizeOffset = stSizeOffset;
64+
this.stBlocksOffset = stBlocksOffset;
65+
}
66+
67+
@Override
68+
public long st_size() {
69+
return memory.getLong(stSizeOffset);
70+
}
71+
72+
@Override
73+
public long st_blocks() {
74+
return memory.getLong(stBlocksOffset);
75+
}
76+
}
77+
78+
public static class JnaFStore implements FStore {
79+
final Memory memory;
80+
81+
JnaFStore() {
82+
this.memory = new Memory(32);
83+
}
6184

6285
@Override
6386
public void set_flags(int flags) {
64-
this.fst_flags = flags;
87+
memory.setInt(0, flags);
6588
}
6689

6790
@Override
6891
public void set_posmode(int posmode) {
69-
this.fst_posmode = posmode;
92+
memory.setInt(4, posmode);
7093
}
7194

7295
@Override
7396
public void set_offset(long offset) {
74-
fst_offset.setValue(offset);
97+
memory.setLong(8, offset);
7598
}
7699

77100
@Override
78101
public void set_length(long length) {
79-
fst_length.setValue(length);
102+
memory.setLong(16, length);
80103
}
81104

82105
@Override
83106
public long bytesalloc() {
84-
return fst_bytesalloc.longValue();
107+
return memory.getLong(24);
85108
}
86109
}
87110

@@ -94,15 +117,40 @@ private interface NativeFunctions extends Library {
94117

95118
int mlockall(int flags);
96119

97-
int fcntl(int fd, int cmd, JnaFStore fst);
120+
int fcntl(int fd, int cmd, Pointer fst);
121+
122+
int ftruncate(int fd, NativeLong length);
123+
124+
int open(String filename, int flags, Object... mode);
125+
126+
int close(int fd);
98127

99128
String strerror(int errno);
100129
}
101130

131+
private interface FStat64Function extends Library {
132+
int fstat64(int fd, Pointer stat);
133+
}
134+
135+
private interface FXStatFunction extends Library {
136+
int __fxstat(int version, int fd, Pointer stat);
137+
}
138+
102139
private final NativeFunctions functions;
140+
private final FStat64Function fstat64;
103141

104142
JnaPosixCLibrary() {
105143
this.functions = Native.load("c", NativeFunctions.class);
144+
FStat64Function fstat64;
145+
try {
146+
fstat64 = Native.load("c", FStat64Function.class);
147+
} catch (UnsatisfiedLinkError e) {
148+
// TODO: explain
149+
var fxstat = Native.load("c", FXStatFunction.class);
150+
int version = System.getProperty("os.arch").equals("aarch64") ? 0 : 1;
151+
fstat64 = (fd, stat) -> fxstat.__fxstat(version, fd, stat);
152+
}
153+
this.fstat64 = fstat64;
106154
}
107155

108156
@Override
@@ -115,6 +163,11 @@ public RLimit newRLimit() {
115163
return new JnaRLimit();
116164
}
117165

166+
@Override
167+
public Stat64 newStat64(int sizeof, int stSizeOffset, int stBlocksOffset) {
168+
return new JnaStat64(sizeof, stSizeOffset, stBlocksOffset);
169+
}
170+
118171
@Override
119172
public int getrlimit(int resource, RLimit rlimit) {
120173
assert rlimit instanceof JnaRLimit;
@@ -143,7 +196,34 @@ public FStore newFStore() {
143196
public int fcntl(int fd, int cmd, FStore fst) {
144197
assert fst instanceof JnaFStore;
145198
var jnaFst = (JnaFStore) fst;
146-
return functions.fcntl(fd, cmd, jnaFst);
199+
return functions.fcntl(fd, cmd, jnaFst.memory);
200+
}
201+
202+
@Override
203+
public int ftruncate(int fd, long length) {
204+
return functions.ftruncate(fd, new NativeLong(length));
205+
}
206+
207+
@Override
208+
public int open(String pathname, int flags) {
209+
return functions.open(pathname, flags);
210+
}
211+
212+
@Override
213+
public int open(String pathname, int flags, int mode) {
214+
return functions.open(pathname, flags, mode);
215+
}
216+
217+
@Override
218+
public int close(int fd) {
219+
return functions.close(fd);
220+
}
221+
222+
@Override
223+
public int fstat64(int fd, Stat64 stats) {
224+
assert stats instanceof JnaStat64;
225+
var jnaStats = (JnaStat64) stats;
226+
return fstat64.fstat64(fd, jnaStats.memory);
147227
}
148228

149229
@Override

libs/native/src/main/java/module-info.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
to
2020
org.elasticsearch.nativeaccess.jna,
2121
org.elasticsearch.server,
22+
org.elasticsearch.blobcache,
2223
org.elasticsearch.simdvec,
2324
org.elasticsearch.systemd;
2425
// allows jna to implement a library provider, and ProviderLocator to load it

libs/native/src/main/java/org/elasticsearch/nativeaccess/LinuxNativeAccess.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818

1919
class LinuxNativeAccess extends PosixNativeAccess {
2020

21+
private static final int STATX_BLOCKS = 0x400; /* Want/got stx_blocks */
22+
2123
/** the preferred method is seccomp(2), since we can apply to all threads of the process */
2224
static final int SECCOMP_SET_MODE_FILTER = 1; // since Linux 3.17
2325
static final int SECCOMP_FILTER_FLAG_TSYNC = 1; // since Linux 3.17
@@ -88,7 +90,7 @@ record Arch(
8890
private final Systemd systemd;
8991

9092
LinuxNativeAccess(NativeLibraryProvider libraryProvider) {
91-
super("Linux", libraryProvider, new PosixConstants(-1L, 9, 1, 8));
93+
super("Linux", libraryProvider, new PosixConstants(-1L, 9, 1, 8, 64, 144, 48, 64));
9294
this.linuxLibc = libraryProvider.getLibrary(LinuxCLibrary.class);
9395
this.systemd = new Systemd(libraryProvider.getLibrary(SystemdLibrary.class));
9496
}
@@ -120,6 +122,16 @@ protected void logMemoryLimitInstructions() {
120122
logger.warn("If you are logged in interactively, you will have to re-login for the new limits to take effect.");
121123
}
122124

125+
@Override
126+
protected boolean nativePreallocate(int fd, long currentSize, long newSize) {
127+
final int rc = linuxLibc.fallocate(fd, 0, currentSize, newSize - currentSize);
128+
if (rc != 0) {
129+
logger.warn("fallocate failed: " + libc.strerror(libc.errno()));
130+
return false;
131+
}
132+
return true;
133+
}
134+
123135
/**
124136
* Installs exec system call filtering for Linux.
125137
* <p>

libs/native/src/main/java/org/elasticsearch/nativeaccess/MacNativeAccess.java

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,11 @@
2222

2323
class MacNativeAccess extends PosixNativeAccess {
2424

25+
private static final int F_PREALLOCATE = 42;
26+
private static final int F_ALLOCATECONTIG = 0x2; // allocate contiguous space
27+
private static final int F_ALLOCATEALL = 0x4; // allocate all the requested space or no space at all
28+
private static final int F_PEOFPOSMODE = 3; // allocate from the physical end of the file
29+
2530
/** The only supported flag... */
2631
static final int SANDBOX_NAMED = 1;
2732
/** Allow everything except process fork and execution */
@@ -30,7 +35,7 @@ class MacNativeAccess extends PosixNativeAccess {
3035
private final MacCLibrary macLibc;
3136

3237
MacNativeAccess(NativeLibraryProvider libraryProvider) {
33-
super("MacOS", libraryProvider, new PosixConstants(9223372036854775807L, 5, 1, 6));
38+
super("MacOS", libraryProvider, new PosixConstants(9223372036854775807L, 5, 1, 6, 512, 144, 96, 104));
3439
this.macLibc = libraryProvider.getLibrary(MacCLibrary.class);
3540
}
3641

@@ -44,6 +49,31 @@ protected void logMemoryLimitInstructions() {
4449
// we don't have instructions for macos
4550
}
4651

52+
@Override
53+
protected boolean nativePreallocate(int fd, long currentSize, long newSize) {
54+
var fst = libc.newFStore();
55+
fst.set_flags(F_ALLOCATECONTIG);
56+
fst.set_posmode(F_PEOFPOSMODE);
57+
fst.set_offset(0);
58+
fst.set_length(newSize);
59+
// first, try allocating contiguously
60+
if (libc.fcntl(fd, F_PREALLOCATE, fst) != 0) {
61+
// TODO: log warning?
62+
// that failed, so let us try allocating non-contiguously
63+
fst.set_flags(F_ALLOCATEALL);
64+
if (libc.fcntl(fd, F_PREALLOCATE, fst) != 0) {
65+
// i'm afraid captain dale had to bail
66+
logger.warn("Could not allocate non-contiguous size: " + libc.strerror(libc.errno()));
67+
return false;
68+
}
69+
}
70+
if (libc.ftruncate(fd, newSize) != 0) {
71+
logger.warn("Could not truncate file: " + libc.strerror(libc.errno()));
72+
return false;
73+
}
74+
return true;
75+
}
76+
4777
/**
4878
* Installs exec system call filtering on MacOS.
4979
* <p>

0 commit comments

Comments
 (0)