diff options
| author | Jiri Kosina <jkosina@suse.cz> | 2010-12-22 18:57:02 +0100 | 
|---|---|---|
| committer | Jiri Kosina <jkosina@suse.cz> | 2010-12-22 18:57:02 +0100 | 
| commit | 4b7bd364700d9ac8372eff48832062b936d0793b (patch) | |
| tree | 0dbf78c95456a0b02d07fcd473281f04a87e266d /fs/btrfs/super.c | |
| parent | c0d8768af260e2cbb4bf659ae6094a262c86b085 (diff) | |
| parent | 90a8a73c06cc32b609a880d48449d7083327e11a (diff) | |
| download | olio-linux-3.10-4b7bd364700d9ac8372eff48832062b936d0793b.tar.xz olio-linux-3.10-4b7bd364700d9ac8372eff48832062b936d0793b.zip  | |
Merge branch 'master' into for-next
Conflicts:
	MAINTAINERS
	arch/arm/mach-omap2/pm24xx.c
	drivers/scsi/bfa/bfa_fcpim.c
Needed to update to apply fixes for which the old branch was too
outdated.
Diffstat (limited to 'fs/btrfs/super.c')
| -rw-r--r-- | fs/btrfs/super.c | 43 | 
1 files changed, 39 insertions, 4 deletions
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 8299a25ffc8..883c6fa1367 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c @@ -244,6 +244,7 @@ int btrfs_parse_options(struct btrfs_root *root, char *options)  		case Opt_space_cache:  			printk(KERN_INFO "btrfs: enabling disk space caching\n");  			btrfs_set_opt(info->mount_opt, SPACE_CACHE); +			break;  		case Opt_clear_cache:  			printk(KERN_INFO "btrfs: force clearing of disk cache\n");  			btrfs_set_opt(info->mount_opt, CLEAR_CACHE); @@ -562,12 +563,26 @@ static int btrfs_show_options(struct seq_file *seq, struct vfsmount *vfs)  static int btrfs_test_super(struct super_block *s, void *data)  { -	struct btrfs_fs_devices *test_fs_devices = data; +	struct btrfs_root *test_root = data;  	struct btrfs_root *root = btrfs_sb(s); -	return root->fs_info->fs_devices == test_fs_devices; +	/* +	 * If this super block is going away, return false as it +	 * can't match as an existing super block. +	 */ +	if (!atomic_read(&s->s_active)) +		return 0; +	return root->fs_info->fs_devices == test_root->fs_info->fs_devices; +} + +static int btrfs_set_super(struct super_block *s, void *data) +{ +	s->s_fs_info = data; + +	return set_anon_super(s, data);  } +  /*   * Find a superblock for the given device / mount point.   * @@ -581,6 +596,8 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags,  	struct super_block *s;  	struct dentry *root;  	struct btrfs_fs_devices *fs_devices = NULL; +	struct btrfs_root *tree_root = NULL; +	struct btrfs_fs_info *fs_info = NULL;  	fmode_t mode = FMODE_READ;  	char *subvol_name = NULL;  	u64 subvol_objectid = 0; @@ -608,8 +625,24 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags,  		goto error_close_devices;  	} +	/* +	 * Setup a dummy root and fs_info for test/set super.  This is because +	 * we don't actually fill this stuff out until open_ctree, but we need +	 * it for searching for existing supers, so this lets us do that and +	 * then open_ctree will properly initialize everything later. +	 */ +	fs_info = kzalloc(sizeof(struct btrfs_fs_info), GFP_NOFS); +	tree_root = kzalloc(sizeof(struct btrfs_root), GFP_NOFS); +	if (!fs_info || !tree_root) { +		error = -ENOMEM; +		goto error_close_devices; +	} +	fs_info->tree_root = tree_root; +	fs_info->fs_devices = fs_devices; +	tree_root->fs_info = fs_info; +  	bdev = fs_devices->latest_bdev; -	s = sget(fs_type, btrfs_test_super, set_anon_super, fs_devices); +	s = sget(fs_type, btrfs_test_super, btrfs_set_super, tree_root);  	if (IS_ERR(s))  		goto error_s; @@ -652,9 +685,9 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags,  		mutex_unlock(&root->d_inode->i_mutex);  		if (IS_ERR(new_root)) { +			dput(root);  			deactivate_locked_super(s);  			error = PTR_ERR(new_root); -			dput(root);  			goto error_free_subvol_name;  		}  		if (!new_root->d_inode) { @@ -675,6 +708,8 @@ error_s:  	error = PTR_ERR(s);  error_close_devices:  	btrfs_close_devices(fs_devices); +	kfree(fs_info); +	kfree(tree_root);  error_free_subvol_name:  	kfree(subvol_name);  	return ERR_PTR(error);  |