< prev index next >

src/java.base/unix/native/libnio/ch/FileDispatcherImpl.c

Print this page




  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 


< prev index next >