author | Alberto Bertogli
<albertito@blitiri.com.ar> 2009-04-03 04:23:37 UTC |
committer | Alberto Bertogli
<albertito@blitiri.com.ar> 2009-04-12 13:51:04 UTC |
parent | 0d244b37ba24ec7564d15a23e7fa1c864c5bd0bb |
libjio/Makefile | +1 | -1 |
libjio/compat.c | +56 | -0 |
libjio/compat.h | +8 | -0 |
libjio/trans.c | +22 | -0 |
diff --git a/libjio/Makefile b/libjio/Makefile index 192a18e..72e4e18 100644 --- a/libjio/Makefile +++ b/libjio/Makefile @@ -39,7 +39,7 @@ endif # objects to build -OBJS = checksum.o common.o trans.o check.o journal.o unix.o ansi.o +OBJS = checksum.o common.o compat.o trans.o check.o journal.o unix.o ansi.o # rules default: all diff --git a/libjio/compat.c b/libjio/compat.c new file mode 100644 index 0000000..80c2300 --- /dev/null +++ b/libjio/compat.c @@ -0,0 +1,56 @@ + + +/* To get sync_file_range() we need to temporarily define _GNU_SOURCE, which + * is not the nicest thing, but is not worth defining globally */ +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#define _REMOVE_GNU_SOURCE +#endif + +#include <fcntl.h> /* sync_range_submit(), if possible */ +#include "compat.h" + + +/* + * sync_file_range() support through an internal similar API + */ + +#ifdef SYNC_FILE_RANGE_WRITE +const int have_sync_range = 1; + +/* Initiate write-out of the dirty pages in the range. */ +int sync_range_submit(int fd, off_t offset, size_t nbytes) +{ + /* We don't need SYNC_FILE_RANGE_WAIT_BEFORE because we have exclusive + * access to the range (guaranteed by the caller) */ + return sync_file_range(fd, offset, nbytes, SYNC_FILE_RANGE_WRITE); +} + +/* Wait for completion of the previously-submitted I/O in the given ranges. + * Does NOT force the submission of any new I/O. */ +int sync_range_wait(int fd, off_t offset, size_t nbytes) +{ + return sync_file_range(fd, offset, nbytes, SYNC_FILE_RANGE_WAIT_BEFORE); +} + +#else + +#warning "No sync_file_range()" +const int have_sync_range = 0; + +int sync_range_submit(int fd, off_t offset, size_t nbytes) +{ + return -1; +} + +int sync_range_wait(int fd, off_t offset, size_t nbytes) +{ + return -1; +} + +#endif /* defined SYNC_FILE_RANGE_WRITE */ + +#ifdef _REMOVE_GNU_SOURCE +#undef _GNU_SOURCE +#endif + diff --git a/libjio/compat.h b/libjio/compat.h index ecc742a..4f9d98d 100644 --- a/libjio/compat.h +++ b/libjio/compat.h @@ -4,6 +4,14 @@ #ifndef _COMPAT_H #define _COMPAT_H +/* sync_file_range() is linux-specific, so we provide an internal similar API, + * with a constant to be able to check for its presence; the implementation is + * in compat.c */ +extern const int have_sync_range; +int sync_range_submit(int fd, off_t offset, size_t nbytes); +int sync_range_wait(int fd, off_t offset, size_t nbytes); + + /* posix_fadvise() was introduced in SUSv3. Because it's the only SUSv3 * function we rely on so far (everything else is SUSv2), we define a void * fallback for systems that do not implement it. diff --git a/libjio/trans.c b/libjio/trans.c index 306a6d0..e4a6e98 100644 --- a/libjio/trans.c +++ b/libjio/trans.c @@ -194,6 +194,14 @@ ssize_t jtrans_commit(struct jtrans *ts) goto rollback_exit; written += rv; + + if (have_sync_range && !(ts->flags & J_LINGER)) { + rv = sync_range_submit(ts->fs->fd, op->len, + op->offset); + if (rv != 0) + goto rollback_exit; + } + fiu_exit_on("jio/commit/wrote_op"); } @@ -211,6 +219,20 @@ ssize_t jtrans_commit(struct jtrans *ts) ts->fs->ltrans = linger; pthread_mutex_unlock(&(ts->fs->ltlock)); } else { + if (have_sync_range) { + for (op = ts->op; op != NULL; op = op->next) { + rv = sync_range_wait(ts->fs->fd, op->len, + op->offset); + if (rv != 0) + goto rollback_exit; + } + } else { + if (fdatasync(ts->fs->fd) != 0) + goto rollback_exit; + } + + /* the transaction has been applied, so we cleanup and remove + * it from the disk */ rv = journal_free(jop); if (rv != 0) goto rollback_exit;