summaryrefslogtreecommitdiffstats
path: root/src/fs/bitmap.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/fs/bitmap.c')
-rw-r--r--src/fs/bitmap.c168
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) ({\
20register int res ; \
21__asm__ __volatile__("btsl %2,%3\n\tsetb %%al": \
22"=a" (res):"0" (0),"r" (nr),"m" (*(addr))); \
23res;})
24
25#define clear_bit(nr,addr) ({\
26register int res ; \
27__asm__ __volatile__("btrl %2,%3\n\tsetnb %%al": \
28"=a" (res):"0" (0),"r" (nr),"m" (*(addr))); \
29res;})
30
31#define find_first_zero(addr) ({ \
32int __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
47void 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
75int 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
107void 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
136struct 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}