summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiklos Szeredi <miklos@szeredi.hu>2007-12-12 11:53:38 +0000
committerMiklos Szeredi <miklos@szeredi.hu>2007-12-12 11:53:38 +0000
commit918f0ad95b73e506d20488cb8ddd35d1a2524c7c (patch)
treec2adf3e3c71b94c59b8d64beb9a0ab83ab87119c
parent0b47f6bc8bfe939f12266ef41cba31a2eb2c5f30 (diff)
downloadfuse-918f0ad95b73e506d20488cb8ddd35d1a2524c7c.tar.gz
Disable old symbol versions if __UCLIBC__ is definedfuse_2_7_2_before_indent
-rw-r--r--ChangeLog13
-rw-r--r--configure.in2
-rw-r--r--kernel/configure.ac2
-rw-r--r--lib/Makefile.am2
-rw-r--r--lib/fuse.c14
-rw-r--r--lib/fuse_lowlevel.c8
-rw-r--r--lib/fuse_misc.h8
-rw-r--r--lib/fuse_mt.c3
-rw-r--r--lib/fuse_opt.c19
-rw-r--r--lib/fuse_session.c3
-rw-r--r--lib/fuse_versionscript1
-rw-r--r--lib/helper.c19
-rw-r--r--lib/mount.c9
-rw-r--r--lib/mount_bsd.c3
-rw-r--r--test/.cvsignore1
-rw-r--r--test/stracedecode.c197
-rw-r--r--test/test.c4
17 files changed, 278 insertions, 30 deletions
diff --git a/ChangeLog b/ChangeLog
index 5cdbc9a..d292db7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2007-12-12 Miklos Szeredi <miklos@szeredi.hu>
+
+ * Disable old symbol versions if __UCLIBC__ is defined. If a
+ symbol in a library has multiple versions, the runtime linker in
+ uClibc seems to randomly choose between them.
+
+ * Remove erroneous 'fuse_opt_insert_arg@FUSE_2_5' from
+ fuse_version_script. fuse_opt_free_args() was added in fuse-2.6.
+
+ * Close fuse device file descriptor before calling umount(),
+ preventing a deadlock when umount is synchronous. Reported by
+ Szabolcs Szakacsits
+
2007-11-12 Miklos Szeredi <miklos@szeredi.hu>
* 'fusermount -u' did not umount the filesystem if /etc/mtab was a
diff --git a/configure.in b/configure.in
index f81dfea..d1f0fcf 100644
--- a/configure.in
+++ b/configure.in
@@ -1,4 +1,4 @@
-AC_INIT(fuse, 2.7.1)
+AC_INIT(fuse, 2.7.2)
AC_CANONICAL_TARGET
AM_INIT_AUTOMAKE
AM_CONFIG_HEADER(include/config.h)
diff --git a/kernel/configure.ac b/kernel/configure.ac
index 489a1e1..ab7b09c 100644
--- a/kernel/configure.ac
+++ b/kernel/configure.ac
@@ -1,4 +1,4 @@
-AC_INIT(fuse-kernel, 2.7.1)
+AC_INIT(fuse-kernel, 2.7.2)
AC_CONFIG_HEADERS([config.h])
AC_PROG_INSTALL
diff --git a/lib/Makefile.am b/lib/Makefile.am
index cf84847..4d14ef4 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -34,7 +34,7 @@ libfuse_la_SOURCES = \
$(iconv_source) \
$(mount_source)
-libfuse_la_LDFLAGS = @libfuse_libs@ -version-number 2:7:1 \
+libfuse_la_LDFLAGS = @libfuse_libs@ -version-number 2:7:2 \
-Wl,--version-script,$(srcdir)/fuse_versionscript
libulockmgr_la_SOURCES = ulockmgr.c
diff --git a/lib/fuse.c b/lib/fuse.c
index 80bfe60..d22e200 100644
--- a/lib/fuse.c
+++ b/lib/fuse.c
@@ -3290,12 +3290,12 @@ struct fuse *fuse_new_compat1(int fd, int flags,
sizeof(struct fuse_operations_compat1), 11);
}
-__asm__(".symver fuse_exited,__fuse_exited@");
-__asm__(".symver fuse_process_cmd,__fuse_process_cmd@");
-__asm__(".symver fuse_read_cmd,__fuse_read_cmd@");
-__asm__(".symver fuse_set_getcontext_func,__fuse_set_getcontext_func@");
-__asm__(".symver fuse_new_compat2,fuse_new@");
-__asm__(".symver fuse_new_compat22,fuse_new@FUSE_2.2");
+FUSE_SYMVER(".symver fuse_exited,__fuse_exited@");
+FUSE_SYMVER(".symver fuse_process_cmd,__fuse_process_cmd@");
+FUSE_SYMVER(".symver fuse_read_cmd,__fuse_read_cmd@");
+FUSE_SYMVER(".symver fuse_set_getcontext_func,__fuse_set_getcontext_func@");
+FUSE_SYMVER(".symver fuse_new_compat2,fuse_new@");
+FUSE_SYMVER(".symver fuse_new_compat22,fuse_new@FUSE_2.2");
#endif /* __FreeBSD__ */
@@ -3307,4 +3307,4 @@ struct fuse *fuse_new_compat25(int fd, struct fuse_args *args,
op_size, 25);
}
-__asm__(".symver fuse_new_compat25,fuse_new@FUSE_2.5");
+FUSE_SYMVER(".symver fuse_new_compat25,fuse_new@FUSE_2.5");
diff --git a/lib/fuse_lowlevel.c b/lib/fuse_lowlevel.c
index 64e2aba..d39a4a1 100644
--- a/lib/fuse_lowlevel.c
+++ b/lib/fuse_lowlevel.c
@@ -1409,9 +1409,9 @@ int fuse_sync_compat_args(struct fuse_args *args)
return 0;
}
-__asm__(".symver fuse_reply_statfs_compat,fuse_reply_statfs@FUSE_2.4");
-__asm__(".symver fuse_reply_open_compat,fuse_reply_open@FUSE_2.4");
-__asm__(".symver fuse_lowlevel_new_compat,fuse_lowlevel_new@FUSE_2.4");
+FUSE_SYMVER(".symver fuse_reply_statfs_compat,fuse_reply_statfs@FUSE_2.4");
+FUSE_SYMVER(".symver fuse_reply_open_compat,fuse_reply_open@FUSE_2.4");
+FUSE_SYMVER(".symver fuse_lowlevel_new_compat,fuse_lowlevel_new@FUSE_2.4");
#else /* __FreeBSD__ */
@@ -1435,4 +1435,4 @@ struct fuse_session *fuse_lowlevel_new_compat25(struct fuse_args *args,
op_size, userdata);
}
-__asm__(".symver fuse_lowlevel_new_compat25,fuse_lowlevel_new@FUSE_2.5");
+FUSE_SYMVER(".symver fuse_lowlevel_new_compat25,fuse_lowlevel_new@FUSE_2.5");
diff --git a/lib/fuse_misc.h b/lib/fuse_misc.h
index 99e5117..4f5236a 100644
--- a/lib/fuse_misc.h
+++ b/lib/fuse_misc.h
@@ -9,9 +9,17 @@
#include "config.h"
#include <pthread.h>
+/* Versioned symbols confuse the dynamic linker in uClibc */
+#ifndef __UCLIBC__
+#define FUSE_SYMVER(x) __asm__(x)
+#else
+#define FUSE_SYMVER(x)
+#endif
+
#ifndef USE_UCLIBC
#define fuse_mutex_init(mut) pthread_mutex_init(mut, NULL)
#else
+/* Is this hack still needed? */
static inline void fuse_mutex_init(pthread_mutex_t *mut)
{
pthread_mutexattr_t attr;
diff --git a/lib/fuse_mt.c b/lib/fuse_mt.c
index 2c1ff2c..cbdc1a3 100644
--- a/lib/fuse_mt.c
+++ b/lib/fuse_mt.c
@@ -7,6 +7,7 @@
*/
#include "fuse_i.h"
+#include "fuse_misc.h"
#include "fuse_lowlevel.h"
#include <stdio.h>
@@ -112,4 +113,4 @@ int fuse_loop_mt(struct fuse *f)
return fuse_session_loop_mt(fuse_get_session(f));
}
-__asm__(".symver fuse_loop_mt_proc,__fuse_loop_mt@");
+FUSE_SYMVER(".symver fuse_loop_mt_proc,__fuse_loop_mt@");
diff --git a/lib/fuse_opt.c b/lib/fuse_opt.c
index 1c6a315..d10e624 100644
--- a/lib/fuse_opt.c
+++ b/lib/fuse_opt.c
@@ -7,6 +7,7 @@
*/
#include "fuse_opt.h"
+#include "fuse_misc.h"
#include <stdio.h>
#include <stdlib.h>
@@ -65,7 +66,8 @@ int fuse_opt_add_arg(struct fuse_args *args, const char *arg)
return 0;
}
-int fuse_opt_insert_arg(struct fuse_args *args, int pos, const char *arg)
+static int fuse_opt_insert_arg_common(struct fuse_args *args, int pos,
+ const char *arg)
{
assert(pos <= args->argc);
if (fuse_opt_add_arg(args, arg) == -1)
@@ -80,6 +82,18 @@ int fuse_opt_insert_arg(struct fuse_args *args, int pos, const char *arg)
return 0;
}
+int fuse_opt_insert_arg(struct fuse_args *args, int pos, const char *arg)
+{
+ return fuse_opt_insert_arg_common(args, pos, arg);
+}
+
+int fuse_opt_insert_arg_compat(struct fuse_args *args, int pos,
+ const char *arg);
+int fuse_opt_insert_arg_compat(struct fuse_args *args, int pos, const char *arg)
+{
+ return fuse_opt_insert_arg_common(args, pos, arg);
+}
+
static int next_arg(struct fuse_opt_context *ctx, const char *opt)
{
if (ctx->argctr + 1 >= ctx->argc) {
@@ -365,3 +379,6 @@ int fuse_opt_parse(struct fuse_args *args, void *data,
fuse_opt_free_args(&ctx.outargs);
return res;
}
+
+/* This symbol version was mistakenly added to the version script */
+FUSE_SYMVER(".symver fuse_opt_insert_arg_compat,fuse_opt_insert_arg@FUSE_2.5");
diff --git a/lib/fuse_session.c b/lib/fuse_session.c
index 33cc59e..cf2e20b 100644
--- a/lib/fuse_session.c
+++ b/lib/fuse_session.c
@@ -7,6 +7,7 @@
*/
#include "fuse_lowlevel.h"
+#include "fuse_misc.h"
#include "fuse_common_compat.h"
#include "fuse_lowlevel_compat.h"
@@ -204,5 +205,5 @@ void fuse_chan_destroy(struct fuse_chan *ch)
}
#ifndef __FreeBSD__
-__asm__(".symver fuse_chan_new_compat24,fuse_chan_new@FUSE_2.4");
+FUSE_SYMVER(".symver fuse_chan_new_compat24,fuse_chan_new@FUSE_2.4");
#endif
diff --git a/lib/fuse_versionscript b/lib/fuse_versionscript
index 9d6642a..3eedd0c 100644
--- a/lib/fuse_versionscript
+++ b/lib/fuse_versionscript
@@ -67,7 +67,6 @@ FUSE_2.5 {
fuse_opt_add_opt;
fuse_opt_add_arg;
fuse_opt_free_args;
- fuse_opt_insert_arg;
fuse_opt_match;
fuse_parse_cmdline;
fuse_remove_signal_handlers;
diff --git a/lib/helper.c b/lib/helper.c
index e79f4b0..fbbf4b2 100644
--- a/lib/helper.c
+++ b/lib/helper.c
@@ -8,6 +8,7 @@
#include "config.h"
#include "fuse_i.h"
+#include "fuse_misc.h"
#include "fuse_opt.h"
#include "fuse_lowlevel.h"
#include "fuse_common_compat.h"
@@ -402,11 +403,11 @@ int fuse_mount_compat1(const char *mountpoint, const char *args[])
return fuse_mount_compat22(mountpoint, NULL);
}
-__asm__(".symver fuse_setup_compat2,__fuse_setup@");
-__asm__(".symver fuse_setup_compat22,fuse_setup@FUSE_2.2");
-__asm__(".symver fuse_teardown,__fuse_teardown@");
-__asm__(".symver fuse_main_compat2,fuse_main@");
-__asm__(".symver fuse_main_real_compat22,fuse_main_real@FUSE_2.2");
+FUSE_SYMVER(".symver fuse_setup_compat2,__fuse_setup@");
+FUSE_SYMVER(".symver fuse_setup_compat22,fuse_setup@FUSE_2.2");
+FUSE_SYMVER(".symver fuse_teardown,__fuse_teardown@");
+FUSE_SYMVER(".symver fuse_main_compat2,fuse_main@");
+FUSE_SYMVER(".symver fuse_main_real_compat22,fuse_main_real@FUSE_2.2");
#endif /* __FreeBSD__ */
@@ -439,7 +440,7 @@ int fuse_mount_compat25(const char *mountpoint, struct fuse_args *args)
return fuse_kern_mount(mountpoint, args);
}
-__asm__(".symver fuse_setup_compat25,fuse_setup@FUSE_2.5");
-__asm__(".symver fuse_teardown_compat22,fuse_teardown@FUSE_2.2");
-__asm__(".symver fuse_main_real_compat25,fuse_main_real@FUSE_2.5");
-__asm__(".symver fuse_mount_compat25,fuse_mount@FUSE_2.5");
+FUSE_SYMVER(".symver fuse_setup_compat25,fuse_setup@FUSE_2.5");
+FUSE_SYMVER(".symver fuse_teardown_compat22,fuse_teardown@FUSE_2.2");
+FUSE_SYMVER(".symver fuse_main_real_compat25,fuse_main_real@FUSE_2.5");
+FUSE_SYMVER(".symver fuse_mount_compat25,fuse_mount@FUSE_2.5");
diff --git a/lib/mount.c b/lib/mount.c
index e0fea56..8a5c5ab 100644
--- a/lib/mount.c
+++ b/lib/mount.c
@@ -8,6 +8,7 @@
#include "config.h"
#include "fuse_i.h"
+#include "fuse_misc.h"
#include "fuse_opt.h"
#include "fuse_common_compat.h"
#include "mount_util.h"
@@ -283,6 +284,10 @@ void fuse_kern_unmount(const char *mountpoint, int fd)
then the filesystem is already unmounted */
if (res == 1 && (pfd.revents & POLLERR))
return;
+
+ /* Need to close file descriptor, otherwise synchronous umount
+ would recurse into filesystem, and deadlock */
+ close(fd);
}
if (geteuid() == 0) {
@@ -579,5 +584,5 @@ int fuse_kern_mount(const char *mountpoint, struct fuse_args *args)
return res;
}
-__asm__(".symver fuse_mount_compat22,fuse_mount@FUSE_2.2");
-__asm__(".symver fuse_unmount_compat22,fuse_unmount@FUSE_2.2");
+FUSE_SYMVER(".symver fuse_mount_compat22,fuse_mount@FUSE_2.2");
+FUSE_SYMVER(".symver fuse_unmount_compat22,fuse_unmount@FUSE_2.2");
diff --git a/lib/mount_bsd.c b/lib/mount_bsd.c
index 1c4030d..5197464 100644
--- a/lib/mount_bsd.c
+++ b/lib/mount_bsd.c
@@ -7,6 +7,7 @@
*/
#include "fuse_i.h"
+#include "fuse_misc.h"
#include "fuse_opt.h"
#include <sys/stat.h>
@@ -360,4 +361,4 @@ int fuse_kern_mount(const char *mountpoint, struct fuse_args *args)
return res;
}
-__asm__(".symver fuse_unmount_compat22,fuse_unmount@FUSE_2.2");
+FUSE_SYMVER(".symver fuse_unmount_compat22,fuse_unmount@FUSE_2.2");
diff --git a/test/.cvsignore b/test/.cvsignore
index 9daeafb..efb4fee 100644
--- a/test/.cvsignore
+++ b/test/.cvsignore
@@ -1 +1,2 @@
test
+stracedecode
diff --git a/test/stracedecode.c b/test/stracedecode.c
new file mode 100644
index 0000000..7908f43
--- /dev/null
+++ b/test/stracedecode.c
@@ -0,0 +1,197 @@
+#include <stdio.h>
+#include <string.h>
+#include "fuse_kernel.h"
+
+static struct {
+ const char *name;
+} fuse_ll_ops[] = {
+ [FUSE_LOOKUP] = { "LOOKUP" },
+ [FUSE_FORGET] = { "FORGET" },
+ [FUSE_GETATTR] = { "GETATTR" },
+ [FUSE_SETATTR] = { "SETATTR" },
+ [FUSE_READLINK] = { "READLINK" },
+ [FUSE_SYMLINK] = { "SYMLINK" },
+ [FUSE_MKNOD] = { "MKNOD" },
+ [FUSE_MKDIR] = { "MKDIR" },
+ [FUSE_UNLINK] = { "UNLINK" },
+ [FUSE_RMDIR] = { "RMDIR" },
+ [FUSE_RENAME] = { "RENAME" },
+ [FUSE_LINK] = { "LINK" },
+ [FUSE_OPEN] = { "OPEN" },
+ [FUSE_READ] = { "READ" },
+ [FUSE_WRITE] = { "WRITE" },
+ [FUSE_STATFS] = { "STATFS" },
+ [FUSE_RELEASE] = { "RELEASE" },
+ [FUSE_FSYNC] = { "FSYNC" },
+ [FUSE_SETXATTR] = { "SETXATTR" },
+ [FUSE_GETXATTR] = { "GETXATTR" },
+ [FUSE_LISTXATTR] = { "LISTXATTR" },
+ [FUSE_REMOVEXATTR] = { "REMOVEXATTR" },
+ [FUSE_FLUSH] = { "FLUSH" },
+ [FUSE_INIT] = { "INIT" },
+ [FUSE_OPENDIR] = { "OPENDIR" },
+ [FUSE_READDIR] = { "READDIR" },
+ [FUSE_RELEASEDIR] = { "RELEASEDIR" },
+ [FUSE_FSYNCDIR] = { "FSYNCDIR" },
+ [FUSE_GETLK] = { "GETLK" },
+ [FUSE_SETLK] = { "SETLK" },
+ [FUSE_SETLKW] = { "SETLKW" },
+ [FUSE_ACCESS] = { "ACCESS" },
+ [FUSE_CREATE] = { "CREATE" },
+ [FUSE_INTERRUPT] = { "INTERRUPT" },
+ [FUSE_BMAP] = { "BMAP" },
+ [FUSE_DESTROY] = { "DESTROY" },
+};
+
+#define FUSE_MAXOP (sizeof(fuse_ll_ops) / sizeof(fuse_ll_ops[0]))
+
+static const char *opname(enum fuse_opcode opcode)
+{
+ if (opcode >= FUSE_MAXOP || !fuse_ll_ops[opcode].name)
+ return "???";
+ else
+ return fuse_ll_ops[opcode].name;
+}
+
+
+static void process_buf(int dir, char *buf, int len)
+{
+ static unsigned long long prevuniq = -1;
+ static int prevopcode;
+
+ if (!dir) {
+ struct fuse_in_header *in = (struct fuse_in_header *) buf;
+ buf += sizeof(struct fuse_in_header);
+
+ printf("unique: %llu, opcode: %s (%i), nodeid: %lu, len: %i, insize: %i\n",
+ (unsigned long long) in->unique,
+ opname((enum fuse_opcode) in->opcode), in->opcode,
+ (unsigned long) in->nodeid, in->len, len);
+
+ switch (in->opcode) {
+ case FUSE_READ: {
+ struct fuse_read_in *arg = (struct fuse_read_in *) buf;
+ printf("-READ fh:%llu off:%llu siz:%u rfl:%u own:%llu fl:%u\n",
+ arg->fh, arg->offset, arg->size, arg->read_flags,
+ arg->lock_owner, arg->flags);
+ break;
+ }
+ case FUSE_WRITE: {
+ struct fuse_write_in *arg = (struct fuse_write_in *) buf;
+ printf("-WRITE fh:%llu off:%llu siz:%u wfl:%u own:%llu fl:%u\n",
+ arg->fh, arg->offset, arg->size, arg->write_flags,
+ arg->lock_owner, arg->flags);
+ break;
+ }
+ }
+ prevuniq = in->unique;
+ prevopcode = in->opcode;
+ } else {
+ struct fuse_out_header *out = (struct fuse_out_header *) buf;
+ buf += sizeof(struct fuse_out_header);
+
+ printf(" unique: %llu, error: %i (%s), len: %i, outsize: %i\n",
+ (unsigned long long) out->unique, out->error,
+ strerror(-out->error), out->len, len);
+
+ if (out->unique == prevuniq) {
+ switch (prevopcode) {
+ case FUSE_GETATTR: {
+ struct fuse_attr_out *arg = (struct fuse_attr_out *) buf;
+ printf("+ATTR v:%llu.%09u i:%llu s:%llu b:%llu\n",
+ arg->attr_valid, arg->attr_valid_nsec,
+ arg->attr.ino, arg->attr.size, arg->attr.blocks);
+ break;
+ }
+ case FUSE_LOOKUP: {
+ struct fuse_entry_out *arg = (struct fuse_entry_out *) buf;
+ printf("+ENTRY nodeid:%llu v:%llu.%09u i:%llu s:%llu b:%llu\n",
+ arg->nodeid, arg->attr_valid, arg->attr_valid_nsec,
+ arg->attr.ino, arg->attr.size, arg->attr.blocks);
+ break;
+ }
+ }
+ }
+ }
+
+}
+
+int main(void)
+{
+ FILE *in = stdin;
+ while (1) {
+ int dir;
+ int res;
+ char buf[1048576];
+ unsigned len = 0;
+
+ memset(buf, 0, sizeof(buf));
+ while (1) {
+ char str[32];
+
+ res = fscanf(in, "%30s", str);
+ if (res != 1 && feof(in))
+ return 0;
+
+ if (res == 0)
+ continue;
+
+ if (strncmp(str, "read(", 5) == 0) {
+ dir = 0;
+ break;
+ } else if (strncmp(str, "writev(", 7) == 0) {
+ dir = 1;
+ break;
+ }
+ }
+
+ while (1) {
+ int c = getc(in);
+ if (c == '"') {
+ while (1) {
+ int val;
+
+ c = getc(in);
+ if (c == EOF) {
+ fprintf(stderr, "eof in string\n");
+ break;
+ }
+ if (c == '\n') {
+ fprintf(stderr, "eol in string\n");
+ break;
+ }
+ if (c == '"')
+ break;
+ if (c != '\\') {
+ val = c;
+ } else {
+ c = getc(in);
+ switch (c) {
+ case 'n': val = '\n'; break;
+ case 'r': val = '\r'; break;
+ case 't': val = '\t'; break;
+ case '"': val = '"'; break;
+ case '\\': val = '\\'; break;
+ case 'x':
+ res = scanf("%x", &val);
+ if (res != 1) {
+ fprintf(stderr, "parse error\n");
+ continue;
+ }
+ break;
+ default:
+ fprintf(stderr, "unknown sequence: '\\%c'\n", c);
+ continue;
+ }
+ }
+ buf[len++] = val;
+ }
+ }
+ if (c == '\n')
+ break;
+ }
+ process_buf(dir, buf, len);
+ memset(buf, 0, len);
+ len = 0;
+ }
+}
diff --git a/test/test.c b/test/test.c
index c1646d2..f9aa823 100644
--- a/test/test.c
+++ b/test/test.c
@@ -1254,6 +1254,10 @@ int main(int argc, char *argv[])
}
basepath = argv[1];
assert(strlen(basepath) < 512);
+ if (basepath[0] != '/') {
+ fprintf(stderr, "testdir must be an absolute path\n");
+ return 1;
+ }
sprintf(testfile, "%s/testfile", basepath);
sprintf(testfile2, "%s/testfile2", basepath);