diff options
Diffstat (limited to 'src/fs/inode.c')
-rw-r--r-- | src/fs/inode.c | 338 |
1 files changed, 338 insertions, 0 deletions
diff --git a/src/fs/inode.c b/src/fs/inode.c new file mode 100644 index 0000000..d0b1c32 --- /dev/null +++ b/src/fs/inode.c | |||
@@ -0,0 +1,338 @@ | |||
1 | /* | ||
2 | * linux/fs/inode.c | ||
3 | * | ||
4 | * (C) 1991 Linus Torvalds | ||
5 | */ | ||
6 | |||
7 | #include <string.h> | ||
8 | #include <sys/stat.h> | ||
9 | |||
10 | #include <linux/sched.h> | ||
11 | #include <linux/kernel.h> | ||
12 | #include <linux/mm.h> | ||
13 | #include <asm/system.h> | ||
14 | |||
15 | struct m_inode inode_table[NR_INODE]={{0,},}; | ||
16 | |||
17 | static void read_inode(struct m_inode * inode); | ||
18 | static void write_inode(struct m_inode * inode); | ||
19 | |||
20 | static inline void wait_on_inode(struct m_inode * inode) | ||
21 | { | ||
22 | cli(); | ||
23 | while (inode->i_lock) | ||
24 | sleep_on(&inode->i_wait); | ||
25 | sti(); | ||
26 | } | ||
27 | |||
28 | static inline void lock_inode(struct m_inode * inode) | ||
29 | { | ||
30 | cli(); | ||
31 | while (inode->i_lock) | ||
32 | sleep_on(&inode->i_wait); | ||
33 | inode->i_lock=1; | ||
34 | sti(); | ||
35 | } | ||
36 | |||
37 | static inline void unlock_inode(struct m_inode * inode) | ||
38 | { | ||
39 | inode->i_lock=0; | ||
40 | wake_up(&inode->i_wait); | ||
41 | } | ||
42 | |||
43 | void invalidate_inodes(int dev) | ||
44 | { | ||
45 | int i; | ||
46 | struct m_inode * inode; | ||
47 | |||
48 | inode = 0+inode_table; | ||
49 | for(i=0 ; i<NR_INODE ; i++,inode++) { | ||
50 | wait_on_inode(inode); | ||
51 | if (inode->i_dev == dev) { | ||
52 | if (inode->i_count) | ||
53 | printk("inode in use on removed disk\n\r"); | ||
54 | inode->i_dev = inode->i_dirt = 0; | ||
55 | } | ||
56 | } | ||
57 | } | ||
58 | |||
59 | void sync_inodes(void) | ||
60 | { | ||
61 | int i; | ||
62 | struct m_inode * inode; | ||
63 | |||
64 | inode = 0+inode_table; | ||
65 | for(i=0 ; i<NR_INODE ; i++,inode++) { | ||
66 | wait_on_inode(inode); | ||
67 | if (inode->i_dirt && !inode->i_pipe) | ||
68 | write_inode(inode); | ||
69 | } | ||
70 | } | ||
71 | |||
72 | static int _bmap(struct m_inode * inode,int block,int create) | ||
73 | { | ||
74 | struct buffer_head * bh; | ||
75 | int i; | ||
76 | |||
77 | if (block<0) | ||
78 | panic("_bmap: block<0"); | ||
79 | if (block >= 7+512+512*512) | ||
80 | panic("_bmap: block>big"); | ||
81 | if (block<7) { | ||
82 | if (create && !inode->i_zone[block]) | ||
83 | if ((inode->i_zone[block]=new_block(inode->i_dev))) { | ||
84 | inode->i_ctime=CURRENT_TIME; | ||
85 | inode->i_dirt=1; | ||
86 | } | ||
87 | return inode->i_zone[block]; | ||
88 | } | ||
89 | block -= 7; | ||
90 | if (block<512) { | ||
91 | if (create && !inode->i_zone[7]) | ||
92 | if ((inode->i_zone[7]=new_block(inode->i_dev))) { | ||
93 | inode->i_dirt=1; | ||
94 | inode->i_ctime=CURRENT_TIME; | ||
95 | } | ||
96 | if (!inode->i_zone[7]) | ||
97 | return 0; | ||
98 | if (!(bh = bread(inode->i_dev,inode->i_zone[7]))) | ||
99 | return 0; | ||
100 | i = ((unsigned short *) (bh->b_data))[block]; | ||
101 | if (create && !i) | ||
102 | if ((i=new_block(inode->i_dev))) { | ||
103 | ((unsigned short *) (bh->b_data))[block]=i; | ||
104 | bh->b_dirt=1; | ||
105 | } | ||
106 | brelse(bh); | ||
107 | return i; | ||
108 | } | ||
109 | block -= 512; | ||
110 | if (create && !inode->i_zone[8]) | ||
111 | if ((inode->i_zone[8]=new_block(inode->i_dev))) { | ||
112 | inode->i_dirt=1; | ||
113 | inode->i_ctime=CURRENT_TIME; | ||
114 | } | ||
115 | if (!inode->i_zone[8]) | ||
116 | return 0; | ||
117 | if (!(bh=bread(inode->i_dev,inode->i_zone[8]))) | ||
118 | return 0; | ||
119 | i = ((unsigned short *)bh->b_data)[block>>9]; | ||
120 | if (create && !i) | ||
121 | if ((i=new_block(inode->i_dev))) { | ||
122 | ((unsigned short *) (bh->b_data))[block>>9]=i; | ||
123 | bh->b_dirt=1; | ||
124 | } | ||
125 | brelse(bh); | ||
126 | if (!i) | ||
127 | return 0; | ||
128 | if (!(bh=bread(inode->i_dev,i))) | ||
129 | return 0; | ||
130 | i = ((unsigned short *)bh->b_data)[block&511]; | ||
131 | if (create && !i) | ||
132 | if ((i=new_block(inode->i_dev))) { | ||
133 | ((unsigned short *) (bh->b_data))[block&511]=i; | ||
134 | bh->b_dirt=1; | ||
135 | } | ||
136 | brelse(bh); | ||
137 | return i; | ||
138 | } | ||
139 | |||
140 | int bmap(struct m_inode * inode,int block) | ||
141 | { | ||
142 | return _bmap(inode,block,0); | ||
143 | } | ||
144 | |||
145 | int create_block(struct m_inode * inode, int block) | ||
146 | { | ||
147 | return _bmap(inode,block,1); | ||
148 | } | ||
149 | |||
150 | void iput(struct m_inode * inode) | ||
151 | { | ||
152 | if (!inode) | ||
153 | return; | ||
154 | wait_on_inode(inode); | ||
155 | if (!inode->i_count) | ||
156 | panic("iput: trying to free free inode"); | ||
157 | if (inode->i_pipe) { | ||
158 | wake_up(&inode->i_wait); | ||
159 | if (--inode->i_count) | ||
160 | return; | ||
161 | free_page(inode->i_size); | ||
162 | inode->i_count=0; | ||
163 | inode->i_dirt=0; | ||
164 | inode->i_pipe=0; | ||
165 | return; | ||
166 | } | ||
167 | if (!inode->i_dev) { | ||
168 | inode->i_count--; | ||
169 | return; | ||
170 | } | ||
171 | if (S_ISBLK(inode->i_mode)) { | ||
172 | sync_dev(inode->i_zone[0]); | ||
173 | wait_on_inode(inode); | ||
174 | } | ||
175 | repeat: | ||
176 | if (inode->i_count>1) { | ||
177 | inode->i_count--; | ||
178 | return; | ||
179 | } | ||
180 | if (!inode->i_nlinks) { | ||
181 | truncate(inode); | ||
182 | free_inode(inode); | ||
183 | return; | ||
184 | } | ||
185 | if (inode->i_dirt) { | ||
186 | write_inode(inode); /* we can sleep - so do again */ | ||
187 | wait_on_inode(inode); | ||
188 | goto repeat; | ||
189 | } | ||
190 | inode->i_count--; | ||
191 | return; | ||
192 | } | ||
193 | |||
194 | struct m_inode * get_empty_inode(void) | ||
195 | { | ||
196 | struct m_inode * inode; | ||
197 | static struct m_inode * last_inode = inode_table; | ||
198 | int i; | ||
199 | |||
200 | do { | ||
201 | inode = NULL; | ||
202 | for (i = NR_INODE; i ; i--) { | ||
203 | if (++last_inode >= inode_table + NR_INODE) | ||
204 | last_inode = inode_table; | ||
205 | if (!last_inode->i_count) { | ||
206 | inode = last_inode; | ||
207 | if (!inode->i_dirt && !inode->i_lock) | ||
208 | break; | ||
209 | } | ||
210 | } | ||
211 | if (!inode) { | ||
212 | for (i=0 ; i<NR_INODE ; i++) | ||
213 | printk("%04x: %6d\t",inode_table[i].i_dev, | ||
214 | inode_table[i].i_num); | ||
215 | panic("No free inodes in mem"); | ||
216 | } | ||
217 | wait_on_inode(inode); | ||
218 | while (inode->i_dirt) { | ||
219 | write_inode(inode); | ||
220 | wait_on_inode(inode); | ||
221 | } | ||
222 | } while (inode->i_count); | ||
223 | memset(inode,0,sizeof(*inode)); | ||
224 | inode->i_count = 1; | ||
225 | return inode; | ||
226 | } | ||
227 | |||
228 | struct m_inode * get_pipe_inode(void) | ||
229 | { | ||
230 | struct m_inode * inode; | ||
231 | |||
232 | if (!(inode = get_empty_inode())) | ||
233 | return NULL; | ||
234 | if (!(inode->i_size=get_free_page())) { | ||
235 | inode->i_count = 0; | ||
236 | return NULL; | ||
237 | } | ||
238 | inode->i_count = 2; /* sum of readers/writers */ | ||
239 | PIPE_HEAD(*inode) = PIPE_TAIL(*inode) = 0; | ||
240 | inode->i_pipe = 1; | ||
241 | return inode; | ||
242 | } | ||
243 | |||
244 | struct m_inode * iget(int dev,int nr) | ||
245 | { | ||
246 | struct m_inode * inode, * empty; | ||
247 | |||
248 | if (!dev) | ||
249 | panic("iget with dev==0"); | ||
250 | empty = get_empty_inode(); | ||
251 | inode = inode_table; | ||
252 | while (inode < NR_INODE+inode_table) { | ||
253 | if (inode->i_dev != dev || inode->i_num != nr) { | ||
254 | inode++; | ||
255 | continue; | ||
256 | } | ||
257 | wait_on_inode(inode); | ||
258 | if (inode->i_dev != dev || inode->i_num != nr) { | ||
259 | inode = inode_table; | ||
260 | continue; | ||
261 | } | ||
262 | inode->i_count++; | ||
263 | if (inode->i_mount) { | ||
264 | int i; | ||
265 | |||
266 | for (i = 0 ; i<NR_SUPER ; i++) | ||
267 | if (super_block[i].s_imount==inode) | ||
268 | break; | ||
269 | if (i >= NR_SUPER) { | ||
270 | printk("Mounted inode hasn't got sb\n"); | ||
271 | if (empty) | ||
272 | iput(empty); | ||
273 | return inode; | ||
274 | } | ||
275 | iput(inode); | ||
276 | dev = super_block[i].s_dev; | ||
277 | nr = ROOT_INO; | ||
278 | inode = inode_table; | ||
279 | continue; | ||
280 | } | ||
281 | if (empty) | ||
282 | iput(empty); | ||
283 | return inode; | ||
284 | } | ||
285 | if (!empty) | ||
286 | return (NULL); | ||
287 | inode=empty; | ||
288 | inode->i_dev = dev; | ||
289 | inode->i_num = nr; | ||
290 | read_inode(inode); | ||
291 | return inode; | ||
292 | } | ||
293 | |||
294 | static void read_inode(struct m_inode * inode) | ||
295 | { | ||
296 | struct super_block * sb; | ||
297 | struct buffer_head * bh; | ||
298 | int block; | ||
299 | |||
300 | lock_inode(inode); | ||
301 | if (!(sb=get_super(inode->i_dev))) | ||
302 | panic("trying to read inode without dev"); | ||
303 | block = 2 + sb->s_imap_blocks + sb->s_zmap_blocks + | ||
304 | (inode->i_num-1)/INODES_PER_BLOCK; | ||
305 | if (!(bh=bread(inode->i_dev,block))) | ||
306 | panic("unable to read i-node block"); | ||
307 | *(struct d_inode *)inode = | ||
308 | ((struct d_inode *)bh->b_data) | ||
309 | [(inode->i_num-1)%INODES_PER_BLOCK]; | ||
310 | brelse(bh); | ||
311 | unlock_inode(inode); | ||
312 | } | ||
313 | |||
314 | static void write_inode(struct m_inode * inode) | ||
315 | { | ||
316 | struct super_block * sb; | ||
317 | struct buffer_head * bh; | ||
318 | int block; | ||
319 | |||
320 | lock_inode(inode); | ||
321 | if (!inode->i_dirt || !inode->i_dev) { | ||
322 | unlock_inode(inode); | ||
323 | return; | ||
324 | } | ||
325 | if (!(sb=get_super(inode->i_dev))) | ||
326 | panic("trying to write inode without device"); | ||
327 | block = 2 + sb->s_imap_blocks + sb->s_zmap_blocks + | ||
328 | (inode->i_num-1)/INODES_PER_BLOCK; | ||
329 | if (!(bh=bread(inode->i_dev,block))) | ||
330 | panic("unable to read i-node block"); | ||
331 | ((struct d_inode *)bh->b_data) | ||
332 | [(inode->i_num-1)%INODES_PER_BLOCK] = | ||
333 | *(struct d_inode *)inode; | ||
334 | bh->b_dirt=1; | ||
335 | inode->i_dirt=0; | ||
336 | brelse(bh); | ||
337 | unlock_inode(inode); | ||
338 | } | ||