xref: /openbmc/linux/fs/btrfs/super.c (revision 39279cc3)
12e635a27SChris Mason #include <linux/module.h>
2e20d96d6SChris Mason #include <linux/buffer_head.h>
32e635a27SChris Mason #include <linux/fs.h>
42e635a27SChris Mason #include <linux/pagemap.h>
52e635a27SChris Mason #include <linux/highmem.h>
62e635a27SChris Mason #include <linux/time.h>
72e635a27SChris Mason #include <linux/init.h>
82e635a27SChris Mason #include <linux/string.h>
92e635a27SChris Mason #include <linux/smp_lock.h>
102e635a27SChris Mason #include <linux/backing-dev.h>
11dee26a9fSChris Mason #include <linux/mpage.h>
1275dfe396SChris Mason #include <linux/swap.h>
1375dfe396SChris Mason #include <linux/writeback.h>
148fd17795SChris Mason #include <linux/statfs.h>
1508607c1bSChris Mason #include <linux/compat.h>
162e635a27SChris Mason #include "ctree.h"
17e20d96d6SChris Mason #include "disk-io.h"
18d5719762SChris Mason #include "transaction.h"
192c90e5d6SChris Mason #include "btrfs_inode.h"
20c5739bbaSChris Mason #include "ioctl.h"
213a686375SChris Mason #include "print-tree.h"
222e635a27SChris Mason 
232e635a27SChris Mason #define BTRFS_SUPER_MAGIC 0x9123682E
24e20d96d6SChris Mason 
25e20d96d6SChris Mason static struct super_operations btrfs_super_ops;
26e20d96d6SChris Mason 
27e20d96d6SChris Mason static void btrfs_put_super (struct super_block * sb)
28e20d96d6SChris Mason {
29e20d96d6SChris Mason 	struct btrfs_root *root = btrfs_sb(sb);
30e20d96d6SChris Mason 	int ret;
31e20d96d6SChris Mason 
32e20d96d6SChris Mason 	ret = close_ctree(root);
33e20d96d6SChris Mason 	if (ret) {
34e20d96d6SChris Mason 		printk("close ctree returns %d\n", ret);
35e20d96d6SChris Mason 	}
36e20d96d6SChris Mason 	sb->s_fs_info = NULL;
37e20d96d6SChris Mason }
382e635a27SChris Mason 
392e635a27SChris Mason static int btrfs_fill_super(struct super_block * sb, void * data, int silent)
402e635a27SChris Mason {
412e635a27SChris Mason 	struct inode * inode;
42e20d96d6SChris Mason 	struct dentry * root_dentry;
43e20d96d6SChris Mason 	struct btrfs_super_block *disk_super;
440f7d52f4SChris Mason 	struct btrfs_root *tree_root;
45d6e4a428SChris Mason 	struct btrfs_inode *bi;
46*39279cc3SChris Mason 	int err;
472e635a27SChris Mason 
482e635a27SChris Mason 	sb->s_maxbytes = MAX_LFS_FILESIZE;
492e635a27SChris Mason 	sb->s_magic = BTRFS_SUPER_MAGIC;
50e20d96d6SChris Mason 	sb->s_op = &btrfs_super_ops;
512e635a27SChris Mason 	sb->s_time_gran = 1;
52e20d96d6SChris Mason 
530f7d52f4SChris Mason 	tree_root = open_ctree(sb);
54d98237b3SChris Mason 
55*39279cc3SChris Mason 	if (!tree_root || IS_ERR(tree_root)) {
56e20d96d6SChris Mason 		printk("btrfs: open_ctree failed\n");
57e20d96d6SChris Mason 		return -EIO;
58e20d96d6SChris Mason 	}
590f7d52f4SChris Mason 	sb->s_fs_info = tree_root;
600f7d52f4SChris Mason 	disk_super = tree_root->fs_info->disk_super;
61c5739bbaSChris Mason 	inode = btrfs_iget_locked(sb, btrfs_super_root_dir(disk_super),
62c5739bbaSChris Mason 				  tree_root);
63d6e4a428SChris Mason 	bi = BTRFS_I(inode);
64d6e4a428SChris Mason 	bi->location.objectid = inode->i_ino;
65d6e4a428SChris Mason 	bi->location.offset = 0;
66d6e4a428SChris Mason 	bi->location.flags = 0;
670f7d52f4SChris Mason 	bi->root = tree_root;
68d6e4a428SChris Mason 	btrfs_set_key_type(&bi->location, BTRFS_INODE_ITEM_KEY);
69d6e4a428SChris Mason 
70*39279cc3SChris Mason 	if (!inode) {
71*39279cc3SChris Mason 		err = -ENOMEM;
72*39279cc3SChris Mason 		goto fail_close;
73*39279cc3SChris Mason 	}
74e20d96d6SChris Mason 	if (inode->i_state & I_NEW) {
75e20d96d6SChris Mason 		btrfs_read_locked_inode(inode);
76e20d96d6SChris Mason 		unlock_new_inode(inode);
77e20d96d6SChris Mason 	}
782e635a27SChris Mason 
79e20d96d6SChris Mason 	root_dentry = d_alloc_root(inode);
80e20d96d6SChris Mason 	if (!root_dentry) {
812e635a27SChris Mason 		iput(inode);
82*39279cc3SChris Mason 		err = -ENOMEM;
83*39279cc3SChris Mason 		goto fail_close;
842e635a27SChris Mason 	}
85e20d96d6SChris Mason 	sb->s_root = root_dentry;
8608607c1bSChris Mason 	btrfs_transaction_queue_work(tree_root, HZ * 30);
872e635a27SChris Mason 	return 0;
882e635a27SChris Mason 
89*39279cc3SChris Mason fail_close:
90*39279cc3SChris Mason 	close_ctree(tree_root);
91d5719762SChris Mason 	return err;
92d5719762SChris Mason }
93d5719762SChris Mason 
94d5719762SChris Mason static int btrfs_sync_fs(struct super_block *sb, int wait)
95d5719762SChris Mason {
96d5719762SChris Mason 	struct btrfs_trans_handle *trans;
97d5719762SChris Mason 	struct btrfs_root *root;
98d5719762SChris Mason 	int ret;
99d98237b3SChris Mason 	root = btrfs_sb(sb);
100df2ce34cSChris Mason 
101d5719762SChris Mason 	sb->s_dirt = 0;
102d561c025SChris Mason 	if (!wait) {
1037cfcc17eSChris Mason 		filemap_flush(root->fs_info->btree_inode->i_mapping);
104df2ce34cSChris Mason 		return 0;
105d561c025SChris Mason 	}
106d561c025SChris Mason 	mutex_lock(&root->fs_info->fs_mutex);
107d5719762SChris Mason 	trans = btrfs_start_transaction(root, 1);
108d5719762SChris Mason 	ret = btrfs_commit_transaction(trans, root);
109d5719762SChris Mason 	sb->s_dirt = 0;
110d5719762SChris Mason 	BUG_ON(ret);
111d561c025SChris Mason 	mutex_unlock(&root->fs_info->fs_mutex);
112d5719762SChris Mason 	return 0;
113d5719762SChris Mason }
114d5719762SChris Mason 
115d561c025SChris Mason static void btrfs_write_super(struct super_block *sb)
116d561c025SChris Mason {
11708607c1bSChris Mason 	sb->s_dirt = 0;
118d561c025SChris Mason }
119d561c025SChris Mason 
1202e635a27SChris Mason static int btrfs_get_sb(struct file_system_type *fs_type,
1212e635a27SChris Mason 	int flags, const char *dev_name, void *data, struct vfsmount *mnt)
1222e635a27SChris Mason {
1232e635a27SChris Mason 	return get_sb_bdev(fs_type, flags, dev_name, data,
1242e635a27SChris Mason 			   btrfs_fill_super, mnt);
1252e635a27SChris Mason }
1262e635a27SChris Mason 
1278fd17795SChris Mason static int btrfs_statfs(struct dentry *dentry, struct kstatfs *buf)
1288fd17795SChris Mason {
1298fd17795SChris Mason 	struct btrfs_root *root = btrfs_sb(dentry->d_sb);
1308fd17795SChris Mason 	struct btrfs_super_block *disk_super = root->fs_info->disk_super;
1318fd17795SChris Mason 
1328fd17795SChris Mason 	buf->f_namelen = BTRFS_NAME_LEN;
1338fd17795SChris Mason 	buf->f_blocks = btrfs_super_total_blocks(disk_super);
1348fd17795SChris Mason 	buf->f_bfree = buf->f_blocks - btrfs_super_blocks_used(disk_super);
1358fd17795SChris Mason 	buf->f_bavail = buf->f_bfree;
1368fd17795SChris Mason 	buf->f_bsize = dentry->d_sb->s_blocksize;
1378fd17795SChris Mason 	buf->f_type = BTRFS_SUPER_MAGIC;
1388fd17795SChris Mason 	return 0;
1398fd17795SChris Mason }
140b5133862SChris Mason 
1412e635a27SChris Mason static struct file_system_type btrfs_fs_type = {
1422e635a27SChris Mason 	.owner		= THIS_MODULE,
1432e635a27SChris Mason 	.name		= "btrfs",
1442e635a27SChris Mason 	.get_sb		= btrfs_get_sb,
1452e635a27SChris Mason 	.kill_sb	= kill_block_super,
1462e635a27SChris Mason 	.fs_flags	= FS_REQUIRES_DEV,
1472e635a27SChris Mason };
1482e635a27SChris Mason 
149e20d96d6SChris Mason static struct super_operations btrfs_super_ops = {
150134e9731SChris Mason 	.delete_inode	= btrfs_delete_inode,
151e20d96d6SChris Mason 	.put_super	= btrfs_put_super,
152e20d96d6SChris Mason 	.read_inode	= btrfs_read_locked_inode,
153d5719762SChris Mason 	.write_super	= btrfs_write_super,
154d5719762SChris Mason 	.sync_fs	= btrfs_sync_fs,
1554730a4bcSChris Mason 	.write_inode	= btrfs_write_inode,
156b5133862SChris Mason 	.dirty_inode	= btrfs_dirty_inode,
1572c90e5d6SChris Mason 	.alloc_inode	= btrfs_alloc_inode,
1582c90e5d6SChris Mason 	.destroy_inode	= btrfs_destroy_inode,
1598fd17795SChris Mason 	.statfs		= btrfs_statfs,
160e20d96d6SChris Mason };
161e20d96d6SChris Mason 
1622e635a27SChris Mason static int __init init_btrfs_fs(void)
1632e635a27SChris Mason {
1642c90e5d6SChris Mason 	int err;
16508607c1bSChris Mason 	btrfs_init_transaction_sys();
166*39279cc3SChris Mason 	err = btrfs_init_cachep();
1672c90e5d6SChris Mason 	if (err)
1682c90e5d6SChris Mason 		return err;
1692e635a27SChris Mason 	return register_filesystem(&btrfs_fs_type);
1702e635a27SChris Mason }
1712e635a27SChris Mason 
1722e635a27SChris Mason static void __exit exit_btrfs_fs(void)
1732e635a27SChris Mason {
17408607c1bSChris Mason 	btrfs_exit_transaction_sys();
175*39279cc3SChris Mason 	btrfs_destroy_cachep();
1762e635a27SChris Mason 	unregister_filesystem(&btrfs_fs_type);
1772e635a27SChris Mason }
1782e635a27SChris Mason 
1792e635a27SChris Mason module_init(init_btrfs_fs)
1802e635a27SChris Mason module_exit(exit_btrfs_fs)
1812e635a27SChris Mason 
1822e635a27SChris Mason MODULE_LICENSE("GPL");
183