summaryrefslogtreecommitdiffstats
path: root/fuse/fuse.c
diff options
context:
space:
mode:
Diffstat (limited to 'fuse/fuse.c')
-rw-r--r--fuse/fuse.c110
1 files changed, 81 insertions, 29 deletions
diff --git a/fuse/fuse.c b/fuse/fuse.c
index 588d44533..2c1aa17d8 100644
--- a/fuse/fuse.c
+++ b/fuse/fuse.c
@@ -30,13 +30,17 @@
#include <limits.h>
#include <errno.h>
#include <signal.h>
-#include <dlfcn.h>
#include <assert.h>
#include <poll.h>
#include <sys/param.h>
#include <sys/uio.h>
#include <sys/time.h>
#include <sys/mman.h>
+#include <sys/file.h>
+
+#ifdef USE_MODULES
+#include <dlfcn.h>
+#endif
#define FUSE_NODE_SLAB 1
@@ -156,8 +160,8 @@ struct fuse {
struct lock {
int type;
- off64_t start;
- off64_t end;
+ loff_t start;
+ loff_t end;
pid_t pid;
uint64_t owner;
struct lock *next;
@@ -175,7 +179,7 @@ struct node {
int open_count;
struct timespec stat_updated;
struct timespec mtime;
- off64_t size;
+ loff_t size;
struct lock *locks;
unsigned int is_hidden : 1;
unsigned int cache_valid : 1;
@@ -221,6 +225,8 @@ struct fuse_context_i {
static pthread_key_t fuse_context_key;
static pthread_mutex_t fuse_context_lock = PTHREAD_MUTEX_INITIALIZER;
static int fuse_context_ref;
+
+#ifdef USE_MODULES
static struct fusemod_so *fuse_current_so;
static struct fuse_module *fuse_modules;
@@ -319,6 +325,7 @@ static void fuse_put_module(struct fuse_module *m)
}
pthread_mutex_unlock(&fuse_context_lock);
}
+#endif
static void init_list_head(struct list_head *list)
{
@@ -1021,10 +1028,12 @@ static void queue_element_unlock(struct fuse *f, struct lock_queue_element *qe)
if (qe->first_locked) {
wnode = qe->wnode1 ? *qe->wnode1 : NULL;
unlock_path(f, qe->nodeid1, wnode, NULL);
+ qe->first_locked = false;
}
if (qe->second_locked) {
wnode = qe->wnode2 ? *qe->wnode2 : NULL;
unlock_path(f, qe->nodeid2, wnode, NULL);
+ qe->second_locked = false;
}
}
@@ -1757,7 +1766,7 @@ static void fuse_free_buf(struct fuse_bufvec *buf)
}
int fuse_fs_read_buf(struct fuse_fs *fs, const char *path,
- struct fuse_bufvec **bufp, size_t size, off64_t off,
+ struct fuse_bufvec **bufp, size_t size, loff_t off,
struct fuse_file_info *fi)
{
fuse_get_context()->private_data = fs->user_data;
@@ -1812,7 +1821,7 @@ int fuse_fs_read_buf(struct fuse_fs *fs, const char *path,
}
int fuse_fs_read(struct fuse_fs *fs, const char *path, char *mem, size_t size,
- off64_t off, struct fuse_file_info *fi)
+ loff_t off, struct fuse_file_info *fi)
{
int res;
struct fuse_bufvec *buf = NULL;
@@ -1830,7 +1839,7 @@ int fuse_fs_read(struct fuse_fs *fs, const char *path, char *mem, size_t size,
}
int fuse_fs_write_buf(struct fuse_fs *fs, const char *path,
- struct fuse_bufvec *buf, off64_t off,
+ struct fuse_bufvec *buf, loff_t off,
struct fuse_file_info *fi)
{
fuse_get_context()->private_data = fs->user_data;
@@ -1894,7 +1903,7 @@ out:
}
int fuse_fs_write(struct fuse_fs *fs, const char *path, const char *mem,
- size_t size, off64_t off, struct fuse_file_info *fi)
+ size_t size, loff_t off, struct fuse_file_info *fi)
{
struct fuse_bufvec bufv = FUSE_BUFVEC_INIT(size);
@@ -1993,7 +2002,7 @@ static int fill_dir_old(struct fuse_dirhandle *dh, const char *name, int type,
}
int fuse_fs_readdir(struct fuse_fs *fs, const char *path, void *buf,
- fuse_fill_dir_t filler, off64_t off,
+ fuse_fill_dir_t filler, loff_t off,
struct fuse_file_info *fi)
{
fuse_get_context()->private_data = fs->user_data;
@@ -2104,7 +2113,7 @@ int fuse_fs_chown(struct fuse_fs *fs, const char *path, uid_t uid, gid_t gid)
}
}
-int fuse_fs_truncate(struct fuse_fs *fs, const char *path, off64_t size)
+int fuse_fs_truncate(struct fuse_fs *fs, const char *path, loff_t size)
{
fuse_get_context()->private_data = fs->user_data;
if (fs->op.truncate) {
@@ -2118,7 +2127,7 @@ int fuse_fs_truncate(struct fuse_fs *fs, const char *path, off64_t size)
}
}
-int fuse_fs_ftruncate(struct fuse_fs *fs, const char *path, off64_t size,
+int fuse_fs_ftruncate(struct fuse_fs *fs, const char *path, loff_t size,
struct fuse_file_info *fi)
{
fuse_get_context()->private_data = fs->user_data;
@@ -2336,7 +2345,7 @@ int fuse_fs_poll(struct fuse_fs *fs, const char *path,
}
int fuse_fs_fallocate(struct fuse_fs *fs, const char *path, int mode,
- off64_t offset, off64_t length, struct fuse_file_info *fi)
+ loff_t offset, loff_t length, struct fuse_file_info *fi)
{
fuse_get_context()->private_data = fs->user_data;
if (fs->op.fallocate) {
@@ -2393,6 +2402,7 @@ static char *hidden_name(struct fuse *f, fuse_ino_t dir, const char *oldname,
if (res)
break;
+ memset(&buf, 0, sizeof(buf));
res = fuse_fs_getattr(f->fs, newpath, &buf);
if (res == -ENOENT)
break;
@@ -2608,8 +2618,10 @@ void fuse_fs_destroy(struct fuse_fs *fs)
fuse_get_context()->private_data = fs->user_data;
if (fs->op.destroy)
fs->op.destroy(fs->user_data);
+#ifdef USE_MODULES
if (fs->m)
fuse_put_module(fs->m);
+#endif
free(fs);
}
@@ -2766,6 +2778,7 @@ static void fuse_lib_setattr(fuse_req_t req, fuse_ino_t ino, struct stat *attr,
char *path;
int err;
+ memset(&buf, 0, sizeof(buf));
if (valid == FUSE_SET_ATTR_SIZE && fi != NULL &&
f->fs->op.ftruncate && f->fs->op.fgetattr)
err = get_path_nullok(f, ino, &path);
@@ -3235,7 +3248,7 @@ static void fuse_lib_open(fuse_req_t req, fuse_ino_t ino,
}
static void fuse_lib_read(fuse_req_t req, fuse_ino_t ino, size_t size,
- off64_t off, struct fuse_file_info *fi)
+ loff_t off, struct fuse_file_info *fi)
{
struct fuse *f = req_fuse_prepare(req);
struct fuse_bufvec *buf = NULL;
@@ -3261,7 +3274,7 @@ static void fuse_lib_read(fuse_req_t req, fuse_ino_t ino, size_t size,
}
static void fuse_lib_write_buf(fuse_req_t req, fuse_ino_t ino,
- struct fuse_bufvec *buf, off64_t off,
+ struct fuse_bufvec *buf, loff_t off,
struct fuse_file_info *fi)
{
struct fuse *f = req_fuse_prepare(req);
@@ -3390,7 +3403,7 @@ static int extend_contents(struct fuse_dh *dh, unsigned minsize)
}
static int fill_dir(void *dh_, const char *name, const struct stat *statp,
- off64_t off)
+ loff_t off)
{
struct fuse_dh *dh = (struct fuse_dh *) dh_;
struct stat stbuf;
@@ -3440,7 +3453,7 @@ static int fill_dir(void *dh_, const char *name, const struct stat *statp,
}
static int readdir_fill(struct fuse *f, fuse_req_t req, fuse_ino_t ino,
- size_t size, off64_t off, struct fuse_dh *dh,
+ size_t size, loff_t off, struct fuse_dh *dh,
struct fuse_file_info *fi)
{
char *path;
@@ -3472,7 +3485,7 @@ static int readdir_fill(struct fuse *f, fuse_req_t req, fuse_ino_t ino,
}
static void fuse_lib_readdir(fuse_req_t req, fuse_ino_t ino, size_t size,
- off64_t off, struct fuse_file_info *llfi)
+ loff_t off, struct fuse_file_info *llfi)
{
struct fuse *f = req_fuse_prepare(req);
struct fuse_file_info fi;
@@ -3995,12 +4008,13 @@ static void fuse_lib_bmap(fuse_req_t req, fuse_ino_t ino, size_t blocksize,
}
static void fuse_lib_ioctl(fuse_req_t req, fuse_ino_t ino, int cmd, void *arg,
- struct fuse_file_info *fi, unsigned int flags,
+ struct fuse_file_info *llfi, unsigned int flags,
const void *in_buf, size_t in_bufsz,
size_t out_bufsz)
{
struct fuse *f = req_fuse_prepare(req);
struct fuse_intr_data d;
+ struct fuse_file_info fi;
char *path, *out_buf = NULL;
int err;
@@ -4008,6 +4022,11 @@ static void fuse_lib_ioctl(fuse_req_t req, fuse_ino_t ino, int cmd, void *arg,
if (flags & FUSE_IOCTL_UNRESTRICTED)
goto err;
+ if (flags & FUSE_IOCTL_DIR)
+ get_dirhandle(llfi, &fi);
+ else
+ fi = *llfi;
+
if (out_bufsz) {
err = -ENOMEM;
out_buf = malloc(out_bufsz);
@@ -4025,7 +4044,7 @@ static void fuse_lib_ioctl(fuse_req_t req, fuse_ino_t ino, int cmd, void *arg,
fuse_prepare_interrupt(f, req, &d);
- err = fuse_fs_ioctl(f->fs, path, cmd, arg, fi, flags,
+ err = fuse_fs_ioctl(f->fs, path, cmd, arg, &fi, flags,
out_buf ?: (void *)in_buf);
fuse_finish_interrupt(f, req, &d);
@@ -4062,7 +4081,7 @@ static void fuse_lib_poll(fuse_req_t req, fuse_ino_t ino,
}
static void fuse_lib_fallocate(fuse_req_t req, fuse_ino_t ino, int mode,
- off64_t offset, off64_t length, struct fuse_file_info *fi)
+ loff_t offset, loff_t length, struct fuse_file_info *fi)
{
struct fuse *f = req_fuse_prepare(req);
struct fuse_intr_data d;
@@ -4415,12 +4434,14 @@ static void fuse_lib_help(void)
" -o ac_attr_timeout=T auto cache timeout for attributes (attr_timeout)\n"
" -o noforget never forget cached inodes\n"
" -o remember=T remember cached inodes for T seconds (0s)\n"
+" -o nopath don't supply path if not necessary\n"
" -o intr allow requests to be interrupted\n"
" -o intr_signal=NUM signal to send on interrupt (%i)\n"
" -o modules=M1[:M2...] names of modules to push onto filesystem stack\n"
"\n", FUSE_DEFAULT_INTR_SIGNAL);
}
+#ifdef USE_MODULES
static void fuse_lib_help_modules(void)
{
struct fuse_module *m;
@@ -4440,6 +4461,7 @@ static void fuse_lib_help_modules(void)
}
pthread_mutex_unlock(&fuse_context_lock);
}
+#endif
static int fuse_lib_opt_proc(void *data, const char *arg, int key,
struct fuse_args *outargs)
@@ -4495,7 +4517,7 @@ static void fuse_restore_intr_signal(int signum)
sigaction(signum, &sa, NULL);
}
-
+#ifdef USE_MODULES
static int fuse_push_module(struct fuse *f, const char *module,
struct fuse_args *args)
{
@@ -4518,6 +4540,7 @@ static int fuse_push_module(struct fuse *f, const char *module,
f->utime_omit_ok = newfs->op.flag_utime_omit_ok && f->utime_omit_ok;
return 0;
}
+#endif
struct fuse_fs *fuse_fs_new(const struct fuse_operations *op, size_t op_size,
void *user_data)
@@ -4555,11 +4578,30 @@ static int node_table_init(struct node_table *t)
return 0;
}
+static void thread_exit_handler(int sig)
+{
+ pthread_exit(0);
+}
+
static void *fuse_prune_nodes(void *fuse)
{
struct fuse *f = fuse;
int sleep_time;
+#if defined(__ANDROID__)
+ struct sigaction actions;
+ memset(&actions, 0, sizeof(actions));
+ sigemptyset(&actions.sa_mask);
+ actions.sa_flags = 0;
+ actions.sa_handler = thread_exit_handler;
+ sigaction(SIGUSR1, &actions, NULL);
+
+ sigset_t setusr1;
+ sigemptyset(&setusr1);
+ sigaddset(&setusr1, SIGUSR1);
+ pthread_sigmask(SIG_BLOCK, &setusr1, NULL);
+#endif
+
while(1) {
sleep_time = fuse_clean_cache(f);
sleep(sleep_time);
@@ -4579,10 +4621,10 @@ void fuse_stop_cleanup_thread(struct fuse *f)
{
if (lru_enabled(f)) {
pthread_mutex_lock(&f->lock);
-#ifndef ANDROID
- pthread_cancel(f->prune_thread);
-#else
+#if defined(__ANDROID__)
pthread_kill(f->prune_thread, SIGUSR1);
+#else
+ pthread_cancel(f->prune_thread);
#endif
pthread_mutex_unlock(&f->lock);
pthread_join(f->prune_thread, NULL);
@@ -4637,6 +4679,7 @@ struct fuse *fuse_new_common(struct fuse_chan *ch, struct fuse_args *args,
fuse_lib_opt_proc) == -1)
goto out_free_fs;
+#ifdef USE_MODULES
if (f->conf.modules) {
char *module;
char *next;
@@ -4651,6 +4694,7 @@ struct fuse *fuse_new_common(struct fuse_chan *ch, struct fuse_args *args,
goto out_free_fs;
}
}
+#endif
if (!f->conf.ac_attr_timeout_set)
f->conf.ac_attr_timeout = f->conf.attr_timeout;
@@ -4670,8 +4714,10 @@ struct fuse *fuse_new_common(struct fuse_chan *ch, struct fuse_args *args,
f->se = fuse_lowlevel_new_common(args, &llop, sizeof(llop), f);
if (f->se == NULL) {
+#ifdef USE_MODULES
if (f->conf.help)
fuse_lib_help_modules();
+#endif
goto out_free_fs;
}
@@ -4700,6 +4746,10 @@ struct fuse *fuse_new_common(struct fuse_chan *ch, struct fuse_args *args,
fprintf(stderr, "fuse: memory allocation failed\n");
goto out_free_id_table;
}
+ if (lru_enabled(f)) {
+ struct node_lru *lnode = node_lru(root);
+ init_list_head(&lnode->lru);
+ }
strcpy(root->inline_name, "/");
root->name = root->inline_name;
@@ -4808,6 +4858,7 @@ static struct fuse *fuse_new_common_compat25(int fd, struct fuse_args *args,
return f;
}
+#ifdef USE_MODULES
/* called with fuse_context_lock held or during initialization (before
main() has been called) */
void fuse_register_module(struct fuse_module *mod)
@@ -4819,6 +4870,7 @@ void fuse_register_module(struct fuse_module *mod)
mod->next = fuse_modules;
fuse_modules = mod;
}
+#endif
#if !defined(__FreeBSD__) && !defined(__NetBSD__)
@@ -4870,11 +4922,11 @@ struct fuse *fuse_new_compat1(int fd, int flags,
11);
}
-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_exited,__fuse_exited@FUSE_UNVERSIONED");
+FUSE_SYMVER(".symver fuse_process_cmd,__fuse_process_cmd@FUSE_UNVERSIONED");
+FUSE_SYMVER(".symver fuse_read_cmd,__fuse_read_cmd@FUSE_UNVERSIONED");
+FUSE_SYMVER(".symver fuse_set_getcontext_func,__fuse_set_getcontext_func@FUSE_UNVERSIONED");
+FUSE_SYMVER(".symver fuse_new_compat2,fuse_new@FUSE_UNVERSIONED");
FUSE_SYMVER(".symver fuse_new_compat22,fuse_new@FUSE_2.2");
#endif /* __FreeBSD__ || __NetBSD__ */