xref: /linux/fs/btrfs/super.c (revision 24bbcf0442ee04660a5a030efdbb6d03f1c275cb)
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>
27a9572a15SEric Paris #include <linux/seq_file.h>
282e635a27SChris Mason #include <linux/string.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>
401bcbf313SQinghuang Feng #include <linux/magic.h>
414b4e25f2SChris Mason #include "compat.h"
422e635a27SChris Mason #include "ctree.h"
43e20d96d6SChris Mason #include "disk-io.h"
44d5719762SChris Mason #include "transaction.h"
452c90e5d6SChris Mason #include "btrfs_inode.h"
46c5739bbaSChris Mason #include "ioctl.h"
473a686375SChris Mason #include "print-tree.h"
485103e947SJosef Bacik #include "xattr.h"
498a4b83ccSChris Mason #include "volumes.h"
50b3c3da71SChris Mason #include "version.h"
51be6e8dc0SBalaji Rao #include "export.h"
52c8b97818SChris Mason #include "compression.h"
532e635a27SChris Mason 
54b87221deSAlexey Dobriyan static const struct super_operations btrfs_super_ops;
55e20d96d6SChris Mason 
56e20d96d6SChris Mason static void btrfs_put_super(struct super_block *sb)
57e20d96d6SChris Mason {
58e20d96d6SChris Mason 	struct btrfs_root *root = btrfs_sb(sb);
59e20d96d6SChris Mason 	int ret;
60e20d96d6SChris Mason 
61e20d96d6SChris Mason 	ret = close_ctree(root);
62e20d96d6SChris Mason 	sb->s_fs_info = NULL;
63e20d96d6SChris Mason }
642e635a27SChris Mason 
6595e05289SChris Mason enum {
6643e570b0SChristoph Hellwig 	Opt_degraded, Opt_subvol, Opt_device, Opt_nodatasum, Opt_nodatacow,
67dfe25020SChris Mason 	Opt_max_extent, Opt_max_inline, Opt_alloc_start, Opt_nobarrier,
68451d7585SChris Mason 	Opt_ssd, Opt_nossd, Opt_ssd_spread, Opt_thread_pool, Opt_noacl,
69e244a0aeSChristoph Hellwig 	Opt_compress, Opt_notreelog, Opt_ratio, Opt_flushoncommit,
70e244a0aeSChristoph Hellwig 	Opt_discard, 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"},
84c8b97818SChris Mason 	{Opt_compress, "compress"},
85e18e4809SChris Mason 	{Opt_ssd, "ssd"},
86451d7585SChris Mason 	{Opt_ssd_spread, "ssd_spread"},
873b30c22fSChris Mason 	{Opt_nossd, "nossd"},
8833268eafSJosef Bacik 	{Opt_noacl, "noacl"},
893a5e1404SSage Weil 	{Opt_notreelog, "notreelog"},
90dccae999SSage Weil 	{Opt_flushoncommit, "flushoncommit"},
9197e728d4SJosef Bacik 	{Opt_ratio, "metadata_ratio=%d"},
92e244a0aeSChristoph Hellwig 	{Opt_discard, "discard"},
9333268eafSJosef Bacik 	{Opt_err, NULL},
9495e05289SChris Mason };
9595e05289SChris Mason 
96edbd8d4eSChris Mason u64 btrfs_parse_size(char *str)
97c59f8951SChris Mason {
98edbd8d4eSChris Mason 	u64 res;
99c59f8951SChris Mason 	int mult = 1;
100c59f8951SChris Mason 	char *end;
101c59f8951SChris Mason 	char last;
102c59f8951SChris Mason 
103c59f8951SChris Mason 	res = simple_strtoul(str, &end, 10);
104c59f8951SChris Mason 
105c59f8951SChris Mason 	last = end[0];
106c59f8951SChris Mason 	if (isalpha(last)) {
107c59f8951SChris Mason 		last = tolower(last);
108c59f8951SChris Mason 		switch (last) {
109c59f8951SChris Mason 		case 'g':
110c59f8951SChris Mason 			mult *= 1024;
111c59f8951SChris Mason 		case 'm':
112c59f8951SChris Mason 			mult *= 1024;
113c59f8951SChris Mason 		case 'k':
114c59f8951SChris Mason 			mult *= 1024;
115c59f8951SChris Mason 		}
116c59f8951SChris Mason 		res = res * mult;
117c59f8951SChris Mason 	}
118c59f8951SChris Mason 	return res;
119c59f8951SChris Mason }
120c59f8951SChris Mason 
121edf24abeSChristoph Hellwig /*
122edf24abeSChristoph Hellwig  * Regular mount options parser.  Everything that is needed only when
123edf24abeSChristoph Hellwig  * reading in a new superblock is parsed here.
124edf24abeSChristoph Hellwig  */
125edf24abeSChristoph Hellwig int btrfs_parse_options(struct btrfs_root *root, char *options)
12695e05289SChris Mason {
127edf24abeSChristoph Hellwig 	struct btrfs_fs_info *info = root->fs_info;
12895e05289SChris Mason 	substring_t args[MAX_OPT_ARGS];
129edf24abeSChristoph Hellwig 	char *p, *num;
1304543df7eSChris Mason 	int intarg;
131b6cda9bcSChris Mason 
13295e05289SChris Mason 	if (!options)
133edf24abeSChristoph Hellwig 		return 0;
13495e05289SChris Mason 
135be20aa9dSChris Mason 	/*
136be20aa9dSChris Mason 	 * strsep changes the string, duplicate it because parse_options
137be20aa9dSChris Mason 	 * gets called twice
138be20aa9dSChris Mason 	 */
139be20aa9dSChris Mason 	options = kstrdup(options, GFP_NOFS);
140be20aa9dSChris Mason 	if (!options)
141be20aa9dSChris Mason 		return -ENOMEM;
142be20aa9dSChris Mason 
143be20aa9dSChris Mason 
14495e05289SChris Mason 	while ((p = strsep(&options, ",")) != NULL) {
14595e05289SChris Mason 		int token;
14695e05289SChris Mason 		if (!*p)
14795e05289SChris Mason 			continue;
14895e05289SChris Mason 
14995e05289SChris Mason 		token = match_token(p, tokens, args);
15095e05289SChris Mason 		switch (token) {
151dfe25020SChris Mason 		case Opt_degraded:
152edf24abeSChristoph Hellwig 			printk(KERN_INFO "btrfs: allowing degraded mounts\n");
153dfe25020SChris Mason 			btrfs_set_opt(info->mount_opt, DEGRADED);
154dfe25020SChris Mason 			break;
15595e05289SChris Mason 		case Opt_subvol:
15643e570b0SChristoph Hellwig 		case Opt_device:
157edf24abeSChristoph Hellwig 			/*
15843e570b0SChristoph Hellwig 			 * These are parsed by btrfs_parse_early_options
159edf24abeSChristoph Hellwig 			 * and can be happily ignored here.
160edf24abeSChristoph Hellwig 			 */
16195e05289SChris Mason 			break;
162b6cda9bcSChris Mason 		case Opt_nodatasum:
163067c28adSChris Mason 			printk(KERN_INFO "btrfs: setting nodatasum\n");
164b6cda9bcSChris Mason 			btrfs_set_opt(info->mount_opt, NODATASUM);
165be20aa9dSChris Mason 			break;
166be20aa9dSChris Mason 		case Opt_nodatacow:
167edf24abeSChristoph Hellwig 			printk(KERN_INFO "btrfs: setting nodatacow\n");
168be20aa9dSChris Mason 			btrfs_set_opt(info->mount_opt, NODATACOW);
169be20aa9dSChris Mason 			btrfs_set_opt(info->mount_opt, NODATASUM);
170b6cda9bcSChris Mason 			break;
171c8b97818SChris Mason 		case Opt_compress:
172c8b97818SChris Mason 			printk(KERN_INFO "btrfs: use compression\n");
173c8b97818SChris Mason 			btrfs_set_opt(info->mount_opt, COMPRESS);
174c8b97818SChris Mason 			break;
175e18e4809SChris Mason 		case Opt_ssd:
176edf24abeSChristoph Hellwig 			printk(KERN_INFO "btrfs: use ssd allocation scheme\n");
177e18e4809SChris Mason 			btrfs_set_opt(info->mount_opt, SSD);
178e18e4809SChris Mason 			break;
179451d7585SChris Mason 		case Opt_ssd_spread:
180451d7585SChris Mason 			printk(KERN_INFO "btrfs: use spread ssd "
181451d7585SChris Mason 			       "allocation scheme\n");
182451d7585SChris Mason 			btrfs_set_opt(info->mount_opt, SSD);
183451d7585SChris Mason 			btrfs_set_opt(info->mount_opt, SSD_SPREAD);
184451d7585SChris Mason 			break;
1853b30c22fSChris Mason 		case Opt_nossd:
186451d7585SChris Mason 			printk(KERN_INFO "btrfs: not using ssd allocation "
187451d7585SChris Mason 			       "scheme\n");
188c289811cSChris Mason 			btrfs_set_opt(info->mount_opt, NOSSD);
1893b30c22fSChris Mason 			btrfs_clear_opt(info->mount_opt, SSD);
190451d7585SChris Mason 			btrfs_clear_opt(info->mount_opt, SSD_SPREAD);
1913b30c22fSChris Mason 			break;
19221ad10cfSChris Mason 		case Opt_nobarrier:
193edf24abeSChristoph Hellwig 			printk(KERN_INFO "btrfs: turning off barriers\n");
19421ad10cfSChris Mason 			btrfs_set_opt(info->mount_opt, NOBARRIER);
19521ad10cfSChris Mason 			break;
1964543df7eSChris Mason 		case Opt_thread_pool:
1974543df7eSChris Mason 			intarg = 0;
1984543df7eSChris Mason 			match_int(&args[0], &intarg);
1994543df7eSChris Mason 			if (intarg) {
2004543df7eSChris Mason 				info->thread_pool_size = intarg;
2014543df7eSChris Mason 				printk(KERN_INFO "btrfs: thread pool %d\n",
2024543df7eSChris Mason 				       info->thread_pool_size);
2034543df7eSChris Mason 			}
2044543df7eSChris Mason 			break;
205c59f8951SChris Mason 		case Opt_max_extent:
206edf24abeSChristoph Hellwig 			num = match_strdup(&args[0]);
207c59f8951SChris Mason 			if (num) {
208edf24abeSChristoph Hellwig 				info->max_extent = btrfs_parse_size(num);
209c59f8951SChris Mason 				kfree(num);
210c59f8951SChris Mason 
211c59f8951SChris Mason 				info->max_extent = max_t(u64,
212edf24abeSChristoph Hellwig 					info->max_extent, root->sectorsize);
213edf24abeSChristoph Hellwig 				printk(KERN_INFO "btrfs: max_extent at %llu\n",
21421380931SJoel Becker 				       (unsigned long long)info->max_extent);
215c59f8951SChris Mason 			}
216c59f8951SChris Mason 			break;
2176f568d35SChris Mason 		case Opt_max_inline:
218edf24abeSChristoph Hellwig 			num = match_strdup(&args[0]);
2196f568d35SChris Mason 			if (num) {
220edf24abeSChristoph Hellwig 				info->max_inline = btrfs_parse_size(num);
2216f568d35SChris Mason 				kfree(num);
2226f568d35SChris Mason 
22315ada040SChris Mason 				if (info->max_inline) {
2246f568d35SChris Mason 					info->max_inline = max_t(u64,
22515ada040SChris Mason 						info->max_inline,
22615ada040SChris Mason 						root->sectorsize);
22715ada040SChris Mason 				}
228edf24abeSChristoph Hellwig 				printk(KERN_INFO "btrfs: max_inline at %llu\n",
22921380931SJoel Becker 					(unsigned long long)info->max_inline);
2306f568d35SChris Mason 			}
2316f568d35SChris Mason 			break;
2328f662a76SChris Mason 		case Opt_alloc_start:
233edf24abeSChristoph Hellwig 			num = match_strdup(&args[0]);
2348f662a76SChris Mason 			if (num) {
235edf24abeSChristoph Hellwig 				info->alloc_start = btrfs_parse_size(num);
2368f662a76SChris Mason 				kfree(num);
237edf24abeSChristoph Hellwig 				printk(KERN_INFO
238edf24abeSChristoph Hellwig 					"btrfs: allocations start at %llu\n",
23921380931SJoel Becker 					(unsigned long long)info->alloc_start);
2408f662a76SChris Mason 			}
2418f662a76SChris Mason 			break;
24233268eafSJosef Bacik 		case Opt_noacl:
24333268eafSJosef Bacik 			root->fs_info->sb->s_flags &= ~MS_POSIXACL;
24433268eafSJosef Bacik 			break;
2453a5e1404SSage Weil 		case Opt_notreelog:
2463a5e1404SSage Weil 			printk(KERN_INFO "btrfs: disabling tree log\n");
2473a5e1404SSage Weil 			btrfs_set_opt(info->mount_opt, NOTREELOG);
2483a5e1404SSage Weil 			break;
249dccae999SSage Weil 		case Opt_flushoncommit:
250dccae999SSage Weil 			printk(KERN_INFO "btrfs: turning on flush-on-commit\n");
251dccae999SSage Weil 			btrfs_set_opt(info->mount_opt, FLUSHONCOMMIT);
252dccae999SSage Weil 			break;
25397e728d4SJosef Bacik 		case Opt_ratio:
25497e728d4SJosef Bacik 			intarg = 0;
25597e728d4SJosef Bacik 			match_int(&args[0], &intarg);
25697e728d4SJosef Bacik 			if (intarg) {
25797e728d4SJosef Bacik 				info->metadata_ratio = intarg;
25897e728d4SJosef Bacik 				printk(KERN_INFO "btrfs: metadata ratio %d\n",
25997e728d4SJosef Bacik 				       info->metadata_ratio);
26097e728d4SJosef Bacik 			}
26197e728d4SJosef Bacik 			break;
262e244a0aeSChristoph Hellwig 		case Opt_discard:
263e244a0aeSChristoph Hellwig 			btrfs_set_opt(info->mount_opt, DISCARD);
264e244a0aeSChristoph Hellwig 			break;
26595e05289SChris Mason 		default:
266be20aa9dSChris Mason 			break;
26795e05289SChris Mason 		}
26895e05289SChris Mason 	}
269be20aa9dSChris Mason 	kfree(options);
270edf24abeSChristoph Hellwig 	return 0;
271edf24abeSChristoph Hellwig }
272edf24abeSChristoph Hellwig 
273edf24abeSChristoph Hellwig /*
274edf24abeSChristoph Hellwig  * Parse mount options that are required early in the mount process.
275edf24abeSChristoph Hellwig  *
276edf24abeSChristoph Hellwig  * All other options will be parsed on much later in the mount process and
277edf24abeSChristoph Hellwig  * only when we need to allocate a new super block.
278edf24abeSChristoph Hellwig  */
27997288f2cSChristoph Hellwig static int btrfs_parse_early_options(const char *options, fmode_t flags,
28043e570b0SChristoph Hellwig 		void *holder, char **subvol_name,
28143e570b0SChristoph Hellwig 		struct btrfs_fs_devices **fs_devices)
282edf24abeSChristoph Hellwig {
283edf24abeSChristoph Hellwig 	substring_t args[MAX_OPT_ARGS];
284edf24abeSChristoph Hellwig 	char *opts, *p;
285edf24abeSChristoph Hellwig 	int error = 0;
286edf24abeSChristoph Hellwig 
287edf24abeSChristoph Hellwig 	if (!options)
288edf24abeSChristoph Hellwig 		goto out;
289edf24abeSChristoph Hellwig 
290edf24abeSChristoph Hellwig 	/*
291edf24abeSChristoph Hellwig 	 * strsep changes the string, duplicate it because parse_options
292edf24abeSChristoph Hellwig 	 * gets called twice
293edf24abeSChristoph Hellwig 	 */
294edf24abeSChristoph Hellwig 	opts = kstrdup(options, GFP_KERNEL);
295edf24abeSChristoph Hellwig 	if (!opts)
296edf24abeSChristoph Hellwig 		return -ENOMEM;
297edf24abeSChristoph Hellwig 
298edf24abeSChristoph Hellwig 	while ((p = strsep(&opts, ",")) != NULL) {
299edf24abeSChristoph Hellwig 		int token;
300edf24abeSChristoph Hellwig 		if (!*p)
301edf24abeSChristoph Hellwig 			continue;
302edf24abeSChristoph Hellwig 
303edf24abeSChristoph Hellwig 		token = match_token(p, tokens, args);
304edf24abeSChristoph Hellwig 		switch (token) {
305edf24abeSChristoph Hellwig 		case Opt_subvol:
306edf24abeSChristoph Hellwig 			*subvol_name = match_strdup(&args[0]);
307edf24abeSChristoph Hellwig 			break;
30843e570b0SChristoph Hellwig 		case Opt_device:
30943e570b0SChristoph Hellwig 			error = btrfs_scan_one_device(match_strdup(&args[0]),
31043e570b0SChristoph Hellwig 					flags, holder, fs_devices);
31143e570b0SChristoph Hellwig 			if (error)
31243e570b0SChristoph Hellwig 				goto out_free_opts;
31343e570b0SChristoph Hellwig 			break;
314edf24abeSChristoph Hellwig 		default:
315edf24abeSChristoph Hellwig 			break;
316edf24abeSChristoph Hellwig 		}
317edf24abeSChristoph Hellwig 	}
318edf24abeSChristoph Hellwig 
31943e570b0SChristoph Hellwig  out_free_opts:
320edf24abeSChristoph Hellwig 	kfree(opts);
321edf24abeSChristoph Hellwig  out:
322edf24abeSChristoph Hellwig 	/*
323edf24abeSChristoph Hellwig 	 * If no subvolume name is specified we use the default one.  Allocate
3243de4586cSChris Mason 	 * a copy of the string "." here so that code later in the
325edf24abeSChristoph Hellwig 	 * mount path doesn't care if it's the default volume or another one.
326edf24abeSChristoph Hellwig 	 */
327edf24abeSChristoph Hellwig 	if (!*subvol_name) {
3283de4586cSChris Mason 		*subvol_name = kstrdup(".", GFP_KERNEL);
329edf24abeSChristoph Hellwig 		if (!*subvol_name)
330edf24abeSChristoph Hellwig 			return -ENOMEM;
331edf24abeSChristoph Hellwig 	}
332edf24abeSChristoph Hellwig 	return error;
33395e05289SChris Mason }
33495e05289SChris Mason 
3358a4b83ccSChris Mason static int btrfs_fill_super(struct super_block *sb,
3368a4b83ccSChris Mason 			    struct btrfs_fs_devices *fs_devices,
3378a4b83ccSChris Mason 			    void *data, int silent)
3382e635a27SChris Mason {
3392e635a27SChris Mason 	struct inode *inode;
340e20d96d6SChris Mason 	struct dentry *root_dentry;
341e20d96d6SChris Mason 	struct btrfs_super_block *disk_super;
3420f7d52f4SChris Mason 	struct btrfs_root *tree_root;
3435d4f98a2SYan Zheng 	struct btrfs_key key;
34439279cc3SChris Mason 	int err;
3452e635a27SChris Mason 
3462e635a27SChris Mason 	sb->s_maxbytes = MAX_LFS_FILESIZE;
3472e635a27SChris Mason 	sb->s_magic = BTRFS_SUPER_MAGIC;
348e20d96d6SChris Mason 	sb->s_op = &btrfs_super_ops;
349be6e8dc0SBalaji Rao 	sb->s_export_op = &btrfs_export_ops;
3505103e947SJosef Bacik 	sb->s_xattr = btrfs_xattr_handlers;
3512e635a27SChris Mason 	sb->s_time_gran = 1;
3520eda294dSChris Mason #ifdef CONFIG_BTRFS_FS_POSIX_ACL
35333268eafSJosef Bacik 	sb->s_flags |= MS_POSIXACL;
35449cf6f45SChris Ball #endif
355e20d96d6SChris Mason 
356dfe25020SChris Mason 	tree_root = open_ctree(sb, fs_devices, (char *)data);
357d98237b3SChris Mason 
358e58ca020SYan 	if (IS_ERR(tree_root)) {
359e20d96d6SChris Mason 		printk("btrfs: open_ctree failed\n");
360e58ca020SYan 		return PTR_ERR(tree_root);
361e20d96d6SChris Mason 	}
3620f7d52f4SChris Mason 	sb->s_fs_info = tree_root;
3635f39d397SChris Mason 	disk_super = &tree_root->fs_info->super_copy;
364b888db2bSChris Mason 
3655d4f98a2SYan Zheng 	key.objectid = BTRFS_FIRST_FREE_OBJECTID;
3665d4f98a2SYan Zheng 	key.type = BTRFS_INODE_ITEM_KEY;
3675d4f98a2SYan Zheng 	key.offset = 0;
3685d4f98a2SYan Zheng 	inode = btrfs_iget(sb, &key, tree_root->fs_info->fs_root);
3695d4f98a2SYan Zheng 	if (IS_ERR(inode)) {
3705d4f98a2SYan Zheng 		err = PTR_ERR(inode);
37139279cc3SChris Mason 		goto fail_close;
37239279cc3SChris Mason 	}
3732e635a27SChris Mason 
374e20d96d6SChris Mason 	root_dentry = d_alloc_root(inode);
375e20d96d6SChris Mason 	if (!root_dentry) {
3762e635a27SChris Mason 		iput(inode);
37739279cc3SChris Mason 		err = -ENOMEM;
37839279cc3SChris Mason 		goto fail_close;
3792e635a27SChris Mason 	}
380e4404d6eSYan Zheng #if 0
38158176a96SJosef Bacik 	/* this does the super kobj at the same time */
38258176a96SJosef Bacik 	err = btrfs_sysfs_add_super(tree_root->fs_info);
38358176a96SJosef Bacik 	if (err)
38458176a96SJosef Bacik 		goto fail_close;
385e4404d6eSYan Zheng #endif
38658176a96SJosef Bacik 
387e20d96d6SChris Mason 	sb->s_root = root_dentry;
3886885f308SChris Mason 
3896885f308SChris Mason 	save_mount_options(sb, data);
3902e635a27SChris Mason 	return 0;
3912e635a27SChris Mason 
39239279cc3SChris Mason fail_close:
39339279cc3SChris Mason 	close_ctree(tree_root);
394d5719762SChris Mason 	return err;
395d5719762SChris Mason }
396d5719762SChris Mason 
3976bf13c0cSSage Weil int btrfs_sync_fs(struct super_block *sb, int wait)
398d5719762SChris Mason {
399d5719762SChris Mason 	struct btrfs_trans_handle *trans;
400dccae999SSage Weil 	struct btrfs_root *root = btrfs_sb(sb);
401d5719762SChris Mason 	int ret;
402df2ce34cSChris Mason 
403d561c025SChris Mason 	if (!wait) {
4047cfcc17eSChris Mason 		filemap_flush(root->fs_info->btree_inode->i_mapping);
405df2ce34cSChris Mason 		return 0;
406d561c025SChris Mason 	}
407771ed689SChris Mason 
408*24bbcf04SYan, Zheng 	btrfs_start_delalloc_inodes(root, 0);
409*24bbcf04SYan, Zheng 	btrfs_wait_ordered_extents(root, 0, 0);
410771ed689SChris Mason 
411d5719762SChris Mason 	trans = btrfs_start_transaction(root, 1);
412d5719762SChris Mason 	ret = btrfs_commit_transaction(trans, root);
41354aa1f4dSChris Mason 	return ret;
414d5719762SChris Mason }
415d5719762SChris Mason 
416a9572a15SEric Paris static int btrfs_show_options(struct seq_file *seq, struct vfsmount *vfs)
417a9572a15SEric Paris {
418a9572a15SEric Paris 	struct btrfs_root *root = btrfs_sb(vfs->mnt_sb);
419a9572a15SEric Paris 	struct btrfs_fs_info *info = root->fs_info;
420a9572a15SEric Paris 
421a9572a15SEric Paris 	if (btrfs_test_opt(root, DEGRADED))
422a9572a15SEric Paris 		seq_puts(seq, ",degraded");
423a9572a15SEric Paris 	if (btrfs_test_opt(root, NODATASUM))
424a9572a15SEric Paris 		seq_puts(seq, ",nodatasum");
425a9572a15SEric Paris 	if (btrfs_test_opt(root, NODATACOW))
426a9572a15SEric Paris 		seq_puts(seq, ",nodatacow");
427a9572a15SEric Paris 	if (btrfs_test_opt(root, NOBARRIER))
428a9572a15SEric Paris 		seq_puts(seq, ",nobarrier");
429a9572a15SEric Paris 	if (info->max_extent != (u64)-1)
43021380931SJoel Becker 		seq_printf(seq, ",max_extent=%llu",
43121380931SJoel Becker 			   (unsigned long long)info->max_extent);
432a9572a15SEric Paris 	if (info->max_inline != 8192 * 1024)
43321380931SJoel Becker 		seq_printf(seq, ",max_inline=%llu",
43421380931SJoel Becker 			   (unsigned long long)info->max_inline);
435a9572a15SEric Paris 	if (info->alloc_start != 0)
43621380931SJoel Becker 		seq_printf(seq, ",alloc_start=%llu",
43721380931SJoel Becker 			   (unsigned long long)info->alloc_start);
438a9572a15SEric Paris 	if (info->thread_pool_size !=  min_t(unsigned long,
439a9572a15SEric Paris 					     num_online_cpus() + 2, 8))
440a9572a15SEric Paris 		seq_printf(seq, ",thread_pool=%d", info->thread_pool_size);
441a9572a15SEric Paris 	if (btrfs_test_opt(root, COMPRESS))
442a9572a15SEric Paris 		seq_puts(seq, ",compress");
443c289811cSChris Mason 	if (btrfs_test_opt(root, NOSSD))
444c289811cSChris Mason 		seq_puts(seq, ",nossd");
445451d7585SChris Mason 	if (btrfs_test_opt(root, SSD_SPREAD))
446451d7585SChris Mason 		seq_puts(seq, ",ssd_spread");
447451d7585SChris Mason 	else if (btrfs_test_opt(root, SSD))
448a9572a15SEric Paris 		seq_puts(seq, ",ssd");
4493a5e1404SSage Weil 	if (btrfs_test_opt(root, NOTREELOG))
4506b65c5c6SSage Weil 		seq_puts(seq, ",notreelog");
451dccae999SSage Weil 	if (btrfs_test_opt(root, FLUSHONCOMMIT))
4526b65c5c6SSage Weil 		seq_puts(seq, ",flushoncommit");
453a9572a15SEric Paris 	if (!(root->fs_info->sb->s_flags & MS_POSIXACL))
454a9572a15SEric Paris 		seq_puts(seq, ",noacl");
455a9572a15SEric Paris 	return 0;
456a9572a15SEric Paris }
457a9572a15SEric Paris 
458a061fc8dSChris Mason static int btrfs_test_super(struct super_block *s, void *data)
4592e635a27SChris Mason {
460a061fc8dSChris Mason 	struct btrfs_fs_devices *test_fs_devices = data;
461a061fc8dSChris Mason 	struct btrfs_root *root = btrfs_sb(s);
4624b82d6e4SYan 
463a061fc8dSChris Mason 	return root->fs_info->fs_devices == test_fs_devices;
4644b82d6e4SYan }
4654b82d6e4SYan 
466edf24abeSChristoph Hellwig /*
467edf24abeSChristoph Hellwig  * Find a superblock for the given device / mount point.
468edf24abeSChristoph Hellwig  *
469edf24abeSChristoph Hellwig  * Note:  This is based on get_sb_bdev from fs/super.c with a few additions
470edf24abeSChristoph Hellwig  *	  for multiple device setup.  Make sure to keep it in sync.
471edf24abeSChristoph Hellwig  */
472edf24abeSChristoph Hellwig static int btrfs_get_sb(struct file_system_type *fs_type, int flags,
473edf24abeSChristoph Hellwig 		const char *dev_name, void *data, struct vfsmount *mnt)
4744b82d6e4SYan {
475edf24abeSChristoph Hellwig 	char *subvol_name = NULL;
4764b82d6e4SYan 	struct block_device *bdev = NULL;
4774b82d6e4SYan 	struct super_block *s;
4784b82d6e4SYan 	struct dentry *root;
4798a4b83ccSChris Mason 	struct btrfs_fs_devices *fs_devices = NULL;
48097288f2cSChristoph Hellwig 	fmode_t mode = FMODE_READ;
4814b82d6e4SYan 	int error = 0;
4824b82d6e4SYan 
48397288f2cSChristoph Hellwig 	if (!(flags & MS_RDONLY))
48497288f2cSChristoph Hellwig 		mode |= FMODE_WRITE;
48597288f2cSChristoph Hellwig 
48697288f2cSChristoph Hellwig 	error = btrfs_parse_early_options(data, mode, fs_type,
48743e570b0SChristoph Hellwig 					  &subvol_name, &fs_devices);
488edf24abeSChristoph Hellwig 	if (error)
4891f483660SShen Feng 		return error;
490edf24abeSChristoph Hellwig 
49197288f2cSChristoph Hellwig 	error = btrfs_scan_one_device(dev_name, mode, fs_type, &fs_devices);
4928a4b83ccSChris Mason 	if (error)
493edf24abeSChristoph Hellwig 		goto error_free_subvol_name;
4944b82d6e4SYan 
49597288f2cSChristoph Hellwig 	error = btrfs_open_devices(fs_devices, mode, fs_type);
4968a4b83ccSChris Mason 	if (error)
497edf24abeSChristoph Hellwig 		goto error_free_subvol_name;
4988a4b83ccSChris Mason 
4992b82032cSYan Zheng 	if (!(flags & MS_RDONLY) && fs_devices->rw_devices == 0) {
5002b82032cSYan Zheng 		error = -EACCES;
5012b82032cSYan Zheng 		goto error_close_devices;
5022b82032cSYan Zheng 	}
5032b82032cSYan Zheng 
504dfe25020SChris Mason 	bdev = fs_devices->latest_bdev;
505a061fc8dSChris Mason 	s = sget(fs_type, btrfs_test_super, set_anon_super, fs_devices);
5064b82d6e4SYan 	if (IS_ERR(s))
5074b82d6e4SYan 		goto error_s;
5084b82d6e4SYan 
5094b82d6e4SYan 	if (s->s_root) {
5104b82d6e4SYan 		if ((flags ^ s->s_flags) & MS_RDONLY) {
5116f5bbff9SAl Viro 			deactivate_locked_super(s);
5124b82d6e4SYan 			error = -EBUSY;
513c146afadSYan Zheng 			goto error_close_devices;
5144b82d6e4SYan 		}
5154b82d6e4SYan 
5162b82032cSYan Zheng 		btrfs_close_devices(fs_devices);
5174b82d6e4SYan 	} else {
5184b82d6e4SYan 		char b[BDEVNAME_SIZE];
5194b82d6e4SYan 
5204b82d6e4SYan 		s->s_flags = flags;
5214b82d6e4SYan 		strlcpy(s->s_id, bdevname(bdev, b), sizeof(s->s_id));
5228a4b83ccSChris Mason 		error = btrfs_fill_super(s, fs_devices, data,
5238a4b83ccSChris Mason 					 flags & MS_SILENT ? 1 : 0);
5244b82d6e4SYan 		if (error) {
5256f5bbff9SAl Viro 			deactivate_locked_super(s);
5261f483660SShen Feng 			goto error_free_subvol_name;
5274b82d6e4SYan 		}
5284b82d6e4SYan 
529788f20ebSChris Mason 		btrfs_sb(s)->fs_info->bdev_holder = fs_type;
5304b82d6e4SYan 		s->s_flags |= MS_ACTIVE;
5314b82d6e4SYan 	}
5324b82d6e4SYan 
53376fcef19SDavid Woodhouse 	if (!strcmp(subvol_name, "."))
53476fcef19SDavid Woodhouse 		root = dget(s->s_root);
53576fcef19SDavid Woodhouse 	else {
536b48652c1SYan Zheng 		mutex_lock(&s->s_root->d_inode->i_mutex);
537d397712bSChris Mason 		root = lookup_one_len(subvol_name, s->s_root,
538d397712bSChris Mason 				      strlen(subvol_name));
539b48652c1SYan Zheng 		mutex_unlock(&s->s_root->d_inode->i_mutex);
540d397712bSChris Mason 
5414b82d6e4SYan 		if (IS_ERR(root)) {
5426f5bbff9SAl Viro 			deactivate_locked_super(s);
5434b82d6e4SYan 			error = PTR_ERR(root);
5441f483660SShen Feng 			goto error_free_subvol_name;
5454b82d6e4SYan 		}
5464b82d6e4SYan 		if (!root->d_inode) {
5474b82d6e4SYan 			dput(root);
5486f5bbff9SAl Viro 			deactivate_locked_super(s);
5494b82d6e4SYan 			error = -ENXIO;
5501f483660SShen Feng 			goto error_free_subvol_name;
5514b82d6e4SYan 		}
55276fcef19SDavid Woodhouse 	}
5534b82d6e4SYan 
5544b82d6e4SYan 	mnt->mnt_sb = s;
5554b82d6e4SYan 	mnt->mnt_root = root;
556edf24abeSChristoph Hellwig 
557edf24abeSChristoph Hellwig 	kfree(subvol_name);
5584b82d6e4SYan 	return 0;
5594b82d6e4SYan 
5604b82d6e4SYan error_s:
5614b82d6e4SYan 	error = PTR_ERR(s);
562c146afadSYan Zheng error_close_devices:
5638a4b83ccSChris Mason 	btrfs_close_devices(fs_devices);
564edf24abeSChristoph Hellwig error_free_subvol_name:
565edf24abeSChristoph Hellwig 	kfree(subvol_name);
5664b82d6e4SYan 	return error;
5674b82d6e4SYan }
5682e635a27SChris Mason 
569c146afadSYan Zheng static int btrfs_remount(struct super_block *sb, int *flags, char *data)
570c146afadSYan Zheng {
571c146afadSYan Zheng 	struct btrfs_root *root = btrfs_sb(sb);
572c146afadSYan Zheng 	int ret;
573c146afadSYan Zheng 
574b288052eSChris Mason 	ret = btrfs_parse_options(root, data);
575b288052eSChris Mason 	if (ret)
576b288052eSChris Mason 		return -EINVAL;
577b288052eSChris Mason 
578c146afadSYan Zheng 	if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY))
579c146afadSYan Zheng 		return 0;
580c146afadSYan Zheng 
581c146afadSYan Zheng 	if (*flags & MS_RDONLY) {
582c146afadSYan Zheng 		sb->s_flags |= MS_RDONLY;
583c146afadSYan Zheng 
584c146afadSYan Zheng 		ret =  btrfs_commit_super(root);
585c146afadSYan Zheng 		WARN_ON(ret);
586c146afadSYan Zheng 	} else {
5872b82032cSYan Zheng 		if (root->fs_info->fs_devices->rw_devices == 0)
5882b82032cSYan Zheng 			return -EACCES;
5892b82032cSYan Zheng 
590c146afadSYan Zheng 		if (btrfs_super_log_root(&root->fs_info->super_copy) != 0)
591c146afadSYan Zheng 			return -EINVAL;
592c146afadSYan Zheng 
5935d4f98a2SYan Zheng 		/* recover relocation */
5945d4f98a2SYan Zheng 		ret = btrfs_recover_relocation(root);
595c146afadSYan Zheng 		WARN_ON(ret);
596c146afadSYan Zheng 
597c146afadSYan Zheng 		ret = btrfs_cleanup_fs_roots(root->fs_info);
598c146afadSYan Zheng 		WARN_ON(ret);
599c146afadSYan Zheng 
600c146afadSYan Zheng 		sb->s_flags &= ~MS_RDONLY;
601c146afadSYan Zheng 	}
602c146afadSYan Zheng 
603c146afadSYan Zheng 	return 0;
604c146afadSYan Zheng }
605c146afadSYan Zheng 
6068fd17795SChris Mason static int btrfs_statfs(struct dentry *dentry, struct kstatfs *buf)
6078fd17795SChris Mason {
6088fd17795SChris Mason 	struct btrfs_root *root = btrfs_sb(dentry->d_sb);
6094b52dff6SChris Mason 	struct btrfs_super_block *disk_super = &root->fs_info->super_copy;
610db94535dSChris Mason 	int bits = dentry->d_sb->s_blocksize_bits;
6119d03632eSDavid Woodhouse 	__be32 *fsid = (__be32 *)root->fs_info->fsid;
6128fd17795SChris Mason 
6138fd17795SChris Mason 	buf->f_namelen = BTRFS_NAME_LEN;
614db94535dSChris Mason 	buf->f_blocks = btrfs_super_total_bytes(disk_super) >> bits;
615db94535dSChris Mason 	buf->f_bfree = buf->f_blocks -
616db94535dSChris Mason 		(btrfs_super_bytes_used(disk_super) >> bits);
6178fd17795SChris Mason 	buf->f_bavail = buf->f_bfree;
6188fd17795SChris Mason 	buf->f_bsize = dentry->d_sb->s_blocksize;
6198fd17795SChris Mason 	buf->f_type = BTRFS_SUPER_MAGIC;
620d397712bSChris Mason 
6219d03632eSDavid Woodhouse 	/* We treat it as constant endianness (it doesn't matter _which_)
6229d03632eSDavid Woodhouse 	   because we want the fsid to come out the same whether mounted
6239d03632eSDavid Woodhouse 	   on a big-endian or little-endian host */
6249d03632eSDavid Woodhouse 	buf->f_fsid.val[0] = be32_to_cpu(fsid[0]) ^ be32_to_cpu(fsid[2]);
6259d03632eSDavid Woodhouse 	buf->f_fsid.val[1] = be32_to_cpu(fsid[1]) ^ be32_to_cpu(fsid[3]);
62632d48fa1SDavid Woodhouse 	/* Mask in the root object ID too, to disambiguate subvols */
62732d48fa1SDavid Woodhouse 	buf->f_fsid.val[0] ^= BTRFS_I(dentry->d_inode)->root->objectid >> 32;
62832d48fa1SDavid Woodhouse 	buf->f_fsid.val[1] ^= BTRFS_I(dentry->d_inode)->root->objectid;
62932d48fa1SDavid Woodhouse 
6308fd17795SChris Mason 	return 0;
6318fd17795SChris Mason }
632b5133862SChris Mason 
6332e635a27SChris Mason static struct file_system_type btrfs_fs_type = {
6342e635a27SChris Mason 	.owner		= THIS_MODULE,
6352e635a27SChris Mason 	.name		= "btrfs",
6362e635a27SChris Mason 	.get_sb		= btrfs_get_sb,
637a061fc8dSChris Mason 	.kill_sb	= kill_anon_super,
6382e635a27SChris Mason 	.fs_flags	= FS_REQUIRES_DEV,
6392e635a27SChris Mason };
640a9218f6bSChris Mason 
641d352ac68SChris Mason /*
642d352ac68SChris Mason  * used by btrfsctl to scan devices when no FS is mounted
643d352ac68SChris Mason  */
6448a4b83ccSChris Mason static long btrfs_control_ioctl(struct file *file, unsigned int cmd,
6458a4b83ccSChris Mason 				unsigned long arg)
6468a4b83ccSChris Mason {
6478a4b83ccSChris Mason 	struct btrfs_ioctl_vol_args *vol;
6488a4b83ccSChris Mason 	struct btrfs_fs_devices *fs_devices;
649c071fcfdSChris Mason 	int ret = -ENOTTY;
6508a4b83ccSChris Mason 
651e441d54dSChris Mason 	if (!capable(CAP_SYS_ADMIN))
652e441d54dSChris Mason 		return -EPERM;
653e441d54dSChris Mason 
654dae7b665SLi Zefan 	vol = memdup_user((void __user *)arg, sizeof(*vol));
655dae7b665SLi Zefan 	if (IS_ERR(vol))
656dae7b665SLi Zefan 		return PTR_ERR(vol);
657c071fcfdSChris Mason 
6588a4b83ccSChris Mason 	switch (cmd) {
6598a4b83ccSChris Mason 	case BTRFS_IOC_SCAN_DEV:
66097288f2cSChristoph Hellwig 		ret = btrfs_scan_one_device(vol->name, FMODE_READ,
6618a4b83ccSChris Mason 					    &btrfs_fs_type, &fs_devices);
6628a4b83ccSChris Mason 		break;
6638a4b83ccSChris Mason 	}
664dae7b665SLi Zefan 
6658a4b83ccSChris Mason 	kfree(vol);
666f819d837SLinda Knippers 	return ret;
6678a4b83ccSChris Mason }
6688a4b83ccSChris Mason 
6690176260fSLinus Torvalds static int btrfs_freeze(struct super_block *sb)
670ed0dab6bSYan {
671ed0dab6bSYan 	struct btrfs_root *root = btrfs_sb(sb);
672a74a4b97SChris Mason 	mutex_lock(&root->fs_info->transaction_kthread_mutex);
673a74a4b97SChris Mason 	mutex_lock(&root->fs_info->cleaner_mutex);
6740176260fSLinus Torvalds 	return 0;
675ed0dab6bSYan }
676ed0dab6bSYan 
6770176260fSLinus Torvalds static int btrfs_unfreeze(struct super_block *sb)
678ed0dab6bSYan {
679ed0dab6bSYan 	struct btrfs_root *root = btrfs_sb(sb);
680a74a4b97SChris Mason 	mutex_unlock(&root->fs_info->cleaner_mutex);
681a74a4b97SChris Mason 	mutex_unlock(&root->fs_info->transaction_kthread_mutex);
6820176260fSLinus Torvalds 	return 0;
683ed0dab6bSYan }
6842e635a27SChris Mason 
685b87221deSAlexey Dobriyan static const struct super_operations btrfs_super_ops = {
68676dda93cSYan, Zheng 	.drop_inode	= btrfs_drop_inode,
687134e9731SChris Mason 	.delete_inode	= btrfs_delete_inode,
688e20d96d6SChris Mason 	.put_super	= btrfs_put_super,
689d5719762SChris Mason 	.sync_fs	= btrfs_sync_fs,
690a9572a15SEric Paris 	.show_options	= btrfs_show_options,
6914730a4bcSChris Mason 	.write_inode	= btrfs_write_inode,
692b5133862SChris Mason 	.dirty_inode	= btrfs_dirty_inode,
6932c90e5d6SChris Mason 	.alloc_inode	= btrfs_alloc_inode,
6942c90e5d6SChris Mason 	.destroy_inode	= btrfs_destroy_inode,
6958fd17795SChris Mason 	.statfs		= btrfs_statfs,
696c146afadSYan Zheng 	.remount_fs	= btrfs_remount,
6970176260fSLinus Torvalds 	.freeze_fs	= btrfs_freeze,
6980176260fSLinus Torvalds 	.unfreeze_fs	= btrfs_unfreeze,
699e20d96d6SChris Mason };
700a9218f6bSChris Mason 
701a9218f6bSChris Mason static const struct file_operations btrfs_ctl_fops = {
702a9218f6bSChris Mason 	.unlocked_ioctl	 = btrfs_control_ioctl,
703a9218f6bSChris Mason 	.compat_ioctl = btrfs_control_ioctl,
704a9218f6bSChris Mason 	.owner	 = THIS_MODULE,
705a9218f6bSChris Mason };
706a9218f6bSChris Mason 
707a9218f6bSChris Mason static struct miscdevice btrfs_misc = {
708a9218f6bSChris Mason 	.minor		= MISC_DYNAMIC_MINOR,
709a9218f6bSChris Mason 	.name		= "btrfs-control",
710a9218f6bSChris Mason 	.fops		= &btrfs_ctl_fops
711a9218f6bSChris Mason };
712a9218f6bSChris Mason 
713a9218f6bSChris Mason static int btrfs_interface_init(void)
714a9218f6bSChris Mason {
715a9218f6bSChris Mason 	return misc_register(&btrfs_misc);
716a9218f6bSChris Mason }
717a9218f6bSChris Mason 
718b2950863SChristoph Hellwig static void btrfs_interface_exit(void)
719a9218f6bSChris Mason {
720a9218f6bSChris Mason 	if (misc_deregister(&btrfs_misc) < 0)
721d397712bSChris Mason 		printk(KERN_INFO "misc_deregister failed for control device");
722a9218f6bSChris Mason }
723a9218f6bSChris Mason 
7242e635a27SChris Mason static int __init init_btrfs_fs(void)
7252e635a27SChris Mason {
7262c90e5d6SChris Mason 	int err;
72758176a96SJosef Bacik 
72858176a96SJosef Bacik 	err = btrfs_init_sysfs();
72958176a96SJosef Bacik 	if (err)
73058176a96SJosef Bacik 		return err;
73158176a96SJosef Bacik 
73239279cc3SChris Mason 	err = btrfs_init_cachep();
7332c90e5d6SChris Mason 	if (err)
734a74a4b97SChris Mason 		goto free_sysfs;
735d1310b2eSChris Mason 
736d1310b2eSChris Mason 	err = extent_io_init();
7372f4cbe64SWyatt Banks 	if (err)
7382f4cbe64SWyatt Banks 		goto free_cachep;
7392f4cbe64SWyatt Banks 
740d1310b2eSChris Mason 	err = extent_map_init();
741d1310b2eSChris Mason 	if (err)
742d1310b2eSChris Mason 		goto free_extent_io;
743d1310b2eSChris Mason 
744a9218f6bSChris Mason 	err = btrfs_interface_init();
7452f4cbe64SWyatt Banks 	if (err)
7462f4cbe64SWyatt Banks 		goto free_extent_map;
747c8b97818SChris Mason 
748a9218f6bSChris Mason 	err = register_filesystem(&btrfs_fs_type);
749a9218f6bSChris Mason 	if (err)
750a9218f6bSChris Mason 		goto unregister_ioctl;
751b3c3da71SChris Mason 
752b3c3da71SChris Mason 	printk(KERN_INFO "%s loaded\n", BTRFS_BUILD_VERSION);
7532f4cbe64SWyatt Banks 	return 0;
7542f4cbe64SWyatt Banks 
755a9218f6bSChris Mason unregister_ioctl:
756a9218f6bSChris Mason 	btrfs_interface_exit();
7572f4cbe64SWyatt Banks free_extent_map:
7582f4cbe64SWyatt Banks 	extent_map_exit();
759d1310b2eSChris Mason free_extent_io:
760d1310b2eSChris Mason 	extent_io_exit();
7612f4cbe64SWyatt Banks free_cachep:
7622f4cbe64SWyatt Banks 	btrfs_destroy_cachep();
763a74a4b97SChris Mason free_sysfs:
7642f4cbe64SWyatt Banks 	btrfs_exit_sysfs();
7652c90e5d6SChris Mason 	return err;
7662e635a27SChris Mason }
7672e635a27SChris Mason 
7682e635a27SChris Mason static void __exit exit_btrfs_fs(void)
7692e635a27SChris Mason {
77039279cc3SChris Mason 	btrfs_destroy_cachep();
771a52d9a80SChris Mason 	extent_map_exit();
772d1310b2eSChris Mason 	extent_io_exit();
773a9218f6bSChris Mason 	btrfs_interface_exit();
7742e635a27SChris Mason 	unregister_filesystem(&btrfs_fs_type);
77558176a96SJosef Bacik 	btrfs_exit_sysfs();
7768a4b83ccSChris Mason 	btrfs_cleanup_fs_uuids();
777c8b97818SChris Mason 	btrfs_zlib_exit();
7782e635a27SChris Mason }
7792e635a27SChris Mason 
7802e635a27SChris Mason module_init(init_btrfs_fs)
7812e635a27SChris Mason module_exit(exit_btrfs_fs)
7822e635a27SChris Mason 
7832e635a27SChris Mason MODULE_LICENSE("GPL");
784