aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/inode.c
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2007-08-07 16:15:09 -0400
committerDavid Woodhouse <dwmw2@hera.kernel.org>2007-08-07 16:15:09 -0400
commit6702ed490ca0bb44e17131818a5a18b773957c5a (patch)
treef6bc4b77e58506a68f1ab539ca6c96854f39f92d /fs/btrfs/inode.c
parent3c69faecb8d83cb2ef085a98b196a3fecea67725 (diff)
Btrfs: Add run time btree defrag, and an ioctl to force btree defrag
This adds two types of btree defrag, a run time form that tries to defrag recently allocated blocks in the btree when they are still in ram, and an ioctl that forces defrag of all btree blocks. File data blocks are not defragged yet, but this can make a huge difference in sequential btree reads. Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/inode.c')
-rw-r--r--fs/btrfs/inode.c33
1 files changed, 30 insertions, 3 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 3889032fc449..12aa043b9f6f 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -554,7 +554,7 @@ static int btrfs_truncate_page(struct address_space *mapping, loff_t from)
554 &alloc_hint); 554 &alloc_hint);
555 if (ret) 555 if (ret)
556 goto out; 556 goto out;
557 ret = btrfs_alloc_extent(trans, root, inode->i_ino, 1, 557 ret = btrfs_alloc_extent(trans, root, inode->i_ino, 1, 0,
558 alloc_hint, (u64)-1, &ins, 1); 558 alloc_hint, (u64)-1, &ins, 1);
559 if (ret) 559 if (ret)
560 goto out; 560 goto out;
@@ -1360,7 +1360,7 @@ not_found:
1360 if (create & BTRFS_GET_BLOCK_CREATE) { 1360 if (create & BTRFS_GET_BLOCK_CREATE) {
1361 struct btrfs_key ins; 1361 struct btrfs_key ins;
1362 ret = btrfs_alloc_extent(trans, root, inode->i_ino, 1362 ret = btrfs_alloc_extent(trans, root, inode->i_ino,
1363 1, alloc_hint, (u64)-1, 1363 1, 0, alloc_hint, (u64)-1,
1364 &ins, 1); 1364 &ins, 1);
1365 if (ret) { 1365 if (ret) {
1366 err = ret; 1366 err = ret;
@@ -1998,7 +1998,7 @@ static int create_subvol(struct btrfs_root *root, char *name, int namelen)
1998 trans = btrfs_start_transaction(root, 1); 1998 trans = btrfs_start_transaction(root, 1);
1999 BUG_ON(!trans); 1999 BUG_ON(!trans);
2000 2000
2001 subvol = btrfs_alloc_free_block(trans, root, 0); 2001 subvol = btrfs_alloc_free_block(trans, root, 0, 0);
2002 if (IS_ERR(subvol)) 2002 if (IS_ERR(subvol))
2003 return PTR_ERR(subvol); 2003 return PTR_ERR(subvol);
2004 leaf = btrfs_buffer_leaf(subvol); 2004 leaf = btrfs_buffer_leaf(subvol);
@@ -2159,7 +2159,9 @@ int btrfs_ioctl(struct inode *inode, struct file *filp, unsigned int
2159{ 2159{
2160 struct btrfs_root *root = BTRFS_I(inode)->root; 2160 struct btrfs_root *root = BTRFS_I(inode)->root;
2161 struct btrfs_ioctl_vol_args vol_args; 2161 struct btrfs_ioctl_vol_args vol_args;
2162 struct btrfs_trans_handle *trans;
2162 int ret = 0; 2163 int ret = 0;
2164 int err;
2163 struct btrfs_dir_item *di; 2165 struct btrfs_dir_item *di;
2164 int namelen; 2166 int namelen;
2165 struct btrfs_path *path; 2167 struct btrfs_path *path;
@@ -2196,6 +2198,31 @@ int btrfs_ioctl(struct inode *inode, struct file *filp, unsigned int
2196 else 2198 else
2197 ret = create_snapshot(root, vol_args.name, namelen); 2199 ret = create_snapshot(root, vol_args.name, namelen);
2198 break; 2200 break;
2201
2202 case BTRFS_IOC_DEFRAG:
2203 mutex_lock(&root->fs_info->fs_mutex);
2204 trans = btrfs_start_transaction(root, 1);
2205 memset(&root->defrag_progress, 0,
2206 sizeof(root->defrag_progress));
2207 while (1) {
2208 root->defrag_running = 1;
2209 err = btrfs_defrag_leaves(trans, root, 0);
2210
2211 btrfs_end_transaction(trans, root);
2212 mutex_unlock(&root->fs_info->fs_mutex);
2213
2214 btrfs_btree_balance_dirty(root);
2215
2216 mutex_lock(&root->fs_info->fs_mutex);
2217 trans = btrfs_start_transaction(root, 1);
2218 if (err != -EAGAIN)
2219 break;
2220 }
2221 root->defrag_running = 0;
2222 btrfs_end_transaction(trans, root);
2223 mutex_unlock(&root->fs_info->fs_mutex);
2224 ret = 0;
2225 break;
2199 default: 2226 default:
2200 return -ENOTTY; 2227 return -ENOTTY;
2201 } 2228 }