aboutsummaryrefslogtreecommitdiffstats
path: root/fs/fuse/inode.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/fuse/inode.c')
-rw-r--r--fs/fuse/inode.c282
1 files changed, 235 insertions, 47 deletions
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index e69a546844d0..c755a0440a66 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -24,6 +24,13 @@ MODULE_LICENSE("GPL");
24 24
25spinlock_t fuse_lock; 25spinlock_t fuse_lock;
26static kmem_cache_t *fuse_inode_cachep; 26static kmem_cache_t *fuse_inode_cachep;
27static struct subsystem connections_subsys;
28
29struct fuse_conn_attr {
30 struct attribute attr;
31 ssize_t (*show)(struct fuse_conn *, char *);
32 ssize_t (*store)(struct fuse_conn *, const char *, size_t);
33};
27 34
28#define FUSE_SUPER_MAGIC 0x65735546 35#define FUSE_SUPER_MAGIC 0x65735546
29 36
@@ -135,12 +142,8 @@ static void fuse_init_inode(struct inode *inode, struct fuse_attr *attr)
135 fuse_init_common(inode); 142 fuse_init_common(inode);
136 init_special_inode(inode, inode->i_mode, 143 init_special_inode(inode, inode->i_mode,
137 new_decode_dev(attr->rdev)); 144 new_decode_dev(attr->rdev));
138 } else { 145 } else
139 /* Don't let user create weird files */ 146 BUG();
140 inode->i_mode = S_IFREG;
141 fuse_init_common(inode);
142 fuse_init_file_inode(inode);
143 }
144} 147}
145 148
146static int fuse_inode_eq(struct inode *inode, void *_nodeidp) 149static int fuse_inode_eq(struct inode *inode, void *_nodeidp)
@@ -193,6 +196,11 @@ struct inode *fuse_iget(struct super_block *sb, unsigned long nodeid,
193 return inode; 196 return inode;
194} 197}
195 198
199static void fuse_umount_begin(struct super_block *sb)
200{
201 fuse_abort_conn(get_fuse_conn_super(sb));
202}
203
196static void fuse_put_super(struct super_block *sb) 204static void fuse_put_super(struct super_block *sb)
197{ 205{
198 struct fuse_conn *fc = get_fuse_conn_super(sb); 206 struct fuse_conn *fc = get_fuse_conn_super(sb);
@@ -204,20 +212,20 @@ static void fuse_put_super(struct super_block *sb)
204 212
205 spin_lock(&fuse_lock); 213 spin_lock(&fuse_lock);
206 fc->mounted = 0; 214 fc->mounted = 0;
207 fc->user_id = 0; 215 fc->connected = 0;
208 fc->group_id = 0; 216 spin_unlock(&fuse_lock);
209 fc->flags = 0; 217 up_write(&fc->sbput_sem);
210 /* Flush all readers on this fs */ 218 /* Flush all readers on this fs */
211 wake_up_all(&fc->waitq); 219 wake_up_all(&fc->waitq);
212 up_write(&fc->sbput_sem); 220 kobject_del(&fc->kobj);
213 fuse_release_conn(fc); 221 kobject_put(&fc->kobj);
214 spin_unlock(&fuse_lock);
215} 222}
216 223
217static void convert_fuse_statfs(struct kstatfs *stbuf, struct fuse_kstatfs *attr) 224static void convert_fuse_statfs(struct kstatfs *stbuf, struct fuse_kstatfs *attr)
218{ 225{
219 stbuf->f_type = FUSE_SUPER_MAGIC; 226 stbuf->f_type = FUSE_SUPER_MAGIC;
220 stbuf->f_bsize = attr->bsize; 227 stbuf->f_bsize = attr->bsize;
228 stbuf->f_frsize = attr->frsize;
221 stbuf->f_blocks = attr->blocks; 229 stbuf->f_blocks = attr->blocks;
222 stbuf->f_bfree = attr->bfree; 230 stbuf->f_bfree = attr->bfree;
223 stbuf->f_bavail = attr->bavail; 231 stbuf->f_bavail = attr->bavail;
@@ -238,10 +246,12 @@ static int fuse_statfs(struct super_block *sb, struct kstatfs *buf)
238 if (!req) 246 if (!req)
239 return -EINTR; 247 return -EINTR;
240 248
249 memset(&outarg, 0, sizeof(outarg));
241 req->in.numargs = 0; 250 req->in.numargs = 0;
242 req->in.h.opcode = FUSE_STATFS; 251 req->in.h.opcode = FUSE_STATFS;
243 req->out.numargs = 1; 252 req->out.numargs = 1;
244 req->out.args[0].size = sizeof(outarg); 253 req->out.args[0].size =
254 fc->minor < 4 ? FUSE_COMPAT_STATFS_SIZE : sizeof(outarg);
245 req->out.args[0].value = &outarg; 255 req->out.args[0].value = &outarg;
246 request_send(fc, req); 256 request_send(fc, req);
247 err = req->out.h.error; 257 err = req->out.h.error;
@@ -357,8 +367,10 @@ static int fuse_show_options(struct seq_file *m, struct vfsmount *mnt)
357 return 0; 367 return 0;
358} 368}
359 369
360static void free_conn(struct fuse_conn *fc) 370static void fuse_conn_release(struct kobject *kobj)
361{ 371{
372 struct fuse_conn *fc = get_fuse_conn_kobj(kobj);
373
362 while (!list_empty(&fc->unused_list)) { 374 while (!list_empty(&fc->unused_list)) {
363 struct fuse_req *req; 375 struct fuse_req *req;
364 req = list_entry(fc->unused_list.next, struct fuse_req, list); 376 req = list_entry(fc->unused_list.next, struct fuse_req, list);
@@ -368,33 +380,28 @@ static void free_conn(struct fuse_conn *fc)
368 kfree(fc); 380 kfree(fc);
369} 381}
370 382
371/* Must be called with the fuse lock held */
372void fuse_release_conn(struct fuse_conn *fc)
373{
374 fc->count--;
375 if (!fc->count)
376 free_conn(fc);
377}
378
379static struct fuse_conn *new_conn(void) 383static struct fuse_conn *new_conn(void)
380{ 384{
381 struct fuse_conn *fc; 385 struct fuse_conn *fc;
382 386
383 fc = kmalloc(sizeof(*fc), GFP_KERNEL); 387 fc = kzalloc(sizeof(*fc), GFP_KERNEL);
384 if (fc != NULL) { 388 if (fc) {
385 int i; 389 int i;
386 memset(fc, 0, sizeof(*fc));
387 init_waitqueue_head(&fc->waitq); 390 init_waitqueue_head(&fc->waitq);
388 INIT_LIST_HEAD(&fc->pending); 391 INIT_LIST_HEAD(&fc->pending);
389 INIT_LIST_HEAD(&fc->processing); 392 INIT_LIST_HEAD(&fc->processing);
393 INIT_LIST_HEAD(&fc->io);
390 INIT_LIST_HEAD(&fc->unused_list); 394 INIT_LIST_HEAD(&fc->unused_list);
391 INIT_LIST_HEAD(&fc->background); 395 INIT_LIST_HEAD(&fc->background);
392 sema_init(&fc->outstanding_sem, 0); 396 sema_init(&fc->outstanding_sem, 1); /* One for INIT */
393 init_rwsem(&fc->sbput_sem); 397 init_rwsem(&fc->sbput_sem);
398 kobj_set_kset_s(fc, connections_subsys);
399 kobject_init(&fc->kobj);
400 atomic_set(&fc->num_waiting, 0);
394 for (i = 0; i < FUSE_MAX_OUTSTANDING; i++) { 401 for (i = 0; i < FUSE_MAX_OUTSTANDING; i++) {
395 struct fuse_req *req = fuse_request_alloc(); 402 struct fuse_req *req = fuse_request_alloc();
396 if (!req) { 403 if (!req) {
397 free_conn(fc); 404 kobject_put(&fc->kobj);
398 return NULL; 405 return NULL;
399 } 406 }
400 list_add(&req->list, &fc->unused_list); 407 list_add(&req->list, &fc->unused_list);
@@ -409,25 +416,32 @@ static struct fuse_conn *new_conn(void)
409static struct fuse_conn *get_conn(struct file *file, struct super_block *sb) 416static struct fuse_conn *get_conn(struct file *file, struct super_block *sb)
410{ 417{
411 struct fuse_conn *fc; 418 struct fuse_conn *fc;
419 int err;
412 420
421 err = -EINVAL;
413 if (file->f_op != &fuse_dev_operations) 422 if (file->f_op != &fuse_dev_operations)
414 return ERR_PTR(-EINVAL); 423 goto out_err;
424
425 err = -ENOMEM;
415 fc = new_conn(); 426 fc = new_conn();
416 if (fc == NULL) 427 if (!fc)
417 return ERR_PTR(-ENOMEM); 428 goto out_err;
429
418 spin_lock(&fuse_lock); 430 spin_lock(&fuse_lock);
419 if (file->private_data) { 431 err = -EINVAL;
420 free_conn(fc); 432 if (file->private_data)
421 fc = ERR_PTR(-EINVAL); 433 goto out_unlock;
422 } else { 434
423 file->private_data = fc; 435 kobject_get(&fc->kobj);
424 *get_fuse_conn_super_p(sb) = fc; 436 file->private_data = fc;
425 fc->mounted = 1;
426 fc->connected = 1;
427 fc->count = 2;
428 }
429 spin_unlock(&fuse_lock); 437 spin_unlock(&fuse_lock);
430 return fc; 438 return fc;
439
440 out_unlock:
441 spin_unlock(&fuse_lock);
442 kobject_put(&fc->kobj);
443 out_err:
444 return ERR_PTR(err);
431} 445}
432 446
433static struct inode *get_root_inode(struct super_block *sb, unsigned mode) 447static struct inode *get_root_inode(struct super_block *sb, unsigned mode)
@@ -446,16 +460,74 @@ static struct super_operations fuse_super_operations = {
446 .read_inode = fuse_read_inode, 460 .read_inode = fuse_read_inode,
447 .clear_inode = fuse_clear_inode, 461 .clear_inode = fuse_clear_inode,
448 .put_super = fuse_put_super, 462 .put_super = fuse_put_super,
463 .umount_begin = fuse_umount_begin,
449 .statfs = fuse_statfs, 464 .statfs = fuse_statfs,
450 .show_options = fuse_show_options, 465 .show_options = fuse_show_options,
451}; 466};
452 467
468static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req)
469{
470 int i;
471 struct fuse_init_out *arg = &req->misc.init_out;
472
473 if (req->out.h.error || arg->major != FUSE_KERNEL_VERSION)
474 fc->conn_error = 1;
475 else {
476 fc->minor = arg->minor;
477 fc->max_write = arg->minor < 5 ? 4096 : arg->max_write;
478 }
479
480 /* After INIT reply is received other requests can go
481 out. So do (FUSE_MAX_OUTSTANDING - 1) number of
482 up()s on outstanding_sem. The last up() is done in
483 fuse_putback_request() */
484 for (i = 1; i < FUSE_MAX_OUTSTANDING; i++)
485 up(&fc->outstanding_sem);
486
487 fuse_put_request(fc, req);
488}
489
490static void fuse_send_init(struct fuse_conn *fc)
491{
492 /* This is called from fuse_read_super() so there's guaranteed
493 to be exactly one request available */
494 struct fuse_req *req = fuse_get_request(fc);
495 struct fuse_init_in *arg = &req->misc.init_in;
496
497 arg->major = FUSE_KERNEL_VERSION;
498 arg->minor = FUSE_KERNEL_MINOR_VERSION;
499 req->in.h.opcode = FUSE_INIT;
500 req->in.numargs = 1;
501 req->in.args[0].size = sizeof(*arg);
502 req->in.args[0].value = arg;
503 req->out.numargs = 1;
504 /* Variable length arguement used for backward compatibility
505 with interface version < 7.5. Rest of init_out is zeroed
506 by do_get_request(), so a short reply is not a problem */
507 req->out.argvar = 1;
508 req->out.args[0].size = sizeof(struct fuse_init_out);
509 req->out.args[0].value = &req->misc.init_out;
510 req->end = process_init_reply;
511 request_send_background(fc, req);
512}
513
514static unsigned long long conn_id(void)
515{
516 static unsigned long long ctr = 1;
517 unsigned long long val;
518 spin_lock(&fuse_lock);
519 val = ctr++;
520 spin_unlock(&fuse_lock);
521 return val;
522}
523
453static int fuse_fill_super(struct super_block *sb, void *data, int silent) 524static int fuse_fill_super(struct super_block *sb, void *data, int silent)
454{ 525{
455 struct fuse_conn *fc; 526 struct fuse_conn *fc;
456 struct inode *root; 527 struct inode *root;
457 struct fuse_mount_data d; 528 struct fuse_mount_data d;
458 struct file *file; 529 struct file *file;
530 struct dentry *root_dentry;
459 int err; 531 int err;
460 532
461 if (!parse_fuse_opt((char *) data, &d)) 533 if (!parse_fuse_opt((char *) data, &d))
@@ -482,25 +554,43 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent)
482 fc->max_read = d.max_read; 554 fc->max_read = d.max_read;
483 if (fc->max_read / PAGE_CACHE_SIZE < fc->bdi.ra_pages) 555 if (fc->max_read / PAGE_CACHE_SIZE < fc->bdi.ra_pages)
484 fc->bdi.ra_pages = fc->max_read / PAGE_CACHE_SIZE; 556 fc->bdi.ra_pages = fc->max_read / PAGE_CACHE_SIZE;
485 fc->max_write = FUSE_MAX_IN / 2; 557
558 /* Used by get_root_inode() */
559 sb->s_fs_info = fc;
486 560
487 err = -ENOMEM; 561 err = -ENOMEM;
488 root = get_root_inode(sb, d.rootmode); 562 root = get_root_inode(sb, d.rootmode);
489 if (root == NULL) 563 if (!root)
490 goto err; 564 goto err;
491 565
492 sb->s_root = d_alloc_root(root); 566 root_dentry = d_alloc_root(root);
493 if (!sb->s_root) { 567 if (!root_dentry) {
494 iput(root); 568 iput(root);
495 goto err; 569 goto err;
496 } 570 }
571
572 err = kobject_set_name(&fc->kobj, "%llu", conn_id());
573 if (err)
574 goto err_put_root;
575
576 err = kobject_add(&fc->kobj);
577 if (err)
578 goto err_put_root;
579
580 sb->s_root = root_dentry;
581 spin_lock(&fuse_lock);
582 fc->mounted = 1;
583 fc->connected = 1;
584 spin_unlock(&fuse_lock);
585
497 fuse_send_init(fc); 586 fuse_send_init(fc);
587
498 return 0; 588 return 0;
499 589
590 err_put_root:
591 dput(root_dentry);
500 err: 592 err:
501 spin_lock(&fuse_lock); 593 kobject_put(&fc->kobj);
502 fuse_release_conn(fc);
503 spin_unlock(&fuse_lock);
504 return err; 594 return err;
505} 595}
506 596
@@ -518,6 +608,69 @@ static struct file_system_type fuse_fs_type = {
518 .kill_sb = kill_anon_super, 608 .kill_sb = kill_anon_super,
519}; 609};
520 610
611static ssize_t fuse_conn_waiting_show(struct fuse_conn *fc, char *page)
612{
613 return sprintf(page, "%i\n", atomic_read(&fc->num_waiting));
614}
615
616static ssize_t fuse_conn_abort_store(struct fuse_conn *fc, const char *page,
617 size_t count)
618{
619 fuse_abort_conn(fc);
620 return count;
621}
622
623static struct fuse_conn_attr fuse_conn_waiting =
624 __ATTR(waiting, 0400, fuse_conn_waiting_show, NULL);
625static struct fuse_conn_attr fuse_conn_abort =
626 __ATTR(abort, 0600, NULL, fuse_conn_abort_store);
627
628static struct attribute *fuse_conn_attrs[] = {
629 &fuse_conn_waiting.attr,
630 &fuse_conn_abort.attr,
631 NULL,
632};
633
634static ssize_t fuse_conn_attr_show(struct kobject *kobj,
635 struct attribute *attr,
636 char *page)
637{
638 struct fuse_conn_attr *fca =
639 container_of(attr, struct fuse_conn_attr, attr);
640
641 if (fca->show)
642 return fca->show(get_fuse_conn_kobj(kobj), page);
643 else
644 return -EACCES;
645}
646
647static ssize_t fuse_conn_attr_store(struct kobject *kobj,
648 struct attribute *attr,
649 const char *page, size_t count)
650{
651 struct fuse_conn_attr *fca =
652 container_of(attr, struct fuse_conn_attr, attr);
653
654 if (fca->store)
655 return fca->store(get_fuse_conn_kobj(kobj), page, count);
656 else
657 return -EACCES;
658}
659
660static struct sysfs_ops fuse_conn_sysfs_ops = {
661 .show = &fuse_conn_attr_show,
662 .store = &fuse_conn_attr_store,
663};
664
665static struct kobj_type ktype_fuse_conn = {
666 .release = fuse_conn_release,
667 .sysfs_ops = &fuse_conn_sysfs_ops,
668 .default_attrs = fuse_conn_attrs,
669};
670
671static decl_subsys(fuse, NULL, NULL);
672static decl_subsys(connections, &ktype_fuse_conn, NULL);
673
521static void fuse_inode_init_once(void *foo, kmem_cache_t *cachep, 674static void fuse_inode_init_once(void *foo, kmem_cache_t *cachep,
522 unsigned long flags) 675 unsigned long flags)
523{ 676{
@@ -555,6 +708,34 @@ static void fuse_fs_cleanup(void)
555 kmem_cache_destroy(fuse_inode_cachep); 708 kmem_cache_destroy(fuse_inode_cachep);
556} 709}
557 710
711static int fuse_sysfs_init(void)
712{
713 int err;
714
715 kset_set_kset_s(&fuse_subsys, fs_subsys);
716 err = subsystem_register(&fuse_subsys);
717 if (err)
718 goto out_err;
719
720 kset_set_kset_s(&connections_subsys, fuse_subsys);
721 err = subsystem_register(&connections_subsys);
722 if (err)
723 goto out_fuse_unregister;
724
725 return 0;
726
727 out_fuse_unregister:
728 subsystem_unregister(&fuse_subsys);
729 out_err:
730 return err;
731}
732
733static void fuse_sysfs_cleanup(void)
734{
735 subsystem_unregister(&connections_subsys);
736 subsystem_unregister(&fuse_subsys);
737}
738
558static int __init fuse_init(void) 739static int __init fuse_init(void)
559{ 740{
560 int res; 741 int res;
@@ -571,8 +752,14 @@ static int __init fuse_init(void)
571 if (res) 752 if (res)
572 goto err_fs_cleanup; 753 goto err_fs_cleanup;
573 754
755 res = fuse_sysfs_init();
756 if (res)
757 goto err_dev_cleanup;
758
574 return 0; 759 return 0;
575 760
761 err_dev_cleanup:
762 fuse_dev_cleanup();
576 err_fs_cleanup: 763 err_fs_cleanup:
577 fuse_fs_cleanup(); 764 fuse_fs_cleanup();
578 err: 765 err:
@@ -583,6 +770,7 @@ static void __exit fuse_exit(void)
583{ 770{
584 printk(KERN_DEBUG "fuse exit\n"); 771 printk(KERN_DEBUG "fuse exit\n");
585 772
773 fuse_sysfs_cleanup();
586 fuse_fs_cleanup(); 774 fuse_fs_cleanup();
587 fuse_dev_cleanup(); 775 fuse_dev_cleanup();
588} 776}