Per the discussion here: <https://bugzilla.samba.org/show_bug.cgi?id=5847>,
the cause appears to be the fact that libsmbclient is not thread-safe.
While fusesmb uses locking around accesses to SMBC contexts, it uses
different locks for different contexts, and ends up making simultaenous
calls into libsmbclient -- something that is not supported. Therefore,
despite the fact that a reentrant libsmbclient would be great, I believe
the bugs lies in fusesmb. The attached patch causes fusesmb to use a single
mutex for all calls, and fixes the problem for me. Whereas without the
patch, gzip'ing a single file would cause a lockup 9/10 times, I can now
consistently gzip 10 files at once with no problems.
--- fusesmb-0.8.7/fusesmb.c 2007-09-06 19:02:44.000000000 -0500
+++ fusesmb-0.8.7.new/fusesmb.c 2009-03-30 15:27:43.000000000 -0500
@@ -53,7 +53,6 @@
*/
static pthread_mutex_t ctx_mutex = PTHREAD_MUTEX_INITIALIZER;
-static pthread_mutex_t rwd_ctx_mutex = PTHREAD_MUTEX_INITIALIZER;
static SMBCCTX *ctx, *rwd_ctx;
pthread_t cleanup_thread;
@@ -129,11 +128,9 @@
pthread_mutex_lock(&ctx_mutex);
ctx->callbacks.purge_cached_fn(ctx);
- pthread_mutex_unlock(&ctx_mutex);
- pthread_mutex_lock(&rwd_ctx_mutex);
rwd_ctx->callbacks.purge_cached_fn(rwd_ctx);
- pthread_mutex_unlock(&rwd_ctx_mutex);
+ pthread_mutex_unlock(&ctx_mutex);
/*
* Look every minute in the notfound cache for items that are
* no longer used
@@ -204,11 +201,9 @@
{
pthread_mutex_lock(&ctx_mutex);
ctx->timeout = opts.global_timeout * 1000;
- pthread_mutex_unlock(&ctx_mutex);
- pthread_mutex_lock(&rwd_ctx_mutex);
rwd_ctx->timeout = opts.global_timeout * 1000;
- pthread_mutex_unlock(&rwd_ctx_mutex);
+ pthread_mutex_unlock(&ctx_mutex);
}
@@ -536,17 +531,17 @@
// return -ENOENT;
strcat(smb_path, stripworkgroup(path));
- pthread_mutex_lock(&rwd_ctx_mutex);
+ pthread_mutex_lock(&ctx_mutex);
file = rwd_ctx->open(rwd_ctx, smb_path, fi->flags, 0);
if (file == NULL)
{
- pthread_mutex_unlock(&rwd_ctx_mutex);
+ pthread_mutex_unlock(&ctx_mutex);
return -errno;
}
fi->fh = (unsigned long)file;
- pthread_mutex_unlock(&rwd_ctx_mutex);
+ pthread_mutex_unlock(&ctx_mutex);
return 0;
}
@@ -563,7 +558,7 @@
int tries = 0; //For number of retries before failing
ssize_t ssize; //Returned by ctx->read
- pthread_mutex_lock(&rwd_ctx_mutex);
+ pthread_mutex_lock(&ctx_mutex);
/* Ugly goto but it works ;) But IMHO easiest solution for error handling
here */
goto seek;
reopen:
@@ -575,7 +570,7 @@
tries++;
if (tries > 4)
{
- pthread_mutex_unlock(&rwd_ctx_mutex);
+ pthread_mutex_unlock(&ctx_mutex);
return -errno;
}
goto reopen;
@@ -583,7 +578,7 @@
/* Other errors from docs cannot be recovered from so returning the
error */
else
{
- pthread_mutex_unlock(&rwd_ctx_mutex);
+ pthread_mutex_unlock(&ctx_mutex);
return -errno;
}
}
@@ -600,7 +595,7 @@
else
{
//SMB Init failed
- pthread_mutex_unlock(&rwd_ctx_mutex);
+ pthread_mutex_unlock(&ctx_mutex);
return -errno;
}
}
@@ -614,11 +609,11 @@
/* Tried opening a directory / or smb_init failed */
else
{
- pthread_mutex_unlock(&rwd_ctx_mutex);
+ pthread_mutex_unlock(&ctx_mutex);
return -errno;
}
}
- pthread_mutex_unlock(&rwd_ctx_mutex);
+ pthread_mutex_unlock(&ctx_mutex);
return (size_t) ssize;
}
@@ -632,7 +627,7 @@
int tries = 0; //For number of retries before failing
ssize_t ssize; //Returned by ctx->read
- pthread_mutex_lock(&rwd_ctx_mutex);
+ pthread_mutex_lock(&ctx_mutex);
/* Ugly goto but it works ;) But IMHO easiest solution for error handling
here */
goto seek;
reopen:
@@ -644,13 +639,13 @@
tries++;
if (tries > 4)
{
- pthread_mutex_unlock(&rwd_ctx_mutex);
+ pthread_mutex_unlock(&ctx_mutex);
return -errno;
}
goto reopen;
}
/* Other errors from docs cannot be recovered from so returning the
error */
- pthread_mutex_unlock(&rwd_ctx_mutex);
+ pthread_mutex_unlock(&ctx_mutex);
return -errno;
}
@@ -667,7 +662,7 @@
else
{
//SMB Init failed
- pthread_mutex_unlock(&rwd_ctx_mutex);
+ pthread_mutex_unlock(&ctx_mutex);
return -errno;
}
}
@@ -681,24 +676,24 @@
/* Tried opening a directory / or smb_init failed */
else
{
- pthread_mutex_unlock(&rwd_ctx_mutex);
+ pthread_mutex_unlock(&ctx_mutex);
return -errno;
}
}
- pthread_mutex_unlock(&rwd_ctx_mutex);
+ pthread_mutex_unlock(&ctx_mutex);
return (size_t) ssize;
}
static int fusesmb_release(const char *path, struct fuse_file_info *fi)
{
(void)path;
- pthread_mutex_lock(&rwd_ctx_mutex);
+ pthread_mutex_lock(&ctx_mutex);
#ifdef HAVE_LIBSMBCLIENT_CLOSE_FN
rwd_ctx->close_fn(rwd_ctx, (SMBCFILE *)fi->fh);
#else
rwd_ctx->close(rwd_ctx, (SMBCFILE *)fi->fh);
#endif
- pthread_mutex_unlock(&rwd_ctx_mutex);
+ pthread_mutex_unlock(&ctx_mutex);
return 0;
}