aboutsummaryrefslogtreecommitdiffstats
path: root/fs/fuse/inode.c
diff options
context:
space:
mode:
authorMiklos Szeredi <miklos@szeredi.hu>2005-09-09 16:10:27 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2005-09-09 17:03:44 -0400
commit334f485df85ac7736ebe14940bf0a059c5f26d7d (patch)
tree754e5528289048a7104f4c1b431cebc1df16e2ce /fs/fuse/inode.c
parentd8a5ba45457e4a22aa39c939121efd7bb6c76672 (diff)
[PATCH] FUSE - device functions
This adds the FUSE device handling functions. This contains the following files: o dev.c - fuse device operations (read, write, release, poll) - registers misc device - support for sending requests to userspace Signed-off-by: Miklos Szeredi <miklos@szeredi.hu> Signed-off-by: Adrian Bunk <bunk@stusta.de> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'fs/fuse/inode.c')
-rw-r--r--fs/fuse/inode.c58
1 files changed, 53 insertions, 5 deletions
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index ea6339c2b6a1..33fad334ba70 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -151,6 +151,8 @@ static void fuse_put_super(struct super_block *sb)
151 mount_count --; 151 mount_count --;
152 fc->sb = NULL; 152 fc->sb = NULL;
153 fc->user_id = 0; 153 fc->user_id = 0;
154 /* Flush all readers on this fs */
155 wake_up_all(&fc->waitq);
154 fuse_release_conn(fc); 156 fuse_release_conn(fc);
155 *get_fuse_conn_super_p(sb) = NULL; 157 *get_fuse_conn_super_p(sb) = NULL;
156 spin_unlock(&fuse_lock); 158 spin_unlock(&fuse_lock);
@@ -229,22 +231,51 @@ static int fuse_show_options(struct seq_file *m, struct vfsmount *mnt)
229 return 0; 231 return 0;
230} 232}
231 233
232void fuse_release_conn(struct fuse_conn *fc) 234static void free_conn(struct fuse_conn *fc)
233{ 235{
236 while (!list_empty(&fc->unused_list)) {
237 struct fuse_req *req;
238 req = list_entry(fc->unused_list.next, struct fuse_req, list);
239 list_del(&req->list);
240 fuse_request_free(req);
241 }
234 kfree(fc); 242 kfree(fc);
235} 243}
236 244
245/* Must be called with the fuse lock held */
246void fuse_release_conn(struct fuse_conn *fc)
247{
248 if (!fc->sb && !fc->file)
249 free_conn(fc);
250}
251
237static struct fuse_conn *new_conn(void) 252static struct fuse_conn *new_conn(void)
238{ 253{
239 struct fuse_conn *fc; 254 struct fuse_conn *fc;
240 255
241 fc = kmalloc(sizeof(*fc), GFP_KERNEL); 256 fc = kmalloc(sizeof(*fc), GFP_KERNEL);
242 if (fc != NULL) { 257 if (fc != NULL) {
258 int i;
243 memset(fc, 0, sizeof(*fc)); 259 memset(fc, 0, sizeof(*fc));
244 fc->sb = NULL; 260 fc->sb = NULL;
261 fc->file = NULL;
245 fc->user_id = 0; 262 fc->user_id = 0;
263 init_waitqueue_head(&fc->waitq);
264 INIT_LIST_HEAD(&fc->pending);
265 INIT_LIST_HEAD(&fc->processing);
266 INIT_LIST_HEAD(&fc->unused_list);
267 sema_init(&fc->outstanding_sem, 0);
268 for (i = 0; i < FUSE_MAX_OUTSTANDING; i++) {
269 struct fuse_req *req = fuse_request_alloc();
270 if (!req) {
271 free_conn(fc);
272 return NULL;
273 }
274 list_add(&req->list, &fc->unused_list);
275 }
246 fc->bdi.ra_pages = (VM_MAX_READAHEAD * 1024) / PAGE_CACHE_SIZE; 276 fc->bdi.ra_pages = (VM_MAX_READAHEAD * 1024) / PAGE_CACHE_SIZE;
247 fc->bdi.unplug_io_fn = default_unplug_io_fn; 277 fc->bdi.unplug_io_fn = default_unplug_io_fn;
278 fc->reqctr = 0;
248 } 279 }
249 return fc; 280 return fc;
250} 281}
@@ -253,11 +284,20 @@ static struct fuse_conn *get_conn(struct file *file, struct super_block *sb)
253{ 284{
254 struct fuse_conn *fc; 285 struct fuse_conn *fc;
255 286
287 if (file->f_op != &fuse_dev_operations)
288 return ERR_PTR(-EINVAL);
256 fc = new_conn(); 289 fc = new_conn();
257 if (fc == NULL) 290 if (fc == NULL)
258 return NULL; 291 return ERR_PTR(-ENOMEM);
259 spin_lock(&fuse_lock); 292 spin_lock(&fuse_lock);
260 fc->sb = sb; 293 if (file->private_data) {
294 free_conn(fc);
295 fc = ERR_PTR(-EINVAL);
296 } else {
297 file->private_data = fc;
298 fc->sb = sb;
299 fc->file = file;
300 }
261 spin_unlock(&fuse_lock); 301 spin_unlock(&fuse_lock);
262 return fc; 302 return fc;
263} 303}
@@ -315,8 +355,8 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent)
315 355
316 fc = get_conn(file, sb); 356 fc = get_conn(file, sb);
317 fput(file); 357 fput(file);
318 if (fc == NULL) 358 if (IS_ERR(fc))
319 return -EINVAL; 359 return PTR_ERR(fc);
320 360
321 fc->user_id = d.user_id; 361 fc->user_id = d.user_id;
322 362
@@ -336,6 +376,7 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent)
336 iput(root); 376 iput(root);
337 goto err; 377 goto err;
338 } 378 }
379 fuse_send_init(fc);
339 return 0; 380 return 0;
340 381
341 err: 382 err:
@@ -411,8 +452,14 @@ static int __init fuse_init(void)
411 if (res) 452 if (res)
412 goto err; 453 goto err;
413 454
455 res = fuse_dev_init();
456 if (res)
457 goto err_fs_cleanup;
458
414 return 0; 459 return 0;
415 460
461 err_fs_cleanup:
462 fuse_fs_cleanup();
416 err: 463 err:
417 return res; 464 return res;
418} 465}
@@ -422,6 +469,7 @@ static void __exit fuse_exit(void)
422 printk(KERN_DEBUG "fuse exit\n"); 469 printk(KERN_DEBUG "fuse exit\n");
423 470
424 fuse_fs_cleanup(); 471 fuse_fs_cleanup();
472 fuse_dev_cleanup();
425} 473}
426 474
427module_init(fuse_init); 475module_init(fuse_init);