xref: /openbmc/linux/fs/btrfs/super.c (revision b3c3da71)
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"
48*b3c3da71SChris Mason #include "version.h"
492e635a27SChris Mason 
505f39d397SChris Mason #define BTRFS_SUPER_MAGIC 0x9123683E
51e20d96d6SChris Mason 
52e20d96d6SChris Mason static struct super_operations btrfs_super_ops;
53e20d96d6SChris Mason 
54e20d96d6SChris Mason static void btrfs_put_super (struct super_block * sb)
55e20d96d6SChris Mason {
56e20d96d6SChris Mason 	struct btrfs_root *root = btrfs_sb(sb);
5758176a96SJosef Bacik 	struct btrfs_fs_info *fs = root->fs_info;
58e20d96d6SChris Mason 	int ret;
59e20d96d6SChris Mason 
60e20d96d6SChris Mason 	ret = close_ctree(root);
61e20d96d6SChris Mason 	if (ret) {
62e20d96d6SChris Mason 		printk("close ctree returns %d\n", ret);
63e20d96d6SChris Mason 	}
6458176a96SJosef Bacik 	btrfs_sysfs_del_super(fs);
65e20d96d6SChris Mason 	sb->s_fs_info = NULL;
66e20d96d6SChris Mason }
672e635a27SChris Mason 
6895e05289SChris Mason enum {
6943e570b0SChristoph Hellwig 	Opt_degraded, Opt_subvol, Opt_device, Opt_nodatasum, Opt_nodatacow,
70dfe25020SChris Mason 	Opt_max_extent, Opt_max_inline, Opt_alloc_start, Opt_nobarrier,
714543df7eSChris Mason 	Opt_ssd, Opt_thread_pool, Opt_err,
7295e05289SChris Mason };
7395e05289SChris Mason 
7495e05289SChris Mason static match_table_t tokens = {
75dfe25020SChris Mason 	{Opt_degraded, "degraded"},
7695e05289SChris Mason 	{Opt_subvol, "subvol=%s"},
7743e570b0SChristoph Hellwig 	{Opt_device, "device=%s"},
78b6cda9bcSChris Mason 	{Opt_nodatasum, "nodatasum"},
79be20aa9dSChris Mason 	{Opt_nodatacow, "nodatacow"},
8021ad10cfSChris Mason 	{Opt_nobarrier, "nobarrier"},
81c59f8951SChris Mason 	{Opt_max_extent, "max_extent=%s"},
826f568d35SChris Mason 	{Opt_max_inline, "max_inline=%s"},
838f662a76SChris Mason 	{Opt_alloc_start, "alloc_start=%s"},
844543df7eSChris Mason 	{Opt_thread_pool, "thread_pool=%d"},
85e18e4809SChris Mason 	{Opt_ssd, "ssd"},
8695e05289SChris Mason 	{Opt_err, NULL}
8795e05289SChris Mason };
8895e05289SChris Mason 
89edbd8d4eSChris Mason u64 btrfs_parse_size(char *str)
90c59f8951SChris Mason {
91edbd8d4eSChris Mason 	u64 res;
92c59f8951SChris Mason 	int mult = 1;
93c59f8951SChris Mason 	char *end;
94c59f8951SChris Mason 	char last;
95c59f8951SChris Mason 
96c59f8951SChris Mason 	res = simple_strtoul(str, &end, 10);
97c59f8951SChris Mason 
98c59f8951SChris Mason 	last = end[0];
99c59f8951SChris Mason 	if (isalpha(last)) {
100c59f8951SChris Mason 		last = tolower(last);
101c59f8951SChris Mason 		switch (last) {
102c59f8951SChris Mason 		case 'g':
103c59f8951SChris Mason 			mult *= 1024;
104c59f8951SChris Mason 		case 'm':
105c59f8951SChris Mason 			mult *= 1024;
106c59f8951SChris Mason 		case 'k':
107c59f8951SChris Mason 			mult *= 1024;
108c59f8951SChris Mason 		}
109c59f8951SChris Mason 		res = res * mult;
110c59f8951SChris Mason 	}
111c59f8951SChris Mason 	return res;
112c59f8951SChris Mason }
113c59f8951SChris Mason 
114edf24abeSChristoph Hellwig /*
115edf24abeSChristoph Hellwig  * Regular mount options parser.  Everything that is needed only when
116edf24abeSChristoph Hellwig  * reading in a new superblock is parsed here.
117edf24abeSChristoph Hellwig  */
118edf24abeSChristoph Hellwig int btrfs_parse_options(struct btrfs_root *root, char *options)
11995e05289SChris Mason {
120edf24abeSChristoph Hellwig 	struct btrfs_fs_info *info = root->fs_info;
12195e05289SChris Mason 	substring_t args[MAX_OPT_ARGS];
122edf24abeSChristoph Hellwig 	char *p, *num;
1234543df7eSChris Mason 	int intarg;
124b6cda9bcSChris Mason 
12595e05289SChris Mason 	if (!options)
126edf24abeSChristoph Hellwig 		return 0;
12795e05289SChris Mason 
128be20aa9dSChris Mason 	/*
129be20aa9dSChris Mason 	 * strsep changes the string, duplicate it because parse_options
130be20aa9dSChris Mason 	 * gets called twice
131be20aa9dSChris Mason 	 */
132be20aa9dSChris Mason 	options = kstrdup(options, GFP_NOFS);
133be20aa9dSChris Mason 	if (!options)
134be20aa9dSChris Mason 		return -ENOMEM;
135be20aa9dSChris Mason 
136be20aa9dSChris Mason 
13795e05289SChris Mason 	while ((p = strsep(&options, ",")) != NULL) {
13895e05289SChris Mason 		int token;
13995e05289SChris Mason 		if (!*p)
14095e05289SChris Mason 			continue;
14195e05289SChris Mason 
14295e05289SChris Mason 		token = match_token(p, tokens, args);
14395e05289SChris Mason 		switch (token) {
144dfe25020SChris Mason 		case Opt_degraded:
145edf24abeSChristoph Hellwig 			printk(KERN_INFO "btrfs: allowing degraded mounts\n");
146dfe25020SChris Mason 			btrfs_set_opt(info->mount_opt, DEGRADED);
147dfe25020SChris Mason 			break;
14895e05289SChris Mason 		case Opt_subvol:
14943e570b0SChristoph Hellwig 		case Opt_device:
150edf24abeSChristoph Hellwig 			/*
15143e570b0SChristoph Hellwig 			 * These are parsed by btrfs_parse_early_options
152edf24abeSChristoph Hellwig 			 * and can be happily ignored here.
153edf24abeSChristoph Hellwig 			 */
15495e05289SChris Mason 			break;
155b6cda9bcSChris Mason 		case Opt_nodatasum:
156edf24abeSChristoph Hellwig 			printk(KERN_INFO "btrfs: setting nodatacsum\n");
157b6cda9bcSChris Mason 			btrfs_set_opt(info->mount_opt, NODATASUM);
158be20aa9dSChris Mason 			break;
159be20aa9dSChris Mason 		case Opt_nodatacow:
160edf24abeSChristoph Hellwig 			printk(KERN_INFO "btrfs: setting nodatacow\n");
161be20aa9dSChris Mason 			btrfs_set_opt(info->mount_opt, NODATACOW);
162be20aa9dSChris Mason 			btrfs_set_opt(info->mount_opt, NODATASUM);
163b6cda9bcSChris Mason 			break;
164e18e4809SChris Mason 		case Opt_ssd:
165edf24abeSChristoph Hellwig 			printk(KERN_INFO "btrfs: use ssd allocation scheme\n");
166e18e4809SChris Mason 			btrfs_set_opt(info->mount_opt, SSD);
167e18e4809SChris Mason 			break;
16821ad10cfSChris Mason 		case Opt_nobarrier:
169edf24abeSChristoph Hellwig 			printk(KERN_INFO "btrfs: turning off barriers\n");
17021ad10cfSChris Mason 			btrfs_set_opt(info->mount_opt, NOBARRIER);
17121ad10cfSChris Mason 			break;
1724543df7eSChris Mason 		case Opt_thread_pool:
1734543df7eSChris Mason 			intarg = 0;
1744543df7eSChris Mason 			match_int(&args[0], &intarg);
1754543df7eSChris Mason 			if (intarg) {
1764543df7eSChris Mason 				info->thread_pool_size = intarg;
1774543df7eSChris Mason 				printk(KERN_INFO "btrfs: thread pool %d\n",
1784543df7eSChris Mason 				       info->thread_pool_size);
1794543df7eSChris Mason 			}
1804543df7eSChris Mason 			break;
181c59f8951SChris Mason 		case Opt_max_extent:
182edf24abeSChristoph Hellwig 			num = match_strdup(&args[0]);
183c59f8951SChris Mason 			if (num) {
184edf24abeSChristoph Hellwig 				info->max_extent = btrfs_parse_size(num);
185c59f8951SChris Mason 				kfree(num);
186c59f8951SChris Mason 
187c59f8951SChris Mason 				info->max_extent = max_t(u64,
188edf24abeSChristoph Hellwig 					info->max_extent, root->sectorsize);
189edf24abeSChristoph Hellwig 				printk(KERN_INFO "btrfs: max_extent at %llu\n",
190c59f8951SChris Mason 				       info->max_extent);
191c59f8951SChris Mason 			}
192c59f8951SChris Mason 			break;
1936f568d35SChris Mason 		case Opt_max_inline:
194edf24abeSChristoph Hellwig 			num = match_strdup(&args[0]);
1956f568d35SChris Mason 			if (num) {
196edf24abeSChristoph Hellwig 				info->max_inline = btrfs_parse_size(num);
1976f568d35SChris Mason 				kfree(num);
1986f568d35SChris Mason 
19915ada040SChris Mason 				if (info->max_inline) {
2006f568d35SChris Mason 					info->max_inline = max_t(u64,
20115ada040SChris Mason 						info->max_inline,
20215ada040SChris Mason 						root->sectorsize);
20315ada040SChris Mason 				}
204edf24abeSChristoph Hellwig 				printk(KERN_INFO "btrfs: max_inline at %llu\n",
2056f568d35SChris Mason 					info->max_inline);
2066f568d35SChris Mason 			}
2076f568d35SChris Mason 			break;
2088f662a76SChris Mason 		case Opt_alloc_start:
209edf24abeSChristoph Hellwig 			num = match_strdup(&args[0]);
2108f662a76SChris Mason 			if (num) {
211edf24abeSChristoph Hellwig 				info->alloc_start = btrfs_parse_size(num);
2128f662a76SChris Mason 				kfree(num);
213edf24abeSChristoph Hellwig 				printk(KERN_INFO
214edf24abeSChristoph Hellwig 					"btrfs: allocations start at %llu\n",
215edf24abeSChristoph Hellwig 					info->alloc_start);
2168f662a76SChris Mason 			}
2178f662a76SChris Mason 			break;
21895e05289SChris Mason 		default:
219be20aa9dSChris Mason 			break;
22095e05289SChris Mason 		}
22195e05289SChris Mason 	}
222be20aa9dSChris Mason 	kfree(options);
223edf24abeSChristoph Hellwig 	return 0;
224edf24abeSChristoph Hellwig }
225edf24abeSChristoph Hellwig 
226edf24abeSChristoph Hellwig /*
227edf24abeSChristoph Hellwig  * Parse mount options that are required early in the mount process.
228edf24abeSChristoph Hellwig  *
229edf24abeSChristoph Hellwig  * All other options will be parsed on much later in the mount process and
230edf24abeSChristoph Hellwig  * only when we need to allocate a new super block.
231edf24abeSChristoph Hellwig  */
23243e570b0SChristoph Hellwig static int btrfs_parse_early_options(const char *options, int flags,
23343e570b0SChristoph Hellwig 		void *holder, char **subvol_name,
23443e570b0SChristoph Hellwig 		struct btrfs_fs_devices **fs_devices)
235edf24abeSChristoph Hellwig {
236edf24abeSChristoph Hellwig 	substring_t args[MAX_OPT_ARGS];
237edf24abeSChristoph Hellwig 	char *opts, *p;
238edf24abeSChristoph Hellwig 	int error = 0;
239edf24abeSChristoph Hellwig 
240edf24abeSChristoph Hellwig 	if (!options)
241edf24abeSChristoph Hellwig 		goto out;
242edf24abeSChristoph Hellwig 
243edf24abeSChristoph Hellwig 	/*
244edf24abeSChristoph Hellwig 	 * strsep changes the string, duplicate it because parse_options
245edf24abeSChristoph Hellwig 	 * gets called twice
246edf24abeSChristoph Hellwig 	 */
247edf24abeSChristoph Hellwig 	opts = kstrdup(options, GFP_KERNEL);
248edf24abeSChristoph Hellwig 	if (!opts)
249edf24abeSChristoph Hellwig 		return -ENOMEM;
250edf24abeSChristoph Hellwig 
251edf24abeSChristoph Hellwig 	while ((p = strsep(&opts, ",")) != NULL) {
252edf24abeSChristoph Hellwig 		int token;
253edf24abeSChristoph Hellwig 		if (!*p)
254edf24abeSChristoph Hellwig 			continue;
255edf24abeSChristoph Hellwig 
256edf24abeSChristoph Hellwig 		token = match_token(p, tokens, args);
257edf24abeSChristoph Hellwig 		switch (token) {
258edf24abeSChristoph Hellwig 		case Opt_subvol:
259edf24abeSChristoph Hellwig 			*subvol_name = match_strdup(&args[0]);
260edf24abeSChristoph Hellwig 			break;
26143e570b0SChristoph Hellwig 		case Opt_device:
26243e570b0SChristoph Hellwig 			error = btrfs_scan_one_device(match_strdup(&args[0]),
26343e570b0SChristoph Hellwig 					flags, holder, fs_devices);
26443e570b0SChristoph Hellwig 			if (error)
26543e570b0SChristoph Hellwig 				goto out_free_opts;
26643e570b0SChristoph Hellwig 			break;
267edf24abeSChristoph Hellwig 		default:
268edf24abeSChristoph Hellwig 			break;
269edf24abeSChristoph Hellwig 		}
270edf24abeSChristoph Hellwig 	}
271edf24abeSChristoph Hellwig 
27243e570b0SChristoph Hellwig  out_free_opts:
273edf24abeSChristoph Hellwig 	kfree(opts);
274edf24abeSChristoph Hellwig  out:
275edf24abeSChristoph Hellwig 	/*
276edf24abeSChristoph Hellwig 	 * If no subvolume name is specified we use the default one.  Allocate
277edf24abeSChristoph Hellwig 	 * a copy of the string "default" here so that code later in the
278edf24abeSChristoph Hellwig 	 * mount path doesn't care if it's the default volume or another one.
279edf24abeSChristoph Hellwig 	 */
280edf24abeSChristoph Hellwig 	if (!*subvol_name) {
281edf24abeSChristoph Hellwig 		*subvol_name = kstrdup("default", GFP_KERNEL);
282edf24abeSChristoph Hellwig 		if (!*subvol_name)
283edf24abeSChristoph Hellwig 			return -ENOMEM;
284edf24abeSChristoph Hellwig 	}
285edf24abeSChristoph Hellwig 	return error;
28695e05289SChris Mason }
28795e05289SChris Mason 
2888a4b83ccSChris Mason static int btrfs_fill_super(struct super_block * sb,
2898a4b83ccSChris Mason 			    struct btrfs_fs_devices *fs_devices,
2908a4b83ccSChris Mason 			    void * data, int silent)
2912e635a27SChris Mason {
2922e635a27SChris Mason 	struct inode * inode;
293e20d96d6SChris Mason 	struct dentry * root_dentry;
294e20d96d6SChris Mason 	struct btrfs_super_block *disk_super;
2950f7d52f4SChris Mason 	struct btrfs_root *tree_root;
296d6e4a428SChris Mason 	struct btrfs_inode *bi;
29739279cc3SChris Mason 	int err;
2982e635a27SChris Mason 
2992e635a27SChris Mason 	sb->s_maxbytes = MAX_LFS_FILESIZE;
3002e635a27SChris Mason 	sb->s_magic = BTRFS_SUPER_MAGIC;
301e20d96d6SChris Mason 	sb->s_op = &btrfs_super_ops;
3025103e947SJosef Bacik 	sb->s_xattr = btrfs_xattr_handlers;
3032e635a27SChris Mason 	sb->s_time_gran = 1;
304e20d96d6SChris Mason 
305dfe25020SChris Mason 	tree_root = open_ctree(sb, fs_devices, (char *)data);
306d98237b3SChris Mason 
307e58ca020SYan 	if (IS_ERR(tree_root)) {
308e20d96d6SChris Mason 		printk("btrfs: open_ctree failed\n");
309e58ca020SYan 		return PTR_ERR(tree_root);
310e20d96d6SChris Mason 	}
3110f7d52f4SChris Mason 	sb->s_fs_info = tree_root;
3125f39d397SChris Mason 	disk_super = &tree_root->fs_info->super_copy;
313c5739bbaSChris Mason 	inode = btrfs_iget_locked(sb, btrfs_super_root_dir(disk_super),
314c5739bbaSChris Mason 				  tree_root);
315d6e4a428SChris Mason 	bi = BTRFS_I(inode);
316d6e4a428SChris Mason 	bi->location.objectid = inode->i_ino;
317d6e4a428SChris Mason 	bi->location.offset = 0;
3180f7d52f4SChris Mason 	bi->root = tree_root;
319b888db2bSChris Mason 
320d6e4a428SChris Mason 	btrfs_set_key_type(&bi->location, BTRFS_INODE_ITEM_KEY);
321d6e4a428SChris Mason 
32239279cc3SChris Mason 	if (!inode) {
32339279cc3SChris Mason 		err = -ENOMEM;
32439279cc3SChris Mason 		goto fail_close;
32539279cc3SChris Mason 	}
326e20d96d6SChris Mason 	if (inode->i_state & I_NEW) {
327e20d96d6SChris Mason 		btrfs_read_locked_inode(inode);
328e20d96d6SChris Mason 		unlock_new_inode(inode);
329e20d96d6SChris Mason 	}
3302e635a27SChris Mason 
331e20d96d6SChris Mason 	root_dentry = d_alloc_root(inode);
332e20d96d6SChris Mason 	if (!root_dentry) {
3332e635a27SChris Mason 		iput(inode);
33439279cc3SChris Mason 		err = -ENOMEM;
33539279cc3SChris Mason 		goto fail_close;
3362e635a27SChris Mason 	}
33758176a96SJosef Bacik 
33858176a96SJosef Bacik 	/* this does the super kobj at the same time */
33958176a96SJosef Bacik 	err = btrfs_sysfs_add_super(tree_root->fs_info);
34058176a96SJosef Bacik 	if (err)
34158176a96SJosef Bacik 		goto fail_close;
34258176a96SJosef Bacik 
343e20d96d6SChris Mason 	sb->s_root = root_dentry;
3446885f308SChris Mason 
3456885f308SChris Mason #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25)
3466885f308SChris Mason 	save_mount_options(sb, data);
3476885f308SChris Mason #endif
3486885f308SChris Mason 
3492e635a27SChris Mason 	return 0;
3502e635a27SChris Mason 
35139279cc3SChris Mason fail_close:
35239279cc3SChris Mason 	close_ctree(tree_root);
353d5719762SChris Mason 	return err;
354d5719762SChris Mason }
355d5719762SChris Mason 
3566bf13c0cSSage Weil int btrfs_sync_fs(struct super_block *sb, int wait)
357d5719762SChris Mason {
358d5719762SChris Mason 	struct btrfs_trans_handle *trans;
359d5719762SChris Mason 	struct btrfs_root *root;
360d5719762SChris Mason 	int ret;
361d98237b3SChris Mason 	root = btrfs_sb(sb);
362df2ce34cSChris Mason 
363d5719762SChris Mason 	sb->s_dirt = 0;
364d561c025SChris Mason 	if (!wait) {
3657cfcc17eSChris Mason 		filemap_flush(root->fs_info->btree_inode->i_mapping);
366df2ce34cSChris Mason 		return 0;
367d561c025SChris Mason 	}
368e9d0b13bSChris Mason 	btrfs_clean_old_snapshots(root);
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);
530a74a4b97SChris Mason 	mutex_lock(&root->fs_info->transaction_kthread_mutex);
531a74a4b97SChris 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);
537a74a4b97SChris Mason 	mutex_unlock(&root->fs_info->cleaner_mutex);
538a74a4b97SChris 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)
593a74a4b97SChris 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;
609*b3c3da71SChris Mason 
610*b3c3da71SChris Mason 	printk(KERN_INFO "%s loaded\n", BTRFS_BUILD_VERSION);
6112f4cbe64SWyatt Banks 	return 0;
6122f4cbe64SWyatt Banks 
613a9218f6bSChris Mason unregister_ioctl:
614a9218f6bSChris Mason 	btrfs_interface_exit();
6152f4cbe64SWyatt Banks free_extent_map:
6162f4cbe64SWyatt Banks 	extent_map_exit();
617d1310b2eSChris Mason free_extent_io:
618d1310b2eSChris Mason 	extent_io_exit();
6192f4cbe64SWyatt Banks free_cachep:
6202f4cbe64SWyatt Banks 	btrfs_destroy_cachep();
621a74a4b97SChris Mason free_sysfs:
6222f4cbe64SWyatt Banks 	btrfs_exit_sysfs();
6232c90e5d6SChris Mason 	return err;
6242e635a27SChris Mason }
6252e635a27SChris Mason 
6262e635a27SChris Mason static void __exit exit_btrfs_fs(void)
6272e635a27SChris Mason {
62839279cc3SChris Mason 	btrfs_destroy_cachep();
629a52d9a80SChris Mason 	extent_map_exit();
630d1310b2eSChris Mason 	extent_io_exit();
631a9218f6bSChris Mason 	btrfs_interface_exit();
6322e635a27SChris Mason 	unregister_filesystem(&btrfs_fs_type);
63358176a96SJosef Bacik 	btrfs_exit_sysfs();
6348a4b83ccSChris Mason 	btrfs_cleanup_fs_uuids();
6352e635a27SChris Mason }
6362e635a27SChris Mason 
6372e635a27SChris Mason module_init(init_btrfs_fs)
6382e635a27SChris Mason module_exit(exit_btrfs_fs)
6392e635a27SChris Mason 
6402e635a27SChris Mason MODULE_LICENSE("GPL");
641