diff options
Diffstat (limited to 'fs/fuse/inode.c')
-rw-r--r-- | fs/fuse/inode.c | 157 |
1 files changed, 84 insertions, 73 deletions
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index 2e99f34b4435..47c96fdca1ac 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | FUSE: Filesystem in Userspace | 2 | FUSE: Filesystem in Userspace |
3 | Copyright (C) 2001-2006 Miklos Szeredi <miklos@szeredi.hu> | 3 | Copyright (C) 2001-2008 Miklos Szeredi <miklos@szeredi.hu> |
4 | 4 | ||
5 | This program can be distributed under the terms of the GNU GPL. | 5 | This program can be distributed under the terms of the GNU GPL. |
6 | See the file COPYING. | 6 | See the file COPYING. |
@@ -37,10 +37,10 @@ struct fuse_mount_data { | |||
37 | unsigned rootmode; | 37 | unsigned rootmode; |
38 | unsigned user_id; | 38 | unsigned user_id; |
39 | unsigned group_id; | 39 | unsigned group_id; |
40 | unsigned fd_present : 1; | 40 | unsigned fd_present:1; |
41 | unsigned rootmode_present : 1; | 41 | unsigned rootmode_present:1; |
42 | unsigned user_id_present : 1; | 42 | unsigned user_id_present:1; |
43 | unsigned group_id_present : 1; | 43 | unsigned group_id_present:1; |
44 | unsigned flags; | 44 | unsigned flags; |
45 | unsigned max_read; | 45 | unsigned max_read; |
46 | unsigned blksize; | 46 | unsigned blksize; |
@@ -94,7 +94,7 @@ void fuse_send_forget(struct fuse_conn *fc, struct fuse_req *req, | |||
94 | req->in.numargs = 1; | 94 | req->in.numargs = 1; |
95 | req->in.args[0].size = sizeof(struct fuse_forget_in); | 95 | req->in.args[0].size = sizeof(struct fuse_forget_in); |
96 | req->in.args[0].value = inarg; | 96 | req->in.args[0].value = inarg; |
97 | request_send_noreply(fc, req); | 97 | fuse_request_send_noreply(fc, req); |
98 | } | 98 | } |
99 | 99 | ||
100 | static void fuse_clear_inode(struct inode *inode) | 100 | static void fuse_clear_inode(struct inode *inode) |
@@ -250,7 +250,7 @@ struct inode *fuse_iget(struct super_block *sb, u64 nodeid, | |||
250 | 250 | ||
251 | fi = get_fuse_inode(inode); | 251 | fi = get_fuse_inode(inode); |
252 | spin_lock(&fc->lock); | 252 | spin_lock(&fc->lock); |
253 | fi->nlookup ++; | 253 | fi->nlookup++; |
254 | spin_unlock(&fc->lock); | 254 | spin_unlock(&fc->lock); |
255 | fuse_change_attributes(inode, attr, attr_valid, attr_version); | 255 | fuse_change_attributes(inode, attr, attr_valid, attr_version); |
256 | 256 | ||
@@ -269,7 +269,7 @@ static void fuse_send_destroy(struct fuse_conn *fc) | |||
269 | fc->destroy_req = NULL; | 269 | fc->destroy_req = NULL; |
270 | req->in.h.opcode = FUSE_DESTROY; | 270 | req->in.h.opcode = FUSE_DESTROY; |
271 | req->force = 1; | 271 | req->force = 1; |
272 | request_send(fc, req); | 272 | fuse_request_send(fc, req); |
273 | fuse_put_request(fc, req); | 273 | fuse_put_request(fc, req); |
274 | } | 274 | } |
275 | } | 275 | } |
@@ -334,7 +334,7 @@ static int fuse_statfs(struct dentry *dentry, struct kstatfs *buf) | |||
334 | req->out.args[0].size = | 334 | req->out.args[0].size = |
335 | fc->minor < 4 ? FUSE_COMPAT_STATFS_SIZE : sizeof(outarg); | 335 | fc->minor < 4 ? FUSE_COMPAT_STATFS_SIZE : sizeof(outarg); |
336 | req->out.args[0].value = &outarg; | 336 | req->out.args[0].value = &outarg; |
337 | request_send(fc, req); | 337 | fuse_request_send(fc, req); |
338 | err = req->out.h.error; | 338 | err = req->out.h.error; |
339 | if (!err) | 339 | if (!err) |
340 | convert_fuse_statfs(buf, &outarg.st); | 340 | convert_fuse_statfs(buf, &outarg.st); |
@@ -462,68 +462,69 @@ static int fuse_show_options(struct seq_file *m, struct vfsmount *mnt) | |||
462 | return 0; | 462 | return 0; |
463 | } | 463 | } |
464 | 464 | ||
465 | static struct fuse_conn *new_conn(struct super_block *sb) | 465 | int fuse_conn_init(struct fuse_conn *fc, struct super_block *sb) |
466 | { | 466 | { |
467 | struct fuse_conn *fc; | ||
468 | int err; | 467 | int err; |
469 | 468 | ||
470 | fc = kzalloc(sizeof(*fc), GFP_KERNEL); | 469 | memset(fc, 0, sizeof(*fc)); |
471 | if (fc) { | 470 | spin_lock_init(&fc->lock); |
472 | spin_lock_init(&fc->lock); | 471 | mutex_init(&fc->inst_mutex); |
473 | mutex_init(&fc->inst_mutex); | 472 | atomic_set(&fc->count, 1); |
474 | atomic_set(&fc->count, 1); | 473 | init_waitqueue_head(&fc->waitq); |
475 | init_waitqueue_head(&fc->waitq); | 474 | init_waitqueue_head(&fc->blocked_waitq); |
476 | init_waitqueue_head(&fc->blocked_waitq); | 475 | init_waitqueue_head(&fc->reserved_req_waitq); |
477 | init_waitqueue_head(&fc->reserved_req_waitq); | 476 | INIT_LIST_HEAD(&fc->pending); |
478 | INIT_LIST_HEAD(&fc->pending); | 477 | INIT_LIST_HEAD(&fc->processing); |
479 | INIT_LIST_HEAD(&fc->processing); | 478 | INIT_LIST_HEAD(&fc->io); |
480 | INIT_LIST_HEAD(&fc->io); | 479 | INIT_LIST_HEAD(&fc->interrupts); |
481 | INIT_LIST_HEAD(&fc->interrupts); | 480 | INIT_LIST_HEAD(&fc->bg_queue); |
482 | INIT_LIST_HEAD(&fc->bg_queue); | 481 | INIT_LIST_HEAD(&fc->entry); |
483 | atomic_set(&fc->num_waiting, 0); | 482 | atomic_set(&fc->num_waiting, 0); |
484 | fc->bdi.ra_pages = (VM_MAX_READAHEAD * 1024) / PAGE_CACHE_SIZE; | 483 | fc->bdi.ra_pages = (VM_MAX_READAHEAD * 1024) / PAGE_CACHE_SIZE; |
485 | fc->bdi.unplug_io_fn = default_unplug_io_fn; | 484 | fc->bdi.unplug_io_fn = default_unplug_io_fn; |
486 | /* fuse does it's own writeback accounting */ | 485 | /* fuse does it's own writeback accounting */ |
487 | fc->bdi.capabilities = BDI_CAP_NO_ACCT_WB; | 486 | fc->bdi.capabilities = BDI_CAP_NO_ACCT_WB; |
488 | fc->dev = sb->s_dev; | 487 | fc->khctr = 0; |
489 | err = bdi_init(&fc->bdi); | 488 | fc->polled_files = RB_ROOT; |
490 | if (err) | 489 | fc->dev = sb->s_dev; |
491 | goto error_kfree; | 490 | err = bdi_init(&fc->bdi); |
492 | if (sb->s_bdev) { | 491 | if (err) |
493 | err = bdi_register(&fc->bdi, NULL, "%u:%u-fuseblk", | 492 | goto error_mutex_destroy; |
494 | MAJOR(fc->dev), MINOR(fc->dev)); | 493 | if (sb->s_bdev) { |
495 | } else { | 494 | err = bdi_register(&fc->bdi, NULL, "%u:%u-fuseblk", |
496 | err = bdi_register_dev(&fc->bdi, fc->dev); | 495 | MAJOR(fc->dev), MINOR(fc->dev)); |
497 | } | 496 | } else { |
498 | if (err) | 497 | err = bdi_register_dev(&fc->bdi, fc->dev); |
499 | goto error_bdi_destroy; | ||
500 | /* | ||
501 | * For a single fuse filesystem use max 1% of dirty + | ||
502 | * writeback threshold. | ||
503 | * | ||
504 | * This gives about 1M of write buffer for memory maps on a | ||
505 | * machine with 1G and 10% dirty_ratio, which should be more | ||
506 | * than enough. | ||
507 | * | ||
508 | * Privileged users can raise it by writing to | ||
509 | * | ||
510 | * /sys/class/bdi/<bdi>/max_ratio | ||
511 | */ | ||
512 | bdi_set_max_ratio(&fc->bdi, 1); | ||
513 | fc->reqctr = 0; | ||
514 | fc->blocked = 1; | ||
515 | fc->attr_version = 1; | ||
516 | get_random_bytes(&fc->scramble_key, sizeof(fc->scramble_key)); | ||
517 | } | 498 | } |
518 | return fc; | 499 | if (err) |
500 | goto error_bdi_destroy; | ||
501 | /* | ||
502 | * For a single fuse filesystem use max 1% of dirty + | ||
503 | * writeback threshold. | ||
504 | * | ||
505 | * This gives about 1M of write buffer for memory maps on a | ||
506 | * machine with 1G and 10% dirty_ratio, which should be more | ||
507 | * than enough. | ||
508 | * | ||
509 | * Privileged users can raise it by writing to | ||
510 | * | ||
511 | * /sys/class/bdi/<bdi>/max_ratio | ||
512 | */ | ||
513 | bdi_set_max_ratio(&fc->bdi, 1); | ||
514 | fc->reqctr = 0; | ||
515 | fc->blocked = 1; | ||
516 | fc->attr_version = 1; | ||
517 | get_random_bytes(&fc->scramble_key, sizeof(fc->scramble_key)); | ||
519 | 518 | ||
520 | error_bdi_destroy: | 519 | return 0; |
520 | |||
521 | error_bdi_destroy: | ||
521 | bdi_destroy(&fc->bdi); | 522 | bdi_destroy(&fc->bdi); |
522 | error_kfree: | 523 | error_mutex_destroy: |
523 | mutex_destroy(&fc->inst_mutex); | 524 | mutex_destroy(&fc->inst_mutex); |
524 | kfree(fc); | 525 | return err; |
525 | return NULL; | ||
526 | } | 526 | } |
527 | EXPORT_SYMBOL_GPL(fuse_conn_init); | ||
527 | 528 | ||
528 | void fuse_conn_put(struct fuse_conn *fc) | 529 | void fuse_conn_put(struct fuse_conn *fc) |
529 | { | 530 | { |
@@ -532,7 +533,7 @@ void fuse_conn_put(struct fuse_conn *fc) | |||
532 | fuse_request_free(fc->destroy_req); | 533 | fuse_request_free(fc->destroy_req); |
533 | mutex_destroy(&fc->inst_mutex); | 534 | mutex_destroy(&fc->inst_mutex); |
534 | bdi_destroy(&fc->bdi); | 535 | bdi_destroy(&fc->bdi); |
535 | kfree(fc); | 536 | fc->release(fc); |
536 | } | 537 | } |
537 | } | 538 | } |
538 | 539 | ||
@@ -542,7 +543,7 @@ struct fuse_conn *fuse_conn_get(struct fuse_conn *fc) | |||
542 | return fc; | 543 | return fc; |
543 | } | 544 | } |
544 | 545 | ||
545 | static struct inode *get_root_inode(struct super_block *sb, unsigned mode) | 546 | static struct inode *fuse_get_root_inode(struct super_block *sb, unsigned mode) |
546 | { | 547 | { |
547 | struct fuse_attr attr; | 548 | struct fuse_attr attr; |
548 | memset(&attr, 0, sizeof(attr)); | 549 | memset(&attr, 0, sizeof(attr)); |
@@ -553,8 +554,7 @@ static struct inode *get_root_inode(struct super_block *sb, unsigned mode) | |||
553 | return fuse_iget(sb, 1, 0, &attr, 0, 0); | 554 | return fuse_iget(sb, 1, 0, &attr, 0, 0); |
554 | } | 555 | } |
555 | 556 | ||
556 | struct fuse_inode_handle | 557 | struct fuse_inode_handle { |
557 | { | ||
558 | u64 nodeid; | 558 | u64 nodeid; |
559 | u32 generation; | 559 | u32 generation; |
560 | }; | 560 | }; |
@@ -761,7 +761,6 @@ static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req) | |||
761 | fc->max_write = max_t(unsigned, 4096, fc->max_write); | 761 | fc->max_write = max_t(unsigned, 4096, fc->max_write); |
762 | fc->conn_init = 1; | 762 | fc->conn_init = 1; |
763 | } | 763 | } |
764 | fuse_put_request(fc, req); | ||
765 | fc->blocked = 0; | 764 | fc->blocked = 0; |
766 | wake_up_all(&fc->blocked_waitq); | 765 | wake_up_all(&fc->blocked_waitq); |
767 | } | 766 | } |
@@ -787,7 +786,12 @@ static void fuse_send_init(struct fuse_conn *fc, struct fuse_req *req) | |||
787 | req->out.args[0].size = sizeof(struct fuse_init_out); | 786 | req->out.args[0].size = sizeof(struct fuse_init_out); |
788 | req->out.args[0].value = &req->misc.init_out; | 787 | req->out.args[0].value = &req->misc.init_out; |
789 | req->end = process_init_reply; | 788 | req->end = process_init_reply; |
790 | request_send_background(fc, req); | 789 | fuse_request_send_background(fc, req); |
790 | } | ||
791 | |||
792 | static void fuse_free_conn(struct fuse_conn *fc) | ||
793 | { | ||
794 | kfree(fc); | ||
791 | } | 795 | } |
792 | 796 | ||
793 | static int fuse_fill_super(struct super_block *sb, void *data, int silent) | 797 | static int fuse_fill_super(struct super_block *sb, void *data, int silent) |
@@ -828,10 +832,17 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent) | |||
828 | if (file->f_op != &fuse_dev_operations) | 832 | if (file->f_op != &fuse_dev_operations) |
829 | return -EINVAL; | 833 | return -EINVAL; |
830 | 834 | ||
831 | fc = new_conn(sb); | 835 | fc = kmalloc(sizeof(*fc), GFP_KERNEL); |
832 | if (!fc) | 836 | if (!fc) |
833 | return -ENOMEM; | 837 | return -ENOMEM; |
834 | 838 | ||
839 | err = fuse_conn_init(fc, sb); | ||
840 | if (err) { | ||
841 | kfree(fc); | ||
842 | return err; | ||
843 | } | ||
844 | |||
845 | fc->release = fuse_free_conn; | ||
835 | fc->flags = d.flags; | 846 | fc->flags = d.flags; |
836 | fc->user_id = d.user_id; | 847 | fc->user_id = d.user_id; |
837 | fc->group_id = d.group_id; | 848 | fc->group_id = d.group_id; |
@@ -841,7 +852,7 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent) | |||
841 | sb->s_fs_info = fc; | 852 | sb->s_fs_info = fc; |
842 | 853 | ||
843 | err = -ENOMEM; | 854 | err = -ENOMEM; |
844 | root = get_root_inode(sb, d.rootmode); | 855 | root = fuse_get_root_inode(sb, d.rootmode); |
845 | if (!root) | 856 | if (!root) |
846 | goto err; | 857 | goto err; |
847 | 858 | ||
@@ -952,7 +963,7 @@ static inline void unregister_fuseblk(void) | |||
952 | 963 | ||
953 | static void fuse_inode_init_once(void *foo) | 964 | static void fuse_inode_init_once(void *foo) |
954 | { | 965 | { |
955 | struct inode * inode = foo; | 966 | struct inode *inode = foo; |
956 | 967 | ||
957 | inode_init_once(inode); | 968 | inode_init_once(inode); |
958 | } | 969 | } |
@@ -1031,7 +1042,7 @@ static int __init fuse_init(void) | |||
1031 | { | 1042 | { |
1032 | int res; | 1043 | int res; |
1033 | 1044 | ||
1034 | printk("fuse init (API version %i.%i)\n", | 1045 | printk(KERN_INFO "fuse init (API version %i.%i)\n", |
1035 | FUSE_KERNEL_VERSION, FUSE_KERNEL_MINOR_VERSION); | 1046 | FUSE_KERNEL_VERSION, FUSE_KERNEL_MINOR_VERSION); |
1036 | 1047 | ||
1037 | INIT_LIST_HEAD(&fuse_conn_list); | 1048 | INIT_LIST_HEAD(&fuse_conn_list); |