aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJosef Bacik <jbacik@redhat.com>2007-08-29 15:47:34 -0400
committerDavid Woodhouse <dwmw2@hera.kernel.org>2007-08-29 15:47:34 -0400
commit58176a9604c5db1784d2c979aea472b3be40b6f0 (patch)
treea0d887c81b2f174de619dfefca19674a43756971
parentb888db2bd7b67f190b32934e6a86181f262ac3ec (diff)
Btrfs: Add per-root block accounting and sysfs entries
Signed-off-by: Chris Mason <chris.mason@oracle.com>
-rw-r--r--fs/btrfs/Makefile2
-rw-r--r--fs/btrfs/ctree.h54
-rw-r--r--fs/btrfs/disk-io.c31
-rw-r--r--fs/btrfs/disk-io.h3
-rw-r--r--fs/btrfs/extent-tree.c17
-rw-r--r--fs/btrfs/inode.c13
-rw-r--r--fs/btrfs/super.c14
-rw-r--r--fs/btrfs/sysfs.c236
-rw-r--r--fs/btrfs/transaction.c34
9 files changed, 393 insertions, 11 deletions
diff --git a/fs/btrfs/Makefile b/fs/btrfs/Makefile
index ea7a22870350..ee505c87ecf3 100644
--- a/fs/btrfs/Makefile
+++ b/fs/btrfs/Makefile
@@ -5,7 +5,7 @@ obj-m := btrfs.o
5btrfs-y := super.o ctree.o extent-tree.o print-tree.o root-tree.o dir-item.o \ 5btrfs-y := super.o ctree.o extent-tree.o print-tree.o root-tree.o dir-item.o \
6 hash.o file-item.o inode-item.o inode-map.o disk-io.o \ 6 hash.o file-item.o inode-item.o inode-map.o disk-io.o \
7 transaction.o bit-radix.o inode.o file.o tree-defrag.o \ 7 transaction.o bit-radix.o inode.o file.o tree-defrag.o \
8 extent_map.o 8 extent_map.o sysfs.o
9 9
10#btrfs-y := ctree.o disk-io.o radix-tree.o extent-tree.o print-tree.o \ 10#btrfs-y := ctree.o disk-io.o radix-tree.o extent-tree.o print-tree.o \
11# root-tree.o dir-item.o hash.o file-item.o inode-item.o \ 11# root-tree.o dir-item.o hash.o file-item.o inode-item.o \
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 947f061ed118..ffeee546a0d7 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -22,6 +22,7 @@
22#include <linux/fs.h> 22#include <linux/fs.h>
23#include <linux/buffer_head.h> 23#include <linux/buffer_head.h>
24#include <linux/workqueue.h> 24#include <linux/workqueue.h>
25#include <linux/completion.h>
25#include "bit-radix.h" 26#include "bit-radix.h"
26 27
27struct btrfs_trans_handle; 28struct btrfs_trans_handle;
@@ -313,6 +314,8 @@ struct btrfs_fs_info {
313 struct list_head trans_list; 314 struct list_head trans_list;
314 struct list_head dead_roots; 315 struct list_head dead_roots;
315 struct delayed_work trans_work; 316 struct delayed_work trans_work;
317 struct kobject super_kobj;
318 struct completion kobj_unregister;
316 int do_barriers; 319 int do_barriers;
317 int closing; 320 int closing;
318}; 321};
@@ -328,6 +331,8 @@ struct btrfs_root {
328 struct btrfs_key root_key; 331 struct btrfs_key root_key;
329 struct btrfs_fs_info *fs_info; 332 struct btrfs_fs_info *fs_info;
330 struct inode *inode; 333 struct inode *inode;
334 struct kobject root_kobj;
335 struct completion kobj_unregister;
331 u64 objectid; 336 u64 objectid;
332 u64 last_trans; 337 u64 last_trans;
333 u32 blocksize; 338 u32 blocksize;
@@ -338,6 +343,7 @@ struct btrfs_root {
338 struct btrfs_key defrag_progress; 343 struct btrfs_key defrag_progress;
339 int defrag_running; 344 int defrag_running;
340 int defrag_level; 345 int defrag_level;
346 char *name;
341}; 347};
342 348
343/* the lower bits in the key flags defines the item type */ 349/* the lower bits in the key flags defines the item type */
@@ -814,6 +820,28 @@ static inline void btrfs_set_root_flags(struct btrfs_root_item *item, u32 val)
814 item->flags = cpu_to_le32(val); 820 item->flags = cpu_to_le32(val);
815} 821}
816 822
823static inline void btrfs_set_root_blocks_used(struct btrfs_root_item *item,
824 u64 val)
825{
826 item->blocks_used = cpu_to_le64(val);
827}
828
829static inline u64 btrfs_root_blocks_used(struct btrfs_root_item *item)
830{
831 return le64_to_cpu(item->blocks_used);
832}
833
834static inline void btrfs_set_root_block_limit(struct btrfs_root_item *item,
835 u64 val)
836{
837 item->block_limit = cpu_to_le64(val);
838}
839
840static inline u64 btrfs_root_block_limit(struct btrfs_root_item *item)
841{
842 return le64_to_cpu(item->block_limit);
843}
844
817static inline u64 btrfs_super_blocknr(struct btrfs_super_block *s) 845static inline u64 btrfs_super_blocknr(struct btrfs_super_block *s)
818{ 846{
819 return le64_to_cpu(s->blocknr); 847 return le64_to_cpu(s->blocknr);
@@ -1014,6 +1042,23 @@ static inline void btrfs_memmove(struct btrfs_root *root,
1014 memmove(dst, src, nr); 1042 memmove(dst, src, nr);
1015} 1043}
1016 1044
1045static inline int btrfs_set_root_name(struct btrfs_root *root,
1046 const char *name, int len)
1047{
1048 /* if we already have a name just free it */
1049 if (root->name)
1050 kfree(root->name);
1051
1052 root->name = kmalloc(len+1, GFP_KERNEL);
1053 if (!root->name)
1054 return -ENOMEM;
1055
1056 memcpy(root->name, name, len);
1057 root->name[len] ='\0';
1058
1059 return 0;
1060}
1061
1017/* helper function to cast into the data area of the leaf. */ 1062/* helper function to cast into the data area of the leaf. */
1018#define btrfs_item_ptr(leaf, slot, type) \ 1063#define btrfs_item_ptr(leaf, slot, type) \
1019 ((type *)(btrfs_leaf_data(leaf) + \ 1064 ((type *)(btrfs_leaf_data(leaf) + \
@@ -1191,4 +1236,13 @@ int btrfs_drop_extents(struct btrfs_trans_handle *trans,
1191/* tree-defrag.c */ 1236/* tree-defrag.c */
1192int btrfs_defrag_leaves(struct btrfs_trans_handle *trans, 1237int btrfs_defrag_leaves(struct btrfs_trans_handle *trans,
1193 struct btrfs_root *root, int cache_only); 1238 struct btrfs_root *root, int cache_only);
1239
1240/* sysfs.c */
1241int btrfs_init_sysfs(void);
1242void btrfs_exit_sysfs(void);
1243int btrfs_sysfs_add_super(struct btrfs_fs_info *fs);
1244int btrfs_sysfs_add_root(struct btrfs_root *root);
1245void btrfs_sysfs_del_root(struct btrfs_root *root);
1246void btrfs_sysfs_del_super(struct btrfs_fs_info *root);
1247
1194#endif 1248#endif
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index b2f79878d51a..c25ef0a68f18 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -294,9 +294,12 @@ static int __setup_root(int blocksize,
294 root->last_trans = 0; 294 root->last_trans = 0;
295 root->highest_inode = 0; 295 root->highest_inode = 0;
296 root->last_inode_alloc = 0; 296 root->last_inode_alloc = 0;
297 root->name = NULL;
297 memset(&root->root_key, 0, sizeof(root->root_key)); 298 memset(&root->root_key, 0, sizeof(root->root_key));
298 memset(&root->root_item, 0, sizeof(root->root_item)); 299 memset(&root->root_item, 0, sizeof(root->root_item));
299 memset(&root->defrag_progress, 0, sizeof(root->defrag_progress)); 300 memset(&root->defrag_progress, 0, sizeof(root->defrag_progress));
301 memset(&root->root_kobj, 0, sizeof(root->root_kobj));
302 init_completion(&root->kobj_unregister);
300 root->defrag_running = 0; 303 root->defrag_running = 0;
301 root->defrag_level = 0; 304 root->defrag_level = 0;
302 root->root_key.objectid = objectid; 305 root->root_key.objectid = objectid;
@@ -384,7 +387,8 @@ insert:
384} 387}
385 388
386struct btrfs_root *btrfs_read_fs_root(struct btrfs_fs_info *fs_info, 389struct btrfs_root *btrfs_read_fs_root(struct btrfs_fs_info *fs_info,
387 struct btrfs_key *location) 390 struct btrfs_key *location,
391 const char *name, int namelen)
388{ 392{
389 struct btrfs_root *root; 393 struct btrfs_root *root;
390 int ret; 394 int ret;
@@ -405,6 +409,22 @@ struct btrfs_root *btrfs_read_fs_root(struct btrfs_fs_info *fs_info,
405 kfree(root); 409 kfree(root);
406 return ERR_PTR(ret); 410 return ERR_PTR(ret);
407 } 411 }
412
413 ret = btrfs_set_root_name(root, name, namelen);
414 if (ret) {
415 brelse(root->node);
416 kfree(root);
417 return ERR_PTR(ret);
418 }
419
420 ret = btrfs_sysfs_add_root(root);
421 if (ret) {
422 brelse(root->node);
423 kfree(root->name);
424 kfree(root);
425 return ERR_PTR(ret);
426 }
427
408 return root; 428 return root;
409} 429}
410 430
@@ -433,6 +453,8 @@ struct btrfs_root *open_ctree(struct super_block *sb)
433 INIT_RADIX_TREE(&fs_info->block_group_data_radix, GFP_KERNEL); 453 INIT_RADIX_TREE(&fs_info->block_group_data_radix, GFP_KERNEL);
434 INIT_LIST_HEAD(&fs_info->trans_list); 454 INIT_LIST_HEAD(&fs_info->trans_list);
435 INIT_LIST_HEAD(&fs_info->dead_roots); 455 INIT_LIST_HEAD(&fs_info->dead_roots);
456 memset(&fs_info->super_kobj, 0, sizeof(fs_info->super_kobj));
457 init_completion(&fs_info->kobj_unregister);
436 sb_set_blocksize(sb, 4096); 458 sb_set_blocksize(sb, 4096);
437 fs_info->running_transaction = NULL; 459 fs_info->running_transaction = NULL;
438 fs_info->last_trans_committed = 0; 460 fs_info->last_trans_committed = 0;
@@ -500,8 +522,10 @@ struct btrfs_root *open_ctree(struct super_block *sb)
500 522
501 fs_info->generation = btrfs_super_generation(disk_super) + 1; 523 fs_info->generation = btrfs_super_generation(disk_super) + 1;
502 ret = btrfs_find_dead_roots(tree_root); 524 ret = btrfs_find_dead_roots(tree_root);
503 if (ret) 525 if (ret) {
526 mutex_unlock(&fs_info->fs_mutex);
504 goto fail_tree_root; 527 goto fail_tree_root;
528 }
505 mutex_unlock(&fs_info->fs_mutex); 529 mutex_unlock(&fs_info->fs_mutex);
506 return tree_root; 530 return tree_root;
507 531
@@ -553,12 +577,15 @@ int btrfs_free_fs_root(struct btrfs_fs_info *fs_info, struct btrfs_root *root)
553{ 577{
554 radix_tree_delete(&fs_info->fs_roots_radix, 578 radix_tree_delete(&fs_info->fs_roots_radix,
555 (unsigned long)root->root_key.objectid); 579 (unsigned long)root->root_key.objectid);
580 btrfs_sysfs_del_root(root);
556 if (root->inode) 581 if (root->inode)
557 iput(root->inode); 582 iput(root->inode);
558 if (root->node) 583 if (root->node)
559 brelse(root->node); 584 brelse(root->node);
560 if (root->commit_root) 585 if (root->commit_root)
561 brelse(root->commit_root); 586 brelse(root->commit_root);
587 if (root->name)
588 kfree(root->name);
562 kfree(root); 589 kfree(root);
563 return 0; 590 return 0;
564} 591}
diff --git a/fs/btrfs/disk-io.h b/fs/btrfs/disk-io.h
index 5261733b8735..da6bb72750f2 100644
--- a/fs/btrfs/disk-io.h
+++ b/fs/btrfs/disk-io.h
@@ -66,7 +66,8 @@ struct buffer_head *btrfs_find_tree_block(struct btrfs_root *root, u64 blocknr);
66int btrfs_csum_data(struct btrfs_root * root, char *data, size_t len, 66int btrfs_csum_data(struct btrfs_root * root, char *data, size_t len,
67 char *result); 67 char *result);
68struct btrfs_root *btrfs_read_fs_root(struct btrfs_fs_info *fs_info, 68struct btrfs_root *btrfs_read_fs_root(struct btrfs_fs_info *fs_info,
69 struct btrfs_key *location); 69 struct btrfs_key *location,
70 const char *name, int namelen);
70struct btrfs_root *btrfs_read_fs_root_no_radix(struct btrfs_fs_info *fs_info, 71struct btrfs_root *btrfs_read_fs_root_no_radix(struct btrfs_fs_info *fs_info,
71 struct btrfs_key *location); 72 struct btrfs_key *location);
72u64 bh_blocknr(struct buffer_head *bh); 73u64 bh_blocknr(struct buffer_head *bh);
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index c31e84d42653..ff3f7c2be605 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -858,16 +858,23 @@ static int __free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
858 btrfs_set_extent_refs(ei, refs); 858 btrfs_set_extent_refs(ei, refs);
859 btrfs_mark_buffer_dirty(path->nodes[0]); 859 btrfs_mark_buffer_dirty(path->nodes[0]);
860 if (refs == 0) { 860 if (refs == 0) {
861 u64 super_blocks_used; 861 u64 super_blocks_used, root_blocks_used;
862 862
863 if (pin) { 863 if (pin) {
864 ret = pin_down_block(root, blocknr, 0); 864 ret = pin_down_block(root, blocknr, 0);
865 BUG_ON(ret); 865 BUG_ON(ret);
866 } 866 }
867 867
868 /* block accounting for super block */
868 super_blocks_used = btrfs_super_blocks_used(&info->super_copy); 869 super_blocks_used = btrfs_super_blocks_used(&info->super_copy);
869 btrfs_set_super_blocks_used(&info->super_copy, 870 btrfs_set_super_blocks_used(&info->super_copy,
870 super_blocks_used - num_blocks); 871 super_blocks_used - num_blocks);
872
873 /* block accounting for root item */
874 root_blocks_used = btrfs_root_blocks_used(&root->root_item);
875 btrfs_set_root_blocks_used(&root->root_item,
876 root_blocks_used - num_blocks);
877
871 ret = btrfs_del_item(trans, extent_root, path); 878 ret = btrfs_del_item(trans, extent_root, path);
872 if (ret) { 879 if (ret) {
873 return ret; 880 return ret;
@@ -1175,7 +1182,7 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans,
1175{ 1182{
1176 int ret; 1183 int ret;
1177 int pending_ret; 1184 int pending_ret;
1178 u64 super_blocks_used; 1185 u64 super_blocks_used, root_blocks_used;
1179 u64 search_start = 0; 1186 u64 search_start = 0;
1180 struct btrfs_fs_info *info = root->fs_info; 1187 struct btrfs_fs_info *info = root->fs_info;
1181 struct btrfs_root *extent_root = info->extent_root; 1188 struct btrfs_root *extent_root = info->extent_root;
@@ -1193,10 +1200,16 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans,
1193 if (ret) 1200 if (ret)
1194 return ret; 1201 return ret;
1195 1202
1203 /* block accounting for super block */
1196 super_blocks_used = btrfs_super_blocks_used(&info->super_copy); 1204 super_blocks_used = btrfs_super_blocks_used(&info->super_copy);
1197 btrfs_set_super_blocks_used(&info->super_copy, super_blocks_used + 1205 btrfs_set_super_blocks_used(&info->super_copy, super_blocks_used +
1198 num_blocks); 1206 num_blocks);
1199 1207
1208 /* block accounting for root item */
1209 root_blocks_used = btrfs_root_blocks_used(&root->root_item);
1210 btrfs_set_root_blocks_used(&root->root_item, root_blocks_used +
1211 num_blocks);
1212
1200 if (root == extent_root) { 1213 if (root == extent_root) {
1201 BUG_ON(num_blocks != 1); 1214 BUG_ON(num_blocks != 1);
1202 set_radix_bit(&root->fs_info->extent_ins_radix, ins->objectid); 1215 set_radix_bit(&root->fs_info->extent_ins_radix, ins->objectid);
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index dc181089aa74..2e3918e6049e 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -733,7 +733,8 @@ out:
733 */ 733 */
734static int fixup_tree_root_location(struct btrfs_root *root, 734static int fixup_tree_root_location(struct btrfs_root *root,
735 struct btrfs_key *location, 735 struct btrfs_key *location,
736 struct btrfs_root **sub_root) 736 struct btrfs_root **sub_root,
737 struct dentry *dentry)
737{ 738{
738 struct btrfs_path *path; 739 struct btrfs_path *path;
739 struct btrfs_root_item *ri; 740 struct btrfs_root_item *ri;
@@ -747,7 +748,9 @@ static int fixup_tree_root_location(struct btrfs_root *root,
747 BUG_ON(!path); 748 BUG_ON(!path);
748 mutex_lock(&root->fs_info->fs_mutex); 749 mutex_lock(&root->fs_info->fs_mutex);
749 750
750 *sub_root = btrfs_read_fs_root(root->fs_info, location); 751 *sub_root = btrfs_read_fs_root(root->fs_info, location,
752 dentry->d_name.name,
753 dentry->d_name.len);
751 if (IS_ERR(*sub_root)) 754 if (IS_ERR(*sub_root))
752 return PTR_ERR(*sub_root); 755 return PTR_ERR(*sub_root);
753 756
@@ -812,7 +815,8 @@ static struct dentry *btrfs_lookup(struct inode *dir, struct dentry *dentry,
812 return ERR_PTR(ret); 815 return ERR_PTR(ret);
813 inode = NULL; 816 inode = NULL;
814 if (location.objectid) { 817 if (location.objectid) {
815 ret = fixup_tree_root_location(root, &location, &sub_root); 818 ret = fixup_tree_root_location(root, &location, &sub_root,
819 dentry);
816 if (ret < 0) 820 if (ret < 0)
817 return ERR_PTR(ret); 821 return ERR_PTR(ret);
818 if (ret > 0) 822 if (ret > 0)
@@ -1829,6 +1833,7 @@ static int create_subvol(struct btrfs_root *root, char *name, int namelen)
1829 1833
1830 btrfs_set_root_blocknr(&root_item, bh_blocknr(subvol)); 1834 btrfs_set_root_blocknr(&root_item, bh_blocknr(subvol));
1831 btrfs_set_root_refs(&root_item, 1); 1835 btrfs_set_root_refs(&root_item, 1);
1836 btrfs_set_root_blocks_used(&root_item, 0);
1832 memset(&root_item.drop_progress, 0, sizeof(root_item.drop_progress)); 1837 memset(&root_item.drop_progress, 0, sizeof(root_item.drop_progress));
1833 root_item.drop_level = 0; 1838 root_item.drop_level = 0;
1834 brelse(subvol); 1839 brelse(subvol);
@@ -1865,7 +1870,7 @@ static int create_subvol(struct btrfs_root *root, char *name, int namelen)
1865 if (ret) 1870 if (ret)
1866 goto fail_commit; 1871 goto fail_commit;
1867 1872
1868 new_root = btrfs_read_fs_root(root->fs_info, &key); 1873 new_root = btrfs_read_fs_root(root->fs_info, &key, name, namelen);
1869 BUG_ON(!new_root); 1874 BUG_ON(!new_root);
1870 1875
1871 trans = btrfs_start_transaction(new_root, 1); 1876 trans = btrfs_start_transaction(new_root, 1);
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
index 7da95538745f..a68101ae1a3b 100644
--- a/fs/btrfs/super.c
+++ b/fs/btrfs/super.c
@@ -45,12 +45,14 @@ static struct super_operations btrfs_super_ops;
45static void btrfs_put_super (struct super_block * sb) 45static void btrfs_put_super (struct super_block * sb)
46{ 46{
47 struct btrfs_root *root = btrfs_sb(sb); 47 struct btrfs_root *root = btrfs_sb(sb);
48 struct btrfs_fs_info *fs = root->fs_info;
48 int ret; 49 int ret;
49 50
50 ret = close_ctree(root); 51 ret = close_ctree(root);
51 if (ret) { 52 if (ret) {
52 printk("close ctree returns %d\n", ret); 53 printk("close ctree returns %d\n", ret);
53 } 54 }
55 btrfs_sysfs_del_super(fs);
54 sb->s_fs_info = NULL; 56 sb->s_fs_info = NULL;
55} 57}
56 58
@@ -101,6 +103,12 @@ static int btrfs_fill_super(struct super_block * sb, void * data, int silent)
101 err = -ENOMEM; 103 err = -ENOMEM;
102 goto fail_close; 104 goto fail_close;
103 } 105 }
106
107 /* this does the super kobj at the same time */
108 err = btrfs_sysfs_add_super(tree_root->fs_info);
109 if (err)
110 goto fail_close;
111
104 sb->s_root = root_dentry; 112 sb->s_root = root_dentry;
105 btrfs_transaction_queue_work(tree_root, HZ * 30); 113 btrfs_transaction_queue_work(tree_root, HZ * 30);
106 return 0; 114 return 0;
@@ -182,6 +190,11 @@ static struct super_operations btrfs_super_ops = {
182static int __init init_btrfs_fs(void) 190static int __init init_btrfs_fs(void)
183{ 191{
184 int err; 192 int err;
193
194 err = btrfs_init_sysfs();
195 if (err)
196 return err;
197
185 btrfs_init_transaction_sys(); 198 btrfs_init_transaction_sys();
186 err = btrfs_init_cachep(); 199 err = btrfs_init_cachep();
187 if (err) 200 if (err)
@@ -196,6 +209,7 @@ static void __exit exit_btrfs_fs(void)
196 btrfs_destroy_cachep(); 209 btrfs_destroy_cachep();
197 extent_map_exit(); 210 extent_map_exit();
198 unregister_filesystem(&btrfs_fs_type); 211 unregister_filesystem(&btrfs_fs_type);
212 btrfs_exit_sysfs();
199} 213}
200 214
201module_init(init_btrfs_fs) 215module_init(init_btrfs_fs)
diff --git a/fs/btrfs/sysfs.c b/fs/btrfs/sysfs.c
index db8917e5b256..2058783373eb 100644
--- a/fs/btrfs/sysfs.c
+++ b/fs/btrfs/sysfs.c
@@ -16,6 +16,242 @@
16 * Boston, MA 021110-1307, USA. 16 * Boston, MA 021110-1307, USA.
17 */ 17 */
18 18
19#include <linux/sched.h>
20#include <linux/slab.h>
21#include <linux/spinlock.h>
22#include <linux/completion.h>
23#include <linux/buffer_head.h>
24#include <linux/module.h>
25#include <linux/kobject.h>
26
19#include "ctree.h" 27#include "ctree.h"
20#include "disk-io.h" 28#include "disk-io.h"
21#include "transaction.h" 29#include "transaction.h"
30
31static ssize_t root_blocks_used_show(struct btrfs_root *root, char *buf)
32{
33 return snprintf(buf, PAGE_SIZE, "%llu\n",
34 (unsigned long long)btrfs_root_blocks_used(&root->root_item));
35}
36
37static ssize_t root_block_limit_show(struct btrfs_root *root, char *buf)
38{
39 return snprintf(buf, PAGE_SIZE, "%llu\n",
40 (unsigned long long)btrfs_root_block_limit(&root->root_item));
41}
42
43static ssize_t super_blocks_used_show(struct btrfs_fs_info *fs, char *buf)
44{
45 return snprintf(buf, PAGE_SIZE, "%llu\n",
46 (unsigned long long)btrfs_super_blocks_used(fs->disk_super));
47}
48
49static ssize_t super_total_blocks_show(struct btrfs_fs_info *fs, char *buf)
50{
51 return snprintf(buf, PAGE_SIZE, "%llu\n",
52 (unsigned long long)btrfs_super_total_blocks(fs->disk_super));
53}
54
55static ssize_t super_blocksize_show(struct btrfs_fs_info *fs, char *buf)
56{
57 return snprintf(buf, PAGE_SIZE, "%llu\n",
58 (unsigned long long)btrfs_super_blocksize(fs->disk_super));
59}
60
61/* this is for root attrs (subvols/snapshots) */
62struct btrfs_root_attr {
63 struct attribute attr;
64 ssize_t (*show)(struct btrfs_root *, char *);
65 ssize_t (*store)(struct btrfs_root *, const char *, size_t);
66};
67
68#define ROOT_ATTR(name, mode, show, store) \
69static struct btrfs_root_attr btrfs_root_attr_##name = __ATTR(name, mode, show, store)
70
71ROOT_ATTR(blocks_used, 0444, root_blocks_used_show, NULL);
72ROOT_ATTR(block_limit, 0644, root_block_limit_show, NULL);
73
74static struct attribute *btrfs_root_attrs[] = {
75 &btrfs_root_attr_blocks_used.attr,
76 &btrfs_root_attr_block_limit.attr,
77 NULL,
78};
79
80/* this is for super attrs (actual full fs) */
81struct btrfs_super_attr {
82 struct attribute attr;
83 ssize_t (*show)(struct btrfs_fs_info *, char *);
84 ssize_t (*store)(struct btrfs_fs_info *, const char *, size_t);
85};
86
87#define SUPER_ATTR(name, mode, show, store) \
88static struct btrfs_super_attr btrfs_super_attr_##name = __ATTR(name, mode, show, store)
89
90SUPER_ATTR(blocks_used, 0444, super_blocks_used_show, NULL);
91SUPER_ATTR(total_blocks, 0444, super_total_blocks_show, NULL);
92SUPER_ATTR(blocksize, 0444, super_blocksize_show, NULL);
93
94static struct attribute *btrfs_super_attrs[] = {
95 &btrfs_super_attr_blocks_used.attr,
96 &btrfs_super_attr_total_blocks.attr,
97 &btrfs_super_attr_blocksize.attr,
98 NULL,
99};
100
101static ssize_t btrfs_super_attr_show(struct kobject *kobj,
102 struct attribute *attr, char *buf)
103{
104 struct btrfs_fs_info *fs = container_of(kobj, struct btrfs_fs_info,
105 super_kobj);
106 struct btrfs_super_attr *a = container_of(attr,
107 struct btrfs_super_attr,
108 attr);
109
110 return a->show ? a->show(fs, buf) : 0;
111}
112
113static ssize_t btrfs_super_attr_store(struct kobject *kobj,
114 struct attribute *attr,
115 const char *buf, size_t len)
116{
117 struct btrfs_fs_info *fs = container_of(kobj, struct btrfs_fs_info,
118 super_kobj);
119 struct btrfs_super_attr *a = container_of(attr,
120 struct btrfs_super_attr,
121 attr);
122
123 return a->store ? a->store(fs, buf, len) : 0;
124}
125
126static ssize_t btrfs_root_attr_show(struct kobject *kobj,
127 struct attribute *attr, char *buf)
128{
129 struct btrfs_root *root = container_of(kobj, struct btrfs_root,
130 root_kobj);
131 struct btrfs_root_attr *a = container_of(attr,
132 struct btrfs_root_attr,
133 attr);
134
135 return a->show ? a->show(root, buf) : 0;
136}
137
138static ssize_t btrfs_root_attr_store(struct kobject *kobj,
139 struct attribute *attr,
140 const char *buf, size_t len)
141{
142 struct btrfs_root *root = container_of(kobj, struct btrfs_root,
143 root_kobj);
144 struct btrfs_root_attr *a = container_of(attr,
145 struct btrfs_root_attr,
146 attr);
147 return a->store ? a->store(root, buf, len) : 0;
148}
149
150static void btrfs_super_release(struct kobject *kobj)
151{
152 struct btrfs_fs_info *fs = container_of(kobj, struct btrfs_fs_info,
153 super_kobj);
154 complete(&fs->kobj_unregister);
155}
156
157static void btrfs_root_release(struct kobject *kobj)
158{
159 struct btrfs_root *root = container_of(kobj, struct btrfs_root,
160 root_kobj);
161 complete(&root->kobj_unregister);
162}
163
164static struct sysfs_ops btrfs_super_attr_ops = {
165 .show = btrfs_super_attr_show,
166 .store = btrfs_super_attr_store,
167};
168
169static struct sysfs_ops btrfs_root_attr_ops = {
170 .show = btrfs_root_attr_show,
171 .store = btrfs_root_attr_store,
172};
173
174static struct kobj_type btrfs_root_ktype = {
175 .default_attrs = btrfs_root_attrs,
176 .sysfs_ops = &btrfs_root_attr_ops,
177 .release = btrfs_root_release,
178};
179
180static struct kobj_type btrfs_super_ktype = {
181 .default_attrs = btrfs_super_attrs,
182 .sysfs_ops = &btrfs_super_attr_ops,
183 .release = btrfs_super_release,
184};
185
186static struct kset btrfs_kset = {
187 .kobj = {.name = "btrfs"},
188};
189
190int btrfs_sysfs_add_super(struct btrfs_fs_info *fs)
191{
192 int error;
193
194 fs->super_kobj.kset = &btrfs_kset;
195 fs->super_kobj.ktype = &btrfs_super_ktype;
196
197 error = kobject_set_name(&fs->super_kobj, "%s",
198 fs->sb->s_id);
199 if (error)
200 goto fail;
201
202 error = kobject_register(&fs->super_kobj);
203 if (error)
204 goto fail;
205
206 return 0;
207
208fail:
209 printk(KERN_ERR "btrfs: sysfs creation for super failed\n");
210 return error;
211}
212
213int btrfs_sysfs_add_root(struct btrfs_root *root)
214{
215 int error;
216
217 root->root_kobj.ktype = &btrfs_root_ktype;
218 root->root_kobj.parent = &root->fs_info->super_kobj;
219
220 error = kobject_set_name(&root->root_kobj, "%s", root->name);
221 if (error) {
222 goto fail;
223 }
224
225 error = kobject_register(&root->root_kobj);
226 if (error)
227 goto fail;
228
229 return 0;
230
231fail:
232 printk(KERN_ERR "btrfs: sysfs creation for root failed\n");
233 return error;
234}
235
236void btrfs_sysfs_del_root(struct btrfs_root *root)
237{
238 kobject_unregister(&root->root_kobj);
239 wait_for_completion(&root->kobj_unregister);
240}
241
242void btrfs_sysfs_del_super(struct btrfs_fs_info *fs)
243{
244 kobject_unregister(&fs->super_kobj);
245 wait_for_completion(&fs->kobj_unregister);
246}
247
248int btrfs_init_sysfs()
249{
250 kobj_set_kset_s(&btrfs_kset, fs_subsys);
251 return kset_register(&btrfs_kset);
252}
253
254void btrfs_exit_sysfs()
255{
256 kset_unregister(&btrfs_kset);
257}
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index 18abea802794..2b15daa3a9f2 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -236,6 +236,7 @@ static int wait_for_commit(struct btrfs_root *root,
236struct dirty_root { 236struct dirty_root {
237 struct list_head list; 237 struct list_head list;
238 struct btrfs_root *root; 238 struct btrfs_root *root;
239 struct btrfs_root *latest_root;
239}; 240};
240 241
241int btrfs_add_dead_root(struct btrfs_root *root, struct list_head *dead_list) 242int btrfs_add_dead_root(struct btrfs_root *root, struct list_head *dead_list)
@@ -278,6 +279,15 @@ static int add_dirty_roots(struct btrfs_trans_handle *trans,
278 btrfs_root_blocknr(&root->root_item)); 279 btrfs_root_blocknr(&root->root_item));
279 brelse(root->commit_root); 280 brelse(root->commit_root);
280 root->commit_root = NULL; 281 root->commit_root = NULL;
282
283 /* make sure to update the root on disk
284 * so we get any updates to the block used
285 * counts
286 */
287 err = btrfs_update_root(trans,
288 root->fs_info->tree_root,
289 &root->root_key,
290 &root->root_item);
281 continue; 291 continue;
282 } 292 }
283 dirty = kmalloc(sizeof(*dirty), GFP_NOFS); 293 dirty = kmalloc(sizeof(*dirty), GFP_NOFS);
@@ -291,6 +301,7 @@ static int add_dirty_roots(struct btrfs_trans_handle *trans,
291 301
292 memcpy(dirty->root, root, sizeof(*root)); 302 memcpy(dirty->root, root, sizeof(*root));
293 dirty->root->node = root->commit_root; 303 dirty->root->node = root->commit_root;
304 dirty->latest_root = root;
294 root->commit_root = NULL; 305 root->commit_root = NULL;
295 306
296 root->root_key.offset = root->fs_info->generation; 307 root->root_key.offset = root->fs_info->generation;
@@ -384,20 +395,29 @@ static int drop_dirty_roots(struct btrfs_root *tree_root,
384{ 395{
385 struct dirty_root *dirty; 396 struct dirty_root *dirty;
386 struct btrfs_trans_handle *trans; 397 struct btrfs_trans_handle *trans;
398 u64 num_blocks;
399 u64 blocks_used;
387 int ret = 0; 400 int ret = 0;
388 int err; 401 int err;
389 402
390 while(!list_empty(list)) { 403 while(!list_empty(list)) {
404 struct btrfs_root *root;
405
391 mutex_lock(&tree_root->fs_info->fs_mutex); 406 mutex_lock(&tree_root->fs_info->fs_mutex);
392 dirty = list_entry(list->next, struct dirty_root, list); 407 dirty = list_entry(list->next, struct dirty_root, list);
393 list_del_init(&dirty->list); 408 list_del_init(&dirty->list);
394 409
410 num_blocks = btrfs_root_blocks_used(&dirty->root->root_item);
411 root = dirty->latest_root;
412
395 while(1) { 413 while(1) {
396 trans = btrfs_start_transaction(tree_root, 1); 414 trans = btrfs_start_transaction(tree_root, 1);
415
397 ret = btrfs_drop_snapshot(trans, dirty->root); 416 ret = btrfs_drop_snapshot(trans, dirty->root);
398 if (ret != -EAGAIN) { 417 if (ret != -EAGAIN) {
399 break; 418 break;
400 } 419 }
420
401 err = btrfs_update_root(trans, 421 err = btrfs_update_root(trans,
402 tree_root, 422 tree_root,
403 &dirty->root->root_key, 423 &dirty->root->root_key,
@@ -414,9 +434,19 @@ static int drop_dirty_roots(struct btrfs_root *tree_root,
414 mutex_lock(&tree_root->fs_info->fs_mutex); 434 mutex_lock(&tree_root->fs_info->fs_mutex);
415 } 435 }
416 BUG_ON(ret); 436 BUG_ON(ret);
437
438 num_blocks -= btrfs_root_blocks_used(&dirty->root->root_item);
439 blocks_used = btrfs_root_blocks_used(&root->root_item);
440 if (num_blocks) {
441 record_root_in_trans(root);
442 btrfs_set_root_blocks_used(&root->root_item,
443 blocks_used - num_blocks);
444 }
417 ret = btrfs_del_root(trans, tree_root, &dirty->root->root_key); 445 ret = btrfs_del_root(trans, tree_root, &dirty->root->root_key);
418 if (ret) 446 if (ret) {
447 BUG();
419 break; 448 break;
449 }
420 ret = btrfs_end_transaction(trans, tree_root); 450 ret = btrfs_end_transaction(trans, tree_root);
421 BUG_ON(ret); 451 BUG_ON(ret);
422 452
@@ -534,10 +564,12 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
534 wake_up(&cur_trans->commit_wait); 564 wake_up(&cur_trans->commit_wait);
535 put_transaction(cur_trans); 565 put_transaction(cur_trans);
536 put_transaction(cur_trans); 566 put_transaction(cur_trans);
567
537 if (root->fs_info->closing) 568 if (root->fs_info->closing)
538 list_splice_init(&root->fs_info->dead_roots, &dirty_fs_roots); 569 list_splice_init(&root->fs_info->dead_roots, &dirty_fs_roots);
539 else 570 else
540 list_splice_init(&dirty_fs_roots, &root->fs_info->dead_roots); 571 list_splice_init(&dirty_fs_roots, &root->fs_info->dead_roots);
572
541 mutex_unlock(&root->fs_info->trans_mutex); 573 mutex_unlock(&root->fs_info->trans_mutex);
542 kmem_cache_free(btrfs_trans_handle_cachep, trans); 574 kmem_cache_free(btrfs_trans_handle_cachep, trans);
543 575