diff options
Diffstat (limited to 'fs/fuse')
-rw-r--r-- | fs/fuse/dev.c | 5 | ||||
-rw-r--r-- | fs/fuse/fuse_i.h | 5 | ||||
-rw-r--r-- | fs/fuse/inode.c | 115 |
3 files changed, 72 insertions, 53 deletions
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index ba76b68c52ff..368189fd4056 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c | |||
@@ -282,7 +282,7 @@ __releases(&fc->lock) | |||
282 | wake_up_all(&fc->blocked_waitq); | 282 | wake_up_all(&fc->blocked_waitq); |
283 | } | 283 | } |
284 | if (fc->num_background == FUSE_CONGESTION_THRESHOLD && | 284 | if (fc->num_background == FUSE_CONGESTION_THRESHOLD && |
285 | fc->connected) { | 285 | fc->connected && fc->bdi_initialized) { |
286 | clear_bdi_congested(&fc->bdi, READ); | 286 | clear_bdi_congested(&fc->bdi, READ); |
287 | clear_bdi_congested(&fc->bdi, WRITE); | 287 | clear_bdi_congested(&fc->bdi, WRITE); |
288 | } | 288 | } |
@@ -408,7 +408,8 @@ static void fuse_request_send_nowait_locked(struct fuse_conn *fc, | |||
408 | fc->num_background++; | 408 | fc->num_background++; |
409 | if (fc->num_background == FUSE_MAX_BACKGROUND) | 409 | if (fc->num_background == FUSE_MAX_BACKGROUND) |
410 | fc->blocked = 1; | 410 | fc->blocked = 1; |
411 | if (fc->num_background == FUSE_CONGESTION_THRESHOLD) { | 411 | if (fc->num_background == FUSE_CONGESTION_THRESHOLD && |
412 | fc->bdi_initialized) { | ||
412 | set_bdi_congested(&fc->bdi, READ); | 413 | set_bdi_congested(&fc->bdi, READ); |
413 | set_bdi_congested(&fc->bdi, WRITE); | 414 | set_bdi_congested(&fc->bdi, WRITE); |
414 | } | 415 | } |
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index ef2e1f3780b5..2efcf12b763a 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h | |||
@@ -394,6 +394,9 @@ struct fuse_conn { | |||
394 | /** Filesystem supports NFS exporting. Only set in INIT */ | 394 | /** Filesystem supports NFS exporting. Only set in INIT */ |
395 | unsigned export_support:1; | 395 | unsigned export_support:1; |
396 | 396 | ||
397 | /** Set if bdi is valid */ | ||
398 | unsigned bdi_initialized:1; | ||
399 | |||
397 | /* | 400 | /* |
398 | * The following bitfields are only for optimization purposes | 401 | * The following bitfields are only for optimization purposes |
399 | * and hence races in setting them will not cause malfunction | 402 | * and hence races in setting them will not cause malfunction |
@@ -662,7 +665,7 @@ struct fuse_conn *fuse_conn_get(struct fuse_conn *fc); | |||
662 | /** | 665 | /** |
663 | * Initialize fuse_conn | 666 | * Initialize fuse_conn |
664 | */ | 667 | */ |
665 | int fuse_conn_init(struct fuse_conn *fc, struct super_block *sb); | 668 | void fuse_conn_init(struct fuse_conn *fc); |
666 | 669 | ||
667 | /** | 670 | /** |
668 | * Release reference to fuse_conn | 671 | * Release reference to fuse_conn |
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index 75ca5ac603ae..fea7c1064d30 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c | |||
@@ -274,11 +274,14 @@ static void fuse_send_destroy(struct fuse_conn *fc) | |||
274 | } | 274 | } |
275 | } | 275 | } |
276 | 276 | ||
277 | static void fuse_put_super(struct super_block *sb) | 277 | static void fuse_bdi_destroy(struct fuse_conn *fc) |
278 | { | 278 | { |
279 | struct fuse_conn *fc = get_fuse_conn_super(sb); | 279 | if (fc->bdi_initialized) |
280 | bdi_destroy(&fc->bdi); | ||
281 | } | ||
280 | 282 | ||
281 | fuse_send_destroy(fc); | 283 | static void fuse_conn_kill(struct fuse_conn *fc) |
284 | { | ||
282 | spin_lock(&fc->lock); | 285 | spin_lock(&fc->lock); |
283 | fc->connected = 0; | 286 | fc->connected = 0; |
284 | fc->blocked = 0; | 287 | fc->blocked = 0; |
@@ -292,7 +295,15 @@ static void fuse_put_super(struct super_block *sb) | |||
292 | list_del(&fc->entry); | 295 | list_del(&fc->entry); |
293 | fuse_ctl_remove_conn(fc); | 296 | fuse_ctl_remove_conn(fc); |
294 | mutex_unlock(&fuse_mutex); | 297 | mutex_unlock(&fuse_mutex); |
295 | bdi_destroy(&fc->bdi); | 298 | fuse_bdi_destroy(fc); |
299 | } | ||
300 | |||
301 | static void fuse_put_super(struct super_block *sb) | ||
302 | { | ||
303 | struct fuse_conn *fc = get_fuse_conn_super(sb); | ||
304 | |||
305 | fuse_send_destroy(fc); | ||
306 | fuse_conn_kill(fc); | ||
296 | fuse_conn_put(fc); | 307 | fuse_conn_put(fc); |
297 | } | 308 | } |
298 | 309 | ||
@@ -463,10 +474,8 @@ static int fuse_show_options(struct seq_file *m, struct vfsmount *mnt) | |||
463 | return 0; | 474 | return 0; |
464 | } | 475 | } |
465 | 476 | ||
466 | int fuse_conn_init(struct fuse_conn *fc, struct super_block *sb) | 477 | void fuse_conn_init(struct fuse_conn *fc) |
467 | { | 478 | { |
468 | int err; | ||
469 | |||
470 | memset(fc, 0, sizeof(*fc)); | 479 | memset(fc, 0, sizeof(*fc)); |
471 | spin_lock_init(&fc->lock); | 480 | spin_lock_init(&fc->lock); |
472 | mutex_init(&fc->inst_mutex); | 481 | mutex_init(&fc->inst_mutex); |
@@ -481,49 +490,12 @@ int fuse_conn_init(struct fuse_conn *fc, struct super_block *sb) | |||
481 | INIT_LIST_HEAD(&fc->bg_queue); | 490 | INIT_LIST_HEAD(&fc->bg_queue); |
482 | INIT_LIST_HEAD(&fc->entry); | 491 | INIT_LIST_HEAD(&fc->entry); |
483 | atomic_set(&fc->num_waiting, 0); | 492 | atomic_set(&fc->num_waiting, 0); |
484 | fc->bdi.ra_pages = (VM_MAX_READAHEAD * 1024) / PAGE_CACHE_SIZE; | ||
485 | fc->bdi.unplug_io_fn = default_unplug_io_fn; | ||
486 | /* fuse does it's own writeback accounting */ | ||
487 | fc->bdi.capabilities = BDI_CAP_NO_ACCT_WB; | ||
488 | fc->khctr = 0; | 493 | fc->khctr = 0; |
489 | fc->polled_files = RB_ROOT; | 494 | fc->polled_files = RB_ROOT; |
490 | fc->dev = sb->s_dev; | ||
491 | err = bdi_init(&fc->bdi); | ||
492 | if (err) | ||
493 | goto error_mutex_destroy; | ||
494 | if (sb->s_bdev) { | ||
495 | err = bdi_register(&fc->bdi, NULL, "%u:%u-fuseblk", | ||
496 | MAJOR(fc->dev), MINOR(fc->dev)); | ||
497 | } else { | ||
498 | err = bdi_register_dev(&fc->bdi, fc->dev); | ||
499 | } | ||
500 | if (err) | ||
501 | goto error_bdi_destroy; | ||
502 | /* | ||
503 | * For a single fuse filesystem use max 1% of dirty + | ||
504 | * writeback threshold. | ||
505 | * | ||
506 | * This gives about 1M of write buffer for memory maps on a | ||
507 | * machine with 1G and 10% dirty_ratio, which should be more | ||
508 | * than enough. | ||
509 | * | ||
510 | * Privileged users can raise it by writing to | ||
511 | * | ||
512 | * /sys/class/bdi/<bdi>/max_ratio | ||
513 | */ | ||
514 | bdi_set_max_ratio(&fc->bdi, 1); | ||
515 | fc->reqctr = 0; | 495 | fc->reqctr = 0; |
516 | fc->blocked = 1; | 496 | fc->blocked = 1; |
517 | fc->attr_version = 1; | 497 | fc->attr_version = 1; |
518 | get_random_bytes(&fc->scramble_key, sizeof(fc->scramble_key)); | 498 | get_random_bytes(&fc->scramble_key, sizeof(fc->scramble_key)); |
519 | |||
520 | return 0; | ||
521 | |||
522 | error_bdi_destroy: | ||
523 | bdi_destroy(&fc->bdi); | ||
524 | error_mutex_destroy: | ||
525 | mutex_destroy(&fc->inst_mutex); | ||
526 | return err; | ||
527 | } | 499 | } |
528 | EXPORT_SYMBOL_GPL(fuse_conn_init); | 500 | EXPORT_SYMBOL_GPL(fuse_conn_init); |
529 | 501 | ||
@@ -794,6 +766,48 @@ static void fuse_free_conn(struct fuse_conn *fc) | |||
794 | kfree(fc); | 766 | kfree(fc); |
795 | } | 767 | } |
796 | 768 | ||
769 | static int fuse_bdi_init(struct fuse_conn *fc, struct super_block *sb) | ||
770 | { | ||
771 | int err; | ||
772 | |||
773 | fc->bdi.ra_pages = (VM_MAX_READAHEAD * 1024) / PAGE_CACHE_SIZE; | ||
774 | fc->bdi.unplug_io_fn = default_unplug_io_fn; | ||
775 | /* fuse does it's own writeback accounting */ | ||
776 | fc->bdi.capabilities = BDI_CAP_NO_ACCT_WB; | ||
777 | |||
778 | err = bdi_init(&fc->bdi); | ||
779 | if (err) | ||
780 | return err; | ||
781 | |||
782 | fc->bdi_initialized = 1; | ||
783 | |||
784 | if (sb->s_bdev) { | ||
785 | err = bdi_register(&fc->bdi, NULL, "%u:%u-fuseblk", | ||
786 | MAJOR(fc->dev), MINOR(fc->dev)); | ||
787 | } else { | ||
788 | err = bdi_register_dev(&fc->bdi, fc->dev); | ||
789 | } | ||
790 | |||
791 | if (err) | ||
792 | return err; | ||
793 | |||
794 | /* | ||
795 | * For a single fuse filesystem use max 1% of dirty + | ||
796 | * writeback threshold. | ||
797 | * | ||
798 | * This gives about 1M of write buffer for memory maps on a | ||
799 | * machine with 1G and 10% dirty_ratio, which should be more | ||
800 | * than enough. | ||
801 | * | ||
802 | * Privileged users can raise it by writing to | ||
803 | * | ||
804 | * /sys/class/bdi/<bdi>/max_ratio | ||
805 | */ | ||
806 | bdi_set_max_ratio(&fc->bdi, 1); | ||
807 | |||
808 | return 0; | ||
809 | } | ||
810 | |||
797 | static int fuse_fill_super(struct super_block *sb, void *data, int silent) | 811 | static int fuse_fill_super(struct super_block *sb, void *data, int silent) |
798 | { | 812 | { |
799 | struct fuse_conn *fc; | 813 | struct fuse_conn *fc; |
@@ -840,11 +854,12 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent) | |||
840 | if (!fc) | 854 | if (!fc) |
841 | goto err_fput; | 855 | goto err_fput; |
842 | 856 | ||
843 | err = fuse_conn_init(fc, sb); | 857 | fuse_conn_init(fc); |
844 | if (err) { | 858 | |
845 | kfree(fc); | 859 | fc->dev = sb->s_dev; |
846 | goto err_fput; | 860 | err = fuse_bdi_init(fc, sb); |
847 | } | 861 | if (err) |
862 | goto err_put_conn; | ||
848 | 863 | ||
849 | fc->release = fuse_free_conn; | 864 | fc->release = fuse_free_conn; |
850 | fc->flags = d.flags; | 865 | fc->flags = d.flags; |
@@ -908,7 +923,7 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent) | |||
908 | err_put_root: | 923 | err_put_root: |
909 | dput(root_dentry); | 924 | dput(root_dentry); |
910 | err_put_conn: | 925 | err_put_conn: |
911 | bdi_destroy(&fc->bdi); | 926 | fuse_bdi_destroy(fc); |
912 | fuse_conn_put(fc); | 927 | fuse_conn_put(fc); |
913 | err_fput: | 928 | err_fput: |
914 | fput(file); | 929 | fput(file); |