xref: /linux/fs/btrfs/super.c (revision a74a4b97b61beede185b4b3ad359d7d378b0d312)
16cbd5570SChris Mason /*
26cbd5570SChris Mason  * Copyright (C) 2007 Oracle.  All rights reserved.
36cbd5570SChris Mason  *
46cbd5570SChris Mason  * This program is free software; you can redistribute it and/or
56cbd5570SChris Mason  * modify it under the terms of the GNU General Public
66cbd5570SChris Mason  * License v2 as published by the Free Software Foundation.
76cbd5570SChris Mason  *
86cbd5570SChris Mason  * This program is distributed in the hope that it will be useful,
96cbd5570SChris Mason  * but WITHOUT ANY WARRANTY; without even the implied warranty of
106cbd5570SChris Mason  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
116cbd5570SChris Mason  * General Public License for more details.
126cbd5570SChris Mason  *
136cbd5570SChris Mason  * You should have received a copy of the GNU General Public
146cbd5570SChris Mason  * License along with this program; if not, write to the
156cbd5570SChris Mason  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
166cbd5570SChris Mason  * Boston, MA 021110-1307, USA.
176cbd5570SChris Mason  */
186cbd5570SChris Mason 
194b82d6e4SYan #include <linux/blkdev.h>
202e635a27SChris Mason #include <linux/module.h>
21e20d96d6SChris Mason #include <linux/buffer_head.h>
222e635a27SChris Mason #include <linux/fs.h>
232e635a27SChris Mason #include <linux/pagemap.h>
242e635a27SChris Mason #include <linux/highmem.h>
252e635a27SChris Mason #include <linux/time.h>
262e635a27SChris Mason #include <linux/init.h>
272e635a27SChris Mason #include <linux/string.h>
282e635a27SChris Mason #include <linux/smp_lock.h>
292e635a27SChris Mason #include <linux/backing-dev.h>
304b82d6e4SYan #include <linux/mount.h>
31dee26a9fSChris Mason #include <linux/mpage.h>
3275dfe396SChris Mason #include <linux/swap.h>
3375dfe396SChris Mason #include <linux/writeback.h>
348fd17795SChris Mason #include <linux/statfs.h>
3508607c1bSChris Mason #include <linux/compat.h>
3695e05289SChris Mason #include <linux/parser.h>
37c59f8951SChris Mason #include <linux/ctype.h>
386da6abaeSChris Mason #include <linux/namei.h>
39a9218f6bSChris Mason #include <linux/miscdevice.h>
402e635a27SChris Mason #include "ctree.h"
41e20d96d6SChris Mason #include "disk-io.h"
42d5719762SChris Mason #include "transaction.h"
432c90e5d6SChris Mason #include "btrfs_inode.h"
44c5739bbaSChris Mason #include "ioctl.h"
453a686375SChris Mason #include "print-tree.h"
465103e947SJosef Bacik #include "xattr.h"
478a4b83ccSChris Mason #include "volumes.h"
482e635a27SChris Mason 
495f39d397SChris Mason #define BTRFS_SUPER_MAGIC 0x9123683E
50e20d96d6SChris Mason 
51e20d96d6SChris Mason static struct super_operations btrfs_super_ops;
52e20d96d6SChris Mason 
53e20d96d6SChris Mason static void btrfs_put_super (struct super_block * sb)
54e20d96d6SChris Mason {
55e20d96d6SChris Mason 	struct btrfs_root *root = btrfs_sb(sb);
5658176a96SJosef Bacik 	struct btrfs_fs_info *fs = root->fs_info;
57e20d96d6SChris Mason 	int ret;
58e20d96d6SChris Mason 
59e20d96d6SChris Mason 	ret = close_ctree(root);
60e20d96d6SChris Mason 	if (ret) {
61e20d96d6SChris Mason 		printk("close ctree returns %d\n", ret);
62e20d96d6SChris Mason 	}
6358176a96SJosef Bacik 	btrfs_sysfs_del_super(fs);
64e20d96d6SChris Mason 	sb->s_fs_info = NULL;
65e20d96d6SChris Mason }
662e635a27SChris Mason 
6795e05289SChris Mason enum {
6843e570b0SChristoph Hellwig 	Opt_degraded, Opt_subvol, Opt_device, Opt_nodatasum, Opt_nodatacow,
69dfe25020SChris Mason 	Opt_max_extent, Opt_max_inline, Opt_alloc_start, Opt_nobarrier,
704543df7eSChris Mason 	Opt_ssd, Opt_thread_pool, Opt_err,
7195e05289SChris Mason };
7295e05289SChris Mason 
7395e05289SChris Mason static match_table_t tokens = {
74dfe25020SChris Mason 	{Opt_degraded, "degraded"},
7595e05289SChris Mason 	{Opt_subvol, "subvol=%s"},
7643e570b0SChristoph Hellwig 	{Opt_device, "device=%s"},
77b6cda9bcSChris Mason 	{Opt_nodatasum, "nodatasum"},
78be20aa9dSChris Mason 	{Opt_nodatacow, "nodatacow"},
7921ad10cfSChris Mason 	{Opt_nobarrier, "nobarrier"},
80c59f8951SChris Mason 	{Opt_max_extent, "max_extent=%s"},
816f568d35SChris Mason 	{Opt_max_inline, "max_inline=%s"},
828f662a76SChris Mason 	{Opt_alloc_start, "alloc_start=%s"},
834543df7eSChris Mason 	{Opt_thread_pool, "thread_pool=%d"},
84e18e4809SChris Mason 	{Opt_ssd, "ssd"},
8595e05289SChris Mason 	{Opt_err, NULL}
8695e05289SChris Mason };
8795e05289SChris Mason 
88edbd8d4eSChris Mason u64 btrfs_parse_size(char *str)
89c59f8951SChris Mason {
90edbd8d4eSChris Mason 	u64 res;
91c59f8951SChris Mason 	int mult = 1;
92c59f8951SChris Mason 	char *end;
93c59f8951SChris Mason 	char last;
94c59f8951SChris Mason 
95c59f8951SChris Mason 	res = simple_strtoul(str, &end, 10);
96c59f8951SChris Mason 
97c59f8951SChris Mason 	last = end[0];
98c59f8951SChris Mason 	if (isalpha(last)) {
99c59f8951SChris Mason 		last = tolower(last);
100c59f8951SChris Mason 		switch (last) {
101c59f8951SChris Mason 		case 'g':
102c59f8951SChris Mason 			mult *= 1024;
103c59f8951SChris Mason 		case 'm':
104c59f8951SChris Mason 			mult *= 1024;
105c59f8951SChris Mason 		case 'k':
106c59f8951SChris Mason 			mult *= 1024;
107c59f8951SChris Mason 		}
108c59f8951SChris Mason 		res = res * mult;
109c59f8951SChris Mason 	}
110c59f8951SChris Mason 	return res;
111c59f8951SChris Mason }
112c59f8951SChris Mason 
113edf24abeSChristoph Hellwig /*
114edf24abeSChristoph Hellwig  * Regular mount options parser.  Everything that is needed only when
115edf24abeSChristoph Hellwig  * reading in a new superblock is parsed here.
116edf24abeSChristoph Hellwig  */
117edf24abeSChristoph Hellwig int btrfs_parse_options(struct btrfs_root *root, char *options)
11895e05289SChris Mason {
119edf24abeSChristoph Hellwig 	struct btrfs_fs_info *info = root->fs_info;
12095e05289SChris Mason 	substring_t args[MAX_OPT_ARGS];
121edf24abeSChristoph Hellwig 	char *p, *num;
1224543df7eSChris Mason 	int intarg;
123b6cda9bcSChris Mason 
12495e05289SChris Mason 	if (!options)
125edf24abeSChristoph Hellwig 		return 0;
12695e05289SChris Mason 
127be20aa9dSChris Mason 	/*
128be20aa9dSChris Mason 	 * strsep changes the string, duplicate it because parse_options
129be20aa9dSChris Mason 	 * gets called twice
130be20aa9dSChris Mason 	 */
131be20aa9dSChris Mason 	options = kstrdup(options, GFP_NOFS);
132be20aa9dSChris Mason 	if (!options)
133be20aa9dSChris Mason 		return -ENOMEM;
134be20aa9dSChris Mason 
135be20aa9dSChris Mason 
13695e05289SChris Mason 	while ((p = strsep(&options, ",")) != NULL) {
13795e05289SChris Mason 		int token;
13895e05289SChris Mason 		if (!*p)
13995e05289SChris Mason 			continue;
14095e05289SChris Mason 
14195e05289SChris Mason 		token = match_token(p, tokens, args);
14295e05289SChris Mason 		switch (token) {
143dfe25020SChris Mason 		case Opt_degraded:
144edf24abeSChristoph Hellwig 			printk(KERN_INFO "btrfs: allowing degraded mounts\n");
145dfe25020SChris Mason 			btrfs_set_opt(info->mount_opt, DEGRADED);
146dfe25020SChris Mason 			break;
14795e05289SChris Mason 		case Opt_subvol:
14843e570b0SChristoph Hellwig 		case Opt_device:
149edf24abeSChristoph Hellwig 			/*
15043e570b0SChristoph Hellwig 			 * These are parsed by btrfs_parse_early_options
151edf24abeSChristoph Hellwig 			 * and can be happily ignored here.
152edf24abeSChristoph Hellwig 			 */
15395e05289SChris Mason 			break;
154b6cda9bcSChris Mason 		case Opt_nodatasum:
155edf24abeSChristoph Hellwig 			printk(KERN_INFO "btrfs: setting nodatacsum\n");
156b6cda9bcSChris Mason 			btrfs_set_opt(info->mount_opt, NODATASUM);
157be20aa9dSChris Mason 			break;
158be20aa9dSChris Mason 		case Opt_nodatacow:
159edf24abeSChristoph Hellwig 			printk(KERN_INFO "btrfs: setting nodatacow\n");
160be20aa9dSChris Mason 			btrfs_set_opt(info->mount_opt, NODATACOW);
161be20aa9dSChris Mason 			btrfs_set_opt(info->mount_opt, NODATASUM);
162b6cda9bcSChris Mason 			break;
163e18e4809SChris Mason 		case Opt_ssd:
164edf24abeSChristoph Hellwig 			printk(KERN_INFO "btrfs: use ssd allocation scheme\n");
165e18e4809SChris Mason 			btrfs_set_opt(info->mount_opt, SSD);
166e18e4809SChris Mason 			break;
16721ad10cfSChris Mason 		case Opt_nobarrier:
168edf24abeSChristoph Hellwig 			printk(KERN_INFO "btrfs: turning off barriers\n");
16921ad10cfSChris Mason 			btrfs_set_opt(info->mount_opt, NOBARRIER);
17021ad10cfSChris Mason 			break;
1714543df7eSChris Mason 		case Opt_thread_pool:
1724543df7eSChris Mason 			intarg = 0;
1734543df7eSChris Mason 			match_int(&args[0], &intarg);
1744543df7eSChris Mason 			if (intarg) {
1754543df7eSChris Mason 				info->thread_pool_size = intarg;
1764543df7eSChris Mason 				printk(KERN_INFO "btrfs: thread pool %d\n",
1774543df7eSChris Mason 				       info->thread_pool_size);
1784543df7eSChris Mason 			}
1794543df7eSChris Mason 			break;
180c59f8951SChris Mason 		case Opt_max_extent:
181edf24abeSChristoph Hellwig 			num = match_strdup(&args[0]);
182c59f8951SChris Mason 			if (num) {
183edf24abeSChristoph Hellwig 				info->max_extent = btrfs_parse_size(num);
184c59f8951SChris Mason 				kfree(num);
185c59f8951SChris Mason 
186c59f8951SChris Mason 				info->max_extent = max_t(u64,
187edf24abeSChristoph Hellwig 					info->max_extent, root->sectorsize);
188edf24abeSChristoph Hellwig 				printk(KERN_INFO "btrfs: max_extent at %llu\n",
189c59f8951SChris Mason 				       info->max_extent);
190c59f8951SChris Mason 			}
191c59f8951SChris Mason 			break;
1926f568d35SChris Mason 		case Opt_max_inline:
193edf24abeSChristoph Hellwig 			num = match_strdup(&args[0]);
1946f568d35SChris Mason 			if (num) {
195edf24abeSChristoph Hellwig 				info->max_inline = btrfs_parse_size(num);
1966f568d35SChris Mason 				kfree(num);
1976f568d35SChris Mason 
19815ada040SChris Mason 				if (info->max_inline) {
1996f568d35SChris Mason 					info->max_inline = max_t(u64,
20015ada040SChris Mason 						info->max_inline,
20115ada040SChris Mason 						root->sectorsize);
20215ada040SChris Mason 				}
203edf24abeSChristoph Hellwig 				printk(KERN_INFO "btrfs: max_inline at %llu\n",
2046f568d35SChris Mason 					info->max_inline);
2056f568d35SChris Mason 			}
2066f568d35SChris Mason 			break;
2078f662a76SChris Mason 		case Opt_alloc_start:
208edf24abeSChristoph Hellwig 			num = match_strdup(&args[0]);
2098f662a76SChris Mason 			if (num) {
210edf24abeSChristoph Hellwig 				info->alloc_start = btrfs_parse_size(num);
2118f662a76SChris Mason 				kfree(num);
212edf24abeSChristoph Hellwig 				printk(KERN_INFO
213edf24abeSChristoph Hellwig 					"btrfs: allocations start at %llu\n",
214edf24abeSChristoph Hellwig 					info->alloc_start);
2158f662a76SChris Mason 			}
2168f662a76SChris Mason 			break;
21795e05289SChris Mason 		default:
218be20aa9dSChris Mason 			break;
21995e05289SChris Mason 		}
22095e05289SChris Mason 	}
221be20aa9dSChris Mason 	kfree(options);
222edf24abeSChristoph Hellwig 	return 0;
223edf24abeSChristoph Hellwig }
224edf24abeSChristoph Hellwig 
225edf24abeSChristoph Hellwig /*
226edf24abeSChristoph Hellwig  * Parse mount options that are required early in the mount process.
227edf24abeSChristoph Hellwig  *
228edf24abeSChristoph Hellwig  * All other options will be parsed on much later in the mount process and
229edf24abeSChristoph Hellwig  * only when we need to allocate a new super block.
230edf24abeSChristoph Hellwig  */
23143e570b0SChristoph Hellwig static int btrfs_parse_early_options(const char *options, int flags,
23243e570b0SChristoph Hellwig 		void *holder, char **subvol_name,
23343e570b0SChristoph Hellwig 		struct btrfs_fs_devices **fs_devices)
234edf24abeSChristoph Hellwig {
235edf24abeSChristoph Hellwig 	substring_t args[MAX_OPT_ARGS];
236edf24abeSChristoph Hellwig 	char *opts, *p;
237edf24abeSChristoph Hellwig 	int error = 0;
238edf24abeSChristoph Hellwig 
239edf24abeSChristoph Hellwig 	if (!options)
240edf24abeSChristoph Hellwig 		goto out;
241edf24abeSChristoph Hellwig 
242edf24abeSChristoph Hellwig 	/*
243edf24abeSChristoph Hellwig 	 * strsep changes the string, duplicate it because parse_options
244edf24abeSChristoph Hellwig 	 * gets called twice
245edf24abeSChristoph Hellwig 	 */
246edf24abeSChristoph Hellwig 	opts = kstrdup(options, GFP_KERNEL);
247edf24abeSChristoph Hellwig 	if (!opts)
248edf24abeSChristoph Hellwig 		return -ENOMEM;
249edf24abeSChristoph Hellwig 
250edf24abeSChristoph Hellwig 	while ((p = strsep(&opts, ",")) != NULL) {
251edf24abeSChristoph Hellwig 		int token;
252edf24abeSChristoph Hellwig 		if (!*p)
253edf24abeSChristoph Hellwig 			continue;
254edf24abeSChristoph Hellwig 
255edf24abeSChristoph Hellwig 		token = match_token(p, tokens, args);
256edf24abeSChristoph Hellwig 		switch (token) {
257edf24abeSChristoph Hellwig 		case Opt_subvol:
258edf24abeSChristoph Hellwig 			*subvol_name = match_strdup(&args[0]);
259edf24abeSChristoph Hellwig 			break;
26043e570b0SChristoph Hellwig 		case Opt_device:
26143e570b0SChristoph Hellwig 			error = btrfs_scan_one_device(match_strdup(&args[0]),
26243e570b0SChristoph Hellwig 					flags, holder, fs_devices);
26343e570b0SChristoph Hellwig 			if (error)
26443e570b0SChristoph Hellwig 				goto out_free_opts;
26543e570b0SChristoph Hellwig 			break;
266edf24abeSChristoph Hellwig 		default:
267edf24abeSChristoph Hellwig 			break;
268edf24abeSChristoph Hellwig 		}
269edf24abeSChristoph Hellwig 	}
270edf24abeSChristoph Hellwig 
27143e570b0SChristoph Hellwig  out_free_opts:
272edf24abeSChristoph Hellwig 	kfree(opts);
273edf24abeSChristoph Hellwig  out:
274edf24abeSChristoph Hellwig 	/*
275edf24abeSChristoph Hellwig 	 * If no subvolume name is specified we use the default one.  Allocate
276edf24abeSChristoph Hellwig 	 * a copy of the string "default" here so that code later in the
277edf24abeSChristoph Hellwig 	 * mount path doesn't care if it's the default volume or another one.
278edf24abeSChristoph Hellwig 	 */
279edf24abeSChristoph Hellwig 	if (!*subvol_name) {
280edf24abeSChristoph Hellwig 		*subvol_name = kstrdup("default", GFP_KERNEL);
281edf24abeSChristoph Hellwig 		if (!*subvol_name)
282edf24abeSChristoph Hellwig 			return -ENOMEM;
283edf24abeSChristoph Hellwig 	}
284edf24abeSChristoph Hellwig 	return error;
28595e05289SChris Mason }
28695e05289SChris Mason 
2878a4b83ccSChris Mason static int btrfs_fill_super(struct super_block * sb,
2888a4b83ccSChris Mason 			    struct btrfs_fs_devices *fs_devices,
2898a4b83ccSChris Mason 			    void * data, int silent)
2902e635a27SChris Mason {
2912e635a27SChris Mason 	struct inode * inode;
292e20d96d6SChris Mason 	struct dentry * root_dentry;
293e20d96d6SChris Mason 	struct btrfs_super_block *disk_super;
2940f7d52f4SChris Mason 	struct btrfs_root *tree_root;
295d6e4a428SChris Mason 	struct btrfs_inode *bi;
29639279cc3SChris Mason 	int err;
2972e635a27SChris Mason 
2982e635a27SChris Mason 	sb->s_maxbytes = MAX_LFS_FILESIZE;
2992e635a27SChris Mason 	sb->s_magic = BTRFS_SUPER_MAGIC;
300e20d96d6SChris Mason 	sb->s_op = &btrfs_super_ops;
3015103e947SJosef Bacik 	sb->s_xattr = btrfs_xattr_handlers;
3022e635a27SChris Mason 	sb->s_time_gran = 1;
303e20d96d6SChris Mason 
304dfe25020SChris Mason 	tree_root = open_ctree(sb, fs_devices, (char *)data);
305d98237b3SChris Mason 
306e58ca020SYan 	if (IS_ERR(tree_root)) {
307e20d96d6SChris Mason 		printk("btrfs: open_ctree failed\n");
308e58ca020SYan 		return PTR_ERR(tree_root);
309e20d96d6SChris Mason 	}
3100f7d52f4SChris Mason 	sb->s_fs_info = tree_root;
3115f39d397SChris Mason 	disk_super = &tree_root->fs_info->super_copy;
312c5739bbaSChris Mason 	inode = btrfs_iget_locked(sb, btrfs_super_root_dir(disk_super),
313c5739bbaSChris Mason 				  tree_root);
314d6e4a428SChris Mason 	bi = BTRFS_I(inode);
315d6e4a428SChris Mason 	bi->location.objectid = inode->i_ino;
316d6e4a428SChris Mason 	bi->location.offset = 0;
3170f7d52f4SChris Mason 	bi->root = tree_root;
318b888db2bSChris Mason 
319d6e4a428SChris Mason 	btrfs_set_key_type(&bi->location, BTRFS_INODE_ITEM_KEY);
320d6e4a428SChris Mason 
32139279cc3SChris Mason 	if (!inode) {
32239279cc3SChris Mason 		err = -ENOMEM;
32339279cc3SChris Mason 		goto fail_close;
32439279cc3SChris Mason 	}
325e20d96d6SChris Mason 	if (inode->i_state & I_NEW) {
326e20d96d6SChris Mason 		btrfs_read_locked_inode(inode);
327e20d96d6SChris Mason 		unlock_new_inode(inode);
328e20d96d6SChris Mason 	}
3292e635a27SChris Mason 
330e20d96d6SChris Mason 	root_dentry = d_alloc_root(inode);
331e20d96d6SChris Mason 	if (!root_dentry) {
3322e635a27SChris Mason 		iput(inode);
33339279cc3SChris Mason 		err = -ENOMEM;
33439279cc3SChris Mason 		goto fail_close;
3352e635a27SChris Mason 	}
33658176a96SJosef Bacik 
33758176a96SJosef Bacik 	/* this does the super kobj at the same time */
33858176a96SJosef Bacik 	err = btrfs_sysfs_add_super(tree_root->fs_info);
33958176a96SJosef Bacik 	if (err)
34058176a96SJosef Bacik 		goto fail_close;
34158176a96SJosef Bacik 
342e20d96d6SChris Mason 	sb->s_root = root_dentry;
3436885f308SChris Mason 
3446885f308SChris Mason #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25)
3456885f308SChris Mason 	save_mount_options(sb, data);
3466885f308SChris Mason #endif
3476885f308SChris Mason 
3482e635a27SChris Mason 	return 0;
3492e635a27SChris Mason 
35039279cc3SChris Mason fail_close:
35139279cc3SChris Mason 	close_ctree(tree_root);
352d5719762SChris Mason 	return err;
353d5719762SChris Mason }
354d5719762SChris Mason 
3556bf13c0cSSage Weil int btrfs_sync_fs(struct super_block *sb, int wait)
356d5719762SChris Mason {
357d5719762SChris Mason 	struct btrfs_trans_handle *trans;
358d5719762SChris Mason 	struct btrfs_root *root;
359d5719762SChris Mason 	int ret;
360d98237b3SChris Mason 	root = btrfs_sb(sb);
361df2ce34cSChris Mason 
362d5719762SChris Mason 	sb->s_dirt = 0;
363d561c025SChris Mason 	if (!wait) {
3647cfcc17eSChris Mason 		filemap_flush(root->fs_info->btree_inode->i_mapping);
365df2ce34cSChris Mason 		return 0;
366d561c025SChris Mason 	}
367e9d0b13bSChris Mason 	btrfs_clean_old_snapshots(root);
368e9d0b13bSChris Mason 	btrfs_defrag_dirty_roots(root->fs_info);
369d5719762SChris Mason 	trans = btrfs_start_transaction(root, 1);
370d5719762SChris Mason 	ret = btrfs_commit_transaction(trans, root);
371d5719762SChris Mason 	sb->s_dirt = 0;
37254aa1f4dSChris Mason 	return ret;
373d5719762SChris Mason }
374d5719762SChris Mason 
375d561c025SChris Mason static void btrfs_write_super(struct super_block *sb)
376d561c025SChris Mason {
37708607c1bSChris Mason 	sb->s_dirt = 0;
378d561c025SChris Mason }
379d561c025SChris Mason 
380a061fc8dSChris Mason static int btrfs_test_super(struct super_block *s, void *data)
3812e635a27SChris Mason {
382a061fc8dSChris Mason 	struct btrfs_fs_devices *test_fs_devices = data;
383a061fc8dSChris Mason 	struct btrfs_root *root = btrfs_sb(s);
3844b82d6e4SYan 
385a061fc8dSChris Mason 	return root->fs_info->fs_devices == test_fs_devices;
3864b82d6e4SYan }
3874b82d6e4SYan 
388edf24abeSChristoph Hellwig /*
389edf24abeSChristoph Hellwig  * Find a superblock for the given device / mount point.
390edf24abeSChristoph Hellwig  *
391edf24abeSChristoph Hellwig  * Note:  This is based on get_sb_bdev from fs/super.c with a few additions
392edf24abeSChristoph Hellwig  *	  for multiple device setup.  Make sure to keep it in sync.
393edf24abeSChristoph Hellwig  */
394edf24abeSChristoph Hellwig static int btrfs_get_sb(struct file_system_type *fs_type, int flags,
395edf24abeSChristoph Hellwig 		const char *dev_name, void *data, struct vfsmount *mnt)
3964b82d6e4SYan {
397edf24abeSChristoph Hellwig 	char *subvol_name = NULL;
3984b82d6e4SYan 	struct block_device *bdev = NULL;
3994b82d6e4SYan 	struct super_block *s;
4004b82d6e4SYan 	struct dentry *root;
4018a4b83ccSChris Mason 	struct btrfs_fs_devices *fs_devices = NULL;
4024b82d6e4SYan 	int error = 0;
4034b82d6e4SYan 
40443e570b0SChristoph Hellwig 	error = btrfs_parse_early_options(data, flags, fs_type,
40543e570b0SChristoph Hellwig 					  &subvol_name, &fs_devices);
406edf24abeSChristoph Hellwig 	if (error)
407edf24abeSChristoph Hellwig 		goto error;
408edf24abeSChristoph Hellwig 
4098a4b83ccSChris Mason 	error = btrfs_scan_one_device(dev_name, flags, fs_type, &fs_devices);
4108a4b83ccSChris Mason 	if (error)
411edf24abeSChristoph Hellwig 		goto error_free_subvol_name;
4124b82d6e4SYan 
4138a4b83ccSChris Mason 	error = btrfs_open_devices(fs_devices, flags, fs_type);
4148a4b83ccSChris Mason 	if (error)
415edf24abeSChristoph Hellwig 		goto error_free_subvol_name;
4168a4b83ccSChris Mason 
417dfe25020SChris Mason 	bdev = fs_devices->latest_bdev;
418a061fc8dSChris Mason 	s = sget(fs_type, btrfs_test_super, set_anon_super, fs_devices);
4194b82d6e4SYan 	if (IS_ERR(s))
4204b82d6e4SYan 		goto error_s;
4214b82d6e4SYan 
4224b82d6e4SYan 	if (s->s_root) {
4234b82d6e4SYan 		if ((flags ^ s->s_flags) & MS_RDONLY) {
4244b82d6e4SYan 			up_write(&s->s_umount);
4254b82d6e4SYan 			deactivate_super(s);
4264b82d6e4SYan 			error = -EBUSY;
4274b82d6e4SYan 			goto error_bdev;
4284b82d6e4SYan 		}
4294b82d6e4SYan 
4304b82d6e4SYan 	} else {
4314b82d6e4SYan 		char b[BDEVNAME_SIZE];
4324b82d6e4SYan 
4334b82d6e4SYan 		s->s_flags = flags;
4344b82d6e4SYan 		strlcpy(s->s_id, bdevname(bdev, b), sizeof(s->s_id));
4358a4b83ccSChris Mason 		error = btrfs_fill_super(s, fs_devices, data,
4368a4b83ccSChris Mason 					 flags & MS_SILENT ? 1 : 0);
4374b82d6e4SYan 		if (error) {
4384b82d6e4SYan 			up_write(&s->s_umount);
4394b82d6e4SYan 			deactivate_super(s);
4404b82d6e4SYan 			goto error;
4414b82d6e4SYan 		}
4424b82d6e4SYan 
443788f20ebSChris Mason 		btrfs_sb(s)->fs_info->bdev_holder = fs_type;
4444b82d6e4SYan 		s->s_flags |= MS_ACTIVE;
4454b82d6e4SYan 	}
4464b82d6e4SYan 
447edf24abeSChristoph Hellwig 	root = lookup_one_len(subvol_name, s->s_root, strlen(subvol_name));
4484b82d6e4SYan 	if (IS_ERR(root)) {
4494b82d6e4SYan 		up_write(&s->s_umount);
4504b82d6e4SYan 		deactivate_super(s);
4514b82d6e4SYan 		error = PTR_ERR(root);
4524b82d6e4SYan 		goto error;
4534b82d6e4SYan 	}
4544b82d6e4SYan 	if (!root->d_inode) {
4554b82d6e4SYan 		dput(root);
4564b82d6e4SYan 		up_write(&s->s_umount);
4574b82d6e4SYan 		deactivate_super(s);
4584b82d6e4SYan 		error = -ENXIO;
4594b82d6e4SYan 		goto error;
4604b82d6e4SYan 	}
4614b82d6e4SYan 
4624b82d6e4SYan 	mnt->mnt_sb = s;
4634b82d6e4SYan 	mnt->mnt_root = root;
464edf24abeSChristoph Hellwig 
465edf24abeSChristoph Hellwig 	kfree(subvol_name);
4664b82d6e4SYan 	return 0;
4674b82d6e4SYan 
4684b82d6e4SYan error_s:
4694b82d6e4SYan 	error = PTR_ERR(s);
4704b82d6e4SYan error_bdev:
4718a4b83ccSChris Mason 	btrfs_close_devices(fs_devices);
472edf24abeSChristoph Hellwig error_free_subvol_name:
473edf24abeSChristoph Hellwig 	kfree(subvol_name);
4744b82d6e4SYan error:
4754b82d6e4SYan 	return error;
4764b82d6e4SYan }
4772e635a27SChris Mason 
4788fd17795SChris Mason static int btrfs_statfs(struct dentry *dentry, struct kstatfs *buf)
4798fd17795SChris Mason {
4808fd17795SChris Mason 	struct btrfs_root *root = btrfs_sb(dentry->d_sb);
4814b52dff6SChris Mason 	struct btrfs_super_block *disk_super = &root->fs_info->super_copy;
482db94535dSChris Mason 	int bits = dentry->d_sb->s_blocksize_bits;
4838fd17795SChris Mason 
4848fd17795SChris Mason 	buf->f_namelen = BTRFS_NAME_LEN;
485db94535dSChris Mason 	buf->f_blocks = btrfs_super_total_bytes(disk_super) >> bits;
486db94535dSChris Mason 	buf->f_bfree = buf->f_blocks -
487db94535dSChris Mason 		(btrfs_super_bytes_used(disk_super) >> bits);
4888fd17795SChris Mason 	buf->f_bavail = buf->f_bfree;
4898fd17795SChris Mason 	buf->f_bsize = dentry->d_sb->s_blocksize;
4908fd17795SChris Mason 	buf->f_type = BTRFS_SUPER_MAGIC;
4918fd17795SChris Mason 	return 0;
4928fd17795SChris Mason }
493b5133862SChris Mason 
4942e635a27SChris Mason static struct file_system_type btrfs_fs_type = {
4952e635a27SChris Mason 	.owner		= THIS_MODULE,
4962e635a27SChris Mason 	.name		= "btrfs",
4972e635a27SChris Mason 	.get_sb		= btrfs_get_sb,
498a061fc8dSChris Mason 	.kill_sb	= kill_anon_super,
4992e635a27SChris Mason 	.fs_flags	= FS_REQUIRES_DEV,
5002e635a27SChris Mason };
501a9218f6bSChris Mason 
5028a4b83ccSChris Mason static long btrfs_control_ioctl(struct file *file, unsigned int cmd,
5038a4b83ccSChris Mason 				unsigned long arg)
5048a4b83ccSChris Mason {
5058a4b83ccSChris Mason 	struct btrfs_ioctl_vol_args *vol;
5068a4b83ccSChris Mason 	struct btrfs_fs_devices *fs_devices;
507f819d837SLinda Knippers 	int ret = 0;
5088a4b83ccSChris Mason 	int len;
5098a4b83ccSChris Mason 
5108a4b83ccSChris Mason 	vol = kmalloc(sizeof(*vol), GFP_KERNEL);
5118a4b83ccSChris Mason 	if (copy_from_user(vol, (void __user *)arg, sizeof(*vol))) {
5128a4b83ccSChris Mason 		ret = -EFAULT;
5138a4b83ccSChris Mason 		goto out;
5148a4b83ccSChris Mason 	}
5158a4b83ccSChris Mason 	len = strnlen(vol->name, BTRFS_PATH_NAME_MAX);
5168a4b83ccSChris Mason 	switch (cmd) {
5178a4b83ccSChris Mason 	case BTRFS_IOC_SCAN_DEV:
5188a4b83ccSChris Mason 		ret = btrfs_scan_one_device(vol->name, MS_RDONLY,
5198a4b83ccSChris Mason 					    &btrfs_fs_type, &fs_devices);
5208a4b83ccSChris Mason 		break;
5218a4b83ccSChris Mason 	}
5228a4b83ccSChris Mason out:
5238a4b83ccSChris Mason 	kfree(vol);
524f819d837SLinda Knippers 	return ret;
5258a4b83ccSChris Mason }
5268a4b83ccSChris Mason 
527ed0dab6bSYan static void btrfs_write_super_lockfs(struct super_block *sb)
528ed0dab6bSYan {
529ed0dab6bSYan 	struct btrfs_root *root = btrfs_sb(sb);
530*a74a4b97SChris Mason 	mutex_lock(&root->fs_info->transaction_kthread_mutex);
531*a74a4b97SChris Mason 	mutex_lock(&root->fs_info->cleaner_mutex);
532ed0dab6bSYan }
533ed0dab6bSYan 
534ed0dab6bSYan static void btrfs_unlockfs(struct super_block *sb)
535ed0dab6bSYan {
536ed0dab6bSYan 	struct btrfs_root *root = btrfs_sb(sb);
537*a74a4b97SChris Mason 	mutex_unlock(&root->fs_info->cleaner_mutex);
538*a74a4b97SChris Mason 	mutex_unlock(&root->fs_info->transaction_kthread_mutex);
539ed0dab6bSYan }
5402e635a27SChris Mason 
541e20d96d6SChris Mason static struct super_operations btrfs_super_ops = {
542134e9731SChris Mason 	.delete_inode	= btrfs_delete_inode,
543e20d96d6SChris Mason 	.put_super	= btrfs_put_super,
544d5719762SChris Mason 	.write_super	= btrfs_write_super,
545d5719762SChris Mason 	.sync_fs	= btrfs_sync_fs,
5466885f308SChris Mason #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25)
5476885f308SChris Mason 	.read_inode     = btrfs_read_locked_inode,
5486885f308SChris Mason #else
5496885f308SChris Mason 	.show_options	= generic_show_options,
5506885f308SChris Mason #endif
5514730a4bcSChris Mason 	.write_inode	= btrfs_write_inode,
552b5133862SChris Mason 	.dirty_inode	= btrfs_dirty_inode,
5532c90e5d6SChris Mason 	.alloc_inode	= btrfs_alloc_inode,
5542c90e5d6SChris Mason 	.destroy_inode	= btrfs_destroy_inode,
5558fd17795SChris Mason 	.statfs		= btrfs_statfs,
556ed0dab6bSYan 	.write_super_lockfs = btrfs_write_super_lockfs,
557ed0dab6bSYan 	.unlockfs	= btrfs_unlockfs,
558e20d96d6SChris Mason };
559a9218f6bSChris Mason 
560a9218f6bSChris Mason static const struct file_operations btrfs_ctl_fops = {
561a9218f6bSChris Mason 	.unlocked_ioctl	 = btrfs_control_ioctl,
562a9218f6bSChris Mason 	.compat_ioctl = btrfs_control_ioctl,
563a9218f6bSChris Mason 	.owner	 = THIS_MODULE,
564a9218f6bSChris Mason };
565a9218f6bSChris Mason 
566a9218f6bSChris Mason static struct miscdevice btrfs_misc = {
567a9218f6bSChris Mason 	.minor		= MISC_DYNAMIC_MINOR,
568a9218f6bSChris Mason 	.name		= "btrfs-control",
569a9218f6bSChris Mason 	.fops		= &btrfs_ctl_fops
570a9218f6bSChris Mason };
571a9218f6bSChris Mason 
572a9218f6bSChris Mason static int btrfs_interface_init(void)
573a9218f6bSChris Mason {
574a9218f6bSChris Mason 	return misc_register(&btrfs_misc);
575a9218f6bSChris Mason }
576a9218f6bSChris Mason 
577a9218f6bSChris Mason void btrfs_interface_exit(void)
578a9218f6bSChris Mason {
579a9218f6bSChris Mason 	if (misc_deregister(&btrfs_misc) < 0)
580a9218f6bSChris Mason 		printk("misc_deregister failed for control device");
581a9218f6bSChris Mason }
582a9218f6bSChris Mason 
5832e635a27SChris Mason static int __init init_btrfs_fs(void)
5842e635a27SChris Mason {
5852c90e5d6SChris Mason 	int err;
58658176a96SJosef Bacik 
58758176a96SJosef Bacik 	err = btrfs_init_sysfs();
58858176a96SJosef Bacik 	if (err)
58958176a96SJosef Bacik 		return err;
59058176a96SJosef Bacik 
59139279cc3SChris Mason 	err = btrfs_init_cachep();
5922c90e5d6SChris Mason 	if (err)
593*a74a4b97SChris Mason 		goto free_sysfs;
594d1310b2eSChris Mason 
595d1310b2eSChris Mason 	err = extent_io_init();
5962f4cbe64SWyatt Banks 	if (err)
5972f4cbe64SWyatt Banks 		goto free_cachep;
5982f4cbe64SWyatt Banks 
599d1310b2eSChris Mason 	err = extent_map_init();
600d1310b2eSChris Mason 	if (err)
601d1310b2eSChris Mason 		goto free_extent_io;
602d1310b2eSChris Mason 
603a9218f6bSChris Mason 	err = btrfs_interface_init();
6042f4cbe64SWyatt Banks 	if (err)
6052f4cbe64SWyatt Banks 		goto free_extent_map;
606a9218f6bSChris Mason 	err = register_filesystem(&btrfs_fs_type);
607a9218f6bSChris Mason 	if (err)
608a9218f6bSChris Mason 		goto unregister_ioctl;
6092f4cbe64SWyatt Banks 	return 0;
6102f4cbe64SWyatt Banks 
611a9218f6bSChris Mason unregister_ioctl:
612a9218f6bSChris Mason 	btrfs_interface_exit();
6132f4cbe64SWyatt Banks free_extent_map:
6142f4cbe64SWyatt Banks 	extent_map_exit();
615d1310b2eSChris Mason free_extent_io:
616d1310b2eSChris Mason 	extent_io_exit();
6172f4cbe64SWyatt Banks free_cachep:
6182f4cbe64SWyatt Banks 	btrfs_destroy_cachep();
619*a74a4b97SChris Mason free_sysfs:
6202f4cbe64SWyatt Banks 	btrfs_exit_sysfs();
6212c90e5d6SChris Mason 	return err;
6222e635a27SChris Mason }
6232e635a27SChris Mason 
6242e635a27SChris Mason static void __exit exit_btrfs_fs(void)
6252e635a27SChris Mason {
62639279cc3SChris Mason 	btrfs_destroy_cachep();
627a52d9a80SChris Mason 	extent_map_exit();
628d1310b2eSChris Mason 	extent_io_exit();
629a9218f6bSChris Mason 	btrfs_interface_exit();
6302e635a27SChris Mason 	unregister_filesystem(&btrfs_fs_type);
63158176a96SJosef Bacik 	btrfs_exit_sysfs();
6328a4b83ccSChris Mason 	btrfs_cleanup_fs_uuids();
6332e635a27SChris Mason }
6342e635a27SChris Mason 
6352e635a27SChris Mason module_init(init_btrfs_fs)
6362e635a27SChris Mason module_exit(exit_btrfs_fs)
6372e635a27SChris Mason 
6382e635a27SChris Mason MODULE_LICENSE("GPL");
639