diff options
-rw-r--r-- | Changes | 2 | ||||
-rw-r--r-- | ecb.h | 4 | ||||
-rw-r--r-- | eio.c | 50 | ||||
-rw-r--r-- | eio.h | 3 | ||||
-rw-r--r-- | eio.pod | 7 | ||||
-rw-r--r-- | libeio.m4 | 12 |
6 files changed, 63 insertions, 15 deletions
@@ -56,4 +56,6 @@ TODO: fadvise request - cancelled requests will still invoke their request callbacks. - add fallocate. - do not acquire any locks when forking. + - incorporated some mingw32 changes by traviscline. + - added syncfs support, using direct syscall. @@ -68,7 +68,7 @@ #ifndef ECB_MEMORY_FENCE #if ECB_GCC_VERSION(2,5) #if __x86 - #define ECB_MEMORY_FENCE __asm__ __volatile__ ("lock; or.b $0, -1(%%esp)" : : : "memory") + #define ECB_MEMORY_FENCE __asm__ __volatile__ ("lock; orb $0, -1(%%esp)" : : : "memory") #define ECB_MEMORY_FENCE_ACQUIRE ECB_MEMORY_FENCE #define ECB_MEMORY_FENCE_RELEASE ECB_MEMORY_FENCE /* better be safe than sorry */ #elif __amd64 @@ -84,7 +84,7 @@ #define ECB_MEMORY_FENCE __sync_synchronize () #define ECB_MEMORY_FENCE_ACQUIRE ({ char dummy = 0; __sync_lock_test_and_set (&dummy, 1); }) #define ECB_MEMORY_FENCE_RELEASE ({ char dummy = 1; __sync_lock_release (&dummy ); }) - #elif _MSC_VER >= 1400 + #elif _MSC_VER >= 1400 && 0 /* TODO: only true when using volatiles */ #define ECB_MEMORY_FENCE do { } while (0) #define ECB_MEMORY_FENCE_ACQUIRE ECB_MEMORY_FENCE #define ECB_MEMORY_FENCE_RELEASE ECB_MEMORY_FENCE @@ -218,6 +218,10 @@ static void eio_destroy (eio_req *req); # endif #endif +#if HAVE_SYS_SYSCALL_H +# include <sys/syscall.h> +#endif + #ifndef D_TYPE # define D_TYPE(de) 0 #endif @@ -939,6 +943,24 @@ eio__futimes (int fd, const struct timeval tv[2]) # define fdatasync(fd) fsync (fd) #endif +static int +eio__syncfs (int fd) +{ + int res; + +#if HAVE_SYS_SYNCFS + res = (int)syscall (__NR_syncfs, (int)(fd)); +#else + res = -1; + errno = ENOSYS; +#endif + + if (res < 0 && errno == ENOSYS && fd >= 0) + sync (); + + return res; +} + /* sync_file_range always needs emulation */ static int eio__sync_file_range (int fd, off_t offset, size_t nbytes, unsigned int flags) @@ -2069,11 +2091,12 @@ eio_execute (etp_worker *self, eio_req *req) case EIO_SYNC: req->result = 0; sync (); break; case EIO_FSYNC: req->result = fsync (req->int1); break; case EIO_FDATASYNC: req->result = fdatasync (req->int1); break; + case EIO_SYNCFS: req->result = eio__syncfs (req->int1); break; + case EIO_SYNC_FILE_RANGE: req->result = eio__sync_file_range (req->int1, req->offs, req->size, req->int2); break; case EIO_MSYNC: req->result = eio__msync (req->ptr2, req->size, req->int1); break; case EIO_MTOUCH: req->result = eio__mtouch (req); break; case EIO_MLOCK: req->result = eio__mlock (req->ptr2, req->size); break; case EIO_MLOCKALL: req->result = eio__mlockall (req->int1); break; - case EIO_SYNC_FILE_RANGE: req->result = eio__sync_file_range (req->int1, req->offs, req->size, req->int2); break; case EIO_FALLOCATE: req->result = eio__fallocate (req->int1, req->int2, req->offs, req->size); break; case EIO_READDIR: eio__scandir (req, self); break; @@ -2164,6 +2187,21 @@ eio_req *eio_msync (void *addr, size_t length, int flags, int pri, eio_cb cb, vo REQ (EIO_MSYNC); req->ptr2 = addr; req->size = length; req->int1 = flags; SEND; } +eio_req *eio_fdatasync (int fd, int pri, eio_cb cb, void *data) +{ + REQ (EIO_FDATASYNC); req->int1 = fd; SEND; +} + +eio_req *eio_syncfs (int fd, int pri, eio_cb cb, void *data) +{ + REQ (EIO_SYNCFS); req->int1 = fd; SEND; +} + +eio_req *eio_sync_file_range (int fd, off_t offset, size_t nbytes, unsigned int flags, int pri, eio_cb cb, void *data) +{ + REQ (EIO_SYNC_FILE_RANGE); req->int1 = fd; req->offs = offset; req->size = nbytes; req->int2 = flags; SEND; +} + eio_req *eio_mtouch (void *addr, size_t length, int flags, int pri, eio_cb cb, void *data) { REQ (EIO_MTOUCH); req->ptr2 = addr; req->size = length; req->int1 = flags; SEND; @@ -2179,21 +2217,11 @@ eio_req *eio_mlockall (int flags, int pri, eio_cb cb, void *data) REQ (EIO_MLOCKALL); req->int1 = flags; SEND; } -eio_req *eio_sync_file_range (int fd, off_t offset, size_t nbytes, unsigned int flags, int pri, eio_cb cb, void *data) -{ - REQ (EIO_SYNC_FILE_RANGE); req->int1 = fd; req->offs = offset; req->size = nbytes; req->int2 = flags; SEND; -} - eio_req *eio_fallocate (int fd, int mode, off_t offset, size_t len, int pri, eio_cb cb, void *data) { REQ (EIO_FALLOCATE); req->int1 = fd; req->int2 = mode; req->offs = offset; req->size = len; SEND; } -eio_req *eio_fdatasync (int fd, int pri, eio_cb cb, void *data) -{ - REQ (EIO_FDATASYNC); req->int1 = fd; SEND; -} - eio_req *eio_close (int fd, int pri, eio_cb cb, void *data) { REQ (EIO_CLOSE); req->int1 = fd; SEND; @@ -179,7 +179,7 @@ enum EIO_UTIME, EIO_FUTIME, EIO_CHMOD, EIO_FCHMOD, EIO_CHOWN, EIO_FCHOWN, - EIO_SYNC, EIO_FSYNC, EIO_FDATASYNC, + EIO_SYNC, EIO_FSYNC, EIO_FDATASYNC, EIO_SYNCFS, EIO_MSYNC, EIO_MTOUCH, EIO_SYNC_FILE_RANGE, EIO_FALLOCATE, EIO_MLOCK, EIO_MLOCKALL, EIO_UNLINK, EIO_RMDIR, EIO_MKDIR, EIO_RENAME, @@ -292,6 +292,7 @@ eio_req *eio_busy (eio_tstamp delay, int pri, eio_cb cb, void *data); /* ti eio_req *eio_sync (int pri, eio_cb cb, void *data); eio_req *eio_fsync (int fd, int pri, eio_cb cb, void *data); eio_req *eio_fdatasync (int fd, int pri, eio_cb cb, void *data); +eio_req *eio_syncfs (int fd, int pri, eio_cb cb, void *data); eio_req *eio_msync (void *addr, size_t length, int flags, int pri, eio_cb cb, void *data); eio_req *eio_mtouch (void *addr, size_t length, int flags, int pri, eio_cb cb, void *data); eio_req *eio_mlock (void *addr, size_t length, int pri, eio_cb cb, void *data); @@ -594,6 +594,13 @@ use. Calls C<readahead(2)>. If the syscall is missing, then the call is emulated by simply reading the data (currently in 64kiB chunks). +=item eio_syncfs (int fd, int pri, eio_cb cb, void *data) + +Calls Linux' C<syncfs> syscall, if available. Returns C<-1> and sets +C<errno> to C<ENOSYS> if the call is missing I<but still calls sync()>, +if the C<fd> is C<< >= 0 >>, so you can probe for the availability of the +syscall with a negative C<fd> argument and checking for C<-1/ENOSYS>. + =item eio_sync_file_range (int fd, off_t offset, size_t nbytes, unsigned int flags, int pri, eio_cb cb, void *data) Calls C<sync_file_range>. If the syscall is missing, then this is the same @@ -1,6 +1,6 @@ dnl openbsd in it's neverending brokenness requires stdint.h for intptr_t, dnl but that header isn't very portable... -AC_CHECK_HEADERS([stdint.h]) +AC_CHECK_HEADERS([stdint.h sys/syscall.h]) AC_SEARCH_LIBS( pthread_create, @@ -138,6 +138,16 @@ int main (void) ],ac_cv_fallocate=yes,ac_cv_fallocate=no)]) test $ac_cv_fallocate = yes && AC_DEFINE(HAVE_FALLOCATE, 1, fallocate(2) is available) +AC_CACHE_CHECK(for sys_syncfs, ac_cv_sys_syncfs, [AC_LINK_IFELSE([ +#include <unistd.h> +#include <sys/syscall.h> +int main (void) +{ + int res = syscall (__NR_syncfs, (int)0); +} +],ac_cv_sys_syncfs=yes,ac_cv_sys_syncfs=no)]) +test $ac_cv_sys_syncfs = yes && AC_DEFINE(HAVE_SYS_SYNCFS, 1, syscall(__NR_syncfs) is available) + dnl ############################################################################# dnl # these checks exist for the benefit of IO::AIO |