Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 188212
b: refs/heads/master
c: 73f7341
h: refs/heads/master
v: v3
  • Loading branch information
Josef Bacik authored and Chris Mason committed Mar 15, 2010
1 parent 40c84e4 commit a67cdbd
Show file tree
Hide file tree
Showing 7 changed files with 159 additions and 35 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 12534832cb7b0abc7369298246e8b7af03b863ca
refs/heads/master: 73f73415caddbc01d9f10c03e0a677d5b3d11569
2 changes: 1 addition & 1 deletion trunk/fs/btrfs/ctree.h
Original file line number Diff line number Diff line change
Expand Up @@ -2335,7 +2335,7 @@ int btrfs_init_cachep(void);
void btrfs_destroy_cachep(void);
long btrfs_ioctl_trans_end(struct file *file);
struct inode *btrfs_iget(struct super_block *s, struct btrfs_key *location,
struct btrfs_root *root);
struct btrfs_root *root, int *was_new);
int btrfs_commit_write(struct file *file, struct page *page,
unsigned from, unsigned to);
struct extent_map *btrfs_get_extent(struct inode *inode, struct page *page,
Expand Down
4 changes: 2 additions & 2 deletions trunk/fs/btrfs/export.c
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ static struct dentry *btrfs_get_dentry(struct super_block *sb, u64 objectid,
btrfs_set_key_type(&key, BTRFS_INODE_ITEM_KEY);
key.offset = 0;

inode = btrfs_iget(sb, &key, root);
inode = btrfs_iget(sb, &key, root, NULL);
if (IS_ERR(inode)) {
err = PTR_ERR(inode);
goto fail;
Expand Down Expand Up @@ -223,7 +223,7 @@ static struct dentry *btrfs_get_parent(struct dentry *child)

key.type = BTRFS_INODE_ITEM_KEY;
key.offset = 0;
dentry = d_obtain_alias(btrfs_iget(root->fs_info->sb, &key, root));
dentry = d_obtain_alias(btrfs_iget(root->fs_info->sb, &key, root, NULL));
if (!IS_ERR(dentry))
dentry->d_op = &btrfs_dentry_operations;
return dentry;
Expand Down
10 changes: 6 additions & 4 deletions trunk/fs/btrfs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -2153,7 +2153,7 @@ void btrfs_orphan_cleanup(struct btrfs_root *root)
found_key.objectid = found_key.offset;
found_key.type = BTRFS_INODE_ITEM_KEY;
found_key.offset = 0;
inode = btrfs_iget(root->fs_info->sb, &found_key, root);
inode = btrfs_iget(root->fs_info->sb, &found_key, root, NULL);
if (IS_ERR(inode))
break;

Expand Down Expand Up @@ -3687,7 +3687,7 @@ static struct inode *btrfs_iget_locked(struct super_block *s,
* Returns in *is_new if the inode was read from disk
*/
struct inode *btrfs_iget(struct super_block *s, struct btrfs_key *location,
struct btrfs_root *root)
struct btrfs_root *root, int *new)
{
struct inode *inode;

Expand All @@ -3702,6 +3702,8 @@ struct inode *btrfs_iget(struct super_block *s, struct btrfs_key *location,

inode_tree_add(inode);
unlock_new_inode(inode);
if (new)
*new = 1;
}

return inode;
Expand Down Expand Up @@ -3754,7 +3756,7 @@ struct inode *btrfs_lookup_dentry(struct inode *dir, struct dentry *dentry)
return NULL;

if (location.type == BTRFS_INODE_ITEM_KEY) {
inode = btrfs_iget(dir->i_sb, &location, root);
inode = btrfs_iget(dir->i_sb, &location, root, NULL);
return inode;
}

Expand All @@ -3769,7 +3771,7 @@ struct inode *btrfs_lookup_dentry(struct inode *dir, struct dentry *dentry)
else
inode = new_simple_dir(dir->i_sb, &location, sub_root);
} else {
inode = btrfs_iget(dir->i_sb, &location, sub_root);
inode = btrfs_iget(dir->i_sb, &location, sub_root, NULL);
}
srcu_read_unlock(&root->fs_info->subvol_srcu, index);

Expand Down
2 changes: 1 addition & 1 deletion trunk/fs/btrfs/relocation.c
Original file line number Diff line number Diff line change
Expand Up @@ -3487,7 +3487,7 @@ static struct inode *create_reloc_inode(struct btrfs_fs_info *fs_info,
key.objectid = objectid;
key.type = BTRFS_INODE_ITEM_KEY;
key.offset = 0;
inode = btrfs_iget(root->fs_info->sb, &key, root);
inode = btrfs_iget(root->fs_info->sb, &key, root, NULL);
BUG_ON(IS_ERR(inode) || is_bad_inode(inode));
BTRFS_I(inode)->index_cnt = group->key.objectid;

Expand Down
172 changes: 147 additions & 25 deletions trunk/fs/btrfs/super.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,17 +63,18 @@ static void btrfs_put_super(struct super_block *sb)
}

enum {
Opt_degraded, Opt_subvol, Opt_device, Opt_nodatasum, Opt_nodatacow,
Opt_max_extent, Opt_max_inline, Opt_alloc_start, Opt_nobarrier,
Opt_ssd, Opt_nossd, Opt_ssd_spread, Opt_thread_pool, Opt_noacl,
Opt_compress, Opt_compress_force, Opt_notreelog, Opt_ratio,
Opt_degraded, Opt_subvol, Opt_subvolid, Opt_device, Opt_nodatasum,
Opt_nodatacow, Opt_max_extent, Opt_max_inline, Opt_alloc_start,
Opt_nobarrier, Opt_ssd, Opt_nossd, Opt_ssd_spread, Opt_thread_pool,
Opt_noacl, Opt_compress, Opt_compress_force, Opt_notreelog, Opt_ratio,
Opt_flushoncommit,
Opt_discard, Opt_err,
};

static match_table_t tokens = {
{Opt_degraded, "degraded"},
{Opt_subvol, "subvol=%s"},
{Opt_subvolid, "subvolid=%d"},
{Opt_device, "device=%s"},
{Opt_nodatasum, "nodatasum"},
{Opt_nodatacow, "nodatacow"},
Expand Down Expand Up @@ -157,6 +158,7 @@ int btrfs_parse_options(struct btrfs_root *root, char *options)
btrfs_set_opt(info->mount_opt, DEGRADED);
break;
case Opt_subvol:
case Opt_subvolid:
case Opt_device:
/*
* These are parsed by btrfs_parse_early_options
Expand Down Expand Up @@ -292,12 +294,13 @@ int btrfs_parse_options(struct btrfs_root *root, char *options)
* only when we need to allocate a new super block.
*/
static int btrfs_parse_early_options(const char *options, fmode_t flags,
void *holder, char **subvol_name,
void *holder, char **subvol_name, u64 *subvol_objectid,
struct btrfs_fs_devices **fs_devices)
{
substring_t args[MAX_OPT_ARGS];
char *opts, *p;
int error = 0;
int intarg;

if (!options)
goto out;
Expand All @@ -320,6 +323,12 @@ static int btrfs_parse_early_options(const char *options, fmode_t flags,
case Opt_subvol:
*subvol_name = match_strdup(&args[0]);
break;
case Opt_subvolid:
intarg = 0;
match_int(&args[0], &intarg);
if (intarg)
*subvol_objectid = intarg;
break;
case Opt_device:
error = btrfs_scan_one_device(match_strdup(&args[0]),
flags, holder, fs_devices);
Expand Down Expand Up @@ -347,6 +356,110 @@ static int btrfs_parse_early_options(const char *options, fmode_t flags,
return error;
}

static struct dentry *get_default_root(struct super_block *sb,
u64 subvol_objectid)
{
struct btrfs_root *root = sb->s_fs_info;
struct btrfs_root *new_root;
struct btrfs_dir_item *di;
struct btrfs_path *path;
struct btrfs_key location;
struct inode *inode;
struct dentry *dentry;
u64 dir_id;
int new = 0;

/*
* We have a specific subvol we want to mount, just setup location and
* go look up the root.
*/
if (subvol_objectid) {
location.objectid = subvol_objectid;
location.type = BTRFS_ROOT_ITEM_KEY;
location.offset = (u64)-1;
goto find_root;
}

path = btrfs_alloc_path();
if (!path)
return ERR_PTR(-ENOMEM);
path->leave_spinning = 1;

/*
* Find the "default" dir item which points to the root item that we
* will mount by default if we haven't been given a specific subvolume
* to mount.
*/
dir_id = btrfs_super_root_dir(&root->fs_info->super_copy);
di = btrfs_lookup_dir_item(NULL, root, path, dir_id, "default", 7, 0);
if (!di) {
/*
* Ok the default dir item isn't there. This is weird since
* it's always been there, but don't freak out, just try and
* mount to root most subvolume.
*/
btrfs_free_path(path);
dir_id = BTRFS_FIRST_FREE_OBJECTID;
new_root = root->fs_info->fs_root;
goto setup_root;
}

btrfs_dir_item_key_to_cpu(path->nodes[0], di, &location);
btrfs_free_path(path);

find_root:
new_root = btrfs_read_fs_root_no_name(root->fs_info, &location);
if (IS_ERR(new_root))
return ERR_PTR(PTR_ERR(new_root));

if (btrfs_root_refs(&new_root->root_item) == 0)
return ERR_PTR(-ENOENT);

dir_id = btrfs_root_dirid(&new_root->root_item);
setup_root:
location.objectid = dir_id;
location.type = BTRFS_INODE_ITEM_KEY;
location.offset = 0;

inode = btrfs_iget(sb, &location, new_root, &new);
if (!inode)
return ERR_PTR(-ENOMEM);

/*
* If we're just mounting the root most subvol put the inode and return
* a reference to the dentry. We will have already gotten a reference
* to the inode in btrfs_fill_super so we're good to go.
*/
if (!new && sb->s_root->d_inode == inode) {
iput(inode);
return dget(sb->s_root);
}

if (new) {
const struct qstr name = { .name = "/", .len = 1 };

/*
* New inode, we need to make the dentry a sibling of s_root so
* everything gets cleaned up properly on unmount.
*/
dentry = d_alloc(sb->s_root, &name);
if (!dentry) {
iput(inode);
return ERR_PTR(-ENOMEM);
}
d_splice_alias(inode, dentry);
} else {
/*
* We found the inode in cache, just find a dentry for it and
* put the reference to the inode we just got.
*/
dentry = d_find_alias(inode);
iput(inode);
}

return dentry;
}

static int btrfs_fill_super(struct super_block *sb,
struct btrfs_fs_devices *fs_devices,
void *data, int silent)
Expand Down Expand Up @@ -380,7 +493,7 @@ static int btrfs_fill_super(struct super_block *sb,
key.objectid = BTRFS_FIRST_FREE_OBJECTID;
key.type = BTRFS_INODE_ITEM_KEY;
key.offset = 0;
inode = btrfs_iget(sb, &key, tree_root->fs_info->fs_root);
inode = btrfs_iget(sb, &key, tree_root->fs_info->fs_root, NULL);
if (IS_ERR(inode)) {
err = PTR_ERR(inode);
goto fail_close;
Expand All @@ -392,12 +505,6 @@ static int btrfs_fill_super(struct super_block *sb,
err = -ENOMEM;
goto fail_close;
}
#if 0
/* this does the super kobj at the same time */
err = btrfs_sysfs_add_super(tree_root->fs_info);
if (err)
goto fail_close;
#endif

sb->s_root = root_dentry;

Expand Down Expand Up @@ -489,19 +596,22 @@ static int btrfs_test_super(struct super_block *s, void *data)
static int btrfs_get_sb(struct file_system_type *fs_type, int flags,
const char *dev_name, void *data, struct vfsmount *mnt)
{
char *subvol_name = NULL;
struct block_device *bdev = NULL;
struct super_block *s;
struct dentry *root;
struct btrfs_fs_devices *fs_devices = NULL;
fmode_t mode = FMODE_READ;
char *subvol_name = NULL;
u64 subvol_objectid = 0;
int error = 0;
int found = 0;

if (!(flags & MS_RDONLY))
mode |= FMODE_WRITE;

error = btrfs_parse_early_options(data, mode, fs_type,
&subvol_name, &fs_devices);
&subvol_name, &subvol_objectid,
&fs_devices);
if (error)
return error;

Expand Down Expand Up @@ -530,6 +640,7 @@ static int btrfs_get_sb(struct file_system_type *fs_type, int flags,
goto error_close_devices;
}

found = 1;
btrfs_close_devices(fs_devices);
} else {
char b[BDEVNAME_SIZE];
Expand All @@ -547,25 +658,35 @@ static int btrfs_get_sb(struct file_system_type *fs_type, int flags,
s->s_flags |= MS_ACTIVE;
}

if (!strcmp(subvol_name, "."))
root = dget(s->s_root);
else {
mutex_lock(&s->s_root->d_inode->i_mutex);
root = lookup_one_len(subvol_name, s->s_root,
root = get_default_root(s, subvol_objectid);
if (IS_ERR(root)) {
error = PTR_ERR(root);
deactivate_locked_super(s);
goto error;
}
/* if they gave us a subvolume name bind mount into that */
if (strcmp(subvol_name, ".")) {
struct dentry *new_root;
mutex_lock(&root->d_inode->i_mutex);
new_root = lookup_one_len(subvol_name, root,
strlen(subvol_name));
mutex_unlock(&s->s_root->d_inode->i_mutex);
mutex_unlock(&root->d_inode->i_mutex);

if (IS_ERR(root)) {
if (IS_ERR(new_root)) {
deactivate_locked_super(s);
error = PTR_ERR(root);
goto error_free_subvol_name;
error = PTR_ERR(new_root);
dput(root);
goto error_close_devices;
}
if (!root->d_inode) {
if (!new_root->d_inode) {
dput(root);
dput(new_root);
deactivate_locked_super(s);
error = -ENXIO;
goto error_free_subvol_name;
goto error_close_devices;
}
dput(root);
root = new_root;
}

mnt->mnt_sb = s;
Expand All @@ -580,6 +701,7 @@ static int btrfs_get_sb(struct file_system_type *fs_type, int flags,
btrfs_close_devices(fs_devices);
error_free_subvol_name:
kfree(subvol_name);
error:
return error;
}

Expand Down
2 changes: 1 addition & 1 deletion trunk/fs/btrfs/tree-log.c
Original file line number Diff line number Diff line change
Expand Up @@ -445,7 +445,7 @@ static noinline struct inode *read_one_inode(struct btrfs_root *root,
key.objectid = objectid;
key.type = BTRFS_INODE_ITEM_KEY;
key.offset = 0;
inode = btrfs_iget(root->fs_info->sb, &key, root);
inode = btrfs_iget(root->fs_info->sb, &key, root, NULL);
if (IS_ERR(inode)) {
inode = NULL;
} else if (is_bad_inode(inode)) {
Expand Down

0 comments on commit a67cdbd

Please sign in to comment.