1 #include <lunaix/mm/valloc.h>
5 bcache_zone_t gdesc_bcache_zone;
8 __cached_gdesc_evict(struct bcache* bc, void* data)
10 struct ext2_gdesc* gd;
11 gd = (struct ext2_gdesc*)data;
13 llist_delete(&gd->groups);
14 llist_delete(&gd->free_grps_blk);
15 llist_delete(&gd->free_grps_ino);
23 __cached_gdesc_sync(struct bcache*, unsigned long tag, void* data)
25 // since all mods to gdesc goes directly into fs buffer,
26 // we just need to invoke the sync on the underlying.
28 struct ext2_gdesc* gd;
29 gd = (struct ext2_gdesc*)data;
31 fsblock_sync(gd->buf);
34 static struct bcache_ops gdesc_bc_ops = {
35 .release_on_evict = __cached_gdesc_evict,
36 .sync_cached = __cached_gdesc_sync
40 ext2gd_prepare_gdt(struct v_superblock* vsb)
42 struct ext2b_super* sb;
43 unsigned int nr_parts;
44 unsigned int nr_gd_pb, nr_gd;
45 struct ext2_sbinfo* ext2sb;
47 ext2sb = EXT2_SB(vsb);
50 nr_gd_pb = ext2sb->block_size / sizeof(struct ext2b_gdesc);
51 nr_gd = ICEIL(sb->s_blk_cnt, sb->s_blk_per_grp);
52 nr_parts = ICEIL(nr_gd, nr_gd_pb);
54 ext2sb->gdt_frag = (bbuf_t*)vcalloc(sizeof(bbuf_t), nr_parts);
55 ext2sb->nr_gdesc_pb = nr_gd_pb;
56 ext2sb->nr_gdesc = nr_gd;
58 bcache_init_zone(&ext2sb->gd_caches, gdesc_bcache_zone,
59 ilog2(64), 0, sizeof(struct ext2b_gdesc), &gdesc_bc_ops);
61 llist_init_head(&ext2sb->gds);
62 llist_init_head(&ext2sb->free_grps_blk);
63 llist_init_head(&ext2sb->free_grps_ino);
67 ext2gd_release_gdt(struct v_superblock* vsb)
69 unsigned int parts_cnt;
70 struct ext2_sbinfo* ext2sb;
72 ext2sb = EXT2_SB(vsb);
73 parts_cnt = ICEIL(ext2sb->nr_gdesc, ext2sb->nr_gdesc_pb);
74 for (size_t i = 0; i < parts_cnt; i++)
76 if (!ext2sb->gdt_frag[i]) {
80 fsblock_put(ext2sb->gdt_frag[i]);
81 ext2sb->gdt_frag[i] = NULL;
86 __try_load_bitmap(struct v_superblock* vsb,
87 struct ext2_gdesc* gd, int type)
89 struct ext2_sbinfo* ext2sb;
91 struct llist_header* flist, *flist_entry;
93 unsigned int blk_id, bmp_blk_id, bmp_size;
95 ext2sb = EXT2_SB(vsb);
97 if (type == GDESC_INO_SEL) {
98 bmp_blk_id = gd->info->bg_ino_map;
99 bmp_size = ext2sb->raw->s_ino_per_grp;
102 else if (type == GDESC_BLK_SEL) {
103 bmp_blk_id = gd->info->bg_blk_map;
104 bmp_size = ext2sb->raw->s_blk_per_grp;
108 fail_fs("unknown bitmap type");
111 flist = &ext2sb->free_list_sel[type];
112 flist_entry = &gd->free_list_sel[type];
114 blk_id = ext2_datablock(vsb, bmp_blk_id);
115 buf = fsblock_get(vsb, blk_id);
116 if (blkbuf_errbuf(buf)) {
120 ext2bmp_init(bmp, buf, bmp_size);
122 if (ext2bmp_check_free(bmp)) {
123 llist_append(flist, flist_entry);
130 ext2gd_take(struct v_superblock* vsb,
131 unsigned int index, struct ext2_gdesc** out)
134 struct ext2_sbinfo* ext2sb;
135 unsigned int blk_id, blk_off;
137 ext2sb = EXT2_SB(vsb);
139 if (index >= ext2sb->nr_gdesc) {
144 if (bcache_tryget(&ext2sb->gd_caches, index, &cached)) {
145 *out = (struct ext2_gdesc*)bcached_data(cached);
149 blk_id = index / ext2sb->nr_gdesc_pb;
150 blk_off = index % ext2sb->nr_gdesc_pb;
152 part = ext2sb->gdt_frag[blk_id];
154 blk_id = ext2_datablock(vsb, blk_id + 1);
155 part = fsblock_get(vsb, blk_id);
160 ext2sb->gdt_frag[blk_id] = part;
163 struct ext2_gdesc* gd;
165 gd = valloc(sizeof(struct ext2_gdesc));
166 *gd = (struct ext2_gdesc) {
167 .info = &block_buffer(part, struct ext2b_gdesc)[blk_off],
169 .base = index * ext2sb->raw->s_blk_per_grp,
170 .ino_base = index * ext2sb->raw->s_ino_per_grp
175 if (!ext2sb->read_only) {
176 if (!__try_load_bitmap(vsb, gd, GDESC_INO_SEL)) {
180 if (!__try_load_bitmap(vsb, gd, GDESC_BLK_SEL)) {
181 llist_delete(&gd->free_grps_ino);
186 llist_append(&ext2sb->gds, &gd->groups);
188 cached = bcache_put_and_ref(&ext2sb->gd_caches, index, gd);
189 gd->cache_ref = cached;
202 __ext2bmp_update_next_free_cell(struct ext2_bmp* e_bmp)
207 i = valid_bmp_slot(e_bmp->next_free) ? e_bmp->next_free : 0;
210 // next fit, try to maximize our locality without going after
211 // some crazy algorithm
213 if (e_bmp->bmp[i] != 0xff) {
214 e_bmp->next_free = i;
218 if (++i == e_bmp->nr_bytes) {
224 e_bmp->next_free = ALLOC_FAIL;
228 ext2bmp_init(struct ext2_bmp* e_bmp, bbuf_t bmp_buf, unsigned int nr_bits)
230 assert(nr_bits % 8 == 0);
232 e_bmp->bmp = blkbuf_data(bmp_buf);
233 e_bmp->raw = bmp_buf;
234 e_bmp->nr_bytes = nr_bits / 8;
236 __ext2bmp_update_next_free_cell(e_bmp);
240 ext2bmp_check_free(struct ext2_bmp* e_bmp)
244 return valid_bmp_slot(e_bmp->next_free);
248 ext2bmp_alloc_one(struct ext2_bmp* e_bmp)
255 if (!valid_bmp_slot(e_bmp->next_free)) {
260 next_free = e_bmp->next_free;
261 cell = e_bmp->bmp[next_free];
262 assert(cell != 0xff);
264 while ((cell & (1 << slot++)));
266 cell |= (1 << --slot);
267 slot += (next_free * 8);
268 e_bmp->bmp[next_free] = cell;
271 __ext2bmp_update_next_free_cell(e_bmp);
274 fsblock_dirty(e_bmp->raw);
279 ext2bmp_free_one(struct ext2_bmp* e_bmp, unsigned int pos)
283 int cell_idx = pos / 8;
284 u8_t cell_mask = 1 << (pos % 8);
285 e_bmp->bmp[cell_idx] &= ~cell_mask;
287 if (!valid_bmp_slot(e_bmp->next_free)) {
288 e_bmp->next_free = cell_idx;
291 fsblock_dirty(e_bmp->raw);
295 ext2bmp_discard(struct ext2_bmp* e_bmp)
299 fsblock_put(e_bmp->raw);