[PATCH] fuse: make fuse connection a kobject

Kobjectify fuse_conn, and make it visible under /sys/fs/fuse/connections.

Lacking any natural naming, connections are numbered.

This patch doesn't add any attributes, just the infrastructure.

Signed-off-by: Miklos Szeredi <miklos@szeredi.hu>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

authored by

Miklos Szeredi and committed by
Linus Torvalds
f543f253 9ba7cbba

+164 -43
+3 -1
fs/fuse/dev.c
··· 852 fc->connected = 0; 853 end_requests(fc, &fc->pending); 854 end_requests(fc, &fc->processing); 855 - fuse_release_conn(fc); 856 } 857 spin_unlock(&fuse_lock); 858 return 0; 859 } 860
··· 852 fc->connected = 0; 853 end_requests(fc, &fc->pending); 854 end_requests(fc, &fc->processing); 855 } 856 spin_unlock(&fuse_lock); 857 + if (fc) 858 + kobject_put(&fc->kobj); 859 + 860 return 0; 861 } 862
+8 -9
fs/fuse/fuse_i.h
··· 196 * unmounted. 197 */ 198 struct fuse_conn { 199 - /** Reference count */ 200 - int count; 201 - 202 /** The user id for this mount */ 203 uid_t user_id; 204 ··· 285 286 /** Backing dev info */ 287 struct backing_dev_info bdi; 288 }; 289 290 static inline struct fuse_conn *get_fuse_conn_super(struct super_block *sb) ··· 298 static inline struct fuse_conn *get_fuse_conn(struct inode *inode) 299 { 300 return get_fuse_conn_super(inode->i_sb); 301 } 302 303 static inline struct fuse_inode *get_fuse_inode(struct inode *inode) ··· 403 * Change attributes of an inode 404 */ 405 void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr); 406 - 407 - /** 408 - * Check if the connection can be released, and if yes, then free the 409 - * connection structure 410 - */ 411 - void fuse_release_conn(struct fuse_conn *fc); 412 413 /** 414 * Initialize the client device
··· 196 * unmounted. 197 */ 198 struct fuse_conn { 199 /** The user id for this mount */ 200 uid_t user_id; 201 ··· 288 289 /** Backing dev info */ 290 struct backing_dev_info bdi; 291 + 292 + /** kobject */ 293 + struct kobject kobj; 294 }; 295 296 static inline struct fuse_conn *get_fuse_conn_super(struct super_block *sb) ··· 298 static inline struct fuse_conn *get_fuse_conn(struct inode *inode) 299 { 300 return get_fuse_conn_super(inode->i_sb); 301 + } 302 + 303 + static inline struct fuse_conn *get_fuse_conn_kobj(struct kobject *obj) 304 + { 305 + return container_of(obj, struct fuse_conn, kobj); 306 } 307 308 static inline struct fuse_inode *get_fuse_inode(struct inode *inode) ··· 398 * Change attributes of an inode 399 */ 400 void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr); 401 402 /** 403 * Initialize the client device
+153 -33
fs/fuse/inode.c
··· 24 25 spinlock_t fuse_lock; 26 static kmem_cache_t *fuse_inode_cachep; 27 28 #define FUSE_SUPER_MAGIC 0x65735546 29 ··· 208 spin_lock(&fuse_lock); 209 fc->mounted = 0; 210 fc->connected = 0; 211 /* Flush all readers on this fs */ 212 wake_up_all(&fc->waitq); 213 - up_write(&fc->sbput_sem); 214 - fuse_release_conn(fc); 215 - spin_unlock(&fuse_lock); 216 } 217 218 static void convert_fuse_statfs(struct kstatfs *stbuf, struct fuse_kstatfs *attr) ··· 362 return 0; 363 } 364 365 - static void free_conn(struct fuse_conn *fc) 366 { 367 while (!list_empty(&fc->unused_list)) { 368 struct fuse_req *req; 369 req = list_entry(fc->unused_list.next, struct fuse_req, list); ··· 375 kfree(fc); 376 } 377 378 - /* Must be called with the fuse lock held */ 379 - void fuse_release_conn(struct fuse_conn *fc) 380 - { 381 - fc->count--; 382 - if (!fc->count) 383 - free_conn(fc); 384 - } 385 - 386 static struct fuse_conn *new_conn(void) 387 { 388 struct fuse_conn *fc; 389 390 fc = kzalloc(sizeof(*fc), GFP_KERNEL); 391 - if (fc != NULL) { 392 int i; 393 init_waitqueue_head(&fc->waitq); 394 INIT_LIST_HEAD(&fc->pending); ··· 390 INIT_LIST_HEAD(&fc->background); 391 sema_init(&fc->outstanding_sem, 1); /* One for INIT */ 392 init_rwsem(&fc->sbput_sem); 393 for (i = 0; i < FUSE_MAX_OUTSTANDING; i++) { 394 struct fuse_req *req = fuse_request_alloc(); 395 if (!req) { 396 - free_conn(fc); 397 return NULL; 398 } 399 list_add(&req->list, &fc->unused_list); ··· 410 static struct fuse_conn *get_conn(struct file *file, struct super_block *sb) 411 { 412 struct fuse_conn *fc; 413 414 if (file->f_op != &fuse_dev_operations) 415 - return ERR_PTR(-EINVAL); 416 fc = new_conn(); 417 - if (fc == NULL) 418 - return ERR_PTR(-ENOMEM); 419 spin_lock(&fuse_lock); 420 - if (file->private_data) { 421 - free_conn(fc); 422 - fc = ERR_PTR(-EINVAL); 423 - } else { 424 - file->private_data = fc; 425 - sb->s_fs_info = fc; 426 - fc->mounted = 1; 427 - fc->connected = 1; 428 - fc->count = 2; 429 - } 430 spin_unlock(&fuse_lock); 431 return fc; 432 } 433 434 static struct inode *get_root_inode(struct super_block *sb, unsigned mode) ··· 458 .show_options = fuse_show_options, 459 }; 460 461 static int fuse_fill_super(struct super_block *sb, void *data, int silent) 462 { 463 struct fuse_conn *fc; 464 struct inode *root; 465 struct fuse_mount_data d; 466 struct file *file; 467 int err; 468 469 if (!parse_fuse_opt((char *) data, &d)) ··· 502 if (fc->max_read / PAGE_CACHE_SIZE < fc->bdi.ra_pages) 503 fc->bdi.ra_pages = fc->max_read / PAGE_CACHE_SIZE; 504 505 err = -ENOMEM; 506 root = get_root_inode(sb, d.rootmode); 507 - if (root == NULL) 508 goto err; 509 510 - sb->s_root = d_alloc_root(root); 511 - if (!sb->s_root) { 512 iput(root); 513 goto err; 514 } 515 fuse_send_init(fc); 516 return 0; 517 518 err: 519 - spin_lock(&fuse_lock); 520 - fuse_release_conn(fc); 521 - spin_unlock(&fuse_lock); 522 return err; 523 } 524 ··· 554 .get_sb = fuse_get_sb, 555 .kill_sb = kill_anon_super, 556 }; 557 558 static void fuse_inode_init_once(void *foo, kmem_cache_t *cachep, 559 unsigned long flags) ··· 636 kmem_cache_destroy(fuse_inode_cachep); 637 } 638 639 static int __init fuse_init(void) 640 { 641 int res; ··· 680 if (res) 681 goto err_fs_cleanup; 682 683 return 0; 684 685 err_fs_cleanup: 686 fuse_fs_cleanup(); 687 err: ··· 698 { 699 printk(KERN_DEBUG "fuse exit\n"); 700 701 fuse_fs_cleanup(); 702 fuse_dev_cleanup(); 703 }
··· 24 25 spinlock_t fuse_lock; 26 static kmem_cache_t *fuse_inode_cachep; 27 + static struct subsystem connections_subsys; 28 + 29 + struct 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 + }; 34 35 #define FUSE_SUPER_MAGIC 0x65735546 36 ··· 201 spin_lock(&fuse_lock); 202 fc->mounted = 0; 203 fc->connected = 0; 204 + spin_unlock(&fuse_lock); 205 + up_write(&fc->sbput_sem); 206 /* Flush all readers on this fs */ 207 wake_up_all(&fc->waitq); 208 + kobject_del(&fc->kobj); 209 + kobject_put(&fc->kobj); 210 } 211 212 static void convert_fuse_statfs(struct kstatfs *stbuf, struct fuse_kstatfs *attr) ··· 354 return 0; 355 } 356 357 + static void fuse_conn_release(struct kobject *kobj) 358 { 359 + struct fuse_conn *fc = get_fuse_conn_kobj(kobj); 360 + 361 while (!list_empty(&fc->unused_list)) { 362 struct fuse_req *req; 363 req = list_entry(fc->unused_list.next, struct fuse_req, list); ··· 365 kfree(fc); 366 } 367 368 static struct fuse_conn *new_conn(void) 369 { 370 struct fuse_conn *fc; 371 372 fc = kzalloc(sizeof(*fc), GFP_KERNEL); 373 + if (fc) { 374 int i; 375 init_waitqueue_head(&fc->waitq); 376 INIT_LIST_HEAD(&fc->pending); ··· 388 INIT_LIST_HEAD(&fc->background); 389 sema_init(&fc->outstanding_sem, 1); /* One for INIT */ 390 init_rwsem(&fc->sbput_sem); 391 + kobj_set_kset_s(fc, connections_subsys); 392 + kobject_init(&fc->kobj); 393 for (i = 0; i < FUSE_MAX_OUTSTANDING; i++) { 394 struct fuse_req *req = fuse_request_alloc(); 395 if (!req) { 396 + kobject_put(&fc->kobj); 397 return NULL; 398 } 399 list_add(&req->list, &fc->unused_list); ··· 406 static struct fuse_conn *get_conn(struct file *file, struct super_block *sb) 407 { 408 struct fuse_conn *fc; 409 + int err; 410 411 + err = -EINVAL; 412 if (file->f_op != &fuse_dev_operations) 413 + goto out_err; 414 + 415 + err = -ENOMEM; 416 fc = new_conn(); 417 + if (!fc) 418 + goto out_err; 419 + 420 spin_lock(&fuse_lock); 421 + err = -EINVAL; 422 + if (file->private_data) 423 + goto out_unlock; 424 + 425 + kobject_get(&fc->kobj); 426 + file->private_data = fc; 427 spin_unlock(&fuse_lock); 428 return fc; 429 + 430 + out_unlock: 431 + spin_unlock(&fuse_lock); 432 + kobject_put(&fc->kobj); 433 + out_err: 434 + return ERR_PTR(err); 435 } 436 437 static struct inode *get_root_inode(struct super_block *sb, unsigned mode) ··· 447 .show_options = fuse_show_options, 448 }; 449 450 + static unsigned long long conn_id(void) 451 + { 452 + static unsigned long long ctr = 1; 453 + unsigned long long val; 454 + spin_lock(&fuse_lock); 455 + val = ctr++; 456 + spin_unlock(&fuse_lock); 457 + return val; 458 + } 459 + 460 static int fuse_fill_super(struct super_block *sb, void *data, int silent) 461 { 462 struct fuse_conn *fc; 463 struct inode *root; 464 struct fuse_mount_data d; 465 struct file *file; 466 + struct dentry *root_dentry; 467 int err; 468 469 if (!parse_fuse_opt((char *) data, &d)) ··· 480 if (fc->max_read / PAGE_CACHE_SIZE < fc->bdi.ra_pages) 481 fc->bdi.ra_pages = fc->max_read / PAGE_CACHE_SIZE; 482 483 + /* Used by get_root_inode() */ 484 + sb->s_fs_info = fc; 485 + 486 err = -ENOMEM; 487 root = get_root_inode(sb, d.rootmode); 488 + if (!root) 489 goto err; 490 491 + root_dentry = d_alloc_root(root); 492 + if (!root_dentry) { 493 iput(root); 494 goto err; 495 } 496 + 497 + err = kobject_set_name(&fc->kobj, "%llu", conn_id()); 498 + if (err) 499 + goto err_put_root; 500 + 501 + err = kobject_add(&fc->kobj); 502 + if (err) 503 + goto err_put_root; 504 + 505 + sb->s_root = root_dentry; 506 + spin_lock(&fuse_lock); 507 + fc->mounted = 1; 508 + fc->connected = 1; 509 + spin_unlock(&fuse_lock); 510 + 511 fuse_send_init(fc); 512 + 513 return 0; 514 515 + err_put_root: 516 + dput(root_dentry); 517 err: 518 + kobject_put(&fc->kobj); 519 return err; 520 } 521 ··· 513 .get_sb = fuse_get_sb, 514 .kill_sb = kill_anon_super, 515 }; 516 + 517 + static struct attribute *fuse_conn_attrs[] = { 518 + NULL, 519 + }; 520 + 521 + static ssize_t fuse_conn_attr_show(struct kobject *kobj, 522 + struct attribute *attr, 523 + char *page) 524 + { 525 + struct fuse_conn_attr *fca = 526 + container_of(attr, struct fuse_conn_attr, attr); 527 + 528 + if (fca->show) 529 + return fca->show(get_fuse_conn_kobj(kobj), page); 530 + else 531 + return -EACCES; 532 + } 533 + 534 + static ssize_t fuse_conn_attr_store(struct kobject *kobj, 535 + struct attribute *attr, 536 + const char *page, size_t count) 537 + { 538 + struct fuse_conn_attr *fca = 539 + container_of(attr, struct fuse_conn_attr, attr); 540 + 541 + if (fca->store) 542 + return fca->store(get_fuse_conn_kobj(kobj), page, count); 543 + else 544 + return -EACCES; 545 + } 546 + 547 + static struct sysfs_ops fuse_conn_sysfs_ops = { 548 + .show = &fuse_conn_attr_show, 549 + .store = &fuse_conn_attr_store, 550 + }; 551 + 552 + static struct kobj_type ktype_fuse_conn = { 553 + .release = fuse_conn_release, 554 + .sysfs_ops = &fuse_conn_sysfs_ops, 555 + .default_attrs = fuse_conn_attrs, 556 + }; 557 + 558 + static decl_subsys(fuse, NULL, NULL); 559 + static decl_subsys(connections, &ktype_fuse_conn, NULL); 560 561 static void fuse_inode_init_once(void *foo, kmem_cache_t *cachep, 562 unsigned long flags) ··· 551 kmem_cache_destroy(fuse_inode_cachep); 552 } 553 554 + static int fuse_sysfs_init(void) 555 + { 556 + int err; 557 + 558 + kset_set_kset_s(&fuse_subsys, fs_subsys); 559 + err = subsystem_register(&fuse_subsys); 560 + if (err) 561 + goto out_err; 562 + 563 + kset_set_kset_s(&connections_subsys, fuse_subsys); 564 + err = subsystem_register(&connections_subsys); 565 + if (err) 566 + goto out_fuse_unregister; 567 + 568 + return 0; 569 + 570 + out_fuse_unregister: 571 + subsystem_unregister(&fuse_subsys); 572 + out_err: 573 + return err; 574 + } 575 + 576 + static void fuse_sysfs_cleanup(void) 577 + { 578 + subsystem_unregister(&connections_subsys); 579 + subsystem_unregister(&fuse_subsys); 580 + } 581 + 582 static int __init fuse_init(void) 583 { 584 int res; ··· 567 if (res) 568 goto err_fs_cleanup; 569 570 + res = fuse_sysfs_init(); 571 + if (res) 572 + goto err_dev_cleanup; 573 + 574 return 0; 575 576 + err_dev_cleanup: 577 + fuse_dev_cleanup(); 578 err_fs_cleanup: 579 fuse_fs_cleanup(); 580 err: ··· 579 { 580 printk(KERN_DEBUG "fuse exit\n"); 581 582 + fuse_sysfs_cleanup(); 583 fuse_fs_cleanup(); 584 fuse_dev_cleanup(); 585 }