add locks to the shared objects of ext2 fs
[lunaix-os.git] / lunaix-os / kernel / fs / ext2 / alloc.c
1 #include "ext2.h"
2
3 static inline unsigned int
4 __ext2_global_slot_alloc(struct v_superblock* vsb, int type_sel, 
5                          struct ext2_gdesc** gd_out)
6 {
7     int alloc;
8     struct ext2_sbinfo* sb;
9     struct ext2_gdesc *pos;
10     struct llist_header *header;
11     
12     alloc = ALLOC_FAIL;
13     sb = EXT2_SB(vsb);
14
15     ext2sb_lock(sb);
16     header = &sb->free_list_sel[type_sel];
17
18     // we have used up all avaliable inodes/blocks
19     if (llist_empty(header))
20         goto done;
21     
22     if (type_sel == GDESC_INO_SEL) {
23         pos = list_entry(header->next, struct ext2_gdesc, free_grps_ino);
24     } 
25     else {
26         pos = list_entry(header->next, struct ext2_gdesc, free_grps_blk);
27     }
28
29     alloc = ext2gd_alloc_slot(pos, type_sel);
30
31     if (valid_bmp_slot(alloc)) {
32         *gd_out = pos;
33     }
34
35 done:
36     ext2sb_unlock(sb);
37     return alloc;
38 }
39
40 int
41 ext2ino_alloc_slot(struct v_superblock* vsb, struct ext2_gdesc** gd_out)
42 {
43     return __ext2_global_slot_alloc(vsb, GDESC_INO_SEL, gd_out);
44 }
45
46 int
47 ext2db_alloc_slot(struct v_superblock* vsb, struct ext2_gdesc** gd_out)
48 {
49     return __ext2_global_slot_alloc(vsb, GDESC_BLK_SEL, gd_out);
50 }
51
52 int
53 ext2gd_alloc_slot(struct ext2_gdesc* gd, int type_sel) 
54 {
55     struct ext2_bmp* bmp;
56     struct ext2_sbinfo *sb;
57     int alloc;
58
59     ext2gd_lock(gd);
60     
61     sb = gd->sb;
62     bmp = &gd->bmps[type_sel];
63     alloc = ext2bmp_alloc_nolock(bmp);
64     
65     if (alloc < 0) {
66         goto done;
67     }
68
69     if (!ext2bmp_check_free(bmp)) {
70         llist_delete(&gd->free_list_sel[type_sel]);
71     }
72
73     if (type_sel == GDESC_INO_SEL) {
74         gd->info->bg_free_ino_cnt--;
75         sb->raw->s_free_ino_cnt--;
76     } else {
77         gd->info->bg_free_blk_cnt--;
78         sb->raw->s_free_blk_cnt--;
79     }
80
81     ext2gd_schedule_sync(gd);
82     ext2sb_schedule_sync(sb);
83
84 done:
85     ext2gd_unlock(gd);
86     return alloc;
87 }
88
89 void
90 ext2gd_free_slot(struct ext2_gdesc* gd, int type_sel, int slot)
91 {
92     struct llist_header *free_ent, *free_list;
93     struct ext2_sbinfo *sb;
94
95     ext2gd_lock(gd);
96
97     ext2bmp_free_nolock(&gd->bmps[type_sel], slot);
98
99     sb = gd->sb;
100     free_ent  = &gd->free_list_sel[slot];
101     free_list = &gd->sb->free_list_sel[slot];
102     if (llist_empty(free_ent)) {
103         llist_append(free_list, free_ent);
104     }
105
106     // FIXME might need arch-depedent impl for atomic operations
107     if (type_sel == GDESC_INO_SEL) {
108         gd->info->bg_free_ino_cnt++;
109         sb->raw->s_free_ino_cnt++;
110     } else {
111         gd->info->bg_free_blk_cnt++;
112         sb->raw->s_free_blk_cnt++;
113     }
114
115     ext2gd_schedule_sync(gd);
116     ext2sb_schedule_sync(sb);
117
118     ext2gd_unlock(gd);
119 }