[ostree/wip/fsync: 1/11] libotutil: Add API to create directory hierarchy recursively *and* fsync
- From: Colin Walters <walters src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [ostree/wip/fsync: 1/11] libotutil: Add API to create directory hierarchy recursively *and* fsync
- Date: Wed, 9 Apr 2014 05:53:07 +0000 (UTC)
commit b70527d46af592a9b422a0cf525214ec301a43c0
Author: Colin Walters <walters verbum org>
Date: Tue Apr 8 17:22:38 2014 -0400
libotutil: Add API to create directory hierarchy recursively *and* fsync
To be really sure that any directory entries have hit disk we need to
call fsync() on the directory fd. This API allows us to conveniently
create a directory hierarchy, fsyncing all of it along the way.
src/libotutil/ot-gio-utils.c | 101 ++++++++++++++++++++++++++++++++++++++++++
src/libotutil/ot-gio-utils.h | 8 +++
2 files changed, 109 insertions(+), 0 deletions(-)
---
diff --git a/src/libotutil/ot-gio-utils.c b/src/libotutil/ot-gio-utils.c
index 643939c..3313570 100644
--- a/src/libotutil/ot-gio-utils.c
+++ b/src/libotutil/ot-gio-utils.c
@@ -365,6 +365,107 @@ ot_gfile_ensure_unlinked (GFile *path,
}
/**
+ * ot_util_fsync_directory:
+ * @dir: Path to a directory
+ * @cancellable: Cancellable
+ * @error: Error
+ *
+ * Ensure that all entries in directory @dir are on disk.
+ */
+gboolean
+ot_util_fsync_directory (GFile *dir,
+ GCancellable *cancellable,
+ GError **error)
+{
+ gboolean ret = FALSE;
+ int dfd = -1;
+
+ if (!gs_file_open_dir_fd (dir, &dfd, cancellable, error))
+ goto out;
+
+ if (fsync (dfd) != 0)
+ {
+ ot_util_set_error_from_errno (error, errno);
+ goto out;
+ }
+
+ ret = TRUE;
+ out:
+ if (dfd != -1)
+ (void) close (dfd);
+ return ret;
+}
+
+/**
+ * ot_util_ensure_directory_and_fsync:
+ * @dir: Path to a directory
+ * @cancellable: Cancellable
+ * @error: Error
+ *
+ * Create @dir (and all intermediate parent directories), ensuring
+ * that all entries are on disk.
+ */
+gboolean
+ot_util_ensure_directory_and_fsync (GFile *dir,
+ GCancellable *cancellable,
+ GError **error)
+{
+ gboolean ret = FALSE;
+ int parentfd = -1;
+ const char *basename = gs_file_get_basename_cached (dir);
+ gs_unref_object GFile *parent = g_file_get_parent (dir);
+
+ again:
+ parentfd = open (gs_file_get_path_cached (parent),
+ O_RDONLY | O_NONBLOCK | O_DIRECTORY | O_CLOEXEC);
+ if (parentfd == -1)
+ {
+ if (errno == ENOENT)
+ {
+ if (!ot_util_ensure_directory_and_fsync (parent, cancellable, error))
+ goto out;
+ goto again;
+ }
+ else
+ {
+ int errsv = errno;
+ g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errsv),
+ "opendir: %s", g_strerror (errsv));
+ goto out;
+ }
+ }
+
+ if (mkdirat (parentfd, basename, 0777) == -1)
+ {
+ if (errno == EEXIST)
+ {
+ ;
+ }
+ else
+ {
+ int errsv = errno;
+ g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errsv),
+ "mkdirat: %s", g_strerror (errsv));
+ goto out;
+ }
+ }
+
+ if (fsync (parentfd) == -1)
+ {
+ int errsv = errno;
+ g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errsv),
+ "fsync: %s", g_strerror (errsv));
+ goto out;
+ }
+
+ ret = TRUE;
+ out:
+ if (parentfd != -1)
+ (void) close (parentfd);
+ return ret;
+}
+
+/**
* ot_gfile_atomic_symlink_swap:
* @path: Replace the contents of this symbolic link
* @target: New symbolic link target
diff --git a/src/libotutil/ot-gio-utils.h b/src/libotutil/ot-gio-utils.h
index 2d585ba..b3cb1f8 100644
--- a/src/libotutil/ot-gio-utils.h
+++ b/src/libotutil/ot-gio-utils.h
@@ -83,5 +83,13 @@ gboolean ot_gfile_atomic_symlink_swap (GFile *path,
GCancellable *cancellable,
GError **error);
+gboolean ot_util_ensure_directory_and_fsync (GFile *dir,
+ GCancellable *cancellable,
+ GError **error);
+
+gboolean ot_util_fsync_directory (GFile *dir,
+ GCancellable *cancellable,
+ GError **error);
+
G_END_DECLS
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]