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.c123
1 files changed, 105 insertions, 18 deletions
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index fc4203570370..12450d2b320e 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -22,7 +22,7 @@ MODULE_AUTHOR("Miklos Szeredi <miklos@szeredi.hu>");
22MODULE_DESCRIPTION("Filesystem in Userspace"); 22MODULE_DESCRIPTION("Filesystem in Userspace");
23MODULE_LICENSE("GPL"); 23MODULE_LICENSE("GPL");
24 24
25static kmem_cache_t *fuse_inode_cachep; 25static struct kmem_cache *fuse_inode_cachep;
26struct list_head fuse_conn_list; 26struct list_head fuse_conn_list;
27DEFINE_MUTEX(fuse_mutex); 27DEFINE_MUTEX(fuse_mutex);
28 28
@@ -39,6 +39,7 @@ struct fuse_mount_data {
39 unsigned group_id_present : 1; 39 unsigned group_id_present : 1;
40 unsigned flags; 40 unsigned flags;
41 unsigned max_read; 41 unsigned max_read;
42 unsigned blksize;
42}; 43};
43 44
44static struct inode *fuse_alloc_inode(struct super_block *sb) 45static struct inode *fuse_alloc_inode(struct super_block *sb)
@@ -46,7 +47,7 @@ static struct inode *fuse_alloc_inode(struct super_block *sb)
46 struct inode *inode; 47 struct inode *inode;
47 struct fuse_inode *fi; 48 struct fuse_inode *fi;
48 49
49 inode = kmem_cache_alloc(fuse_inode_cachep, SLAB_KERNEL); 50 inode = kmem_cache_alloc(fuse_inode_cachep, GFP_KERNEL);
50 if (!inode) 51 if (!inode)
51 return NULL; 52 return NULL;
52 53
@@ -205,10 +206,23 @@ static void fuse_umount_begin(struct vfsmount *vfsmnt, int flags)
205 fuse_abort_conn(get_fuse_conn_super(vfsmnt->mnt_sb)); 206 fuse_abort_conn(get_fuse_conn_super(vfsmnt->mnt_sb));
206} 207}
207 208
209static void fuse_send_destroy(struct fuse_conn *fc)
210{
211 struct fuse_req *req = fc->destroy_req;
212 if (req && fc->conn_init) {
213 fc->destroy_req = NULL;
214 req->in.h.opcode = FUSE_DESTROY;
215 req->force = 1;
216 request_send(fc, req);
217 fuse_put_request(fc, req);
218 }
219}
220
208static void fuse_put_super(struct super_block *sb) 221static void fuse_put_super(struct super_block *sb)
209{ 222{
210 struct fuse_conn *fc = get_fuse_conn_super(sb); 223 struct fuse_conn *fc = get_fuse_conn_super(sb);
211 224
225 fuse_send_destroy(fc);
212 spin_lock(&fc->lock); 226 spin_lock(&fc->lock);
213 fc->connected = 0; 227 fc->connected = 0;
214 fc->blocked = 0; 228 fc->blocked = 0;
@@ -274,6 +288,7 @@ enum {
274 OPT_DEFAULT_PERMISSIONS, 288 OPT_DEFAULT_PERMISSIONS,
275 OPT_ALLOW_OTHER, 289 OPT_ALLOW_OTHER,
276 OPT_MAX_READ, 290 OPT_MAX_READ,
291 OPT_BLKSIZE,
277 OPT_ERR 292 OPT_ERR
278}; 293};
279 294
@@ -285,14 +300,16 @@ static match_table_t tokens = {
285 {OPT_DEFAULT_PERMISSIONS, "default_permissions"}, 300 {OPT_DEFAULT_PERMISSIONS, "default_permissions"},
286 {OPT_ALLOW_OTHER, "allow_other"}, 301 {OPT_ALLOW_OTHER, "allow_other"},
287 {OPT_MAX_READ, "max_read=%u"}, 302 {OPT_MAX_READ, "max_read=%u"},
303 {OPT_BLKSIZE, "blksize=%u"},
288 {OPT_ERR, NULL} 304 {OPT_ERR, NULL}
289}; 305};
290 306
291static int parse_fuse_opt(char *opt, struct fuse_mount_data *d) 307static int parse_fuse_opt(char *opt, struct fuse_mount_data *d, int is_bdev)
292{ 308{
293 char *p; 309 char *p;
294 memset(d, 0, sizeof(struct fuse_mount_data)); 310 memset(d, 0, sizeof(struct fuse_mount_data));
295 d->max_read = ~0; 311 d->max_read = ~0;
312 d->blksize = 512;
296 313
297 while ((p = strsep(&opt, ",")) != NULL) { 314 while ((p = strsep(&opt, ",")) != NULL) {
298 int token; 315 int token;
@@ -345,6 +362,12 @@ static int parse_fuse_opt(char *opt, struct fuse_mount_data *d)
345 d->max_read = value; 362 d->max_read = value;
346 break; 363 break;
347 364
365 case OPT_BLKSIZE:
366 if (!is_bdev || match_int(&args[0], &value))
367 return 0;
368 d->blksize = value;
369 break;
370
348 default: 371 default:
349 return 0; 372 return 0;
350 } 373 }
@@ -400,6 +423,8 @@ static struct fuse_conn *new_conn(void)
400void fuse_conn_put(struct fuse_conn *fc) 423void fuse_conn_put(struct fuse_conn *fc)
401{ 424{
402 if (atomic_dec_and_test(&fc->count)) { 425 if (atomic_dec_and_test(&fc->count)) {
426 if (fc->destroy_req)
427 fuse_request_free(fc->destroy_req);
403 mutex_destroy(&fc->inst_mutex); 428 mutex_destroy(&fc->inst_mutex);
404 kfree(fc); 429 kfree(fc);
405 } 430 }
@@ -456,6 +481,7 @@ static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req)
456 fc->bdi.ra_pages = min(fc->bdi.ra_pages, ra_pages); 481 fc->bdi.ra_pages = min(fc->bdi.ra_pages, ra_pages);
457 fc->minor = arg->minor; 482 fc->minor = arg->minor;
458 fc->max_write = arg->minor < 5 ? 4096 : arg->max_write; 483 fc->max_write = arg->minor < 5 ? 4096 : arg->max_write;
484 fc->conn_init = 1;
459 } 485 }
460 fuse_put_request(fc, req); 486 fuse_put_request(fc, req);
461 fc->blocked = 0; 487 fc->blocked = 0;
@@ -500,15 +526,23 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent)
500 struct dentry *root_dentry; 526 struct dentry *root_dentry;
501 struct fuse_req *init_req; 527 struct fuse_req *init_req;
502 int err; 528 int err;
529 int is_bdev = sb->s_bdev != NULL;
503 530
504 if (sb->s_flags & MS_MANDLOCK) 531 if (sb->s_flags & MS_MANDLOCK)
505 return -EINVAL; 532 return -EINVAL;
506 533
507 if (!parse_fuse_opt((char *) data, &d)) 534 if (!parse_fuse_opt((char *) data, &d, is_bdev))
508 return -EINVAL; 535 return -EINVAL;
509 536
510 sb->s_blocksize = PAGE_CACHE_SIZE; 537 if (is_bdev) {
511 sb->s_blocksize_bits = PAGE_CACHE_SHIFT; 538#ifdef CONFIG_BLOCK
539 if (!sb_set_blocksize(sb, d.blksize))
540 return -EINVAL;
541#endif
542 } else {
543 sb->s_blocksize = PAGE_CACHE_SIZE;
544 sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
545 }
512 sb->s_magic = FUSE_SUPER_MAGIC; 546 sb->s_magic = FUSE_SUPER_MAGIC;
513 sb->s_op = &fuse_super_operations; 547 sb->s_op = &fuse_super_operations;
514 sb->s_maxbytes = MAX_LFS_FILESIZE; 548 sb->s_maxbytes = MAX_LFS_FILESIZE;
@@ -547,6 +581,12 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent)
547 if (!init_req) 581 if (!init_req)
548 goto err_put_root; 582 goto err_put_root;
549 583
584 if (is_bdev) {
585 fc->destroy_req = fuse_request_alloc();
586 if (!fc->destroy_req)
587 goto err_put_root;
588 }
589
550 mutex_lock(&fuse_mutex); 590 mutex_lock(&fuse_mutex);
551 err = -EINVAL; 591 err = -EINVAL;
552 if (file->private_data) 592 if (file->private_data)
@@ -598,10 +638,47 @@ static struct file_system_type fuse_fs_type = {
598 .kill_sb = kill_anon_super, 638 .kill_sb = kill_anon_super,
599}; 639};
600 640
641#ifdef CONFIG_BLOCK
642static int fuse_get_sb_blk(struct file_system_type *fs_type,
643 int flags, const char *dev_name,
644 void *raw_data, struct vfsmount *mnt)
645{
646 return get_sb_bdev(fs_type, flags, dev_name, raw_data, fuse_fill_super,
647 mnt);
648}
649
650static struct file_system_type fuseblk_fs_type = {
651 .owner = THIS_MODULE,
652 .name = "fuseblk",
653 .get_sb = fuse_get_sb_blk,
654 .kill_sb = kill_block_super,
655 .fs_flags = FS_REQUIRES_DEV,
656};
657
658static inline int register_fuseblk(void)
659{
660 return register_filesystem(&fuseblk_fs_type);
661}
662
663static inline void unregister_fuseblk(void)
664{
665 unregister_filesystem(&fuseblk_fs_type);
666}
667#else
668static inline int register_fuseblk(void)
669{
670 return 0;
671}
672
673static inline void unregister_fuseblk(void)
674{
675}
676#endif
677
601static decl_subsys(fuse, NULL, NULL); 678static decl_subsys(fuse, NULL, NULL);
602static decl_subsys(connections, NULL, NULL); 679static decl_subsys(connections, NULL, NULL);
603 680
604static void fuse_inode_init_once(void *foo, kmem_cache_t *cachep, 681static void fuse_inode_init_once(void *foo, struct kmem_cache *cachep,
605 unsigned long flags) 682 unsigned long flags)
606{ 683{
607 struct inode * inode = foo; 684 struct inode * inode = foo;
@@ -617,24 +694,34 @@ static int __init fuse_fs_init(void)
617 694
618 err = register_filesystem(&fuse_fs_type); 695 err = register_filesystem(&fuse_fs_type);
619 if (err) 696 if (err)
620 printk("fuse: failed to register filesystem\n"); 697 goto out;
621 else {
622 fuse_inode_cachep = kmem_cache_create("fuse_inode",
623 sizeof(struct fuse_inode),
624 0, SLAB_HWCACHE_ALIGN,
625 fuse_inode_init_once, NULL);
626 if (!fuse_inode_cachep) {
627 unregister_filesystem(&fuse_fs_type);
628 err = -ENOMEM;
629 }
630 }
631 698
699 err = register_fuseblk();
700 if (err)
701 goto out_unreg;
702
703 fuse_inode_cachep = kmem_cache_create("fuse_inode",
704 sizeof(struct fuse_inode),
705 0, SLAB_HWCACHE_ALIGN,
706 fuse_inode_init_once, NULL);
707 err = -ENOMEM;
708 if (!fuse_inode_cachep)
709 goto out_unreg2;
710
711 return 0;
712
713 out_unreg2:
714 unregister_fuseblk();
715 out_unreg:
716 unregister_filesystem(&fuse_fs_type);
717 out:
632 return err; 718 return err;
633} 719}
634 720
635static void fuse_fs_cleanup(void) 721static void fuse_fs_cleanup(void)
636{ 722{
637 unregister_filesystem(&fuse_fs_type); 723 unregister_filesystem(&fuse_fs_type);
724 unregister_fuseblk();
638 kmem_cache_destroy(fuse_inode_cachep); 725 kmem_cache_destroy(fuse_inode_cachep);
639} 726}
640 727