aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/disk-io.c
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2007-02-23 08:38:36 -0500
committerDavid Woodhouse <dwmw2@hera.kernel.org>2007-02-23 08:38:36 -0500
commit9a8dd1502de6aa683ae46cf0397e9b6e636416fb (patch)
tree2422c1c316fe97014d8972431dbbe3f91a28853a /fs/btrfs/disk-io.c
parent5c680ed620c2b69cf751aecf1a5e03ce2c89c7f3 (diff)
Btrfs: Block sized tree extents and extent deletion
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/disk-io.c')
-rw-r--r--fs/btrfs/disk-io.c90
1 files changed, 31 insertions, 59 deletions
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index a696a4278ac5..14955e440773 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -12,33 +12,13 @@
12 12
13static int allocated_blocks = 0; 13static int allocated_blocks = 0;
14 14
15static int get_free_block(struct ctree_root *root, u64 *block) 15static int check_tree_block(struct ctree_root *root, struct tree_buffer *buf)
16{ 16{
17 struct stat st; 17 if (buf->blocknr != buf->node.header.blocknr)
18 int ret = 0; 18 BUG();
19 19 if (root->node && buf->node.header.parentid != root->node->node.header.parentid)
20 if (root->alloc_extent->num_used >= root->alloc_extent->num_blocks) 20 BUG();
21 return -1; 21 return 0;
22
23 *block = root->alloc_extent->blocknr + root->alloc_extent->num_used;
24 root->alloc_extent->num_used += 1;
25 if (root->alloc_extent->num_used >= root->alloc_extent->num_blocks) {
26 struct alloc_extent *ae = root->alloc_extent;
27 root->alloc_extent = root->reserve_extent;
28 root->reserve_extent = ae;
29 ae->num_blocks = 0;
30 }
31 st.st_size = 0;
32 ret = fstat(root->fp, &st);
33 if (st.st_size < (*block + 1) * CTREE_BLOCKSIZE) {
34 ret = ftruncate(root->fp,
35 (*block + 1) * CTREE_BLOCKSIZE);
36 if (ret) {
37 perror("ftruncate");
38 exit(1);
39 }
40 }
41 return ret;
42} 22}
43 23
44struct tree_buffer *alloc_tree_block(struct ctree_root *root, u64 blocknr) 24struct tree_buffer *alloc_tree_block(struct ctree_root *root, u64 blocknr)
@@ -61,22 +41,23 @@ struct tree_buffer *alloc_tree_block(struct ctree_root *root, u64 blocknr)
61 return buf; 41 return buf;
62} 42}
63 43
64struct tree_buffer *alloc_free_block(struct ctree_root *root) 44struct tree_buffer *find_tree_block(struct ctree_root *root, u64 blocknr)
65{ 45{
66 u64 free_block; 46 struct tree_buffer *buf;
67 int ret; 47 buf = radix_tree_lookup(&root->cache_radix, blocknr);
68 struct tree_buffer * buf; 48 if (buf) {
69 ret = get_free_block(root, &free_block); 49 buf->count++;
70 if (ret) { 50 } else {
71 BUG(); 51 buf = alloc_tree_block(root, blocknr);
72 return NULL; 52 if (!buf) {
53 BUG();
54 return NULL;
55 }
73 } 56 }
74 buf = alloc_tree_block(root, free_block);
75 if (!buf)
76 BUG();
77 return buf; 57 return buf;
78} 58}
79 59
60
80struct tree_buffer *read_tree_block(struct ctree_root *root, u64 blocknr) 61struct tree_buffer *read_tree_block(struct ctree_root *root, u64 blocknr)
81{ 62{
82 loff_t offset = blocknr * CTREE_BLOCKSIZE; 63 loff_t offset = blocknr * CTREE_BLOCKSIZE;
@@ -86,20 +67,17 @@ struct tree_buffer *read_tree_block(struct ctree_root *root, u64 blocknr)
86 buf = radix_tree_lookup(&root->cache_radix, blocknr); 67 buf = radix_tree_lookup(&root->cache_radix, blocknr);
87 if (buf) { 68 if (buf) {
88 buf->count++; 69 buf->count++;
89 goto test; 70 } else {
90 } 71 buf = alloc_tree_block(root, blocknr);
91 buf = alloc_tree_block(root, blocknr); 72 if (!buf)
92 if (!buf) 73 return NULL;
93 return NULL; 74 ret = pread(root->fp, &buf->node, CTREE_BLOCKSIZE, offset);
94 ret = pread(root->fp, &buf->node, CTREE_BLOCKSIZE, offset); 75 if (ret != CTREE_BLOCKSIZE) {
95 if (ret != CTREE_BLOCKSIZE) { 76 free(buf);
96 free(buf); 77 return NULL;
97 return NULL; 78 }
98 } 79 }
99test: 80 if (check_tree_block(root, buf))
100 if (buf->blocknr != buf->node.header.blocknr)
101 BUG();
102 if (root->node && buf->node.header.parentid != root->node->node.header.parentid)
103 BUG(); 81 BUG();
104 return buf; 82 return buf;
105} 83}
@@ -121,17 +99,10 @@ int write_tree_block(struct ctree_root *root, struct tree_buffer *buf)
121static int __setup_root(struct ctree_root *root, struct ctree_root *extent_root, 99static int __setup_root(struct ctree_root *root, struct ctree_root *extent_root,
122 struct ctree_root_info *info, int fp) 100 struct ctree_root_info *info, int fp)
123{ 101{
124 INIT_RADIX_TREE(&root->cache_radix, GFP_KERNEL);
125 root->fp = fp; 102 root->fp = fp;
126 root->node = NULL; 103 root->node = NULL;
127 root->node = read_tree_block(root, info->tree_root); 104 root->node = read_tree_block(root, info->tree_root);
128 root->extent_root = extent_root; 105 root->extent_root = extent_root;
129 memcpy(&root->ai1, &info->alloc_extent, sizeof(info->alloc_extent));
130 memcpy(&root->ai2, &info->reserve_extent, sizeof(info->reserve_extent));
131 root->alloc_extent = &root->ai1;
132 root->reserve_extent = &root->ai2;
133 printf("setup done reading root %p, used %lu available %lu\n", root, root->alloc_extent->num_used, root->alloc_extent->num_blocks);
134 printf("setup done reading root %p, reserve used %lu available %lu\n", root, root->reserve_extent->num_used, root->reserve_extent->num_blocks);
135 return 0; 106 return 0;
136} 107}
137 108
@@ -147,6 +118,8 @@ struct ctree_root *open_ctree(char *filename, struct ctree_super_block *super)
147 free(root); 118 free(root);
148 return NULL; 119 return NULL;
149 } 120 }
121 INIT_RADIX_TREE(&root->cache_radix, GFP_KERNEL);
122 INIT_RADIX_TREE(&extent_root->cache_radix, GFP_KERNEL);
150 ret = pread(fp, super, sizeof(struct ctree_super_block), 123 ret = pread(fp, super, sizeof(struct ctree_super_block),
151 CTREE_SUPER_INFO_OFFSET(CTREE_BLOCKSIZE)); 124 CTREE_SUPER_INFO_OFFSET(CTREE_BLOCKSIZE));
152 if (ret == 0 || super->root_info.tree_root == 0) { 125 if (ret == 0 || super->root_info.tree_root == 0) {
@@ -168,8 +141,6 @@ struct ctree_root *open_ctree(char *filename, struct ctree_super_block *super)
168static int __update_root(struct ctree_root *root, struct ctree_root_info *info) 141static int __update_root(struct ctree_root *root, struct ctree_root_info *info)
169{ 142{
170 info->tree_root = root->node->blocknr; 143 info->tree_root = root->node->blocknr;
171 memcpy(&info->alloc_extent, root->alloc_extent, sizeof(struct alloc_extent));
172 memcpy(&info->reserve_extent, root->reserve_extent, sizeof(struct alloc_extent));
173 return 0; 144 return 0;
174} 145}
175 146
@@ -201,6 +172,7 @@ int close_ctree(struct ctree_root *root)
201void tree_block_release(struct ctree_root *root, struct tree_buffer *buf) 172void tree_block_release(struct ctree_root *root, struct tree_buffer *buf)
202{ 173{
203 buf->count--; 174 buf->count--;
175 write_tree_block(root, buf);
204 if (buf->count < 0) 176 if (buf->count < 0)
205 BUG(); 177 BUG();
206 if (buf->count == 0) { 178 if (buf->count == 0) {