aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2007-09-10 19:58:16 -0400
committerDavid Woodhouse <dwmw2@hera.kernel.org>2007-09-10 19:58:16 -0400
commit86479a04eef8f304a13aeb8b64bcc8e506a68268 (patch)
treecda7e66d469bcdc2f41144ea91405aeb96d1f777 /fs/btrfs
parent8e21528f87854314792aaef4d279bc9e5a9be997 (diff)
Add support for defragging files via btrfsctl -d. Avoid OOM on extent tree
defrag. Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs')
-rw-r--r--fs/btrfs/ctree.c4
-rw-r--r--fs/btrfs/disk-io.h2
-rw-r--r--fs/btrfs/extent_map.c16
-rw-r--r--fs/btrfs/inode.c93
-rw-r--r--fs/btrfs/tree-defrag.c3
5 files changed, 100 insertions, 18 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
index 89e282c35ce2..b41f48ade419 100644
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -217,6 +217,9 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans,
217 root->fs_info->generation); 217 root->fs_info->generation);
218 WARN_ON(1); 218 WARN_ON(1);
219 } 219 }
220 if (buffer_defrag_done(parent))
221 return 0;
222
220 parent_node = btrfs_buffer_node(parent); 223 parent_node = btrfs_buffer_node(parent);
221 parent_nritems = btrfs_header_nritems(&parent_node->header); 224 parent_nritems = btrfs_header_nritems(&parent_node->header);
222 parent_level = btrfs_header_level(&parent_node->header); 225 parent_level = btrfs_header_level(&parent_node->header);
@@ -274,6 +277,7 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans,
274 *last_ret = search_start; 277 *last_ret = search_start;
275 if (parent_level == 1) 278 if (parent_level == 1)
276 clear_buffer_defrag(tmp_bh); 279 clear_buffer_defrag(tmp_bh);
280 set_buffer_defrag_done(tmp_bh);
277 brelse(tmp_bh); 281 brelse(tmp_bh);
278 } 282 }
279 return err; 283 return err;
diff --git a/fs/btrfs/disk-io.h b/fs/btrfs/disk-io.h
index da6bb72750f2..714fa877438b 100644
--- a/fs/btrfs/disk-io.h
+++ b/fs/btrfs/disk-io.h
@@ -26,9 +26,11 @@
26enum btrfs_bh_state_bits { 26enum btrfs_bh_state_bits {
27 BH_Checked = BH_PrivateStart, 27 BH_Checked = BH_PrivateStart,
28 BH_Defrag, 28 BH_Defrag,
29 BH_DefragDone,
29}; 30};
30BUFFER_FNS(Checked, checked); 31BUFFER_FNS(Checked, checked);
31BUFFER_FNS(Defrag, defrag); 32BUFFER_FNS(Defrag, defrag);
33BUFFER_FNS(DefragDone, defrag_done);
32 34
33static inline struct btrfs_node *btrfs_buffer_node(struct buffer_head *bh) 35static inline struct btrfs_node *btrfs_buffer_node(struct buffer_head *bh)
34{ 36{
diff --git a/fs/btrfs/extent_map.c b/fs/btrfs/extent_map.c
index 8ad6f8efc5a0..33f7a18dddf7 100644
--- a/fs/btrfs/extent_map.c
+++ b/fs/btrfs/extent_map.c
@@ -10,6 +10,12 @@
10#include <linux/blkdev.h> 10#include <linux/blkdev.h>
11#include "extent_map.h" 11#include "extent_map.h"
12 12
13/* temporary define until extent_map moves out of btrfs */
14struct kmem_cache *btrfs_cache_create(const char *name, size_t size,
15 unsigned long extra_flags,
16 void (*ctor)(void *, struct kmem_cache *,
17 unsigned long));
18
13static struct kmem_cache *extent_map_cache; 19static struct kmem_cache *extent_map_cache;
14static struct kmem_cache *extent_state_cache; 20static struct kmem_cache *extent_state_cache;
15 21
@@ -32,14 +38,12 @@ struct tree_entry {
32 38
33void __init extent_map_init(void) 39void __init extent_map_init(void)
34{ 40{
35 extent_map_cache = kmem_cache_create("extent_map", 41 extent_map_cache = btrfs_cache_create("extent_map",
36 sizeof(struct extent_map), 0, 42 sizeof(struct extent_map),
37 SLAB_RECLAIM_ACCOUNT |
38 SLAB_DESTROY_BY_RCU, 43 SLAB_DESTROY_BY_RCU,
39 NULL); 44 NULL);
40 extent_state_cache = kmem_cache_create("extent_state", 45 extent_state_cache = btrfs_cache_create("extent_state",
41 sizeof(struct extent_state), 0, 46 sizeof(struct extent_state),
42 SLAB_RECLAIM_ACCOUNT |
43 SLAB_DESTROY_BY_RCU, 47 SLAB_DESTROY_BY_RCU,
44 NULL); 48 NULL);
45} 49}
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 64710fa77d01..6b3e4404dc6a 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -1904,6 +1904,70 @@ fail:
1904 return ret; 1904 return ret;
1905} 1905}
1906 1906
1907static unsigned long force_ra(struct address_space *mapping,
1908 struct file_ra_state *ra, struct file *file,
1909 pgoff_t offset, pgoff_t last_index)
1910{
1911 pgoff_t req_size;
1912
1913#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
1914 req_size = last_index - offset + 1;
1915 offset = page_cache_readahead(mapping, ra, file, offset, req_size);
1916 return offset;
1917#else
1918 req_size = min(last_index - offset + 1, (pgoff_t)128);
1919 page_cache_sync_readahead(mapping, ra, file, offset, req_size);
1920 return offset + req_size;
1921#endif
1922}
1923
1924int btrfs_defrag_file(struct file *file) {
1925 struct inode *inode = file->f_path.dentry->d_inode;
1926 struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree;
1927 struct page *page;
1928 unsigned long last_index;
1929 unsigned long ra_index = 0;
1930 u64 page_start;
1931 u64 page_end;
1932 unsigned long i;
1933
1934 mutex_lock(&inode->i_mutex);
1935 last_index = inode->i_size >> PAGE_CACHE_SHIFT;
1936 for (i = 0; i <= last_index; i++) {
1937 if (i == ra_index) {
1938 ra_index = force_ra(inode->i_mapping, &file->f_ra,
1939 file, ra_index, last_index);
1940 }
1941 page = grab_cache_page(inode->i_mapping, i);
1942 if (!page)
1943 goto out_unlock;
1944 if (!PageUptodate(page)) {
1945 btrfs_readpage(NULL, page);
1946 lock_page(page);
1947 if (!PageUptodate(page)) {
1948 unlock_page(page);
1949 page_cache_release(page);
1950 goto out_unlock;
1951 }
1952 }
1953 page_start = page->index << PAGE_CACHE_SHIFT;
1954 page_end = page_start + PAGE_CACHE_SIZE - 1;
1955
1956 lock_extent(em_tree, page_start, page_end, GFP_NOFS);
1957 set_extent_delalloc(em_tree, page_start,
1958 page_end, GFP_NOFS);
1959 unlock_extent(em_tree, page_start, page_end, GFP_NOFS);
1960 set_page_dirty(page);
1961 unlock_page(page);
1962 page_cache_release(page);
1963 balance_dirty_pages_ratelimited_nr(inode->i_mapping, 1);
1964 }
1965
1966out_unlock:
1967 mutex_unlock(&inode->i_mutex);
1968 return 0;
1969}
1970
1907int btrfs_ioctl(struct inode *inode, struct file *filp, unsigned int 1971int btrfs_ioctl(struct inode *inode, struct file *filp, unsigned int
1908 cmd, unsigned long arg) 1972 cmd, unsigned long arg)
1909{ 1973{
@@ -1948,10 +2012,14 @@ int btrfs_ioctl(struct inode *inode, struct file *filp, unsigned int
1948 break; 2012 break;
1949 2013
1950 case BTRFS_IOC_DEFRAG: 2014 case BTRFS_IOC_DEFRAG:
1951 mutex_lock(&root->fs_info->fs_mutex); 2015 if (S_ISDIR(inode->i_mode)) {
1952 btrfs_defrag_root(root, 0); 2016 mutex_lock(&root->fs_info->fs_mutex);
1953 btrfs_defrag_root(root->fs_info->extent_root, 0); 2017 btrfs_defrag_root(root, 0);
1954 mutex_unlock(&root->fs_info->fs_mutex); 2018 btrfs_defrag_root(root->fs_info->extent_root, 0);
2019 mutex_unlock(&root->fs_info->fs_mutex);
2020 } else if (S_ISREG(inode->i_mode)) {
2021 btrfs_defrag_file(filp);
2022 }
1955 ret = 0; 2023 ret = 0;
1956 break; 2024 break;
1957 default: 2025 default:
@@ -2018,7 +2086,7 @@ void btrfs_destroy_cachep(void)
2018 kmem_cache_destroy(btrfs_path_cachep); 2086 kmem_cache_destroy(btrfs_path_cachep);
2019} 2087}
2020 2088
2021static struct kmem_cache *cache_create(const char *name, size_t size, 2089struct kmem_cache *btrfs_cache_create(const char *name, size_t size,
2022 unsigned long extra_flags, 2090 unsigned long extra_flags,
2023 void (*ctor)(void *, struct kmem_cache *, 2091 void (*ctor)(void *, struct kmem_cache *,
2024 unsigned long)) 2092 unsigned long))
@@ -2033,27 +2101,28 @@ static struct kmem_cache *cache_create(const char *name, size_t size,
2033 2101
2034int btrfs_init_cachep(void) 2102int btrfs_init_cachep(void)
2035{ 2103{
2036 btrfs_inode_cachep = cache_create("btrfs_inode_cache", 2104 btrfs_inode_cachep = btrfs_cache_create("btrfs_inode_cache",
2037 sizeof(struct btrfs_inode), 2105 sizeof(struct btrfs_inode),
2038 0, init_once); 2106 0, init_once);
2039 if (!btrfs_inode_cachep) 2107 if (!btrfs_inode_cachep)
2040 goto fail; 2108 goto fail;
2041 btrfs_trans_handle_cachep = cache_create("btrfs_trans_handle_cache", 2109 btrfs_trans_handle_cachep =
2042 sizeof(struct btrfs_trans_handle), 2110 btrfs_cache_create("btrfs_trans_handle_cache",
2043 0, NULL); 2111 sizeof(struct btrfs_trans_handle),
2112 0, NULL);
2044 if (!btrfs_trans_handle_cachep) 2113 if (!btrfs_trans_handle_cachep)
2045 goto fail; 2114 goto fail;
2046 btrfs_transaction_cachep = cache_create("btrfs_transaction_cache", 2115 btrfs_transaction_cachep = btrfs_cache_create("btrfs_transaction_cache",
2047 sizeof(struct btrfs_transaction), 2116 sizeof(struct btrfs_transaction),
2048 0, NULL); 2117 0, NULL);
2049 if (!btrfs_transaction_cachep) 2118 if (!btrfs_transaction_cachep)
2050 goto fail; 2119 goto fail;
2051 btrfs_path_cachep = cache_create("btrfs_path_cache", 2120 btrfs_path_cachep = btrfs_cache_create("btrfs_path_cache",
2052 sizeof(struct btrfs_transaction), 2121 sizeof(struct btrfs_transaction),
2053 0, NULL); 2122 0, NULL);
2054 if (!btrfs_path_cachep) 2123 if (!btrfs_path_cachep)
2055 goto fail; 2124 goto fail;
2056 btrfs_bit_radix_cachep = cache_create("btrfs_radix", 256, 2125 btrfs_bit_radix_cachep = btrfs_cache_create("btrfs_radix", 256,
2057 SLAB_DESTROY_BY_RCU, NULL); 2126 SLAB_DESTROY_BY_RCU, NULL);
2058 if (!btrfs_bit_radix_cachep) 2127 if (!btrfs_bit_radix_cachep)
2059 goto fail; 2128 goto fail;
diff --git a/fs/btrfs/tree-defrag.c b/fs/btrfs/tree-defrag.c
index 35fd20d24645..420597127ed1 100644
--- a/fs/btrfs/tree-defrag.c
+++ b/fs/btrfs/tree-defrag.c
@@ -113,6 +113,8 @@ static int defrag_walk_down(struct btrfs_trans_handle *trans,
113 } 113 }
114 WARN_ON(*level < 0); 114 WARN_ON(*level < 0);
115 WARN_ON(*level >= BTRFS_MAX_LEVEL); 115 WARN_ON(*level >= BTRFS_MAX_LEVEL);
116 clear_buffer_defrag(path->nodes[*level]);
117 clear_buffer_defrag_done(path->nodes[*level]);
116 btrfs_block_release(root, path->nodes[*level]); 118 btrfs_block_release(root, path->nodes[*level]);
117 path->nodes[*level] = NULL; 119 path->nodes[*level] = NULL;
118 *level += 1; 120 *level += 1;
@@ -143,6 +145,7 @@ static int defrag_walk_up(struct btrfs_trans_handle *trans,
143 return 0; 145 return 0;
144 } else { 146 } else {
145 clear_buffer_defrag(path->nodes[*level]); 147 clear_buffer_defrag(path->nodes[*level]);
148 clear_buffer_defrag_done(path->nodes[*level]);
146 btrfs_block_release(root, path->nodes[*level]); 149 btrfs_block_release(root, path->nodes[*level]);
147 path->nodes[*level] = NULL; 150 path->nodes[*level] = NULL;
148 *level = i + 1; 151 *level = i + 1;