From 8e0a4a03c0a7923057eeb2b8b2ac16338fc87e76 Mon Sep 17 00:00:00 2001 From: Raymond Lu Date: Mon, 6 Nov 2006 17:17:46 -0500 Subject: [svn-r12870] Add a new macro H5_HAVE_DIRECT_ALIGN in configure.in. Some systems like copper and sleipnir doesn't require alignment for Direct I/O. If this's true, write or read data just like sec2 does. --- configure | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++++ configure.in | 42 ++++++++++++++++++++++++++- src/H5FDdirect.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++++++---- src/H5config.h.in | 3 ++ test/h5test.c | 2 +- test/vfd.c | 6 ++++ 6 files changed, 215 insertions(+), 7 deletions(-) diff --git a/configure b/configure index d4377b5..91c8792 100755 --- a/configure +++ b/configure @@ -51071,6 +51071,89 @@ else fi + +if test ${hdf5_direct_io} = "yes"; then + echo "$as_me:$LINENO: checking for Direct VFD alignment requirement" >&5 +echo $ECHO_N "checking for Direct VFD alignment requirement... $ECHO_C" >&6 + + if test "${hdf5_direct_align+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "$cross_compiling" = yes; then + { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot run test program while cross compiling +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + #include + #include + #include + #include + int main(void) + { + int *buf; + int fid; + fid=open("tst_file", O_CREAT | O_TRUNC | O_DIRECT | O_RDWR, 0755); + buf = (int*)malloc(sizeof(int)); + if(write(fid, (void*)buf, sizeof(int))<0) { + close(fid); + free(buf); + remove("tst_file"); + exit(1); + } + close(fid); + remove("tst_file"); + free(buf); + exit (0); + } +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + hdf5_direct_align=no +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +hdf5_direct_align=yes +fi +rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi +fi + + + if test ${hdf5_direct_align} = "yes"; then + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + +cat >>confdefs.h <<\_ACEOF +#define HAVE_DIRECT_ALIGN 1 +_ACEOF + + else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + fi +fi + echo "$as_me:$LINENO: checking whether exception handling functions is checked during data conversions" >&5 echo $ECHO_N "checking whether exception handling functions is checked during data conversions... $ECHO_C" >&6 # Check whether --enable-dconv-exception or --disable-dconv-exception was given. diff --git a/configure.in b/configure.in index fa13ecd..ff618c7 100644 --- a/configure.in +++ b/configure.in @@ -2572,7 +2572,7 @@ if test "$STREAM_VFD" = "yes"; then fi dnl ---------------------------------------------------------------------- -dnl Check if Direct I/O driver is wanted by --enable-direct-vfd +dnl Check if Direct I/O driver is enabled by --enable-direct-vfd dnl AC_MSG_CHECKING([for Direct Virtual File Driver support]) @@ -2612,6 +2612,46 @@ else fi AM_CONDITIONAL([DIRECT_VFD_CONDITIONAL], [test "X$DIRECT_VFD" = "Xyes"]) + +dnl ---------------------------------------------------------------------- +dnl Check if Direct I/O driver requires alignment. +dnl + +if test ${hdf5_direct_io} = "yes"; then + AC_MSG_CHECKING([for Direct VFD alignment requirement]) + + AC_CACHE_VAL([hdf5_direct_align], + [AC_TRY_RUN([ + #include + #include + #include + #include + int main(void) + { + int *buf; + int fid; + fid=open("tst_file", O_CREAT | O_TRUNC | O_DIRECT | O_RDWR, 0755); + buf = (int*)malloc(sizeof(int)); + if(write(fid, (void*)buf, sizeof(int))<0) { + close(fid); + free(buf); + remove("tst_file"); + exit(1); + } + close(fid); + remove("tst_file"); + free(buf); + exit (0); + }], [hdf5_direct_align=no], [hdf5_direct_align=yes],)]) + + if test ${hdf5_direct_align} = "yes"; then + AC_MSG_RESULT([yes]) + AC_DEFINE([HAVE_DIRECT_ALIGN], [1], + [Define if the direct I/O VFD requires alignment]) + else + AC_MSG_RESULT([no]) + fi +fi dnl ---------------------------------------------------------------------- dnl Decide whether the presence of user's exception handling functions is diff --git a/src/H5FDdirect.c b/src/H5FDdirect.c index 8a6a27a..89bf099 100644 --- a/src/H5FDdirect.c +++ b/src/H5FDdirect.c @@ -861,6 +861,8 @@ H5FD_direct_read(H5FD_t *_file, H5FD_mem_t UNUSED type, hid_t UNUSED dxpl_id, ha { H5FD_direct_t *file = (H5FD_direct_t*)_file; ssize_t nbytes; + herr_t ret_value=SUCCEED; /* Return value */ +#ifdef H5_HAVE_DIRECT_ALIGN size_t alloc_size; void *copy_buf, *p2, *p3; size_t _boundary; @@ -868,7 +870,7 @@ H5FD_direct_read(H5FD_t *_file, H5FD_mem_t UNUSED type, hid_t UNUSED dxpl_id, ha size_t _cbsize; haddr_t copy_addr = addr; size_t copy_size = size; - herr_t ret_value=SUCCEED; /* Return value */ +#endif /*H5_HAVE_DIRECT_ALIGN*/ FUNC_ENTER_NOAPI(H5FD_direct_read, FAIL) @@ -883,6 +885,7 @@ H5FD_direct_read(H5FD_t *_file, H5FD_mem_t UNUSED type, hid_t UNUSED dxpl_id, ha if (addr+size>file->eoa) HGOTO_ERROR(H5E_ARGS, H5E_OVERFLOW, FAIL, "addr overflow") +#ifdef H5_HAVE_DIRECT_ALIGN /* If the system requires data to be aligned */ /* Get the memory boundary for alignment, file system block size, and maximal * copy buffer size. */ @@ -928,7 +931,7 @@ H5FD_direct_read(H5FD_t *_file, H5FD_mem_t UNUSED type, hid_t UNUSED dxpl_id, ha else alloc_size = _cbsize; if (HDposix_memalign(©_buf, _boundary, alloc_size) != 0) - HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "posix_memalign failed") + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "HDposix_memalign failed") /* look for the aligned position for reading the data */ if(file_seek(file->fd, (file_offset_t)(copy_addr - copy_addr % _fbsize), SEEK_SET) < 0) @@ -985,6 +988,42 @@ H5FD_direct_read(H5FD_t *_file, H5FD_mem_t UNUSED type, hid_t UNUSED dxpl_id, ha HDfree(copy_buf); } +#else /*H5_HAVE_DIRECT_ALIGN*/ + /* If the system doesn't require data to be aligned, read the data in + * the same way as sec2 driver. + */ + + /* Seek to the correct location */ + if ((addr!=file->pos || OP_READ!=file->op) && + file_seek(file->fd, (file_offset_t)addr, SEEK_SET)<0) + HSYS_GOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "unable to seek to proper position") + + /* + * Read data, being careful of interrupted system calls, partial results, + * and the end of the file. + */ + while (size>0) { + do { + nbytes = HDread(file->fd, buf, size); + } while (-1==nbytes && EINTR==errno); + if (-1==nbytes) /* error */ + HSYS_GOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "file read failed") + if (0==nbytes) { + /* end of file but not end of format address space */ + HDmemset(buf, 0, size); + break; + } + assert(nbytes>=0); + assert((size_t)nbytes<=size); + H5_CHECK_OVERFLOW(nbytes,ssize_t,size_t); + size -= (size_t)nbytes; + H5_CHECK_OVERFLOW(nbytes,ssize_t,haddr_t); + addr += (haddr_t)nbytes; + buf = (char*)buf + nbytes; + } + +#endif /*H5_HAVE_DIRECT_ALIGN*/ + /* Update current position */ file->pos = addr; file->op = OP_READ; @@ -1024,6 +1063,8 @@ H5FD_direct_write(H5FD_t *_file, H5FD_mem_t UNUSED type, hid_t UNUSED dxpl_id, h { H5FD_direct_t *file = (H5FD_direct_t*)_file; ssize_t nbytes; + herr_t ret_value=SUCCEED; /* Return value */ +#ifdef H5_HAVE_DIRECT_ALIGN size_t alloc_size; void *copy_buf, *p1, *p3; size_t _boundary; @@ -1031,7 +1072,7 @@ H5FD_direct_write(H5FD_t *_file, H5FD_mem_t UNUSED type, hid_t UNUSED dxpl_id, h size_t _cbsize; haddr_t copy_addr = addr; size_t copy_size = size; - herr_t ret_value=SUCCEED; /* Return value */ +#endif /*H5_HAVE_DIRECT_ALIGN*/ FUNC_ENTER_NOAPI(H5FD_direct_write, FAIL) @@ -1046,6 +1087,7 @@ H5FD_direct_write(H5FD_t *_file, H5FD_mem_t UNUSED type, hid_t UNUSED dxpl_id, h if (addr+size>file->eoa) HGOTO_ERROR(H5E_ARGS, H5E_OVERFLOW, FAIL, "addr overflow") +#ifdef H5_HAVE_DIRECT_ALIGN /* If the system requires data to be aligned */ /* Get the memory boundary for alignment, file system block size, and maximal * copy buffer size. */ @@ -1088,7 +1130,7 @@ H5FD_direct_write(H5FD_t *_file, H5FD_mem_t UNUSED type, hid_t UNUSED dxpl_id, h alloc_size = _cbsize; if (HDposix_memalign(©_buf, _boundary, alloc_size) != 0) - HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "posix_memalign failed") + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "HDposix_memalign failed") /* look for the right position for reading the data */ if(file_seek(file->fd, (file_offset_t)(copy_addr - copy_addr % _fbsize), SEEK_SET) < 0) @@ -1162,6 +1204,37 @@ H5FD_direct_write(H5FD_t *_file, H5FD_mem_t UNUSED type, hid_t UNUSED dxpl_id, h HDfree(copy_buf); } +#else /*H5_HAVE_DIRECT_ALIGN*/ + /* If the system doesn't require data to be aligned, write the data in + * the same way as sec2 driver. + */ + + /* Seek to the correct location */ + if ((addr!=file->pos || OP_WRITE!=file->op) && + file_seek(file->fd, (file_offset_t)addr, SEEK_SET)<0) + HSYS_GOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "unable to seek to proper position") + + /* + * Write the data, being careful of interrupted system calls and partial + * results + */ + while (size>0) { + do { + nbytes = HDwrite(file->fd, buf, size); + } while (-1==nbytes && EINTR==errno); + if (-1==nbytes) /* error */ + HSYS_GOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "file write failed") + assert(nbytes>0); + assert((size_t)nbytes<=size); + H5_CHECK_OVERFLOW(nbytes,ssize_t,size_t); + size -= (size_t)nbytes; + H5_CHECK_OVERFLOW(nbytes,ssize_t,haddr_t); + addr += (haddr_t)nbytes; + buf = (const char*)buf + nbytes; + } + +#endif /*H5_HAVE_DIRECT_ALIGN*/ + /* Update current position and eof */ file->pos = addr; file->op = OP_WRITE; @@ -1232,13 +1305,16 @@ H5FD_direct_flush(H5FD_t *_file, hid_t UNUSED dxpl_id, unsigned UNUSED closing) /* Reset last file I/O information */ file->pos = HADDR_UNDEF; file->op = OP_UNKNOWN; - } else { + } +#ifdef H5_HAVE_DIRECT_ALIGN + else { /*Even though eof is equal to eoa, file is still truncated because Direct I/O *write introduces some extra data for alignment. */ if (-1==file_truncate(file->fd, (file_offset_t)file->eof)) HSYS_GOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "unable to extend file properly") } +#endif /*H5_HAVE_DIRECT_ALIGN*/ done: FUNC_LEAVE_NOAPI(ret_value) diff --git a/src/H5config.h.in b/src/H5config.h.in index 0853964..998a616 100644 --- a/src/H5config.h.in +++ b/src/H5config.h.in @@ -57,6 +57,9 @@ /* Define if the direct I/O virtual file driver should be compiled */ #undef HAVE_DIRECT +/* Define if the direct I/O VFD requires alignment */ +#undef HAVE_DIRECT_ALIGN + /* Define to 1 if you have the header file. */ #undef HAVE_DLFCN_H diff --git a/test/h5test.c b/test/h5test.c index 840e126..93f992e 100644 --- a/test/h5test.c +++ b/test/h5test.c @@ -581,7 +581,7 @@ h5_fileaccess(void) #ifdef H5_HAVE_DIRECT /* Linux direct read() and write() system calls. Set memory boundary, file block size, * and copy buffer size to the default values. */ - if (H5Pset_fapl_direct(fapl, 1024, 4096, 7*4096)<0) return -1; + if (H5Pset_fapl_direct(fapl, 1024, 4096, 8*4096)<0) return -1; #endif } else { /* Unknown driver */ diff --git a/test/vfd.c b/test/vfd.c index fdd710d..c8b67f7 100644 --- a/test/vfd.c +++ b/test/vfd.c @@ -214,6 +214,7 @@ test_direct(void) if(file_size<1*KB || file_size>4*KB) TEST_ERROR; +#ifdef H5_HAVE_DIRECT_ALIGN /* Allocate aligned memory for data set 1. For data set 1, everything is aligned including * memory address, size of data, and file address. */ if(posix_memalign(&points, (size_t)FBSIZE, (size_t)(DSET1_DIM1*DSET1_DIM2*sizeof(int)))!=0) @@ -221,6 +222,11 @@ test_direct(void) if(posix_memalign(&check, (size_t)FBSIZE, (size_t)(DSET1_DIM1*DSET1_DIM2*sizeof(int)))!=0) TEST_ERROR; +#else + /* Allocate aligned memory for data set 1. No need for alignment. */ + points=(int*)malloc(DSET1_DIM1*DSET1_DIM2*sizeof(int)); + check=(int*)malloc(DSET1_DIM1*DSET1_DIM2*sizeof(int)); +#endif /* Initialize the dset1 */ p1 = points; -- cgit v0.12