Package: gvfs
Version: 1.6.3-2
Severity: normal
Tags: upstream patch

The gvfs metatree code has misaligned accesses to 64 bit data.  On the Alpha
architecture this causes traps to the kernel to complete the memory access
(i.e. very inefficient) and pollutes the kernel logs with messages.  While
not a show stopper it is nevertheless annoying, particularly as the gvfs
library is linked in a number of other packages (such as nautilus and evince)
and they are all generating unaligned trap messages in the kernel log.

I attach a patch that "fixes" the problem by providing a means to tell the
compiler (provided it is gcc) that the access is misaligned at the specific
points in the code, thus the compiler generates code that can access the
datum without causing unaligned traps to the kernel.  The patch is really
just to illustrate where the problem occurs -- a better approach is probably
to fix the "Journal Entry" in the code to contain the 64 bit data (the field
"mtime" in the structure) on 64 bit boundaries.  I noted a comment in the
code that said the mtime field must be 32 bit aligned but didn't give any
reasons why, so I decided not to risk modifying the alignment.

-- System Information:
Debian Release: squeeze/sid
  APT prefers unstable
  APT policy: (500, 'unstable')
Architecture: alpha

Kernel: Linux 2.6.35.4-dp264-p+
Locale: LANG=en_GB.UTF-8, LC_CTYPE=en_GB.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash

Versions of packages gvfs depends on:
ii  libc6.1                       2.11.2-5   Embedded GNU C Library: Shared lib
ii  libdbus-1-3                   1.2.24-3   simple interprocess messaging syst
ii  libexpat1                     2.0.1-7    XML parsing C library - runtime li
ii  libgconf2-4                   2.28.1-3   GNOME configuration database syste
ii  libgdu0                       2.30.1-2   GObject based Disk Utility Library
ii  libglib2.0-0                  2.24.1-1   The GLib library of C routines
ii  libgnome-keyring0             2.30.1-1   GNOME keyring services library
ii  libudev0                      161-1      libudev shared library
ii  x11-utils                     7.5+4      X11 utilities

Versions of packages gvfs recommends:
ii  dbus                          1.2.24-3   simple interprocess messaging syst
ii  policykit-1-gnome             0.96-2     GNOME authentication agent for Pol

Versions of packages gvfs suggests:
ii  gvfs-backends                 1.6.3-2    userspace virtual filesystem - bac

-- no debconf information
--- gvfs-1.6.3/metadata/metatree.c	2010-02-21 14:53:30.000000000 +1300
+++ gvfs-1.6.3-mod/metadata/metatree.c	2010-09-06 22:18:48.000000000 +1200
@@ -170,6 +170,27 @@ struct _MetaTree {
   MetaJournal *journal;
 };
 
+/* Unfortunately the journal entries are only aligned to 32 bit boundaries
+   but on some 64-bit RISC architectures (e.g. Alpha) this is insufficient
+   to guarantee correct alignment of 64-bit accesses. This is not a show
+   stopper but does cause inefficient traps to the kernel and pollution of
+   kernel logs.  Rather than fix the alignment we provide a helper function,
+   dependent on features specific to gcc, to correctly access a 64-bit datum
+   that may be misaligned.  This causes no loss of inefficiency on
+   architectures where alignment is not an issue provided we are compiled
+   with compiler optimisation turned on. */
+#ifdef __GNUC__
+struct una_u64 { guint64 x __attribute__((packed)); };
+static inline guint64 ldq_u(guint64 *p)
+{
+        const struct una_u64 *ptr = (const struct una_u64 *) p;
+        return ptr->x;
+}
+#else
+#define ldq_u(x) (*(x))
+#endif
+
+
 static void         meta_tree_refresh_locked   (MetaTree    *tree);
 static MetaJournal *meta_journal_open          (MetaTree    *tree,
 						const char  *filename,
@@ -1303,7 +1324,7 @@ meta_journal_iterate (MetaJournal *journ
       sizep = (guint32 *)entry;
       entry = (MetaJournalEntry *)((char *)entry - GUINT32_FROM_BE (*(sizep-1)));
 
-      mtime = GUINT64_FROM_BE (entry->mtime);
+      mtime = GUINT64_FROM_BE( ldq_u(&(entry->mtime)) );
       journal_path = &entry->path[0];
 
       if (journal_entry_is_key_type (entry) &&
@@ -2287,7 +2308,7 @@ apply_journal_to_builder (MetaTree *tree
   entry = journal->first_entry;
   while (entry < journal->last_entry)
     {
-      mtime = GUINT64_FROM_BE (entry->mtime);
+      mtime = GUINT64_FROM_BE( ldq_u(&(entry->mtime)) );
       journal_path = &entry->path[0];
 
       switch (entry->entry_type)

Reply via email to