[gvfs/gnome-3-8] metadata: Put journal in $XDG_RUNTIME_DIR for shared NFS homedir case
- From: Tomas Bzatek <tbzatek src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gvfs/gnome-3-8] metadata: Put journal in $XDG_RUNTIME_DIR for shared NFS homedir case
- Date: Tue, 14 May 2013 16:15:10 +0000 (UTC)
commit 34db4bdf35935b153da26bf8d0654242a6c6da9c
Author: Tomas Bzatek <tbzatek redhat com>
Date: Mon May 13 17:43:02 2013 +0200
metadata: Put journal in $XDG_RUNTIME_DIR for shared NFS homedir case
This essentially moves is_on_nfs() from metatree.c in metabuilder.c
as the more appropriate place for shared functions. It's used in
meta_builder_get_journal_filename() to determine whether to use original
metadata directory or temporary $XDG_RUNTIME_DIR location to work around
certain NFS issues.
The idea behind this change is to have separate journals for every client
that is accessing shared homedir. Then the only possible point of conflict
is on rotation which is backed up by atomic file rename. Without this,
there were multiple metadata daemons writing to the same journal file,
overwriting changes to each other and being racy in flush and rotation.
There will always be a conflict between clients, overwriting tree file
data by flushing their journals.
https://bugzilla.gnome.org/show_bug.cgi?id=637095
(cherry picked from commit 749c872b9192a84e65d83bc0f0eb697ab247fdd8)
metadata/metabuilder.c | 135 ++++++++++++++++++++++++++++++++++++++++++++++--
metadata/metabuilder.h | 3 +
metadata/metatree.c | 103 +------------------------------------
3 files changed, 136 insertions(+), 105 deletions(-)
---
diff --git a/metadata/metabuilder.c b/metadata/metabuilder.c
index c7e69fa..af9e99d 100644
--- a/metadata/metabuilder.c
+++ b/metadata/metabuilder.c
@@ -1,3 +1,4 @@
+#include "config.h"
#include "metabuilder.h"
#include <sys/types.h>
#include <sys/stat.h>
@@ -8,6 +9,44 @@
#include <sys/mman.h>
#include <glib/gstdio.h>
+#if HAVE_SYS_STATFS_H
+#include <sys/statfs.h>
+#endif
+#if HAVE_SYS_STATVFS_H
+#include <sys/statvfs.h>
+#endif
+#if HAVE_SYS_VFS_H
+#include <sys/vfs.h>
+#elif HAVE_SYS_MOUNT_H
+#if HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+#include <sys/mount.h>
+#endif
+
+#if defined(HAVE_STATFS) && defined(HAVE_STATVFS)
+/* Some systems have both statfs and statvfs, pick the
+ most "native" for these */
+# if !defined(HAVE_STRUCT_STATFS_F_BAVAIL)
+ /* on solaris and irix, statfs doesn't even have the
+ f_bavail field */
+# define USE_STATVFS
+# else
+ /* at least on linux, statfs is the actual syscall */
+# define USE_STATFS
+# endif
+
+#elif defined(HAVE_STATFS)
+
+# define USE_STATFS
+
+#elif defined(HAVE_STATVFS)
+
+# define USE_STATVFS
+
+#endif
+
+
#define MAJOR_VERSION 1
#define MINOR_VERSION 0
#define MAJOR_JOURNAL_VERSION 1
@@ -825,12 +864,89 @@ write_all_data_and_close (int fd, char *data, gsize len)
return res;
}
+gboolean
+meta_builder_is_on_nfs (const char *filename)
+{
+#ifdef USE_STATFS
+ struct statfs statfs_buffer;
+ int statfs_result;
+#elif defined(USE_STATVFS) && defined(HAVE_STRUCT_STATVFS_F_BASETYPE)
+ struct statvfs statfs_buffer;
+ int statfs_result;
+#endif
+ char *dirname;
+ gboolean res;
+
+ dirname = g_path_get_dirname (filename);
+
+ res = FALSE;
+
+#ifdef USE_STATFS
+
+# if STATFS_ARGS == 2
+ statfs_result = statfs (dirname, &statfs_buffer);
+# elif STATFS_ARGS == 4
+ statfs_result = statfs (dirname, &statfs_buffer,
+ sizeof (statfs_buffer), 0);
+# endif
+ if (statfs_result == 0)
+#ifdef __OpenBSD__
+ res = strcmp(statfs_buffer.f_fstypename, MOUNT_NFS) == 0;
+#else
+ res = statfs_buffer.f_type == 0x6969;
+#endif
+
+#elif defined(USE_STATVFS) && defined(HAVE_STRUCT_STATVFS_F_BASETYPE)
+ statfs_result = statvfs (dirname, &statfs_buffer);
+
+ if (statfs_result == 0)
+ res = strcmp (statfs_buffer.f_basetype, "nfs") == 0;
+#endif
+
+ g_free (dirname);
+
+ return res;
+}
+
static char *
-get_journal_filename (const char *filename, guint32 random_tag)
+get_runtime_journal_dir (const char *tree_filename)
+{
+ const char *rd;
+ char *dbname;
+ char *real_path;
+ char *ret;
+
+ rd = g_get_user_runtime_dir ();
+ if (! rd || *rd == '\0')
+ return NULL;
+
+ real_path = g_build_filename (rd, "gvfs-metadata", NULL);
+ if (! g_file_test (real_path, G_FILE_TEST_EXISTS))
+ {
+ if (g_mkdir_with_parents (real_path, 0700) != 0)
+ {
+ g_free (real_path);
+ return NULL;
+ }
+ }
+
+ dbname = g_path_get_basename (tree_filename);
+ ret = g_build_filename (real_path, dbname, NULL);
+
+ g_free (dbname);
+ g_free (real_path);
+
+ return ret;
+}
+
+char *
+meta_builder_get_journal_filename (const char *tree_filename, guint32 random_tag)
{
const char *hexdigits = "0123456789abcdef";
char tag[9];
int i;
+ char *ret;
+ char *real_filename = NULL;
for (i = 7; i >= 0; i--)
{
@@ -840,7 +956,18 @@ get_journal_filename (const char *filename, guint32 random_tag)
tag[8] = 0;
- return g_strconcat (filename, "-", tag, ".log", NULL);
+ if (meta_builder_is_on_nfs (tree_filename))
+ {
+ /* Put the journal in $XDG_RUNTIME_DIR to avoid file usage from concurrent clients */
+ real_filename = get_runtime_journal_dir (tree_filename);
+ }
+
+ if (! real_filename)
+ return g_strconcat (tree_filename, "-", tag, ".log", NULL);
+
+ ret = g_strconcat (real_filename, "-", tag, ".log", NULL);
+ g_free (real_filename);
+ return ret;
}
gboolean
@@ -852,7 +979,7 @@ meta_builder_create_new_journal (const char *filename, guint32 random_tag)
gsize pos;
gboolean res;
- journal_name = get_journal_filename (filename, random_tag);
+ journal_name = meta_builder_get_journal_filename (filename, random_tag);
out = g_string_new (NULL);
@@ -1055,7 +1182,7 @@ meta_builder_write (MetaBuilder *builder,
munmap (data, RANDOM_TAG_OFFSET + 4);
close (fd2);
- old_log = get_journal_filename (filename, old_tag);
+ old_log = meta_builder_get_journal_filename (filename, old_tag);
g_unlink (old_log);
g_free (old_log);
}
diff --git a/metadata/metabuilder.h b/metadata/metabuilder.h
index ad3876f..aa173c5 100644
--- a/metadata/metabuilder.h
+++ b/metadata/metabuilder.h
@@ -70,6 +70,9 @@ gboolean meta_builder_write (MetaBuilder *builder,
const char *filename);
gboolean meta_builder_create_new_journal (const char *filename,
guint32 random_tag);
+char * meta_builder_get_journal_filename (const char *tree_filename,
+ guint32 random_tag);
+gboolean meta_builder_is_on_nfs (const char *filename);
MetaFile * metafile_new (const char *name,
MetaFile *parent);
void metafile_free (MetaFile *file);
diff --git a/metadata/metatree.c b/metadata/metatree.c
index 8e2ab46..31ef8a6 100644
--- a/metadata/metatree.c
+++ b/metadata/metatree.c
@@ -9,43 +9,6 @@
#include <stdlib.h>
#include <time.h>
-#if HAVE_SYS_STATFS_H
-#include <sys/statfs.h>
-#endif
-#if HAVE_SYS_STATVFS_H
-#include <sys/statvfs.h>
-#endif
-#if HAVE_SYS_VFS_H
-#include <sys/vfs.h>
-#elif HAVE_SYS_MOUNT_H
-#if HAVE_SYS_PARAM_H
-#include <sys/param.h>
-#endif
-#include <sys/mount.h>
-#endif
-
-#if defined(HAVE_STATFS) && defined(HAVE_STATVFS)
-/* Some systems have both statfs and statvfs, pick the
- most "native" for these */
-# if !defined(HAVE_STRUCT_STATFS_F_BAVAIL)
- /* on solaris and irix, statfs doesn't even have the
- f_bavail field */
-# define USE_STATVFS
-# else
- /* at least on linux, statfs is the actual syscall */
-# define USE_STATFS
-# endif
-
-#elif defined(HAVE_STATFS)
-
-# define USE_STATFS
-
-#elif defined(HAVE_STATVFS)
-
-# define USE_STATVFS
-
-#endif
-
#include "metatree.h"
#include "metabuilder.h"
#include <glib.h>
@@ -278,50 +241,6 @@ meta_tree_clear (MetaTree *tree)
}
static gboolean
-is_on_nfs (char *filename)
-{
-#ifdef USE_STATFS
- struct statfs statfs_buffer;
- int statfs_result;
-#elif defined(USE_STATVFS) && defined(HAVE_STRUCT_STATVFS_F_BASETYPE)
- struct statvfs statfs_buffer;
- int statfs_result;
-#endif
- char *dirname;
- gboolean res;
-
- dirname = g_path_get_dirname (filename);
-
- res = FALSE;
-
-#ifdef USE_STATFS
-
-# if STATFS_ARGS == 2
- statfs_result = statfs (dirname, &statfs_buffer);
-# elif STATFS_ARGS == 4
- statfs_result = statfs (dirname, &statfs_buffer,
- sizeof (statfs_buffer), 0);
-# endif
- if (statfs_result == 0)
-#ifdef __OpenBSD__
- res = strcmp(statfs_buffer.f_fstypename, MOUNT_NFS) == 0;
-#else
- res = statfs_buffer.f_type == 0x6969;
-#endif
-
-#elif defined(USE_STATVFS) && defined(HAVE_STRUCT_STATVFS_F_BASETYPE)
- statfs_result = statvfs (dirname, &statfs_buffer);
-
- if (statfs_result == 0)
- res = strcmp (statfs_buffer.f_basetype, "nfs") == 0;
-#endif
-
- g_free (dirname);
-
- return res;
-}
-
-static gboolean
link_to_tmp (const char *source, char *tmpl)
{
char *XXXXXX;
@@ -431,7 +350,7 @@ meta_tree_init (MetaTree *tree)
retried = FALSE;
retry:
- tree->on_nfs = is_on_nfs (tree->filename);
+ tree->on_nfs = meta_builder_is_on_nfs (tree->filename);
fd = safe_open (tree, tree->filename, O_RDONLY);
if (fd == -1)
{
@@ -845,24 +764,6 @@ meta_data_get_key (MetaTree *tree,
return dataent;
}
-static char *
-get_journal_filename (const char *filename, guint32 random_tag)
-{
- const char *hexdigits = "0123456789abcdef";
- char tag[9];
- int i;
-
- for (i = 7; i >= 0; i--)
- {
- tag[i] = hexdigits[random_tag % 0x10];
- random_tag >>= 4;
- }
-
- tag[8] = 0;
-
- return g_strconcat (filename, "-", tag, ".log", NULL);
-}
-
static void
meta_journal_free (MetaJournal *journal)
{
@@ -1157,7 +1058,7 @@ meta_journal_open (MetaTree *tree, const char *filename, gboolean for_write, gui
open_flags = O_RDONLY;
retry:
- journal_filename = get_journal_filename (filename, tag);
+ journal_filename = meta_builder_get_journal_filename (filename, tag);
fd = safe_open (tree, journal_filename, open_flags);
g_free (journal_filename);
if (fd == -1)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]