1 #define _XOPEN_SOURCE 500
8 #include "kerncompat.h"
9 #include "radix-tree.h"
13 static int allocated_blocks
= 0;
15 static int get_free_block(struct ctree_root
*root
, u64
*block
)
20 if (root
->alloc_extent
->num_used
>= root
->alloc_extent
->num_blocks
)
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
;
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
);
44 struct tree_buffer
*alloc_tree_block(struct ctree_root
*root
, u64 blocknr
)
46 struct tree_buffer
*buf
;
48 buf
= malloc(sizeof(struct tree_buffer
));
52 buf
->blocknr
= blocknr
;
54 radix_tree_preload(GFP_KERNEL
);
55 ret
= radix_tree_insert(&root
->cache_radix
, blocknr
, buf
);
56 radix_tree_preload_end();
64 struct tree_buffer
*alloc_free_block(struct ctree_root
*root
)
68 struct tree_buffer
* buf
;
69 ret
= get_free_block(root
, &free_block
);
74 buf
= alloc_tree_block(root
, free_block
);
80 struct tree_buffer
*read_tree_block(struct ctree_root
*root
, u64 blocknr
)
82 loff_t offset
= blocknr
* CTREE_BLOCKSIZE
;
83 struct tree_buffer
*buf
;
86 buf
= radix_tree_lookup(&root
->cache_radix
, blocknr
);
91 buf
= alloc_tree_block(root
, blocknr
);
94 ret
= pread(root
->fp
, &buf
->node
, CTREE_BLOCKSIZE
, offset
);
95 if (ret
!= CTREE_BLOCKSIZE
) {
100 if (buf
->blocknr
!= buf
->node
.header
.blocknr
)
102 if (root
->node
&& buf
->node
.header
.parentid
!= root
->node
->node
.header
.parentid
)
107 int write_tree_block(struct ctree_root
*root
, struct tree_buffer
*buf
)
109 u64 blocknr
= buf
->blocknr
;
110 loff_t offset
= blocknr
* CTREE_BLOCKSIZE
;
113 if (buf
->blocknr
!= buf
->node
.header
.blocknr
)
115 ret
= pwrite(root
->fp
, &buf
->node
, CTREE_BLOCKSIZE
, offset
);
116 if (ret
!= CTREE_BLOCKSIZE
)
121 static int __setup_root(struct ctree_root
*root
, struct ctree_root
*extent_root
,
122 struct ctree_root_info
*info
, int fp
)
124 INIT_RADIX_TREE(&root
->cache_radix
, GFP_KERNEL
);
127 root
->node
= read_tree_block(root
, info
->tree_root
);
128 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
);
138 struct ctree_root
*open_ctree(char *filename
, struct ctree_super_block
*super
)
140 struct ctree_root
*root
= malloc(sizeof(struct ctree_root
));
141 struct ctree_root
*extent_root
= malloc(sizeof(struct ctree_root
));
145 fp
= open(filename
, O_CREAT
| O_RDWR
);
150 ret
= pread(fp
, super
, sizeof(struct ctree_super_block
),
151 CTREE_SUPER_INFO_OFFSET(CTREE_BLOCKSIZE
));
156 ret
= pread(fp
, super
, sizeof(struct ctree_super_block
),
157 CTREE_SUPER_INFO_OFFSET(CTREE_BLOCKSIZE
));
158 if (ret
!= sizeof(struct ctree_super_block
))
162 __setup_root(root
, extent_root
, &super
->root_info
, fp
);
163 __setup_root(extent_root
, extent_root
, &super
->extent_info
, fp
);
167 static int __update_root(struct ctree_root
*root
, struct ctree_root_info
*info
)
169 info
->tree_root
= root
->node
->blocknr
;
170 memcpy(&info
->alloc_extent
, root
->alloc_extent
, sizeof(struct alloc_extent
));
171 memcpy(&info
->reserve_extent
, root
->reserve_extent
, sizeof(struct alloc_extent
));
175 int write_ctree_super(struct ctree_root
*root
, struct ctree_super_block
*s
)
178 __update_root(root
, &s
->root_info
);
179 __update_root(root
->extent_root
, &s
->extent_info
);
180 ret
= pwrite(root
->fp
, s
, sizeof(*s
), CTREE_SUPER_INFO_OFFSET(CTREE_BLOCKSIZE
));
181 if (ret
!= sizeof(*s
)) {
182 fprintf(stderr
, "failed to write new super block err %d\n", ret
);
188 int close_ctree(struct ctree_root
*root
)
192 tree_block_release(root
, root
->node
);
193 if (root
->extent_root
->node
)
194 tree_block_release(root
->extent_root
, root
->extent_root
->node
);
196 printf("on close %d blocks are allocated\n", allocated_blocks
);
200 void tree_block_release(struct ctree_root
*root
, struct tree_buffer
*buf
)
205 if (buf
->count
== 0) {
206 if (!radix_tree_lookup(&root
->cache_radix
, buf
->blocknr
))
208 radix_tree_delete(&root
->cache_radix
, buf
->blocknr
);
209 memset(buf
, 0, sizeof(*buf
));
211 BUG_ON(allocated_blocks
== 0);
This page took 0.038732 seconds and 6 git commands to generate.