diff options
author | Chris Mason <chris.mason@oracle.com> | 2007-12-17 20:14:04 -0500 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2008-09-25 11:03:58 -0400 |
commit | c59f8951d48c5eb000926935f3ab063d8181d1ee (patch) | |
tree | ddf1e3ecb8a03fc30add98ee263c23eb6d382621 /fs | |
parent | d10c5f31c79c6a703974ae29d0a05781b828fe30 (diff) |
Btrfs: Add mount option to enforce a max extent size
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/btrfs/ctree.h | 1 | ||||
-rw-r--r-- | fs/btrfs/disk-io.c | 1 | ||||
-rw-r--r-- | fs/btrfs/inode.c | 28 | ||||
-rw-r--r-- | fs/btrfs/super.c | 46 |
4 files changed, 65 insertions, 11 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index b51b021fff85..32b24460ec82 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
@@ -322,6 +322,7 @@ struct btrfs_fs_info { | |||
322 | u64 generation; | 322 | u64 generation; |
323 | u64 last_trans_committed; | 323 | u64 last_trans_committed; |
324 | unsigned long mount_opt; | 324 | unsigned long mount_opt; |
325 | u64 max_extent; | ||
325 | struct btrfs_transaction *running_transaction; | 326 | struct btrfs_transaction *running_transaction; |
326 | struct btrfs_super_block super_copy; | 327 | struct btrfs_super_block super_copy; |
327 | struct extent_buffer *sb_buffer; | 328 | struct extent_buffer *sb_buffer; |
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 278564178993..7213012c27d5 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -569,6 +569,7 @@ struct btrfs_root *open_ctree(struct super_block *sb) | |||
569 | fs_info->extent_root = extent_root; | 569 | fs_info->extent_root = extent_root; |
570 | fs_info->sb = sb; | 570 | fs_info->sb = sb; |
571 | fs_info->mount_opt = 0; | 571 | fs_info->mount_opt = 0; |
572 | fs_info->max_extent = (u64)-1; | ||
572 | fs_info->btree_inode = new_inode(sb); | 573 | fs_info->btree_inode = new_inode(sb); |
573 | fs_info->btree_inode->i_ino = 1; | 574 | fs_info->btree_inode->i_ino = 1; |
574 | fs_info->btree_inode->i_nlink = 1; | 575 | fs_info->btree_inode->i_nlink = 1; |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 91f3fc43e2a9..686dd03f34f2 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -78,6 +78,7 @@ static int cow_file_range(struct inode *inode, u64 start, u64 end) | |||
78 | struct btrfs_trans_handle *trans; | 78 | struct btrfs_trans_handle *trans; |
79 | u64 alloc_hint = 0; | 79 | u64 alloc_hint = 0; |
80 | u64 num_bytes; | 80 | u64 num_bytes; |
81 | u64 cur_alloc_size; | ||
81 | u64 blocksize = root->sectorsize; | 82 | u64 blocksize = root->sectorsize; |
82 | struct btrfs_key ins; | 83 | struct btrfs_key ins; |
83 | int ret; | 84 | int ret; |
@@ -94,17 +95,24 @@ static int cow_file_range(struct inode *inode, u64 start, u64 end) | |||
94 | if (alloc_hint == EXTENT_MAP_INLINE) | 95 | if (alloc_hint == EXTENT_MAP_INLINE) |
95 | goto out; | 96 | goto out; |
96 | 97 | ||
97 | ret = btrfs_alloc_extent(trans, root, num_bytes, | 98 | while(num_bytes > 0) { |
98 | root->root_key.objectid, trans->transid, | 99 | cur_alloc_size = min(num_bytes, root->fs_info->max_extent); |
99 | inode->i_ino, start, 0, | 100 | ret = btrfs_alloc_extent(trans, root, cur_alloc_size, |
100 | alloc_hint, (u64)-1, &ins, 1); | 101 | root->root_key.objectid, |
101 | if (ret) { | 102 | trans->transid, |
102 | WARN_ON(1); | 103 | inode->i_ino, start, 0, |
103 | goto out; | 104 | alloc_hint, (u64)-1, &ins, 1); |
105 | if (ret) { | ||
106 | WARN_ON(1); | ||
107 | goto out; | ||
108 | } | ||
109 | ret = btrfs_insert_file_extent(trans, root, inode->i_ino, | ||
110 | start, ins.objectid, ins.offset, | ||
111 | ins.offset); | ||
112 | num_bytes -= cur_alloc_size; | ||
113 | alloc_hint = ins.objectid + ins.offset; | ||
114 | start += cur_alloc_size; | ||
104 | } | 115 | } |
105 | ret = btrfs_insert_file_extent(trans, root, inode->i_ino, | ||
106 | start, ins.objectid, ins.offset, | ||
107 | ins.offset); | ||
108 | out: | 116 | out: |
109 | btrfs_end_transaction(trans, root); | 117 | btrfs_end_transaction(trans, root); |
110 | return ret; | 118 | return ret; |
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 2116728d1f98..b7323914bf5a 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c | |||
@@ -34,6 +34,7 @@ | |||
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 <linux/parser.h> |
37 | #include <linux/ctype.h> | ||
37 | #include "ctree.h" | 38 | #include "ctree.h" |
38 | #include "disk-io.h" | 39 | #include "disk-io.h" |
39 | #include "transaction.h" | 40 | #include "transaction.h" |
@@ -61,16 +62,42 @@ static void btrfs_put_super (struct super_block * sb) | |||
61 | } | 62 | } |
62 | 63 | ||
63 | enum { | 64 | enum { |
64 | Opt_subvol, Opt_nodatasum, Opt_nodatacow, Opt_err, | 65 | Opt_subvol, Opt_nodatasum, Opt_nodatacow, Opt_max_extent, Opt_err, |
65 | }; | 66 | }; |
66 | 67 | ||
67 | static match_table_t tokens = { | 68 | static match_table_t tokens = { |
68 | {Opt_subvol, "subvol=%s"}, | 69 | {Opt_subvol, "subvol=%s"}, |
69 | {Opt_nodatasum, "nodatasum"}, | 70 | {Opt_nodatasum, "nodatasum"}, |
70 | {Opt_nodatacow, "nodatacow"}, | 71 | {Opt_nodatacow, "nodatacow"}, |
72 | {Opt_max_extent, "max_extent=%s"}, | ||
71 | {Opt_err, NULL} | 73 | {Opt_err, NULL} |
72 | }; | 74 | }; |
73 | 75 | ||
76 | static unsigned long parse_size(char *str) | ||
77 | { | ||
78 | unsigned long res; | ||
79 | int mult = 1; | ||
80 | char *end; | ||
81 | char last; | ||
82 | |||
83 | res = simple_strtoul(str, &end, 10); | ||
84 | |||
85 | last = end[0]; | ||
86 | if (isalpha(last)) { | ||
87 | last = tolower(last); | ||
88 | switch (last) { | ||
89 | case 'g': | ||
90 | mult *= 1024; | ||
91 | case 'm': | ||
92 | mult *= 1024; | ||
93 | case 'k': | ||
94 | mult *= 1024; | ||
95 | } | ||
96 | res = res * mult; | ||
97 | } | ||
98 | return res; | ||
99 | } | ||
100 | |||
74 | static int parse_options (char * options, | 101 | static int parse_options (char * options, |
75 | struct btrfs_root *root, | 102 | struct btrfs_root *root, |
76 | char **subvol_name) | 103 | char **subvol_name) |
@@ -118,6 +145,21 @@ static int parse_options (char * options, | |||
118 | btrfs_set_opt(info->mount_opt, NODATASUM); | 145 | btrfs_set_opt(info->mount_opt, NODATASUM); |
119 | } | 146 | } |
120 | break; | 147 | break; |
148 | case Opt_max_extent: | ||
149 | if (info) { | ||
150 | char *num = match_strdup(&args[0]); | ||
151 | if (num) { | ||
152 | info->max_extent = parse_size(num); | ||
153 | kfree(num); | ||
154 | |||
155 | info->max_extent = max_t(u64, | ||
156 | info->max_extent, | ||
157 | root->sectorsize); | ||
158 | printk("btrfs: max_extent at %Lu\n", | ||
159 | info->max_extent); | ||
160 | } | ||
161 | } | ||
162 | break; | ||
121 | default: | 163 | default: |
122 | break; | 164 | break; |
123 | } | 165 | } |
@@ -329,6 +371,8 @@ static int btrfs_get_sb(struct file_system_type *fs_type, | |||
329 | ret = btrfs_get_sb_bdev(fs_type, flags, dev_name, data, | 371 | ret = btrfs_get_sb_bdev(fs_type, flags, dev_name, data, |
330 | btrfs_fill_super, mnt, | 372 | btrfs_fill_super, mnt, |
331 | subvol_name ? subvol_name : "default"); | 373 | subvol_name ? subvol_name : "default"); |
374 | if (subvol_name) | ||
375 | kfree(subvol_name); | ||
332 | return ret; | 376 | return ret; |
333 | } | 377 | } |
334 | 378 | ||