diff options
-rw-r--r-- | fs/btrfs/TODO | 1 | ||||
-rw-r--r-- | fs/btrfs/ctree.h | 5 | ||||
-rw-r--r-- | fs/btrfs/disk-io.c | 4 | ||||
-rw-r--r-- | fs/btrfs/super.c | 27 | ||||
-rw-r--r-- | fs/btrfs/transaction.c | 60 | ||||
-rw-r--r-- | fs/btrfs/transaction.h | 8 |
6 files changed, 98 insertions, 7 deletions
diff --git a/fs/btrfs/TODO b/fs/btrfs/TODO index 861e34ae0979..61d25b5de287 100644 --- a/fs/btrfs/TODO +++ b/fs/btrfs/TODO | |||
@@ -7,7 +7,6 @@ | |||
7 | * Get rid of struct ctree_path, limiting tree levels held at one time | 7 | * Get rid of struct ctree_path, limiting tree levels held at one time |
8 | * Add generation number to key pointer in nodes | 8 | * Add generation number to key pointer in nodes |
9 | * Add generation number to inode | 9 | * Add generation number to inode |
10 | * Add ability to switch a block group from data to metadata or vice versa | ||
11 | * forbid cross subvolume renames and hardlinks | 10 | * forbid cross subvolume renames and hardlinks |
12 | * Release | 11 | * Release |
13 | * Do real tree locking | 12 | * Do real tree locking |
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index a1c95c980fdc..74e6aadf6bb7 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
@@ -3,7 +3,7 @@ | |||
3 | 3 | ||
4 | #include <linux/fs.h> | 4 | #include <linux/fs.h> |
5 | #include <linux/buffer_head.h> | 5 | #include <linux/buffer_head.h> |
6 | #include <linux/kobject.h> | 6 | #include <linux/workqueue.h> |
7 | #include "bit-radix.h" | 7 | #include "bit-radix.h" |
8 | 8 | ||
9 | struct btrfs_trans_handle; | 9 | struct btrfs_trans_handle; |
@@ -281,6 +281,7 @@ struct btrfs_block_group_cache { | |||
281 | }; | 281 | }; |
282 | 282 | ||
283 | struct crypto_hash; | 283 | struct crypto_hash; |
284 | |||
284 | struct btrfs_fs_info { | 285 | struct btrfs_fs_info { |
285 | struct btrfs_root *extent_root; | 286 | struct btrfs_root *extent_root; |
286 | struct btrfs_root *tree_root; | 287 | struct btrfs_root *tree_root; |
@@ -308,9 +309,9 @@ struct btrfs_fs_info { | |||
308 | struct mutex fs_mutex; | 309 | struct mutex fs_mutex; |
309 | struct list_head trans_list; | 310 | struct list_head trans_list; |
310 | struct crypto_hash *hash_tfm; | 311 | struct crypto_hash *hash_tfm; |
312 | struct delayed_work trans_work; | ||
311 | spinlock_t hash_lock; | 313 | spinlock_t hash_lock; |
312 | int do_barriers; | 314 | int do_barriers; |
313 | struct kobject kobj; | ||
314 | }; | 315 | }; |
315 | 316 | ||
316 | /* | 317 | /* |
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 3da057f78bc8..048282f06afb 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -577,6 +577,7 @@ struct btrfs_root *open_ctree(struct super_block *sb) | |||
577 | fs_info->do_barriers = 1; | 577 | fs_info->do_barriers = 1; |
578 | fs_info->extent_tree_insert_nr = 0; | 578 | fs_info->extent_tree_insert_nr = 0; |
579 | fs_info->extent_tree_prealloc_nr = 0; | 579 | fs_info->extent_tree_prealloc_nr = 0; |
580 | INIT_DELAYED_WORK(&fs_info->trans_work, btrfs_transaction_cleaner); | ||
580 | BTRFS_I(fs_info->btree_inode)->root = tree_root; | 581 | BTRFS_I(fs_info->btree_inode)->root = tree_root; |
581 | memset(&BTRFS_I(fs_info->btree_inode)->location, 0, | 582 | memset(&BTRFS_I(fs_info->btree_inode)->location, 0, |
582 | sizeof(struct btrfs_key)); | 583 | sizeof(struct btrfs_key)); |
@@ -648,7 +649,6 @@ struct btrfs_root *open_ctree(struct super_block *sb) | |||
648 | btrfs_read_block_groups(extent_root); | 649 | btrfs_read_block_groups(extent_root); |
649 | 650 | ||
650 | fs_info->generation = btrfs_super_generation(disk_super) + 1; | 651 | fs_info->generation = btrfs_super_generation(disk_super) + 1; |
651 | memset(&fs_info->kobj, 0, sizeof(fs_info->kobj)); | ||
652 | mutex_unlock(&fs_info->fs_mutex); | 652 | mutex_unlock(&fs_info->fs_mutex); |
653 | return tree_root; | 653 | return tree_root; |
654 | } | 654 | } |
@@ -746,6 +746,7 @@ int close_ctree(struct btrfs_root *root) | |||
746 | struct btrfs_trans_handle *trans; | 746 | struct btrfs_trans_handle *trans; |
747 | struct btrfs_fs_info *fs_info = root->fs_info; | 747 | struct btrfs_fs_info *fs_info = root->fs_info; |
748 | 748 | ||
749 | btrfs_transaction_flush_work(root); | ||
749 | mutex_lock(&fs_info->fs_mutex); | 750 | mutex_lock(&fs_info->fs_mutex); |
750 | trans = btrfs_start_transaction(root, 1); | 751 | trans = btrfs_start_transaction(root, 1); |
751 | btrfs_commit_transaction(trans, root); | 752 | btrfs_commit_transaction(trans, root); |
@@ -776,7 +777,6 @@ int close_ctree(struct btrfs_root *root) | |||
776 | del_fs_roots(fs_info); | 777 | del_fs_roots(fs_info); |
777 | kfree(fs_info->extent_root); | 778 | kfree(fs_info->extent_root); |
778 | kfree(fs_info->tree_root); | 779 | kfree(fs_info->tree_root); |
779 | kobject_unregister(&fs_info->kobj); | ||
780 | return 0; | 780 | return 0; |
781 | } | 781 | } |
782 | 782 | ||
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index b58b4cf66766..5864917953a4 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include <linux/swap.h> | 12 | #include <linux/swap.h> |
13 | #include <linux/writeback.h> | 13 | #include <linux/writeback.h> |
14 | #include <linux/statfs.h> | 14 | #include <linux/statfs.h> |
15 | #include <linux/compat.h> | ||
15 | #include "ctree.h" | 16 | #include "ctree.h" |
16 | #include "disk-io.h" | 17 | #include "disk-io.h" |
17 | #include "transaction.h" | 18 | #include "transaction.h" |
@@ -950,7 +951,7 @@ static int btrfs_fill_super(struct super_block * sb, void * data, int silent) | |||
950 | return -ENOMEM; | 951 | return -ENOMEM; |
951 | } | 952 | } |
952 | sb->s_root = root_dentry; | 953 | sb->s_root = root_dentry; |
953 | 954 | btrfs_transaction_queue_work(tree_root, HZ * 30); | |
954 | return 0; | 955 | return 0; |
955 | } | 956 | } |
956 | 957 | ||
@@ -1452,7 +1453,7 @@ static int btrfs_prepare_write(struct file *file, struct page *page, | |||
1452 | 1453 | ||
1453 | static void btrfs_write_super(struct super_block *sb) | 1454 | static void btrfs_write_super(struct super_block *sb) |
1454 | { | 1455 | { |
1455 | btrfs_sync_fs(sb, 1); | 1456 | sb->s_dirt = 0; |
1456 | } | 1457 | } |
1457 | 1458 | ||
1458 | static int btrfs_readpage(struct file *file, struct page *page) | 1459 | static int btrfs_readpage(struct file *file, struct page *page) |
@@ -2698,6 +2699,20 @@ static int btrfs_ioctl(struct inode *inode, struct file *filp, unsigned int | |||
2698 | return ret; | 2699 | return ret; |
2699 | } | 2700 | } |
2700 | 2701 | ||
2702 | #ifdef CONFIG_COMPAT | ||
2703 | static long btrfs_compat_ioctl(struct file *file, unsigned int cmd, | ||
2704 | unsigned long arg) | ||
2705 | { | ||
2706 | struct inode *inode = file->f_path.dentry->d_inode; | ||
2707 | int ret; | ||
2708 | lock_kernel(); | ||
2709 | ret = btrfs_ioctl(inode, file, cmd, (unsigned long) compat_ptr(arg)); | ||
2710 | unlock_kernel(); | ||
2711 | return ret; | ||
2712 | |||
2713 | } | ||
2714 | #endif | ||
2715 | |||
2701 | static struct kmem_cache *btrfs_inode_cachep; | 2716 | static struct kmem_cache *btrfs_inode_cachep; |
2702 | struct kmem_cache *btrfs_trans_handle_cachep; | 2717 | struct kmem_cache *btrfs_trans_handle_cachep; |
2703 | struct kmem_cache *btrfs_transaction_cachep; | 2718 | struct kmem_cache *btrfs_transaction_cachep; |
@@ -3042,6 +3057,9 @@ static struct file_operations btrfs_dir_file_operations = { | |||
3042 | .read = generic_read_dir, | 3057 | .read = generic_read_dir, |
3043 | .readdir = btrfs_readdir, | 3058 | .readdir = btrfs_readdir, |
3044 | .ioctl = btrfs_ioctl, | 3059 | .ioctl = btrfs_ioctl, |
3060 | #ifdef CONFIG_COMPAT | ||
3061 | .compat_ioctl = btrfs_compat_ioctl, | ||
3062 | #endif | ||
3045 | }; | 3063 | }; |
3046 | 3064 | ||
3047 | static struct address_space_operations btrfs_aops = { | 3065 | static struct address_space_operations btrfs_aops = { |
@@ -3073,6 +3091,9 @@ static struct file_operations btrfs_file_operations = { | |||
3073 | .open = generic_file_open, | 3091 | .open = generic_file_open, |
3074 | .ioctl = btrfs_ioctl, | 3092 | .ioctl = btrfs_ioctl, |
3075 | .fsync = btrfs_sync_file, | 3093 | .fsync = btrfs_sync_file, |
3094 | #ifdef CONFIG_COMPAT | ||
3095 | .compat_ioctl = btrfs_compat_ioctl, | ||
3096 | #endif | ||
3076 | }; | 3097 | }; |
3077 | 3098 | ||
3078 | static struct inode_operations btrfs_symlink_inode_operations = { | 3099 | static struct inode_operations btrfs_symlink_inode_operations = { |
@@ -3085,6 +3106,7 @@ static int __init init_btrfs_fs(void) | |||
3085 | { | 3106 | { |
3086 | int err; | 3107 | int err; |
3087 | printk("btrfs loaded!\n"); | 3108 | printk("btrfs loaded!\n"); |
3109 | btrfs_init_transaction_sys(); | ||
3088 | err = init_inodecache(); | 3110 | err = init_inodecache(); |
3089 | if (err) | 3111 | if (err) |
3090 | return err; | 3112 | return err; |
@@ -3095,6 +3117,7 @@ static int __init init_btrfs_fs(void) | |||
3095 | 3117 | ||
3096 | static void __exit exit_btrfs_fs(void) | 3118 | static void __exit exit_btrfs_fs(void) |
3097 | { | 3119 | { |
3120 | btrfs_exit_transaction_sys(); | ||
3098 | destroy_inodecache(); | 3121 | destroy_inodecache(); |
3099 | unregister_filesystem(&btrfs_fs_type); | 3122 | unregister_filesystem(&btrfs_fs_type); |
3100 | printk("btrfs unloaded\n"); | 3123 | printk("btrfs unloaded\n"); |
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index f0f03121b7b2..bf7eef67ba0b 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c | |||
@@ -8,6 +8,8 @@ static int total_trans = 0; | |||
8 | extern struct kmem_cache *btrfs_trans_handle_cachep; | 8 | extern struct kmem_cache *btrfs_trans_handle_cachep; |
9 | extern struct kmem_cache *btrfs_transaction_cachep; | 9 | extern struct kmem_cache *btrfs_transaction_cachep; |
10 | 10 | ||
11 | static struct workqueue_struct *trans_wq; | ||
12 | |||
11 | #define BTRFS_ROOT_TRANS_TAG 0 | 13 | #define BTRFS_ROOT_TRANS_TAG 0 |
12 | 14 | ||
13 | #define TRANS_MAGIC 0xE1E10E | 15 | #define TRANS_MAGIC 0xE1E10E |
@@ -44,6 +46,7 @@ static int join_transaction(struct btrfs_root *root) | |||
44 | cur_trans->in_commit = 0; | 46 | cur_trans->in_commit = 0; |
45 | cur_trans->use_count = 1; | 47 | cur_trans->use_count = 1; |
46 | cur_trans->commit_done = 0; | 48 | cur_trans->commit_done = 0; |
49 | cur_trans->start_time = get_seconds(); | ||
47 | list_add_tail(&cur_trans->list, &root->fs_info->trans_list); | 50 | list_add_tail(&cur_trans->list, &root->fs_info->trans_list); |
48 | init_bit_radix(&cur_trans->dirty_pages); | 51 | init_bit_radix(&cur_trans->dirty_pages); |
49 | } | 52 | } |
@@ -350,3 +353,60 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
350 | return ret; | 353 | return ret; |
351 | } | 354 | } |
352 | 355 | ||
356 | void btrfs_transaction_cleaner(struct work_struct *work) | ||
357 | { | ||
358 | struct btrfs_fs_info *fs_info = container_of(work, | ||
359 | struct btrfs_fs_info, | ||
360 | trans_work.work); | ||
361 | |||
362 | struct btrfs_root *root = fs_info->tree_root; | ||
363 | struct btrfs_transaction *cur; | ||
364 | struct btrfs_trans_handle *trans; | ||
365 | unsigned long now; | ||
366 | unsigned long delay = HZ * 30; | ||
367 | int ret; | ||
368 | |||
369 | printk("btrfs transaction cleaner\n"); | ||
370 | mutex_lock(&root->fs_info->fs_mutex); | ||
371 | mutex_lock(&root->fs_info->trans_mutex); | ||
372 | cur = root->fs_info->running_transaction; | ||
373 | if (!cur) { | ||
374 | mutex_unlock(&root->fs_info->trans_mutex); | ||
375 | goto out; | ||
376 | } | ||
377 | now = get_seconds(); | ||
378 | if (now < cur->start_time || now - cur->start_time < 30) { | ||
379 | mutex_unlock(&root->fs_info->trans_mutex); | ||
380 | delay = HZ * 5; | ||
381 | goto out; | ||
382 | } | ||
383 | mutex_unlock(&root->fs_info->trans_mutex); | ||
384 | printk("forcing commit\n"); | ||
385 | trans = btrfs_start_transaction(root, 1); | ||
386 | ret = btrfs_commit_transaction(trans, root); | ||
387 | out: | ||
388 | mutex_unlock(&root->fs_info->fs_mutex); | ||
389 | btrfs_transaction_queue_work(root, delay); | ||
390 | } | ||
391 | |||
392 | void btrfs_transaction_queue_work(struct btrfs_root *root, int delay) | ||
393 | { | ||
394 | queue_delayed_work(trans_wq, &root->fs_info->trans_work, delay); | ||
395 | } | ||
396 | |||
397 | void btrfs_transaction_flush_work(struct btrfs_root *root) | ||
398 | { | ||
399 | cancel_rearming_delayed_workqueue(trans_wq, &root->fs_info->trans_work); | ||
400 | flush_workqueue(trans_wq); | ||
401 | } | ||
402 | |||
403 | void __init btrfs_init_transaction_sys(void) | ||
404 | { | ||
405 | trans_wq = create_workqueue("btrfs"); | ||
406 | } | ||
407 | |||
408 | void __exit btrfs_exit_transaction_sys(void) | ||
409 | { | ||
410 | destroy_workqueue(trans_wq); | ||
411 | } | ||
412 | |||
diff --git a/fs/btrfs/transaction.h b/fs/btrfs/transaction.h index b5378119e76c..0b08208be853 100644 --- a/fs/btrfs/transaction.h +++ b/fs/btrfs/transaction.h | |||
@@ -11,6 +11,7 @@ struct btrfs_transaction { | |||
11 | int magic; | 11 | int magic; |
12 | struct list_head list; | 12 | struct list_head list; |
13 | struct radix_tree_root dirty_pages; | 13 | struct radix_tree_root dirty_pages; |
14 | unsigned long start_time; | ||
14 | wait_queue_head_t writer_wait; | 15 | wait_queue_head_t writer_wait; |
15 | wait_queue_head_t commit_wait; | 16 | wait_queue_head_t commit_wait; |
16 | }; | 17 | }; |
@@ -47,4 +48,11 @@ int btrfs_write_and_wait_transaction(struct btrfs_trans_handle *trans, | |||
47 | struct btrfs_root *root); | 48 | struct btrfs_root *root); |
48 | int btrfs_commit_tree_roots(struct btrfs_trans_handle *trans, | 49 | int btrfs_commit_tree_roots(struct btrfs_trans_handle *trans, |
49 | struct btrfs_root *root); | 50 | struct btrfs_root *root); |
51 | |||
52 | void btrfs_transaction_cleaner(struct work_struct *work); | ||
53 | void btrfs_transaction_flush_work(struct btrfs_root *root); | ||
54 | void btrfs_transaction_queue_work(struct btrfs_root *root, int delay); | ||
55 | void btrfs_init_transaction_sys(void); | ||
56 | void btrfs_exit_transaction_sys(void); | ||
57 | |||
50 | #endif | 58 | #endif |