diff options
Diffstat (limited to 'src/fs/bitmap.c')
-rw-r--r-- | src/fs/bitmap.c | 168 |
1 files changed, 168 insertions, 0 deletions
diff --git a/src/fs/bitmap.c b/src/fs/bitmap.c new file mode 100644 index 0000000..fb0741d --- /dev/null +++ b/src/fs/bitmap.c | |||
@@ -0,0 +1,168 @@ | |||
1 | /* | ||
2 | * linux/fs/bitmap.c | ||
3 | * | ||
4 | * (C) 1991 Linus Torvalds | ||
5 | */ | ||
6 | |||
7 | /* bitmap.c contains the code that handles the inode and block bitmaps */ | ||
8 | #include <string.h> | ||
9 | |||
10 | #include <linux/sched.h> | ||
11 | #include <linux/kernel.h> | ||
12 | |||
13 | #define clear_block(addr) \ | ||
14 | __asm__ __volatile__ ("cld\n\t" \ | ||
15 | "rep\n\t" \ | ||
16 | "stosl" \ | ||
17 | ::"a" (0),"c" (BLOCK_SIZE/4),"D" ((long) (addr))) | ||
18 | |||
19 | #define set_bit(nr,addr) ({\ | ||
20 | register int res ; \ | ||
21 | __asm__ __volatile__("btsl %2,%3\n\tsetb %%al": \ | ||
22 | "=a" (res):"0" (0),"r" (nr),"m" (*(addr))); \ | ||
23 | res;}) | ||
24 | |||
25 | #define clear_bit(nr,addr) ({\ | ||
26 | register int res ; \ | ||
27 | __asm__ __volatile__("btrl %2,%3\n\tsetnb %%al": \ | ||
28 | "=a" (res):"0" (0),"r" (nr),"m" (*(addr))); \ | ||
29 | res;}) | ||
30 | |||
31 | #define find_first_zero(addr) ({ \ | ||
32 | int __res; \ | ||
33 | __asm__ __volatile__ ("cld\n" \ | ||
34 | "1:\tlodsl\n\t" \ | ||
35 | "notl %%eax\n\t" \ | ||
36 | "bsfl %%eax,%%edx\n\t" \ | ||
37 | "je 2f\n\t" \ | ||
38 | "addl %%edx,%%ecx\n\t" \ | ||
39 | "jmp 3f\n" \ | ||
40 | "2:\taddl $32,%%ecx\n\t" \ | ||
41 | "cmpl $8192,%%ecx\n\t" \ | ||
42 | "jl 1b\n" \ | ||
43 | "3:" \ | ||
44 | :"=c" (__res):"c" (0),"S" (addr)); \ | ||
45 | __res;}) | ||
46 | |||
47 | void free_block(int dev, int block) | ||
48 | { | ||
49 | struct super_block * sb; | ||
50 | struct buffer_head * bh; | ||
51 | |||
52 | if (!(sb = get_super(dev))) | ||
53 | panic("trying to free block on nonexistent device"); | ||
54 | if (block < sb->s_firstdatazone || block >= sb->s_nzones) | ||
55 | panic("trying to free block not in datazone"); | ||
56 | bh = get_hash_table(dev,block); | ||
57 | if (bh) { | ||
58 | if (bh->b_count != 1) { | ||
59 | printk("trying to free block (%04x:%d), count=%d\n", | ||
60 | dev,block,bh->b_count); | ||
61 | return; | ||
62 | } | ||
63 | bh->b_dirt=0; | ||
64 | bh->b_uptodate=0; | ||
65 | brelse(bh); | ||
66 | } | ||
67 | block -= sb->s_firstdatazone - 1 ; | ||
68 | if (clear_bit(block&8191,sb->s_zmap[block/8192]->b_data)) { | ||
69 | printk("block (%04x:%d) ",dev,block+sb->s_firstdatazone-1); | ||
70 | panic("free_block: bit already cleared"); | ||
71 | } | ||
72 | sb->s_zmap[block/8192]->b_dirt = 1; | ||
73 | } | ||
74 | |||
75 | int new_block(int dev) | ||
76 | { | ||
77 | struct buffer_head * bh; | ||
78 | struct super_block * sb; | ||
79 | int i,j; | ||
80 | |||
81 | if (!(sb = get_super(dev))) | ||
82 | panic("trying to get new block from nonexistant device"); | ||
83 | j = 8192; | ||
84 | for (i=0 ; i<8 ; i++) | ||
85 | if ((bh=sb->s_zmap[i])) | ||
86 | if ((j=find_first_zero(bh->b_data))<8192) | ||
87 | break; | ||
88 | if (i>=8 || !bh || j>=8192) | ||
89 | return 0; | ||
90 | if (set_bit(j,bh->b_data)) | ||
91 | panic("new_block: bit already set"); | ||
92 | bh->b_dirt = 1; | ||
93 | j += i*8192 + sb->s_firstdatazone-1; | ||
94 | if (j >= sb->s_nzones) | ||
95 | return 0; | ||
96 | if (!(bh=getblk(dev,j))) | ||
97 | panic("new_block: cannot get block"); | ||
98 | if (bh->b_count != 1) | ||
99 | panic("new block: count is != 1"); | ||
100 | clear_block(bh->b_data); | ||
101 | bh->b_uptodate = 1; | ||
102 | bh->b_dirt = 1; | ||
103 | brelse(bh); | ||
104 | return j; | ||
105 | } | ||
106 | |||
107 | void free_inode(struct m_inode * inode) | ||
108 | { | ||
109 | struct super_block * sb; | ||
110 | struct buffer_head * bh; | ||
111 | |||
112 | if (!inode) | ||
113 | return; | ||
114 | if (!inode->i_dev) { | ||
115 | memset(inode,0,sizeof(*inode)); | ||
116 | return; | ||
117 | } | ||
118 | if (inode->i_count>1) { | ||
119 | printk("trying to free inode with count=%d\n",inode->i_count); | ||
120 | panic("free_inode"); | ||
121 | } | ||
122 | if (inode->i_nlinks) | ||
123 | panic("trying to free inode with links"); | ||
124 | if (!(sb = get_super(inode->i_dev))) | ||
125 | panic("trying to free inode on nonexistent device"); | ||
126 | if (inode->i_num < 1 || inode->i_num > sb->s_ninodes) | ||
127 | panic("trying to free inode 0 or nonexistant inode"); | ||
128 | if (!(bh=sb->s_imap[inode->i_num>>13])) | ||
129 | panic("nonexistent imap in superblock"); | ||
130 | if (clear_bit(inode->i_num&8191,bh->b_data)) | ||
131 | printk("free_inode: bit already cleared.\n\r"); | ||
132 | bh->b_dirt = 1; | ||
133 | memset(inode,0,sizeof(*inode)); | ||
134 | } | ||
135 | |||
136 | struct m_inode * new_inode(int dev) | ||
137 | { | ||
138 | struct m_inode * inode; | ||
139 | struct super_block * sb; | ||
140 | struct buffer_head * bh; | ||
141 | int i,j; | ||
142 | |||
143 | if (!(inode=get_empty_inode())) | ||
144 | return NULL; | ||
145 | if (!(sb = get_super(dev))) | ||
146 | panic("new_inode with unknown device"); | ||
147 | j = 8192; | ||
148 | for (i=0 ; i<8 ; i++) | ||
149 | if ((bh=sb->s_imap[i])) | ||
150 | if ((j=find_first_zero(bh->b_data))<8192) | ||
151 | break; | ||
152 | if (!bh || j >= 8192 || j+i*8192 > sb->s_ninodes) { | ||
153 | iput(inode); | ||
154 | return NULL; | ||
155 | } | ||
156 | if (set_bit(j,bh->b_data)) | ||
157 | panic("new_inode: bit already set"); | ||
158 | bh->b_dirt = 1; | ||
159 | inode->i_count=1; | ||
160 | inode->i_nlinks=1; | ||
161 | inode->i_dev=dev; | ||
162 | inode->i_uid=current->euid; | ||
163 | inode->i_gid=current->egid; | ||
164 | inode->i_dirt=1; | ||
165 | inode->i_num = j + i*8192; | ||
166 | inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; | ||
167 | return inode; | ||
168 | } | ||