aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/fuse/dev.c4
-rw-r--r--fs/fuse/fuse_i.h17
-rw-r--r--fs/fuse/inode.c186
3 files changed, 164 insertions, 43 deletions
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index 5cd43bf917a4..de4a0a0bda8a 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -852,9 +852,11 @@ static int fuse_dev_release(struct inode *inode, struct file *file)
852 fc->connected = 0; 852 fc->connected = 0;
853 end_requests(fc, &fc->pending); 853 end_requests(fc, &fc->pending);
854 end_requests(fc, &fc->processing); 854 end_requests(fc, &fc->processing);
855 fuse_release_conn(fc);
856 } 855 }
857 spin_unlock(&fuse_lock); 856 spin_unlock(&fuse_lock);
857 if (fc)
858 kobject_put(&fc->kobj);
859
858 return 0; 860 return 0;
859} 861}
860 862
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index e824a09d3151..6ef1e5f5873b 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -196,9 +196,6 @@ struct fuse_req {
196 * unmounted. 196 * unmounted.
197 */ 197 */
198struct fuse_conn { 198struct fuse_conn {
199 /** Reference count */
200 int count;
201
202 /** The user id for this mount */ 199 /** The user id for this mount */
203 uid_t user_id; 200 uid_t user_id;
204 201
@@ -288,6 +285,9 @@ struct fuse_conn {
288 285
289 /** Backing dev info */ 286 /** Backing dev info */
290 struct backing_dev_info bdi; 287 struct backing_dev_info bdi;
288
289 /** kobject */
290 struct kobject kobj;
291}; 291};
292 292
293static inline struct fuse_conn *get_fuse_conn_super(struct super_block *sb) 293static inline struct fuse_conn *get_fuse_conn_super(struct super_block *sb)
@@ -300,6 +300,11 @@ static inline struct fuse_conn *get_fuse_conn(struct inode *inode)
300 return get_fuse_conn_super(inode->i_sb); 300 return get_fuse_conn_super(inode->i_sb);
301} 301}
302 302
303static inline struct fuse_conn *get_fuse_conn_kobj(struct kobject *obj)
304{
305 return container_of(obj, struct fuse_conn, kobj);
306}
307
303static inline struct fuse_inode *get_fuse_inode(struct inode *inode) 308static inline struct fuse_inode *get_fuse_inode(struct inode *inode)
304{ 309{
305 return container_of(inode, struct fuse_inode, inode); 310 return container_of(inode, struct fuse_inode, inode);
@@ -400,12 +405,6 @@ void fuse_init_symlink(struct inode *inode);
400void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr); 405void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr);
401 406
402/** 407/**
403 * Check if the connection can be released, and if yes, then free the
404 * connection structure
405 */
406void fuse_release_conn(struct fuse_conn *fc);
407
408/**
409 * Initialize the client device 408 * Initialize the client device
410 */ 409 */
411int fuse_dev_init(void); 410int fuse_dev_init(void);
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index d6a09fdaa941..514b700c863d 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
@@ -201,11 +208,12 @@ static void fuse_put_super(struct super_block *sb)
201 spin_lock(&fuse_lock); 208 spin_lock(&fuse_lock);
202 fc->mounted = 0; 209 fc->mounted = 0;
203 fc->connected = 0; 210 fc->connected = 0;
211 spin_unlock(&fuse_lock);
212 up_write(&fc->sbput_sem);
204 /* Flush all readers on this fs */ 213 /* Flush all readers on this fs */
205 wake_up_all(&fc->waitq); 214 wake_up_all(&fc->waitq);
206 up_write(&fc->sbput_sem); 215 kobject_del(&fc->kobj);
207 fuse_release_conn(fc); 216 kobject_put(&fc->kobj);
208 spin_unlock(&fuse_lock);
209} 217}
210 218
211static void convert_fuse_statfs(struct kstatfs *stbuf, struct fuse_kstatfs *attr) 219static void convert_fuse_statfs(struct kstatfs *stbuf, struct fuse_kstatfs *attr)
@@ -354,8 +362,10 @@ static int fuse_show_options(struct seq_file *m, struct vfsmount *mnt)
354 return 0; 362 return 0;
355} 363}
356 364
357static void free_conn(struct fuse_conn *fc) 365static void fuse_conn_release(struct kobject *kobj)
358{ 366{
367 struct fuse_conn *fc = get_fuse_conn_kobj(kobj);
368
359 while (!list_empty(&fc->unused_list)) { 369 while (!list_empty(&fc->unused_list)) {
360 struct fuse_req *req; 370 struct fuse_req *req;
361 req = list_entry(fc->unused_list.next, struct fuse_req, list); 371 req = list_entry(fc->unused_list.next, struct fuse_req, list);
@@ -365,20 +375,12 @@ static void free_conn(struct fuse_conn *fc)
365 kfree(fc); 375 kfree(fc);
366} 376}
367 377
368/* Must be called with the fuse lock held */
369void fuse_release_conn(struct fuse_conn *fc)
370{
371 fc->count--;
372 if (!fc->count)
373 free_conn(fc);
374}
375
376static struct fuse_conn *new_conn(void) 378static struct fuse_conn *new_conn(void)
377{ 379{
378 struct fuse_conn *fc; 380 struct fuse_conn *fc;
379 381
380 fc = kzalloc(sizeof(*fc), GFP_KERNEL); 382 fc = kzalloc(sizeof(*fc), GFP_KERNEL);
381 if (fc != NULL) { 383 if (fc) {
382 int i; 384 int i;
383 init_waitqueue_head(&fc->waitq); 385 init_waitqueue_head(&fc->waitq);
384 INIT_LIST_HEAD(&fc->pending); 386 INIT_LIST_HEAD(&fc->pending);
@@ -388,10 +390,12 @@ static struct fuse_conn *new_conn(void)
388 INIT_LIST_HEAD(&fc->background); 390 INIT_LIST_HEAD(&fc->background);
389 sema_init(&fc->outstanding_sem, 1); /* One for INIT */ 391 sema_init(&fc->outstanding_sem, 1); /* One for INIT */
390 init_rwsem(&fc->sbput_sem); 392 init_rwsem(&fc->sbput_sem);
393 kobj_set_kset_s(fc, connections_subsys);
394 kobject_init(&fc->kobj);
391 for (i = 0; i < FUSE_MAX_OUTSTANDING; i++) { 395 for (i = 0; i < FUSE_MAX_OUTSTANDING; i++) {
392 struct fuse_req *req = fuse_request_alloc(); 396 struct fuse_req *req = fuse_request_alloc();
393 if (!req) { 397 if (!req) {
394 free_conn(fc); 398 kobject_put(&fc->kobj);
395 return NULL; 399 return NULL;
396 } 400 }
397 list_add(&req->list, &fc->unused_list); 401 list_add(&req->list, &fc->unused_list);
@@ -406,25 +410,32 @@ static struct fuse_conn *new_conn(void)
406static struct fuse_conn *get_conn(struct file *file, struct super_block *sb) 410static struct fuse_conn *get_conn(struct file *file, struct super_block *sb)
407{ 411{
408 struct fuse_conn *fc; 412 struct fuse_conn *fc;
413 int err;
409 414
415 err = -EINVAL;
410 if (file->f_op != &fuse_dev_operations) 416 if (file->f_op != &fuse_dev_operations)
411 return ERR_PTR(-EINVAL); 417 goto out_err;
418
419 err = -ENOMEM;
412 fc = new_conn(); 420 fc = new_conn();
413 if (fc == NULL) 421 if (!fc)
414 return ERR_PTR(-ENOMEM); 422 goto out_err;
423
415 spin_lock(&fuse_lock); 424 spin_lock(&fuse_lock);
416 if (file->private_data) { 425 err = -EINVAL;
417 free_conn(fc); 426 if (file->private_data)
418 fc = ERR_PTR(-EINVAL); 427 goto out_unlock;
419 } else { 428
420 file->private_data = fc; 429 kobject_get(&fc->kobj);
421 sb->s_fs_info = fc; 430 file->private_data = fc;
422 fc->mounted = 1;
423 fc->connected = 1;
424 fc->count = 2;
425 }
426 spin_unlock(&fuse_lock); 431 spin_unlock(&fuse_lock);
427 return fc; 432 return fc;
433
434 out_unlock:
435 spin_unlock(&fuse_lock);
436 kobject_put(&fc->kobj);
437 out_err:
438 return ERR_PTR(err);
428} 439}
429 440
430static struct inode *get_root_inode(struct super_block *sb, unsigned mode) 441static struct inode *get_root_inode(struct super_block *sb, unsigned mode)
@@ -447,12 +458,23 @@ static struct super_operations fuse_super_operations = {
447 .show_options = fuse_show_options, 458 .show_options = fuse_show_options,
448}; 459};
449 460
461static unsigned long long conn_id(void)
462{
463 static unsigned long long ctr = 1;
464 unsigned long long val;
465 spin_lock(&fuse_lock);
466 val = ctr++;
467 spin_unlock(&fuse_lock);
468 return val;
469}
470
450static int fuse_fill_super(struct super_block *sb, void *data, int silent) 471static int fuse_fill_super(struct super_block *sb, void *data, int silent)
451{ 472{
452 struct fuse_conn *fc; 473 struct fuse_conn *fc;
453 struct inode *root; 474 struct inode *root;
454 struct fuse_mount_data d; 475 struct fuse_mount_data d;
455 struct file *file; 476 struct file *file;
477 struct dentry *root_dentry;
456 int err; 478 int err;
457 479
458 if (!parse_fuse_opt((char *) data, &d)) 480 if (!parse_fuse_opt((char *) data, &d))
@@ -480,23 +502,42 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent)
480 if (fc->max_read / PAGE_CACHE_SIZE < fc->bdi.ra_pages) 502 if (fc->max_read / PAGE_CACHE_SIZE < fc->bdi.ra_pages)
481 fc->bdi.ra_pages = fc->max_read / PAGE_CACHE_SIZE; 503 fc->bdi.ra_pages = fc->max_read / PAGE_CACHE_SIZE;
482 504
505 /* Used by get_root_inode() */
506 sb->s_fs_info = fc;
507
483 err = -ENOMEM; 508 err = -ENOMEM;
484 root = get_root_inode(sb, d.rootmode); 509 root = get_root_inode(sb, d.rootmode);
485 if (root == NULL) 510 if (!root)
486 goto err; 511 goto err;
487 512
488 sb->s_root = d_alloc_root(root); 513 root_dentry = d_alloc_root(root);
489 if (!sb->s_root) { 514 if (!root_dentry) {
490 iput(root); 515 iput(root);
491 goto err; 516 goto err;
492 } 517 }
518
519 err = kobject_set_name(&fc->kobj, "%llu", conn_id());
520 if (err)
521 goto err_put_root;
522
523 err = kobject_add(&fc->kobj);
524 if (err)
525 goto err_put_root;
526
527 sb->s_root = root_dentry;
528 spin_lock(&fuse_lock);
529 fc->mounted = 1;
530 fc->connected = 1;
531 spin_unlock(&fuse_lock);
532
493 fuse_send_init(fc); 533 fuse_send_init(fc);
534
494 return 0; 535 return 0;
495 536
537 err_put_root:
538 dput(root_dentry);
496 err: 539 err:
497 spin_lock(&fuse_lock); 540 kobject_put(&fc->kobj);
498 fuse_release_conn(fc);
499 spin_unlock(&fuse_lock);
500 return err; 541 return err;
501} 542}
502 543
@@ -514,6 +555,50 @@ static struct file_system_type fuse_fs_type = {
514 .kill_sb = kill_anon_super, 555 .kill_sb = kill_anon_super,
515}; 556};
516 557
558static struct attribute *fuse_conn_attrs[] = {
559 NULL,
560};
561
562static ssize_t fuse_conn_attr_show(struct kobject *kobj,
563 struct attribute *attr,
564 char *page)
565{
566 struct fuse_conn_attr *fca =
567 container_of(attr, struct fuse_conn_attr, attr);
568
569 if (fca->show)
570 return fca->show(get_fuse_conn_kobj(kobj), page);
571 else
572 return -EACCES;
573}
574
575static ssize_t fuse_conn_attr_store(struct kobject *kobj,
576 struct attribute *attr,
577 const char *page, size_t count)
578{
579 struct fuse_conn_attr *fca =
580 container_of(attr, struct fuse_conn_attr, attr);
581
582 if (fca->store)
583 return fca->store(get_fuse_conn_kobj(kobj), page, count);
584 else
585 return -EACCES;
586}
587
588static struct sysfs_ops fuse_conn_sysfs_ops = {
589 .show = &fuse_conn_attr_show,
590 .store = &fuse_conn_attr_store,
591};
592
593static struct kobj_type ktype_fuse_conn = {
594 .release = fuse_conn_release,
595 .sysfs_ops = &fuse_conn_sysfs_ops,
596 .default_attrs = fuse_conn_attrs,
597};
598
599static decl_subsys(fuse, NULL, NULL);
600static decl_subsys(connections, &ktype_fuse_conn, NULL);
601
517static void fuse_inode_init_once(void *foo, kmem_cache_t *cachep, 602static void fuse_inode_init_once(void *foo, kmem_cache_t *cachep,
518 unsigned long flags) 603 unsigned long flags)
519{ 604{
@@ -551,6 +636,34 @@ static void fuse_fs_cleanup(void)
551 kmem_cache_destroy(fuse_inode_cachep); 636 kmem_cache_destroy(fuse_inode_cachep);
552} 637}
553 638
639static int fuse_sysfs_init(void)
640{
641 int err;
642
643 kset_set_kset_s(&fuse_subsys, fs_subsys);
644 err = subsystem_register(&fuse_subsys);
645 if (err)
646 goto out_err;
647
648 kset_set_kset_s(&connections_subsys, fuse_subsys);
649 err = subsystem_register(&connections_subsys);
650 if (err)
651 goto out_fuse_unregister;
652
653 return 0;
654
655 out_fuse_unregister:
656 subsystem_unregister(&fuse_subsys);
657 out_err:
658 return err;
659}
660
661static void fuse_sysfs_cleanup(void)
662{
663 subsystem_unregister(&connections_subsys);
664 subsystem_unregister(&fuse_subsys);
665}
666
554static int __init fuse_init(void) 667static int __init fuse_init(void)
555{ 668{
556 int res; 669 int res;
@@ -567,8 +680,14 @@ static int __init fuse_init(void)
567 if (res) 680 if (res)
568 goto err_fs_cleanup; 681 goto err_fs_cleanup;
569 682
683 res = fuse_sysfs_init();
684 if (res)
685 goto err_dev_cleanup;
686
570 return 0; 687 return 0;
571 688
689 err_dev_cleanup:
690 fuse_dev_cleanup();
572 err_fs_cleanup: 691 err_fs_cleanup:
573 fuse_fs_cleanup(); 692 fuse_fs_cleanup();
574 err: 693 err:
@@ -579,6 +698,7 @@ static void __exit fuse_exit(void)
579{ 698{
580 printk(KERN_DEBUG "fuse exit\n"); 699 printk(KERN_DEBUG "fuse exit\n");
581 700
701 fuse_sysfs_cleanup();
582 fuse_fs_cleanup(); 702 fuse_fs_cleanup();
583 fuse_dev_cleanup(); 703 fuse_dev_cleanup();
584} 704}