super.c 12.6 KB
Newer Older
C
Chris Mason 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
/*
 * Copyright (C) 2007 Oracle.  All rights reserved.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public
 * License v2 as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public
 * License along with this program; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 021110-1307, USA.
 */

Y
Yan 已提交
19
#include <linux/blkdev.h>
20
#include <linux/module.h>
C
Chris Mason 已提交
21
#include <linux/buffer_head.h>
22 23 24 25 26 27 28 29
#include <linux/fs.h>
#include <linux/pagemap.h>
#include <linux/highmem.h>
#include <linux/time.h>
#include <linux/init.h>
#include <linux/string.h>
#include <linux/smp_lock.h>
#include <linux/backing-dev.h>
Y
Yan 已提交
30
#include <linux/mount.h>
C
Chris Mason 已提交
31
#include <linux/mpage.h>
C
Chris Mason 已提交
32 33
#include <linux/swap.h>
#include <linux/writeback.h>
C
Chris Mason 已提交
34
#include <linux/statfs.h>
C
Chris Mason 已提交
35
#include <linux/compat.h>
36
#include <linux/parser.h>
37
#include <linux/ctype.h>
38
#include <linux/namei.h>
39
#include <linux/miscdevice.h>
40
#include "ctree.h"
C
Chris Mason 已提交
41
#include "disk-io.h"
42
#include "transaction.h"
C
Chris Mason 已提交
43
#include "btrfs_inode.h"
C
Chris Mason 已提交
44
#include "ioctl.h"
C
Chris Mason 已提交
45
#include "print-tree.h"
J
Josef Bacik 已提交
46
#include "xattr.h"
47

48
#define BTRFS_SUPER_MAGIC 0x9123683E
C
Chris Mason 已提交
49

C
Chris Mason 已提交
50
static struct super_operations btrfs_super_ops;
C
Chris Mason 已提交
51

C
Chris Mason 已提交
52
static void btrfs_put_super (struct super_block * sb)
C
Chris Mason 已提交
53
{
C
Chris Mason 已提交
54
	struct btrfs_root *root = btrfs_sb(sb);
55
	struct btrfs_fs_info *fs = root->fs_info;
C
Chris Mason 已提交
56 57
	int ret;

C
Chris Mason 已提交
58 59 60
	ret = close_ctree(root);
	if (ret) {
		printk("close ctree returns %d\n", ret);
C
Chris Mason 已提交
61
	}
62
	btrfs_sysfs_del_super(fs);
C
Chris Mason 已提交
63
	sb->s_fs_info = NULL;
C
Chris Mason 已提交
64 65
}

66
enum {
67
	Opt_subvol, Opt_nodatasum, Opt_nodatacow, Opt_max_extent,
68
	Opt_max_inline, Opt_alloc_start, Opt_nobarrier, Opt_ssd, Opt_err,
69 70 71 72
};

static match_table_t tokens = {
	{Opt_subvol, "subvol=%s"},
73
	{Opt_nodatasum, "nodatasum"},
74
	{Opt_nodatacow, "nodatacow"},
75
	{Opt_nobarrier, "nobarrier"},
76
	{Opt_max_extent, "max_extent=%s"},
77
	{Opt_max_inline, "max_inline=%s"},
78
	{Opt_alloc_start, "alloc_start=%s"},
79
	{Opt_ssd, "ssd"},
80 81 82
	{Opt_err, NULL}
};

83
u64 btrfs_parse_size(char *str)
84
{
85
	u64 res;
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
	int mult = 1;
	char *end;
	char last;

	res = simple_strtoul(str, &end, 10);

	last = end[0];
	if (isalpha(last)) {
		last = tolower(last);
		switch (last) {
		case 'g':
			mult *= 1024;
		case 'm':
			mult *= 1024;
		case 'k':
			mult *= 1024;
		}
		res = res * mult;
	}
	return res;
}

108 109 110 111 112
static int parse_options (char * options,
			  struct btrfs_root *root,
			  char **subvol_name)
{
	char * p;
113
	struct btrfs_fs_info *info = NULL;
114
	substring_t args[MAX_OPT_ARGS];
115

116 117 118
	if (!options)
		return 1;

119 120 121 122 123 124 125 126 127 128 129
	/*
	 * strsep changes the string, duplicate it because parse_options
	 * gets called twice
	 */
	options = kstrdup(options, GFP_NOFS);
	if (!options)
		return -ENOMEM;

	if (root)
		info = root->fs_info;

130 131 132 133 134 135 136 137
	while ((p = strsep (&options, ",")) != NULL) {
		int token;
		if (!*p)
			continue;

		token = match_token(p, tokens, args);
		switch (token) {
		case Opt_subvol:
138
			if (subvol_name) {
139
				*subvol_name = match_strdup(&args[0]);
140
			}
141 142
			break;
		case Opt_nodatasum:
143 144
			if (info) {
				printk("btrfs: setting nodatacsum\n");
145
				btrfs_set_opt(info->mount_opt, NODATASUM);
146 147 148 149 150 151 152 153
			}
			break;
		case Opt_nodatacow:
			if (info) {
				printk("btrfs: setting nodatacow\n");
				btrfs_set_opt(info->mount_opt, NODATACOW);
				btrfs_set_opt(info->mount_opt, NODATASUM);
			}
154
			break;
155 156 157 158 159 160
		case Opt_ssd:
			if (info) {
				printk("btrfs: use ssd allocation scheme\n");
				btrfs_set_opt(info->mount_opt, SSD);
			}
			break;
161 162 163 164 165 166
		case Opt_nobarrier:
			if (info) {
				printk("btrfs: turning off barriers\n");
				btrfs_set_opt(info->mount_opt, NOBARRIER);
			}
			break;
167 168 169 170
		case Opt_max_extent:
			if (info) {
				char *num = match_strdup(&args[0]);
				if (num) {
171 172
					info->max_extent =
						btrfs_parse_size(num);
173 174 175 176 177 178 179 180 181 182
					kfree(num);

					info->max_extent = max_t(u64,
							 info->max_extent,
							 root->sectorsize);
					printk("btrfs: max_extent at %Lu\n",
					       info->max_extent);
				}
			}
			break;
183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198
		case Opt_max_inline:
			if (info) {
				char *num = match_strdup(&args[0]);
				if (num) {
					info->max_inline =
						btrfs_parse_size(num);
					kfree(num);

					info->max_inline = max_t(u64,
							 info->max_inline,
							 root->sectorsize);
					printk("btrfs: max_inline at %Lu\n",
					       info->max_inline);
				}
			}
			break;
199 200 201 202 203 204 205 206 207 208 209 210
		case Opt_alloc_start:
			if (info) {
				char *num = match_strdup(&args[0]);
				if (num) {
					info->alloc_start =
						btrfs_parse_size(num);
					kfree(num);
					printk("btrfs: allocations start at "
					       "%Lu\n", info->alloc_start);
				}
			}
			break;
211
		default:
212
			break;
213 214
		}
	}
215
	kfree(options);
216 217 218
	return 1;
}

C
Chris Mason 已提交
219
static int btrfs_fill_super(struct super_block * sb, void * data, int silent)
C
Chris Mason 已提交
220
{
C
Chris Mason 已提交
221 222 223 224 225 226
	struct inode * inode;
	struct dentry * root_dentry;
	struct btrfs_super_block *disk_super;
	struct btrfs_root *tree_root;
	struct btrfs_inode *bi;
	int err;
227

C
Chris Mason 已提交
228 229 230
	sb->s_maxbytes = MAX_LFS_FILESIZE;
	sb->s_magic = BTRFS_SUPER_MAGIC;
	sb->s_op = &btrfs_super_ops;
J
Josef Bacik 已提交
231
	sb->s_xattr = btrfs_xattr_handlers;
C
Chris Mason 已提交
232
	sb->s_time_gran = 1;
233

C
Chris Mason 已提交
234
	tree_root = open_ctree(sb);
235

C
Chris Mason 已提交
236 237 238
	if (!tree_root || IS_ERR(tree_root)) {
		printk("btrfs: open_ctree failed\n");
		return -EIO;
239
	}
C
Chris Mason 已提交
240
	sb->s_fs_info = tree_root;
241
	disk_super = &tree_root->fs_info->super_copy;
C
Chris Mason 已提交
242 243 244 245 246 247
	inode = btrfs_iget_locked(sb, btrfs_super_root_dir(disk_super),
				  tree_root);
	bi = BTRFS_I(inode);
	bi->location.objectid = inode->i_ino;
	bi->location.offset = 0;
	bi->root = tree_root;
248

C
Chris Mason 已提交
249
	btrfs_set_key_type(&bi->location, BTRFS_INODE_ITEM_KEY);
250

C
Chris Mason 已提交
251
	if (!inode) {
252
		err = -ENOMEM;
C
Chris Mason 已提交
253
		goto fail_close;
C
Chris Mason 已提交
254
	}
C
Chris Mason 已提交
255 256 257
	if (inode->i_state & I_NEW) {
		btrfs_read_locked_inode(inode);
		unlock_new_inode(inode);
C
Chris Mason 已提交
258 259
	}

C
Chris Mason 已提交
260 261 262 263 264
	root_dentry = d_alloc_root(inode);
	if (!root_dentry) {
		iput(inode);
		err = -ENOMEM;
		goto fail_close;
C
Chris Mason 已提交
265
	}
266

267 268
	parse_options((char *)data, tree_root, NULL);

269 270 271 272 273
	/* this does the super kobj at the same time */
	err = btrfs_sysfs_add_super(tree_root->fs_info);
	if (err)
		goto fail_close;

C
Chris Mason 已提交
274 275
	sb->s_root = root_dentry;
	btrfs_transaction_queue_work(tree_root, HZ * 30);
C
Chris Mason 已提交
276 277 278 279 280

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25)
	save_mount_options(sb, data);
#endif

C
Chris Mason 已提交
281
	return 0;
C
Chris Mason 已提交
282 283 284 285

fail_close:
	close_ctree(tree_root);
	return err;
C
Chris Mason 已提交
286 287
}

C
Chris Mason 已提交
288
static int btrfs_sync_fs(struct super_block *sb, int wait)
C
Chris Mason 已提交
289 290
{
	struct btrfs_trans_handle *trans;
C
Chris Mason 已提交
291
	struct btrfs_root *root;
C
Chris Mason 已提交
292
	int ret;
C
Chris Mason 已提交
293
	root = btrfs_sb(sb);
C
Chris Mason 已提交
294

C
Chris Mason 已提交
295 296 297 298 299
	sb->s_dirt = 0;
	if (!wait) {
		filemap_flush(root->fs_info->btree_inode->i_mapping);
		return 0;
	}
300
	btrfs_clean_old_snapshots(root);
C
Chris Mason 已提交
301
	mutex_lock(&root->fs_info->fs_mutex);
302
	btrfs_defrag_dirty_roots(root->fs_info);
C
Chris Mason 已提交
303 304
	trans = btrfs_start_transaction(root, 1);
	ret = btrfs_commit_transaction(trans, root);
C
Chris Mason 已提交
305
	sb->s_dirt = 0;
C
Chris Mason 已提交
306
	mutex_unlock(&root->fs_info->fs_mutex);
307
	return ret;
C
Chris Mason 已提交
308 309
}

C
Chris Mason 已提交
310
static void btrfs_write_super(struct super_block *sb)
C
Chris Mason 已提交
311
{
C
Chris Mason 已提交
312
	sb->s_dirt = 0;
C
Chris Mason 已提交
313 314
}

Y
Yan 已提交
315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416
/*
 * This is almost a copy of get_sb_bdev in fs/super.c.
 * We need the local copy to allow direct mounting of
 * subvolumes, but this could be easily integrated back
 * into the generic version.  --hch
 */

/* start copy & paste */
static int set_bdev_super(struct super_block *s, void *data)
{
	s->s_bdev = data;
	s->s_dev = s->s_bdev->bd_dev;
	return 0;
}

static int test_bdev_super(struct super_block *s, void *data)
{
	return (void *)s->s_bdev == data;
}

int btrfs_get_sb_bdev(struct file_system_type *fs_type,
	int flags, const char *dev_name, void *data,
	int (*fill_super)(struct super_block *, void *, int),
	struct vfsmount *mnt, const char *subvol)
{
	struct block_device *bdev = NULL;
	struct super_block *s;
	struct dentry *root;
	int error = 0;

	bdev = open_bdev_excl(dev_name, flags, fs_type);
	if (IS_ERR(bdev))
		return PTR_ERR(bdev);

	/*
	 * once the super is inserted into the list by sget, s_umount
	 * will protect the lockfs code from trying to start a snapshot
	 * while we are mounting
	 */
	down(&bdev->bd_mount_sem);
	s = sget(fs_type, test_bdev_super, set_bdev_super, bdev);
	up(&bdev->bd_mount_sem);
	if (IS_ERR(s))
		goto error_s;

	if (s->s_root) {
		if ((flags ^ s->s_flags) & MS_RDONLY) {
			up_write(&s->s_umount);
			deactivate_super(s);
			error = -EBUSY;
			goto error_bdev;
		}

		close_bdev_excl(bdev);
	} else {
		char b[BDEVNAME_SIZE];

		s->s_flags = flags;
		strlcpy(s->s_id, bdevname(bdev, b), sizeof(s->s_id));
		sb_set_blocksize(s, block_size(bdev));
		error = fill_super(s, data, flags & MS_SILENT ? 1 : 0);
		if (error) {
			up_write(&s->s_umount);
			deactivate_super(s);
			goto error;
		}

		s->s_flags |= MS_ACTIVE;
	}

	if (subvol) {
		root = lookup_one_len(subvol, s->s_root, strlen(subvol));
		if (IS_ERR(root)) {
			up_write(&s->s_umount);
			deactivate_super(s);
			error = PTR_ERR(root);
			goto error;
		}
		if (!root->d_inode) {
			dput(root);
			up_write(&s->s_umount);
			deactivate_super(s);
			error = -ENXIO;
			goto error;
		}
	} else {
		root = dget(s->s_root);
	}

	mnt->mnt_sb = s;
	mnt->mnt_root = root;
	return 0;

error_s:
	error = PTR_ERR(s);
error_bdev:
	close_bdev_excl(bdev);
error:
	return error;
}
/* end copy & paste */

417
static int btrfs_get_sb(struct file_system_type *fs_type,
418
	int flags, const char *dev_name, void *data, struct vfsmount *mnt)
419
{
Y
Yan 已提交
420
	int ret;
421
	char *subvol_name = NULL;
Y
Yan 已提交
422

423
	parse_options((char *)data, NULL, &subvol_name);
Y
Yan 已提交
424 425 426
	ret = btrfs_get_sb_bdev(fs_type, flags, dev_name, data,
			btrfs_fill_super, mnt,
			subvol_name ? subvol_name : "default");
427 428
	if (subvol_name)
		kfree(subvol_name);
Y
Yan 已提交
429
	return ret;
430 431
}

C
Chris Mason 已提交
432 433 434
static int btrfs_statfs(struct dentry *dentry, struct kstatfs *buf)
{
	struct btrfs_root *root = btrfs_sb(dentry->d_sb);
435
	struct btrfs_super_block *disk_super = &root->fs_info->super_copy;
436
	int bits = dentry->d_sb->s_blocksize_bits;
C
Chris Mason 已提交
437 438

	buf->f_namelen = BTRFS_NAME_LEN;
439 440 441
	buf->f_blocks = btrfs_super_total_bytes(disk_super) >> bits;
	buf->f_bfree = buf->f_blocks -
		(btrfs_super_bytes_used(disk_super) >> bits);
C
Chris Mason 已提交
442 443 444 445 446
	buf->f_bavail = buf->f_bfree;
	buf->f_bsize = dentry->d_sb->s_blocksize;
	buf->f_type = BTRFS_SUPER_MAGIC;
	return 0;
}
C
Chris Mason 已提交
447

448 449 450 451 452 453 454
static long btrfs_control_ioctl(struct file *file, unsigned int cmd,
				unsigned long arg)
{
	printk("btrfs control ioctl %d\n", cmd);
	return 0;
}

455 456 457 458 459 460 461
static struct file_system_type btrfs_fs_type = {
	.owner		= THIS_MODULE,
	.name		= "btrfs",
	.get_sb		= btrfs_get_sb,
	.kill_sb	= kill_block_super,
	.fs_flags	= FS_REQUIRES_DEV,
};
462

Y
Yan 已提交
463 464 465 466 467 468 469 470 471 472 473
static void btrfs_write_super_lockfs(struct super_block *sb)
{
	struct btrfs_root *root = btrfs_sb(sb);
	btrfs_transaction_flush_work(root);
}

static void btrfs_unlockfs(struct super_block *sb)
{
	struct btrfs_root *root = btrfs_sb(sb);
	btrfs_transaction_queue_work(root, HZ * 30);
}
474

C
Chris Mason 已提交
475
static struct super_operations btrfs_super_ops = {
C
Chris Mason 已提交
476
	.delete_inode	= btrfs_delete_inode,
477
	.put_inode	= btrfs_put_inode,
C
Chris Mason 已提交
478
	.put_super	= btrfs_put_super,
479 480
	.write_super	= btrfs_write_super,
	.sync_fs	= btrfs_sync_fs,
C
Chris Mason 已提交
481 482 483 484 485
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25)
	.read_inode     = btrfs_read_locked_inode,
#else
	.show_options	= generic_show_options,
#endif
C
Chris Mason 已提交
486
	.write_inode	= btrfs_write_inode,
C
Chris Mason 已提交
487
	.dirty_inode	= btrfs_dirty_inode,
C
Chris Mason 已提交
488 489
	.alloc_inode	= btrfs_alloc_inode,
	.destroy_inode	= btrfs_destroy_inode,
C
Chris Mason 已提交
490
	.statfs		= btrfs_statfs,
Y
Yan 已提交
491 492
	.write_super_lockfs = btrfs_write_super_lockfs,
	.unlockfs	= btrfs_unlockfs,
C
Chris Mason 已提交
493
};
494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517

static const struct file_operations btrfs_ctl_fops = {
	.unlocked_ioctl	 = btrfs_control_ioctl,
	.compat_ioctl = btrfs_control_ioctl,
	.owner	 = THIS_MODULE,
};

static struct miscdevice btrfs_misc = {
	.minor		= MISC_DYNAMIC_MINOR,
	.name		= "btrfs-control",
	.fops		= &btrfs_ctl_fops
};

static int btrfs_interface_init(void)
{
	return misc_register(&btrfs_misc);
}

void btrfs_interface_exit(void)
{
	if (misc_deregister(&btrfs_misc) < 0)
		printk("misc_deregister failed for control device");
}

518 519
static int __init init_btrfs_fs(void)
{
C
Chris Mason 已提交
520
	int err;
521 522 523 524 525

	err = btrfs_init_sysfs();
	if (err)
		return err;

C
Chris Mason 已提交
526
	btrfs_init_transaction_sys();
C
Chris Mason 已提交
527
	err = btrfs_init_cachep();
C
Chris Mason 已提交
528
	if (err)
529
		goto free_transaction_sys;
530 531

	err = extent_io_init();
532 533 534
	if (err)
		goto free_cachep;

535 536 537 538
	err = extent_map_init();
	if (err)
		goto free_extent_io;

539
	err = btrfs_interface_init();
540 541
	if (err)
		goto free_extent_map;
542 543 544
	err = register_filesystem(&btrfs_fs_type);
	if (err)
		goto unregister_ioctl;
545 546
	return 0;

547 548
unregister_ioctl:
	btrfs_interface_exit();
549 550
free_extent_map:
	extent_map_exit();
551 552
free_extent_io:
	extent_io_exit();
553 554 555 556 557 558
free_cachep:
	btrfs_destroy_cachep();
free_transaction_sys:
	btrfs_exit_transaction_sys();
	btrfs_exit_sysfs();
	return err;
559 560 561 562
}

static void __exit exit_btrfs_fs(void)
{
C
Chris Mason 已提交
563
	btrfs_exit_transaction_sys();
C
Chris Mason 已提交
564
	btrfs_destroy_cachep();
565
	extent_map_exit();
566
	extent_io_exit();
567
	btrfs_interface_exit();
568
	unregister_filesystem(&btrfs_fs_type);
569
	btrfs_exit_sysfs();
570 571 572 573 574 575
}

module_init(init_btrfs_fs)
module_exit(exit_btrfs_fs)

MODULE_LICENSE("GPL");