aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/btrfs/TODO1
-rw-r--r--fs/btrfs/ctree.h5
-rw-r--r--fs/btrfs/disk-io.c4
-rw-r--r--fs/btrfs/super.c27
-rw-r--r--fs/btrfs/transaction.c60
-rw-r--r--fs/btrfs/transaction.h8
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
9struct btrfs_trans_handle; 9struct btrfs_trans_handle;
@@ -281,6 +281,7 @@ struct btrfs_block_group_cache {
281}; 281};
282 282
283struct crypto_hash; 283struct crypto_hash;
284
284struct btrfs_fs_info { 285struct 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
1453static void btrfs_write_super(struct super_block *sb) 1454static 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
1458static int btrfs_readpage(struct file *file, struct page *page) 1459static 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
2703static 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
2701static struct kmem_cache *btrfs_inode_cachep; 2716static struct kmem_cache *btrfs_inode_cachep;
2702struct kmem_cache *btrfs_trans_handle_cachep; 2717struct kmem_cache *btrfs_trans_handle_cachep;
2703struct kmem_cache *btrfs_transaction_cachep; 2718struct 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
3047static struct address_space_operations btrfs_aops = { 3065static 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
3078static struct inode_operations btrfs_symlink_inode_operations = { 3099static 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
3096static void __exit exit_btrfs_fs(void) 3118static 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;
8extern struct kmem_cache *btrfs_trans_handle_cachep; 8extern struct kmem_cache *btrfs_trans_handle_cachep;
9extern struct kmem_cache *btrfs_transaction_cachep; 9extern struct kmem_cache *btrfs_transaction_cachep;
10 10
11static 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
356void 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
369printk("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);
384printk("forcing commit\n");
385 trans = btrfs_start_transaction(root, 1);
386 ret = btrfs_commit_transaction(trans, root);
387out:
388 mutex_unlock(&root->fs_info->fs_mutex);
389 btrfs_transaction_queue_work(root, delay);
390}
391
392void 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
397void 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
403void __init btrfs_init_transaction_sys(void)
404{
405 trans_wq = create_workqueue("btrfs");
406}
407
408void __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);
48int btrfs_commit_tree_roots(struct btrfs_trans_handle *trans, 49int btrfs_commit_tree_roots(struct btrfs_trans_handle *trans,
49 struct btrfs_root *root); 50 struct btrfs_root *root);
51
52void btrfs_transaction_cleaner(struct work_struct *work);
53void btrfs_transaction_flush_work(struct btrfs_root *root);
54void btrfs_transaction_queue_work(struct btrfs_root *root, int delay);
55void btrfs_init_transaction_sys(void);
56void btrfs_exit_transaction_sys(void);
57
50#endif 58#endif