1 |
/* |
2 |
FUSE: Filesystem in Userspace |
3 |
Copyright (C) 2001-2004 Miklos Szeredi <miklos@szeredi.hu> |
4 |
|
5 |
This program can be distributed under the terms of the GNU GPL. |
6 |
See the file COPYING. |
7 |
*/ |
8 |
|
9 |
|
10 |
#include <linux/fuse.h> |
11 |
#include <linux/version.h> |
12 |
|
13 |
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) && LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) |
14 |
#error Kernel version 2.5.* not supported |
15 |
#endif |
16 |
|
17 |
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) |
18 |
#define KERNEL_2_6 |
19 |
#endif |
20 |
|
21 |
#ifndef KERNEL_2_6 |
22 |
#include <linux/config.h> |
23 |
#ifdef CONFIG_MODVERSIONS |
24 |
#define MODVERSIONS |
25 |
#include <linux/modversions.h> |
26 |
#endif |
27 |
#include <config.h> |
28 |
#ifndef HAVE_I_SIZE_FUNC |
29 |
#define i_size_read(inode) ((inode)->i_size) |
30 |
#define i_size_write(inode, size) do { (inode)->i_size = size; } while(0) |
31 |
#endif |
32 |
#endif |
33 |
#include <linux/kernel.h> |
34 |
#include <linux/module.h> |
35 |
#include <linux/fs.h> |
36 |
#include <linux/list.h> |
37 |
#include <linux/spinlock.h> |
38 |
|
39 |
/** Read combining parameters */ |
40 |
#define FUSE_BLOCK_SHIFT 16 |
41 |
#define FUSE_BLOCK_SIZE 65536 |
42 |
#define FUSE_BLOCK_MASK 0xffff0000 |
43 |
|
44 |
#define FUSE_BLOCK_PAGE_SHIFT (FUSE_BLOCK_SHIFT - PAGE_CACHE_SHIFT) |
45 |
|
46 |
#define FUSE_MAX_PAGES_PER_REQ 32 |
47 |
|
48 |
/** If the FUSE_DEFAULT_PERMISSIONS flag is given, the filesystem |
49 |
module will check permissions based on the file mode. Otherwise no |
50 |
permission checking is done in the kernel */ |
51 |
#define FUSE_DEFAULT_PERMISSIONS (1 << 0) |
52 |
|
53 |
/** If the FUSE_ALLOW_OTHER flag is given, then not only the user |
54 |
doing the mount will be allowed to access the filesystem */ |
55 |
#define FUSE_ALLOW_OTHER (1 << 1) |
56 |
|
57 |
/** If the FUSE_KERNEL_CACHE flag is given, then files will be cached |
58 |
until the INVALIDATE operation is invoked */ |
59 |
#define FUSE_KERNEL_CACHE (1 << 2) |
60 |
|
61 |
#ifndef KERNEL_2_6 |
62 |
/** Allow FUSE to combine reads into 64k chunks. This is useful if |
63 |
the filesystem is better at handling large chunks. NOTE: in |
64 |
current implementation the raw throughput is worse for large reads |
65 |
than for small. */ |
66 |
#define FUSE_LARGE_READ (1 << 31) |
67 |
#endif |
68 |
|
69 |
/** Bypass the page cache for read and write operations */ |
70 |
#define FUSE_DIRECT_IO (1 << 3) |
71 |
|
72 |
/** FUSE specific inode data */ |
73 |
struct fuse_inode { |
74 |
struct fuse_req *forget_req; |
75 |
struct rw_semaphore write_sem; |
76 |
unsigned long i_time; |
77 |
/* Files which can provide file handles in writepage. |
78 |
Protected by write_sem */ |
79 |
struct list_head write_files; |
80 |
}; |
81 |
|
82 |
/** FUSE specific file data */ |
83 |
struct fuse_file { |
84 |
struct fuse_req *release_req; |
85 |
unsigned int fh; |
86 |
struct list_head ff_list; |
87 |
}; |
88 |
|
89 |
/** One input argument of a request */ |
90 |
struct fuse_in_arg { |
91 |
unsigned int size; |
92 |
const void *value; |
93 |
}; |
94 |
|
95 |
/** The request input */ |
96 |
struct fuse_in { |
97 |
struct fuse_in_header h; |
98 |
unsigned int numargs; |
99 |
struct fuse_in_arg args[3]; |
100 |
}; |
101 |
|
102 |
/** One output argument of a request */ |
103 |
struct fuse_out_arg { |
104 |
unsigned int size; |
105 |
void *value; |
106 |
}; |
107 |
|
108 |
/** The request output */ |
109 |
struct fuse_out { |
110 |
struct fuse_out_header h; |
111 |
unsigned int argvar; |
112 |
unsigned int numargs; |
113 |
struct fuse_out_arg args[3]; |
114 |
}; |
115 |
|
116 |
struct fuse_req; |
117 |
struct fuse_conn; |
118 |
|
119 |
typedef void (*fuse_reqend_t)(struct fuse_conn *, struct fuse_req *); |
120 |
typedef int (*fuse_copyout_t)(struct fuse_req *, const char *, size_t); |
121 |
|
122 |
/** |
123 |
* A request to the client |
124 |
*/ |
125 |
struct fuse_req { |
126 |
/** The request list */ |
127 |
struct list_head list; |
128 |
|
129 |
/** True if the request is synchronous */ |
130 |
unsigned int issync:1; |
131 |
|
132 |
/** The request is locked */ |
133 |
unsigned int locked:1; |
134 |
|
135 |
/** The request has been interrupted while it was locked */ |
136 |
unsigned int interrupted:1; |
137 |
|
138 |
/* The request has been sent to the client */ |
139 |
unsigned int sent:1; |
140 |
|
141 |
/* The request is preallocated */ |
142 |
unsigned int preallocated:1; |
143 |
|
144 |
/* The request is finished */ |
145 |
unsigned int finished; |
146 |
|
147 |
/** The request input */ |
148 |
struct fuse_in in; |
149 |
|
150 |
/** The request output */ |
151 |
struct fuse_out out; |
152 |
|
153 |
/** Used to wake up the task waiting for completion of request*/ |
154 |
wait_queue_head_t waitq; |
155 |
|
156 |
/** Request completion callback */ |
157 |
fuse_reqend_t end; |
158 |
|
159 |
/** Request copy out function */ |
160 |
fuse_copyout_t copy_out; |
161 |
|
162 |
/** User data */ |
163 |
void *data; |
164 |
|
165 |
/** Data for asynchronous requests */ |
166 |
union { |
167 |
struct { |
168 |
struct fuse_write_in in; |
169 |
struct fuse_write_out out; |
170 |
|
171 |
} write; |
172 |
struct fuse_read_in read_in; |
173 |
struct fuse_release_in release_in; |
174 |
struct fuse_forget_in forget_in; |
175 |
} misc; |
176 |
|
177 |
struct page *pages[FUSE_MAX_PAGES_PER_REQ]; |
178 |
unsigned num_pages; |
179 |
}; |
180 |
|
181 |
/** |
182 |
* A Fuse connection. |
183 |
* |
184 |
* This structure is created, when the client device is opened, and is |
185 |
* destroyed, when the client device is closed _and_ the filesystem is |
186 |
* unmounted. |
187 |
*/ |
188 |
struct fuse_conn { |
189 |
/** The superblock of the mounted filesystem */ |
190 |
struct super_block *sb; |
191 |
|
192 |
/** The opened client device */ |
193 |
struct file *file; |
194 |
|
195 |
/** The user id for this mount */ |
196 |
uid_t uid; |
197 |
|
198 |
/** The fuse mount flags for this mount */ |
199 |
unsigned int flags; |
200 |
|
201 |
/** Maximum read size */ |
202 |
unsigned int max_read; |
203 |
|
204 |
/** Maximum write size */ |
205 |
unsigned int max_write; |
206 |
|
207 |
/** Readers of the connection are waiting on this */ |
208 |
wait_queue_head_t waitq; |
209 |
|
210 |
/** The list of pending requests */ |
211 |
struct list_head pending; |
212 |
|
213 |
/** The list of requests being processed */ |
214 |
struct list_head processing; |
215 |
|
216 |
/** Controls the maximum number of outstanding requests */ |
217 |
struct semaphore unused_sem; |
218 |
|
219 |
/** The list of unused requests */ |
220 |
struct list_head unused_list; |
221 |
|
222 |
/** The next unique request id */ |
223 |
int reqctr; |
224 |
|
225 |
/** Is fsync not implemented by fs? */ |
226 |
unsigned int no_fsync : 1; |
227 |
|
228 |
/** Is flush not implemented by fs? */ |
229 |
unsigned int no_flush : 1; |
230 |
|
231 |
/** Is setxattr not implemented by fs? */ |
232 |
unsigned int no_setxattr : 1; |
233 |
|
234 |
/** Is getxattr not implemented by fs? */ |
235 |
unsigned int no_getxattr : 1; |
236 |
|
237 |
/** Is listxattr not implemented by fs? */ |
238 |
unsigned int no_listxattr : 1; |
239 |
|
240 |
/** Is removexattr not implemented by fs? */ |
241 |
unsigned int no_removexattr : 1; |
242 |
}; |
243 |
|
244 |
struct fuse_getdir_out_i { |
245 |
int fd; |
246 |
void *file; /* Used by kernel only */ |
247 |
}; |
248 |
|
249 |
#ifdef KERNEL_2_6 |
250 |
#define SB_FC(sb) ((sb)->s_fs_info) |
251 |
#else |
252 |
#define SB_FC(sb) ((sb)->u.generic_sbp) |
253 |
#endif |
254 |
#define INO_FC(inode) SB_FC((inode)->i_sb) |
255 |
#define DEV_FC(file) ((file)->private_data) |
256 |
#define INO_FI(inode) ((inode)->u.generic_ip) |
257 |
|
258 |
|
259 |
/** |
260 |
* The proc entry for the client device ("/proc/fs/fuse/dev") |
261 |
*/ |
262 |
extern struct proc_dir_entry *proc_fuse_dev; |
263 |
|
264 |
/** |
265 |
* The lock to protect fuses structures |
266 |
*/ |
267 |
extern spinlock_t fuse_lock; |
268 |
|
269 |
|
270 |
/** |
271 |
* Get a filled in inode |
272 |
*/ |
273 |
struct inode *fuse_iget(struct super_block *sb, ino_t ino, int generation, |
274 |
struct fuse_attr *attr, int version); |
275 |
|
276 |
|
277 |
/** |
278 |
* Send FORGET command |
279 |
*/ |
280 |
void fuse_send_forget(struct fuse_conn *fc, struct fuse_req *req, ino_t ino, |
281 |
int version); |
282 |
|
283 |
/** |
284 |
* Initialise operations on regular file |
285 |
*/ |
286 |
void fuse_init_file_inode(struct inode *inode); |
287 |
|
288 |
/** |
289 |
* Check if the connection can be released, and if yes, then free the |
290 |
* connection structure |
291 |
*/ |
292 |
void fuse_release_conn(struct fuse_conn *fc); |
293 |
|
294 |
/** |
295 |
* Initialize the client device |
296 |
*/ |
297 |
int fuse_dev_init(void); |
298 |
|
299 |
/** |
300 |
* Cleanup the client device |
301 |
*/ |
302 |
void fuse_dev_cleanup(void); |
303 |
|
304 |
/** |
305 |
* Initialize the fuse filesystem |
306 |
*/ |
307 |
int fuse_fs_init(void); |
308 |
|
309 |
/** |
310 |
* Cleanup the fuse filesystem |
311 |
*/ |
312 |
void fuse_fs_cleanup(void); |
313 |
|
314 |
|
315 |
/** |
316 |
* Allocate a request |
317 |
*/ |
318 |
struct fuse_req *fuse_request_alloc(void); |
319 |
|
320 |
/** |
321 |
* Free a request |
322 |
*/ |
323 |
void fuse_request_free(struct fuse_req *req); |
324 |
|
325 |
/** |
326 |
* Reinitialize a request, the preallocated flag is left unmodified |
327 |
*/ |
328 |
void fuse_reset_request(struct fuse_req *req); |
329 |
|
330 |
/** |
331 |
* Reserve a preallocated request |
332 |
*/ |
333 |
struct fuse_req *fuse_get_request(struct fuse_conn *fc); |
334 |
|
335 |
/** |
336 |
* Reserve a preallocated request, non-blocking |
337 |
*/ |
338 |
struct fuse_req *fuse_get_request_nonblock(struct fuse_conn *fc); |
339 |
|
340 |
/** |
341 |
* Free a request |
342 |
*/ |
343 |
void fuse_put_request(struct fuse_conn *fc, struct fuse_req *req); |
344 |
|
345 |
/** |
346 |
* Send a request |
347 |
*/ |
348 |
void request_send(struct fuse_conn *fc, struct fuse_req *req); |
349 |
|
350 |
/** |
351 |
* Send a request for which a reply is not expected |
352 |
*/ |
353 |
void request_send_noreply(struct fuse_conn *fc, struct fuse_req *req); |
354 |
|
355 |
/** |
356 |
* Send a synchronous request without blocking |
357 |
*/ |
358 |
void request_send_nonblock(struct fuse_conn *fc, struct fuse_req *req, |
359 |
fuse_reqend_t end, void *data); |
360 |
|
361 |
/** |
362 |
* Get the attributes of a file |
363 |
*/ |
364 |
int fuse_do_getattr(struct inode *inode); |
365 |
|
366 |
/** |
367 |
* Write dirty pages |
368 |
*/ |
369 |
void fuse_sync_inode(struct inode *inode); |
370 |
|
371 |
/** |
372 |
* Allocate fuse specific inode data |
373 |
*/ |
374 |
struct fuse_inode *fuse_inode_alloc(void); |
375 |
|
376 |
/* |
377 |
* Local Variables: |
378 |
* indent-tabs-mode: t |
379 |
* c-basic-offset: 8 |
380 |
* End: |
381 |
*/ |