17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 #include "jni.h"
27 #include "jni_util.h"
28 #include "jvm.h"
29 #include "jlong.h"
30 #include "sun_nio_ch_FileDispatcherImpl.h"
31 #include "java_lang_Long.h"
32 #include <sys/types.h>
33 #include <sys/socket.h>
34 #include <fcntl.h>
35 #include <sys/uio.h>
36 #include <unistd.h>
37 #if defined(__linux__)
38 #include <linux/fs.h>
39 #include <sys/ioctl.h>
40 #endif
41 #include "nio.h"
42 #include "nio_util.h"
43
44 #ifdef _ALLBSD_SOURCE
45 #define stat64 stat
46 #define flock64 flock
47 #define off64_t off_t
48 #define F_SETLKW64 F_SETLKW
49 #define F_SETLK64 F_SETLK
50
51 #define pread64 pread
52 #define pwrite64 pwrite
53 #define ftruncate64 ftruncate
54 #define fstat64 fstat
55
56 #define fdatasync fsync
57 #endif
58
59 static int preCloseFD = -1; /* File descriptor to which we dup other fd's
60 before closing them for real */
61
62
63 JNIEXPORT void JNICALL
64 Java_sun_nio_ch_FileDispatcherImpl_init(JNIEnv *env, jclass cl)
65 {
66 int sp[2];
67 if (socketpair(PF_UNIX, SOCK_STREAM, 0, sp) < 0) {
68 JNU_ThrowIOExceptionWithLastError(env, "socketpair failed");
69 return;
70 }
71 preCloseFD = sp[0];
72 close(sp[1]);
73 }
74
75 JNIEXPORT jint JNICALL
76 Java_sun_nio_ch_FileDispatcherImpl_read0(JNIEnv *env, jclass clazz,
77 jobject fdo, jlong address, jint len)
78 {
79 jint fd = fdval(env, fdo);
80 void *buf = (void *)jlong_to_ptr(address);
81
82 return convertReturnVal(env, read(fd, buf, len), JNI_TRUE);
83 }
84
85 JNIEXPORT jint JNICALL
86 Java_sun_nio_ch_FileDispatcherImpl_pread0(JNIEnv *env, jclass clazz, jobject fdo,
87 jlong address, jint len, jlong offset)
88 {
89 jint fd = fdval(env, fdo);
90 void *buf = (void *)jlong_to_ptr(address);
91
92 return convertReturnVal(env, pread64(fd, buf, len, offset), JNI_TRUE);
93 }
94
95 JNIEXPORT jlong JNICALL
96 Java_sun_nio_ch_FileDispatcherImpl_readv0(JNIEnv *env, jclass clazz,
97 jobject fdo, jlong address, jint len)
98 {
99 jint fd = fdval(env, fdo);
100 struct iovec *iov = (struct iovec *)jlong_to_ptr(address);
101 return convertLongReturnVal(env, readv(fd, iov, len), JNI_TRUE);
102 }
103
104 JNIEXPORT jint JNICALL
105 Java_sun_nio_ch_FileDispatcherImpl_write0(JNIEnv *env, jclass clazz,
106 jobject fdo, jlong address, jint len)
107 {
108 jint fd = fdval(env, fdo);
109 void *buf = (void *)jlong_to_ptr(address);
110
111 return convertReturnVal(env, write(fd, buf, len), JNI_FALSE);
112 }
113
114 JNIEXPORT jint JNICALL
115 Java_sun_nio_ch_FileDispatcherImpl_pwrite0(JNIEnv *env, jclass clazz, jobject fdo,
116 jlong address, jint len, jlong offset)
117 {
118 jint fd = fdval(env, fdo);
119 void *buf = (void *)jlong_to_ptr(address);
120
121 return convertReturnVal(env, pwrite64(fd, buf, len, offset), JNI_FALSE);
122 }
123
124 JNIEXPORT jlong JNICALL
125 Java_sun_nio_ch_FileDispatcherImpl_writev0(JNIEnv *env, jclass clazz,
126 jobject fdo, jlong address, jint len)
127 {
128 jint fd = fdval(env, fdo);
129 struct iovec *iov = (struct iovec *)jlong_to_ptr(address);
130 return convertLongReturnVal(env, writev(fd, iov, len), JNI_FALSE);
131 }
132
133 static jlong
134 handle(JNIEnv *env, jlong rv, char *msg)
135 {
136 if (rv >= 0)
137 return rv;
138 if (errno == EINTR)
139 return IOS_INTERRUPTED;
140 JNU_ThrowIOExceptionWithLastError(env, msg);
141 return IOS_THROWN;
142 }
143
144 JNIEXPORT jint JNICALL
145 Java_sun_nio_ch_FileDispatcherImpl_force0(JNIEnv *env, jobject this,
146 jobject fdo, jboolean md)
147 {
148 jint fd = fdval(env, fdo);
149 int result = 0;
150
|
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 #include "jni.h"
27 #include "jni_util.h"
28 #include "jvm.h"
29 #include "jlong.h"
30 #include "sun_nio_ch_FileDispatcherImpl.h"
31 #include "java_lang_Long.h"
32 #include <sys/types.h>
33 #include <sys/socket.h>
34 #include <fcntl.h>
35 #include <sys/uio.h>
36 #include <unistd.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #if defined(__linux__)
40 #include <linux/fs.h>
41 #include <sys/ioctl.h>
42 #endif
43 #include "nio.h"
44 #include "nio_util.h"
45
46 #ifdef _ALLBSD_SOURCE
47 #define stat64 stat
48 #define flock64 flock
49 #define off64_t off_t
50 #define F_SETLKW64 F_SETLKW
51 #define F_SETLK64 F_SETLK
52
53 #define pread64 pread
54 #define pwrite64 pwrite
55 #define ftruncate64 ftruncate
56 #define fstat64 fstat
57
58 #define fdatasync fsync
59 #endif
60
61 static int preCloseFD = -1; /* File descriptor to which we dup other fd's
62 before closing them for real */
63 static int pageSize = -1;
64
65 JNIEXPORT void JNICALL
66 Java_sun_nio_ch_FileDispatcherImpl_init(JNIEnv *env, jclass cl)
67 {
68 int sp[2];
69 if (socketpair(PF_UNIX, SOCK_STREAM, 0, sp) < 0) {
70 JNU_ThrowIOExceptionWithLastError(env, "socketpair failed");
71 return;
72 }
73 preCloseFD = sp[0];
74 close(sp[1]);
75
76 pageSize = getpagesize();
77 }
78
79 jint readDirect(JNIEnv *env, jclass clazz, jint fd, jlong offset, jint len, void *buf, jint pageSize)
80 {
81 int gap = 0;
82 int newLen = -1;
83 long newStartLocation = -1;
84 void *bytes = NULL;
85 int nread = -1;
86
87 newStartLocation = offset;
88 if ((newStartLocation % pageSize) != 0) {
89 newStartLocation = offset / pageSize * pageSize;
90 gap = offset - newStartLocation;
91 }
92
93 lseek(fd, newStartLocation, SEEK_SET);
94
95 newLen = len;
96 if ((newLen % pageSize) != 0) {
97 newLen = (len / pageSize + 1) * pageSize;
98 }
99
100 if ((newLen - gap) < len) {
101 newLen = newLen + pageSize;
102 }
103
104 posix_memalign(&bytes, pageSize, newLen);
105
106 nread = read(fd, bytes, newLen);
107
108 if (nread > gap) {
109 if ((nread - gap) >= len) {
110 memcpy(buf, bytes+gap, len);
111 nread = len;
112 } else {
113 memcpy(buf, bytes+gap, (nread-gap));
114 nread = nread - gap;
115 }
116 } else if (nread == -1) {
117 JNU_ThrowIOExceptionWithLastError(env, "Read error");
118 } else { /*EOF*/
119 nread = 0;
120 }
121
122 free(bytes);
123
124 return nread;
125 }
126
127 jint writeDirect(JNIEnv *env, jclass clazz, jint fd, jlong offset, jint len, void *buf, jint pageSize)
128 {
129 void *bytes = NULL;
130 int nwrite = -1;
131 posix_memalign(&bytes, pageSize, len);
132 memcpy(bytes, buf, len);
133
134 lseek(fd, offset, SEEK_SET);
135
136 nwrite = write(fd, bytes, len);
137 if (nwrite == -1) {
138 JNU_ThrowIOExceptionWithLastError(env, "Write error");
139 }
140
141 free(bytes);
142
143 return nwrite;
144 }
145
146 JNIEXPORT jint JNICALL
147 Java_sun_nio_ch_FileDispatcherImpl_read0(JNIEnv *env, jclass clazz,
148 jobject fdo, jlong address, jint len)
149 {
150 jint fd = fdval(env, fdo);
151 void *buf = (void *)jlong_to_ptr(address);
152
153 return convertReturnVal(env, read(fd, buf, len), JNI_TRUE);
154 }
155
156 JNIEXPORT jint JNICALL
157 Java_sun_nio_ch_FileDispatcherImpl_readDirect0(JNIEnv *env, jclass clazz,
158 jobject fdo, jlong address, jint len)
159 {
160 jint fd = fdval(env, fdo);
161 void *buf = (void *)jlong_to_ptr(address);
162 long currentLocation = lseek(fd, 0, SEEK_CUR);
163
164 if (currentLocation % pageSize == 0 && len % pageSize == 0 && address % pageSize == 0) {
165 return convertReturnVal(env, read(fd, buf, len), JNI_TRUE);
166 }
167
168 int nread = readDirect(env, clazz, fd, currentLocation, len, buf, pageSize);
169 lseek(fd, (currentLocation + nread), SEEK_SET);
170 return convertReturnVal(env, nread, JNI_TRUE);
171 }
172
173 JNIEXPORT jint JNICALL
174 Java_sun_nio_ch_FileDispatcherImpl_pread0(JNIEnv *env, jclass clazz, jobject fdo,
175 jlong address, jint len, jlong offset)
176 {
177 jint fd = fdval(env, fdo);
178 void *buf = (void *)jlong_to_ptr(address);
179
180 return convertReturnVal(env, pread64(fd, buf, len, offset), JNI_TRUE);
181 }
182
183 JNIEXPORT jint JNICALL
184 Java_sun_nio_ch_FileDispatcherImpl_preadDirect0(JNIEnv *env, jclass clazz, jobject fdo,
185 jlong address, jint len, jlong offset)
186 {
187 jint fd = fdval(env, fdo);
188 void *buf = (void *)jlong_to_ptr(address);
189
190 long currentLocation = lseek(fd, 0, SEEK_CUR);
191
192 if (offset % pageSize == 0 && len % pageSize == 0 && address % pageSize == 0) {
193 return convertReturnVal(env, pread64(fd, buf, len, offset), JNI_TRUE);
194 }
195
196 int nread = readDirect(env, clazz, fd, offset, len, buf, pageSize);
197 lseek(fd, currentLocation, SEEK_SET);
198 return convertReturnVal(env, nread, JNI_TRUE);
199 }
200
201 JNIEXPORT jlong JNICALL
202 Java_sun_nio_ch_FileDispatcherImpl_readv0(JNIEnv *env, jclass clazz,
203 jobject fdo, jlong address, jint len)
204 {
205 jint fd = fdval(env, fdo);
206 struct iovec *iov = (struct iovec *)jlong_to_ptr(address);
207
208 return convertLongReturnVal(env, readv(fd, iov, len), JNI_TRUE);
209 }
210
211 JNIEXPORT jlong JNICALL
212 Java_sun_nio_ch_FileDispatcherImpl_readvDirect0(JNIEnv *env, jclass clazz,
213 jobject fdo, jlong address, jint len)
214 {
215 int i;
216 int totalLen = 0;
217 int newLen = 0;
218 int gap = 0;
219 int nread = 0;
220 int result = 0;
221 void *bytes = NULL;
222 long currentLocation = -1;
223 long newStartLocation = -1;
224
225 jint fd = fdval(env, fdo);
226 struct iovec *iov = (struct iovec *)jlong_to_ptr(address);
227
228 currentLocation = lseek(fd, 0, SEEK_CUR);
229 newStartLocation = currentLocation;
230 if ((newStartLocation % pageSize) != 0) {
231 newStartLocation = currentLocation / pageSize * pageSize;
232 gap = currentLocation - newStartLocation;
233 }
234
235 lseek(fd, newStartLocation, SEEK_SET);
236
237 for (i = 0; i < len; i++) {
238 totalLen += iov[i].iov_len;
239 }
240
241 newLen = totalLen;
242 if ((newLen % pageSize) != 0) {
243 newLen = (totalLen / pageSize + 1) * pageSize;
244 }
245
246 if ((newLen - gap) < totalLen) {
247 newLen += pageSize;
248 }
249
250 posix_memalign(&bytes, pageSize, newLen);
251 nread = read(fd, bytes, newLen);
252
253 if (nread > gap) {
254 if ((nread - gap) >= totalLen) {
255 nread = totalLen;
256 } else {
257 nread -= gap;
258 }
259 } else if (nread == -1) {
260 JNU_ThrowIOExceptionWithLastError(env, "Read error");
261 } else { /*EOF*/
262 nread = 0;
263 }
264
265 i = 0;
266 int tempLen;
267 while (nread > 0) {
268 tempLen = iov[i].iov_len;
269 if (nread >= tempLen) {
270 memcpy(iov[i].iov_base, (bytes + gap + result), tempLen);
271 result += tempLen;
272 nread -= tempLen;
273 } else {
274 memcpy(iov[i].iov_base, (bytes + gap + result), nread);
275 result += nread;
276 nread = 0;
277 }
278 i++;
279 }
280
281 free(bytes);
282
283 lseek(fd, (currentLocation + result), SEEK_SET);
284
285 return convertLongReturnVal(env, result, JNI_TRUE);
286 }
287
288 JNIEXPORT jint JNICALL
289 Java_sun_nio_ch_FileDispatcherImpl_write0(JNIEnv *env, jclass clazz,
290 jobject fdo, jlong address, jint len)
291 {
292 jint fd = fdval(env, fdo);
293 void *buf = (void *)jlong_to_ptr(address);
294
295 return convertReturnVal(env, write(fd, buf, len), JNI_FALSE);
296 }
297
298 JNIEXPORT jint JNICALL
299 Java_sun_nio_ch_FileDispatcherImpl_writeDirect0(JNIEnv *env, jclass clazz,
300 jobject fdo, jlong address, jint len)
301 {
302 jint fd = fdval(env, fdo);
303 void *buf = (void *)jlong_to_ptr(address);
304
305 long currentLocation = lseek(fd, 0, SEEK_CUR);
306
307 if ((len % pageSize != 0) || (currentLocation % pageSize != 0)) {
308 JNU_ThrowByNameWithMessageAndLastError(env, "java/io/IOException",
309 "In DirectIO mode, the IO size and currentLocation must be aligned with kernel page size");
310 }
311
312 if (address % pageSize == 0) {
313 return convertReturnVal(env, write(fd, buf, len), JNI_FALSE);
314 }
315
316 int nwrite = writeDirect(env, clazz, fd, currentLocation, len, buf, pageSize);
317
318 lseek(fd, (currentLocation + nwrite), SEEK_SET);
319
320 return convertReturnVal(env, nwrite, JNI_FALSE);
321 }
322
323 JNIEXPORT jint JNICALL
324 Java_sun_nio_ch_FileDispatcherImpl_pwrite0(JNIEnv *env, jclass clazz, jobject fdo,
325 jlong address, jint len, jlong offset)
326 {
327 jint fd = fdval(env, fdo);
328 void *buf = (void *)jlong_to_ptr(address);
329
330 return convertReturnVal(env, pwrite64(fd, buf, len, offset), JNI_FALSE);
331 }
332
333 JNIEXPORT jint JNICALL
334 Java_sun_nio_ch_FileDispatcherImpl_pwriteDirect0(JNIEnv *env, jclass clazz, jobject fdo,
335 jlong address, jint len, jlong offset)
336 {
337 jint fd = fdval(env, fdo);
338 void *buf = (void *)jlong_to_ptr(address);
339
340 if ((len % pageSize != 0) || (offset % pageSize != 0)) {
341 JNU_ThrowByNameWithMessageAndLastError(env, "java/io/IOException",
342 "In DirectIO mode, the IO size and offset must be aligned with kernel page size");
343 }
344
345 if (address % pageSize == 0) {
346 return convertReturnVal(env, pwrite64(fd, buf, len, offset), JNI_FALSE);
347 }
348
349 long currentLocation = lseek(fd, 0, SEEK_CUR);
350
351 int nwrite = writeDirect(env, clazz, fd, offset, len, buf, pageSize);
352
353 lseek(fd, currentLocation, SEEK_SET);
354
355 return convertReturnVal(env, nwrite, JNI_FALSE);
356 }
357
358 JNIEXPORT jlong JNICALL
359 Java_sun_nio_ch_FileDispatcherImpl_writev0(JNIEnv *env, jclass clazz,
360 jobject fdo, jlong address, jint len)
361 {
362 jint fd = fdval(env, fdo);
363 struct iovec *iov = (struct iovec *)jlong_to_ptr(address);
364
365 return convertLongReturnVal(env, writev(fd, iov, len), JNI_FALSE);
366 }
367
368 JNIEXPORT jlong JNICALL
369 Java_sun_nio_ch_FileDispatcherImpl_writevDirect0(JNIEnv *env, jclass clazz,
370 jobject fdo, jlong address, jint len)
371 {
372 int i;
373 int totalLen = 0;
374 int currentLocation = -1;
375 int nwrite = 0;
376 int result = 0;
377 void *bytes = NULL;
378
379 jint fd = fdval(env, fdo);
380 struct iovec *iov = (struct iovec *)jlong_to_ptr(address);
381
382 for (i = 0; i < len; i++) {
383 totalLen += iov[i].iov_len;
384 }
385
386 currentLocation = lseek(fd, 0, SEEK_CUR);
387
388 if ((totalLen % pageSize != 0) || (currentLocation % pageSize != 0)) {
389 JNU_ThrowByNameWithMessageAndLastError(env, "java/io/IOException",
390 "In DirectIO mode, the IO size and offset must be aligned with kernel page size");
391 }
392
393 posix_memalign(&bytes, pageSize, totalLen);
394
395 int tempLen;
396 for (i = 0; i < len; i++) {
397 tempLen = iov[i].iov_len;
398 memcpy((bytes + result), iov[i].iov_base, tempLen);
399 result += tempLen;
400 }
401 nwrite = write(fd, bytes, totalLen);
402 if (nwrite == -1) {
403 JNU_ThrowIOExceptionWithLastError(env, "Write error");
404 }
405
406 free(bytes);
407
408 return convertLongReturnVal(env, nwrite, JNI_FALSE);
409
410 }
411
412 static jlong
413 handle(JNIEnv *env, jlong rv, char *msg)
414 {
415 if (rv >= 0)
416 return rv;
417 if (errno == EINTR)
418 return IOS_INTERRUPTED;
419 JNU_ThrowIOExceptionWithLastError(env, msg);
420 return IOS_THROWN;
421 }
422
423 JNIEXPORT jint JNICALL
424 Java_sun_nio_ch_FileDispatcherImpl_force0(JNIEnv *env, jobject this,
425 jobject fdo, jboolean md)
426 {
427 jint fd = fdval(env, fdo);
428 int result = 0;
429
|