Commit c59f8951 authored by Chris Mason's avatar Chris Mason
Browse files

Btrfs: Add mount option to enforce a max extent size

parent d10c5f31
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -322,6 +322,7 @@ struct btrfs_fs_info {
	u64 generation;
	u64 last_trans_committed;
	unsigned long mount_opt;
	u64 max_extent;
	struct btrfs_transaction *running_transaction;
	struct btrfs_super_block super_copy;
	struct extent_buffer *sb_buffer;
+1 −0
Original line number Diff line number Diff line
@@ -569,6 +569,7 @@ struct btrfs_root *open_ctree(struct super_block *sb)
	fs_info->extent_root = extent_root;
	fs_info->sb = sb;
	fs_info->mount_opt = 0;
	fs_info->max_extent = (u64)-1;
	fs_info->btree_inode = new_inode(sb);
	fs_info->btree_inode->i_ino = 1;
	fs_info->btree_inode->i_nlink = 1;
+18 −10
Original line number Diff line number Diff line
@@ -78,6 +78,7 @@ static int cow_file_range(struct inode *inode, u64 start, u64 end)
	struct btrfs_trans_handle *trans;
	u64 alloc_hint = 0;
	u64 num_bytes;
	u64 cur_alloc_size;
	u64 blocksize = root->sectorsize;
	struct btrfs_key ins;
	int ret;
@@ -94,8 +95,11 @@ static int cow_file_range(struct inode *inode, u64 start, u64 end)
	if (alloc_hint == EXTENT_MAP_INLINE)
		goto out;

	ret = btrfs_alloc_extent(trans, root, num_bytes,
				 root->root_key.objectid, trans->transid,
	while(num_bytes > 0) {
		cur_alloc_size = min(num_bytes, root->fs_info->max_extent);
		ret = btrfs_alloc_extent(trans, root, cur_alloc_size,
					 root->root_key.objectid,
					 trans->transid,
					 inode->i_ino, start, 0,
					 alloc_hint, (u64)-1, &ins, 1);
		if (ret) {
@@ -105,6 +109,10 @@ static int cow_file_range(struct inode *inode, u64 start, u64 end)
		ret = btrfs_insert_file_extent(trans, root, inode->i_ino,
					       start, ins.objectid, ins.offset,
					       ins.offset);
		num_bytes -= cur_alloc_size;
		alloc_hint = ins.objectid + ins.offset;
		start += cur_alloc_size;
	}
out:
	btrfs_end_transaction(trans, root);
	return ret;
+45 −1
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@
#include <linux/statfs.h>
#include <linux/compat.h>
#include <linux/parser.h>
#include <linux/ctype.h>
#include "ctree.h"
#include "disk-io.h"
#include "transaction.h"
@@ -61,16 +62,42 @@ static void btrfs_put_super (struct super_block * sb)
}

enum {
	Opt_subvol, Opt_nodatasum, Opt_nodatacow, Opt_err,
	Opt_subvol, Opt_nodatasum, Opt_nodatacow, Opt_max_extent, Opt_err,
};

static match_table_t tokens = {
	{Opt_subvol, "subvol=%s"},
	{Opt_nodatasum, "nodatasum"},
	{Opt_nodatacow, "nodatacow"},
	{Opt_max_extent, "max_extent=%s"},
	{Opt_err, NULL}
};

static unsigned long parse_size(char *str)
{
	unsigned long res;
	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;
}

static int parse_options (char * options,
			  struct btrfs_root *root,
			  char **subvol_name)
@@ -118,6 +145,21 @@ static int parse_options (char * options,
				btrfs_set_opt(info->mount_opt, NODATASUM);
			}
			break;
		case Opt_max_extent:
			if (info) {
				char *num = match_strdup(&args[0]);
				if (num) {
					info->max_extent = parse_size(num);
					kfree(num);

					info->max_extent = max_t(u64,
							 info->max_extent,
							 root->sectorsize);
					printk("btrfs: max_extent at %Lu\n",
					       info->max_extent);
				}
			}
			break;
		default:
			break;
		}
@@ -329,6 +371,8 @@ static int btrfs_get_sb(struct file_system_type *fs_type,
	ret = btrfs_get_sb_bdev(fs_type, flags, dev_name, data,
			btrfs_fill_super, mnt,
			subvol_name ? subvol_name : "default");
	if (subvol_name)
		kfree(subvol_name);
	return ret;
}