aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/btrfs/ctree.h6
-rw-r--r--fs/btrfs/super.c49
2 files changed, 45 insertions, 10 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index ffeee546a0d7..cd75c906048f 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -1064,6 +1064,12 @@ static inline int btrfs_set_root_name(struct btrfs_root *root,
1064 ((type *)(btrfs_leaf_data(leaf) + \ 1064 ((type *)(btrfs_leaf_data(leaf) + \
1065 btrfs_item_offset((leaf)->items + (slot)))) 1065 btrfs_item_offset((leaf)->items + (slot))))
1066 1066
1067/* mount option defines and helpers */
1068#define BTRFS_MOUNT_SUBVOL 0x000001
1069#define btrfs_clear_opt(o, opt) o &= ~BTRFS_MOUNT_##opt
1070#define btrfs_set_opt(o, opt) o |= BTRFS_MOUNT_##opt
1071#define btrfs_test_opt(sb, opt) (BTRFS_SB(sb)->s_mount_opt & \
1072 BTRFS_MOUNT_##opt)
1067/* extent-tree.c */ 1073/* extent-tree.c */
1068int btrfs_extent_post_op(struct btrfs_trans_handle *trans, 1074int btrfs_extent_post_op(struct btrfs_trans_handle *trans,
1069 struct btrfs_root *root); 1075 struct btrfs_root *root);
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
index 8a94be1a773b..66a01cbbbea1 100644
--- a/fs/btrfs/super.c
+++ b/fs/btrfs/super.c
@@ -33,6 +33,7 @@
33#include <linux/writeback.h> 33#include <linux/writeback.h>
34#include <linux/statfs.h> 34#include <linux/statfs.h>
35#include <linux/compat.h> 35#include <linux/compat.h>
36#include <linux/parser.h>
36#include "ctree.h" 37#include "ctree.h"
37#include "disk-io.h" 38#include "disk-io.h"
38#include "transaction.h" 39#include "transaction.h"
@@ -58,6 +59,41 @@ static void btrfs_put_super (struct super_block * sb)
58 sb->s_fs_info = NULL; 59 sb->s_fs_info = NULL;
59} 60}
60 61
62enum {
63 Opt_subvol, Opt_err,
64};
65
66static match_table_t tokens = {
67 {Opt_subvol, "subvol=%s"},
68 {Opt_err, NULL}
69};
70
71static int parse_options (char * options,
72 struct btrfs_root *root,
73 char **subvol_name)
74{
75 char * p;
76 substring_t args[MAX_OPT_ARGS];
77 if (!options)
78 return 1;
79
80 while ((p = strsep (&options, ",")) != NULL) {
81 int token;
82 if (!*p)
83 continue;
84
85 token = match_token(p, tokens, args);
86 switch (token) {
87 case Opt_subvol:
88 *subvol_name = match_strdup(&args[0]);
89 break;
90 default:
91 return 0;
92 }
93 }
94 return 1;
95}
96
61static int btrfs_fill_super(struct super_block * sb, void * data, int silent) 97static int btrfs_fill_super(struct super_block * sb, void * data, int silent)
62{ 98{
63 struct inode * inode; 99 struct inode * inode;
@@ -250,22 +286,15 @@ error:
250/* end copy & paste */ 286/* end copy & paste */
251 287
252static int btrfs_get_sb(struct file_system_type *fs_type, 288static int btrfs_get_sb(struct file_system_type *fs_type,
253 int flags, const char *identifier, void *data, struct vfsmount *mnt) 289 int flags, const char *dev_name, void *data, struct vfsmount *mnt)
254{ 290{
255 int ret; 291 int ret;
256 char *_identifier = kstrdup(identifier, GFP_KERNEL); 292 char *subvol_name = NULL;
257 char *subvol_name;
258 const char *dev_name;
259
260 subvol_name = _identifier;
261 dev_name = strsep(&subvol_name, ":");
262 if (!dev_name)
263 return -ENOMEM;
264 293
294 parse_options((char *)data, NULL, &subvol_name);
265 ret = btrfs_get_sb_bdev(fs_type, flags, dev_name, data, 295 ret = btrfs_get_sb_bdev(fs_type, flags, dev_name, data,
266 btrfs_fill_super, mnt, 296 btrfs_fill_super, mnt,
267 subvol_name ? subvol_name : "default"); 297 subvol_name ? subvol_name : "default");
268 kfree(_identifier);
269 return ret; 298 return ret;
270} 299}
271 300