-
Notifications
You must be signed in to change notification settings - Fork 0
/
vfs_fuse.c
119 lines (105 loc) · 3.38 KB
/
vfs_fuse.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#include <signal.h>
#include <errno.h>
#define FUSE_USE_VERSION 26
#include <fuse/fuse_i.h>
#include <fuse/fuse_lowlevel.h>
#include "conf.h"
#include "db.h"
#include "evt.h"
#include "logger.h"
#include "memory.h"
#include "pkg.h"
#include "vfs.h"
#define VFS_FUSE_C /* required for vfs_fuse_spill.h */
#include "vfs_pkg.h"
#include "vfs_spill.h"
#undef VFS_FUSE_C
static ev_io vfs_fuse_evt;
static struct fuse_chan *vfs_fuse_chan = NULL;
static struct fuse_session *vfs_fuse_sess = NULL;
struct fuse_args vfs_fuse_args = { 0, NULL, 0 };
/* FUSE operations */
static struct fuse_lowlevel_ops vfs_fuse_ops = {
/* File operations */
.lookup = vfs_fuse_lookup,
.readlink = vfs_fuse_readlink,
.open = vfs_fuse_open,
.release = vfs_fuse_release,
.read = vfs_fuse_read,
/* Stat/permissions */
.getattr = vfs_fuse_getattr,
.access = vfs_fuse_access,
.statfs = vfs_fuse_statfs,
.getxattr = vfs_fuse_getxattr,
.listxattr = vfs_fuse_listxattr,
/* Directory operations */
.opendir = vfs_fuse_opendir,
.readdir = vfs_fuse_readdir,
.releasedir = vfs_fuse_releasedir,
/* Spillover operations, unsupported for now */
.create = vfs_fuse_create,
.mknod = vfs_fuse_mknod,
.mkdir = vfs_fuse_mkdir,
.symlink = vfs_fuse_symlink,
.unlink = vfs_fuse_unlink,
.rmdir = vfs_fuse_rmdir,
.rename = vfs_fuse_rename,
.link = vfs_fuse_link,
.write = vfs_fuse_write,
.setxattr = vfs_fuse_setxattr,
.removexattr = vfs_fuse_removexattr
};
/* This is a hacked up version of fuse/fuse_loop.c, hope it works -bk */
static void vfs_fuse_read_cb(struct ev_loop *loop, ev_io * w, int revents) {
int res = 0;
struct fuse_chan *ch = fuse_session_next_chan(vfs_fuse_sess, NULL);
struct fuse_chan *tmpch = ch;
size_t bufsize = fuse_chan_bufsize(ch);
char *buf;
if (!(buf = mem_alloc(bufsize))) {
Log(LOG_FATAL, "fuse: failed to allocate read buffer\n");
conf.dying = 1;
return;
}
res = fuse_chan_recv(&tmpch, buf, bufsize);
if (!(res == -EINTR || res <= 0))
fuse_session_process(vfs_fuse_sess, buf, res, tmpch);
mem_free(buf);
fuse_session_reset(vfs_fuse_sess);
}
void vfs_fuse_fini(void) {
if (vfs_fuse_sess != NULL)
fuse_session_destroy(vfs_fuse_sess);
if (vfs_fuse_chan != NULL) {
fuse_session_remove_chan(vfs_fuse_chan);
fuse_unmount(dconf_get_str("path.mountpoint", "/"), vfs_fuse_chan);
}
if (vfs_fuse_args.allocated)
fuse_opt_free_args(&vfs_fuse_args);
}
void vfs_fuse_init(void) {
if ((vfs_fuse_chan = fuse_mount(conf.mountpoint, &vfs_fuse_args)) == NULL) {
Log(LOG_FATAL, "FUSE: mount error");
conf.dying = 1;
raise(SIGTERM);
}
if ((vfs_fuse_sess = fuse_lowlevel_new(&vfs_fuse_args, &vfs_fuse_ops,
sizeof(vfs_fuse_ops), NULL)) != NULL) {
fuse_session_add_chan(vfs_fuse_sess, vfs_fuse_chan);
} else {
Log(LOG_FATAL, "FUSE: unable to create session");
conf.dying = 1;
raise(SIGTERM);
}
/*
* Register an interest in events on the fuse fd
*/
ev_io_init(&vfs_fuse_evt, vfs_fuse_read_cb, fuse_chan_fd(vfs_fuse_chan), EV_READ);
ev_io_start(evt_loop, &vfs_fuse_evt);
/*
* Set up our various blockheaps
*/
vfs_handle_heap =
blockheap_create(sizeof(vfs_handle_t),
dconf_get_int("tuning.heap.vfs_handle", 128), "vfs_handle");
}