This source file includes following definitions.
- ext_put_inode
- ext_put_super
- ext_read_super
- ext_write_super
- ext_statfs
- block_bmap
- ext_bmap
- inode_getblk
- block_getblk
- ext_getblk
- ext_bread
- ext_read_inode
- ext_update_inode
- ext_write_inode
- ext_sync_inode
- init_module
- cleanup_module
1
2
3
4
5
6
7
8
9
10
11
12
13 #ifdef MODULE
14 #include <linux/module.h>
15 #include <linux/version.h>
16 #else
17 #define MOD_INC_USE_COUNT
18 #define MOD_DEC_USE_COUNT
19 #endif
20
21 #include <linux/sched.h>
22 #include <linux/ext_fs.h>
23 #include <linux/kernel.h>
24 #include <linux/mm.h>
25 #include <linux/string.h>
26 #include <linux/stat.h>
27 #include <linux/locks.h>
28
29 #include <asm/system.h>
30 #include <asm/segment.h>
31
32 void ext_put_inode(struct inode *inode)
33 {
34 if (inode->i_nlink)
35 return;
36 inode->i_size = 0;
37 ext_truncate(inode);
38 ext_free_inode(inode);
39 }
40
41 void ext_put_super(struct super_block *sb)
42 {
43
44 lock_super(sb);
45 sb->s_dev = 0;
46 if (sb->u.ext_sb.s_firstfreeinodeblock)
47 brelse (sb->u.ext_sb.s_firstfreeinodeblock);
48 if (sb->u.ext_sb.s_firstfreeblock)
49 brelse (sb->u.ext_sb.s_firstfreeblock);
50 unlock_super(sb);
51 MOD_DEC_USE_COUNT;
52 return;
53 }
54
55 static struct super_operations ext_sops = {
56 ext_read_inode,
57 NULL,
58 ext_write_inode,
59 ext_put_inode,
60 ext_put_super,
61 ext_write_super,
62 ext_statfs,
63 NULL
64 };
65
66 struct super_block *ext_read_super(struct super_block *s,void *data,
67 int silent)
68 {
69 struct buffer_head *bh;
70 struct ext_super_block *es;
71 int dev = s->s_dev,block;
72
73 MOD_INC_USE_COUNT;
74 lock_super(s);
75 set_blocksize(dev, BLOCK_SIZE);
76 if (!(bh = bread(dev, 1, BLOCK_SIZE))) {
77 s->s_dev=0;
78 unlock_super(s);
79 printk("EXT-fs: unable to read superblock\n");
80 MOD_DEC_USE_COUNT;
81 return NULL;
82 }
83 es = (struct ext_super_block *) bh->b_data;
84 s->s_blocksize = 1024;
85 s->s_blocksize_bits = 10;
86 s->u.ext_sb.s_ninodes = es->s_ninodes;
87 s->u.ext_sb.s_nzones = es->s_nzones;
88 s->u.ext_sb.s_firstdatazone = es->s_firstdatazone;
89 s->u.ext_sb.s_log_zone_size = es->s_log_zone_size;
90 s->u.ext_sb.s_max_size = es->s_max_size;
91 s->s_magic = es->s_magic;
92 s->u.ext_sb.s_firstfreeblocknumber = es->s_firstfreeblock;
93 s->u.ext_sb.s_freeblockscount = es->s_freeblockscount;
94 s->u.ext_sb.s_firstfreeinodenumber = es->s_firstfreeinode;
95 s->u.ext_sb.s_freeinodescount = es->s_freeinodescount;
96 brelse(bh);
97 if (s->s_magic != EXT_SUPER_MAGIC) {
98 s->s_dev = 0;
99 unlock_super(s);
100 if (!silent)
101 printk("VFS: Can't find an extfs filesystem on dev 0x%04x.\n",
102 dev);
103 MOD_DEC_USE_COUNT;
104 return NULL;
105 }
106 if (!s->u.ext_sb.s_firstfreeblocknumber)
107 s->u.ext_sb.s_firstfreeblock = NULL;
108 else
109 if (!(s->u.ext_sb.s_firstfreeblock = bread(dev,
110 s->u.ext_sb.s_firstfreeblocknumber, BLOCK_SIZE))) {
111 printk("ext_read_super: unable to read first free block\n");
112 s->s_dev = 0;
113 unlock_super(s);
114 MOD_DEC_USE_COUNT;
115 return NULL;
116 }
117 if (!s->u.ext_sb.s_firstfreeinodenumber)
118 s->u.ext_sb.s_firstfreeinodeblock = NULL;
119 else {
120 block = 2 + (s->u.ext_sb.s_firstfreeinodenumber - 1) / EXT_INODES_PER_BLOCK;
121 if (!(s->u.ext_sb.s_firstfreeinodeblock = bread(dev, block, BLOCK_SIZE))) {
122 printk("ext_read_super: unable to read first free inode block\n");
123 brelse(s->u.ext_sb.s_firstfreeblock);
124 s->s_dev = 0;
125 unlock_super (s);
126 MOD_DEC_USE_COUNT;
127 return NULL;
128 }
129 }
130 unlock_super(s);
131
132 s->s_dev = dev;
133 s->s_op = &ext_sops;
134 if (!(s->s_mounted = iget(s,EXT_ROOT_INO))) {
135 s->s_dev=0;
136 printk("EXT-fs: get root inode failed\n");
137 MOD_DEC_USE_COUNT;
138 return NULL;
139 }
140 return s;
141 }
142
143 void ext_write_super (struct super_block *sb)
144 {
145 struct buffer_head * bh;
146 struct ext_super_block * es;
147
148 if (!(bh = bread(sb->s_dev, 1, BLOCK_SIZE))) {
149 printk ("ext_write_super: bread failed\n");
150 return;
151 }
152 es = (struct ext_super_block *) bh->b_data;
153 es->s_firstfreeblock = sb->u.ext_sb.s_firstfreeblocknumber;
154 es->s_freeblockscount = sb->u.ext_sb.s_freeblockscount;
155 es->s_firstfreeinode = sb->u.ext_sb.s_firstfreeinodenumber;
156 es->s_freeinodescount = sb->u.ext_sb.s_freeinodescount;
157 mark_buffer_dirty(bh, 1);
158 brelse (bh);
159 sb->s_dirt = 0;
160 }
161
162 void ext_statfs (struct super_block *sb, struct statfs *buf, int bufsiz)
163 {
164 struct statfs tmp;
165
166 tmp.f_type = EXT_SUPER_MAGIC;
167 tmp.f_bsize = 1024;
168 tmp.f_blocks = sb->u.ext_sb.s_nzones << sb->u.ext_sb.s_log_zone_size;
169 tmp.f_bfree = ext_count_free_blocks(sb);
170 tmp.f_bavail = tmp.f_bfree;
171 tmp.f_files = sb->u.ext_sb.s_ninodes;
172 tmp.f_ffree = ext_count_free_inodes(sb);
173 tmp.f_namelen = EXT_NAME_LEN;
174 memcpy_tofs(buf, &tmp, bufsiz);
175 }
176
177 #define inode_bmap(inode,nr) ((inode)->u.ext_i.i_data[(nr)])
178
179 static int block_bmap(struct buffer_head * bh, int nr)
180 {
181 int tmp;
182
183 if (!bh)
184 return 0;
185 tmp = ((unsigned long *) bh->b_data)[nr];
186 brelse(bh);
187 return tmp;
188 }
189
190 int ext_bmap(struct inode * inode,int block)
191 {
192 int i;
193
194 if (block<0) {
195 printk("ext_bmap: block<0");
196 return 0;
197 }
198 if (block >= 9+256+256*256+256*256*256) {
199 printk("ext_bmap: block>big");
200 return 0;
201 }
202 if (block<9)
203 return inode_bmap(inode,block);
204 block -= 9;
205 if (block<256) {
206 i = inode_bmap(inode,9);
207 if (!i)
208 return 0;
209 return block_bmap(bread(inode->i_dev,i,BLOCK_SIZE),block);
210 }
211 block -= 256;
212 if (block<256*256) {
213 i = inode_bmap(inode,10);
214 if (!i)
215 return 0;
216 i = block_bmap(bread(inode->i_dev,i,BLOCK_SIZE),block>>8);
217 if (!i)
218 return 0;
219 return block_bmap(bread(inode->i_dev,i,BLOCK_SIZE),block & 255);
220 }
221 block -= 256*256;
222 i = inode_bmap(inode,11);
223 if (!i)
224 return 0;
225 i = block_bmap(bread(inode->i_dev,i,BLOCK_SIZE),block>>16);
226 if (!i)
227 return 0;
228 i = block_bmap(bread(inode->i_dev,i,BLOCK_SIZE),(block>>8) & 255);
229 if (!i)
230 return 0;
231 return block_bmap(bread(inode->i_dev,i,BLOCK_SIZE),block & 255);
232 }
233
234 static struct buffer_head * inode_getblk(struct inode * inode, int nr, int create)
235 {
236 int tmp;
237 unsigned long * p;
238 struct buffer_head * result;
239
240 p = inode->u.ext_i.i_data + nr;
241 repeat:
242 tmp = *p;
243 if (tmp) {
244 result = getblk(inode->i_dev, tmp, BLOCK_SIZE);
245 if (tmp == *p)
246 return result;
247 brelse(result);
248 goto repeat;
249 }
250 if (!create)
251 return NULL;
252 tmp = ext_new_block(inode->i_sb);
253 if (!tmp)
254 return NULL;
255 result = getblk(inode->i_dev, tmp, BLOCK_SIZE);
256 if (*p) {
257 ext_free_block(inode->i_sb,tmp);
258 brelse(result);
259 goto repeat;
260 }
261 *p = tmp;
262 inode->i_ctime = CURRENT_TIME;
263 inode->i_dirt = 1;
264 return result;
265 }
266
267 static struct buffer_head * block_getblk(struct inode * inode,
268 struct buffer_head * bh, int nr, int create)
269 {
270 int tmp;
271 unsigned long * p;
272 struct buffer_head * result;
273
274 if (!bh)
275 return NULL;
276 if (!bh->b_uptodate) {
277 ll_rw_block(READ, 1, &bh);
278 wait_on_buffer(bh);
279 if (!bh->b_uptodate) {
280 brelse(bh);
281 return NULL;
282 }
283 }
284 p = nr + (unsigned long *) bh->b_data;
285 repeat:
286 tmp = *p;
287 if (tmp) {
288 result = getblk(bh->b_dev, tmp, BLOCK_SIZE);
289 if (tmp == *p) {
290 brelse(bh);
291 return result;
292 }
293 brelse(result);
294 goto repeat;
295 }
296 if (!create) {
297 brelse(bh);
298 return NULL;
299 }
300 tmp = ext_new_block(inode->i_sb);
301 if (!tmp) {
302 brelse(bh);
303 return NULL;
304 }
305 result = getblk(bh->b_dev, tmp, BLOCK_SIZE);
306 if (*p) {
307 ext_free_block(inode->i_sb,tmp);
308 brelse(result);
309 goto repeat;
310 }
311 *p = tmp;
312 mark_buffer_dirty(bh, 1);
313 brelse(bh);
314 return result;
315 }
316
317 struct buffer_head * ext_getblk(struct inode * inode, int block, int create)
318 {
319 struct buffer_head * bh;
320
321 if (block<0) {
322 printk("ext_getblk: block<0\n");
323 return NULL;
324 }
325 if (block >= 9+256+256*256+256*256*256) {
326 printk("ext_getblk: block>big\n");
327 return NULL;
328 }
329 if (block<9)
330 return inode_getblk(inode,block,create);
331 block -= 9;
332 if (block<256) {
333 bh = inode_getblk(inode,9,create);
334 return block_getblk(inode,bh,block,create);
335 }
336 block -= 256;
337 if (block<256*256) {
338 bh = inode_getblk(inode,10,create);
339 bh = block_getblk(inode,bh,block>>8,create);
340 return block_getblk(inode,bh,block & 255,create);
341 }
342 block -= 256*256;
343 bh = inode_getblk(inode,11,create);
344 bh = block_getblk(inode,bh,block>>16,create);
345 bh = block_getblk(inode,bh,(block>>8) & 255,create);
346 return block_getblk(inode,bh,block & 255,create);
347 }
348
349 struct buffer_head * ext_bread(struct inode * inode, int block, int create)
350 {
351 struct buffer_head * bh;
352
353 bh = ext_getblk(inode,block,create);
354 if (!bh || bh->b_uptodate)
355 return bh;
356 ll_rw_block(READ, 1, &bh);
357 wait_on_buffer(bh);
358 if (bh->b_uptodate)
359 return bh;
360 brelse(bh);
361 return NULL;
362 }
363
364 void ext_read_inode(struct inode * inode)
365 {
366 struct buffer_head * bh;
367 struct ext_inode * raw_inode;
368 int block;
369
370 block = 2 + (inode->i_ino-1)/EXT_INODES_PER_BLOCK;
371 if (!(bh=bread(inode->i_dev, block, BLOCK_SIZE)))
372 panic("unable to read i-node block");
373 raw_inode = ((struct ext_inode *) bh->b_data) +
374 (inode->i_ino-1)%EXT_INODES_PER_BLOCK;
375 inode->i_mode = raw_inode->i_mode;
376 inode->i_uid = raw_inode->i_uid;
377 inode->i_gid = raw_inode->i_gid;
378 inode->i_nlink = raw_inode->i_nlinks;
379 inode->i_size = raw_inode->i_size;
380 inode->i_mtime = inode->i_atime = inode->i_ctime = raw_inode->i_time;
381 inode->i_blocks = inode->i_blksize = 0;
382 if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
383 inode->i_rdev = raw_inode->i_zone[0];
384 else for (block = 0; block < 12; block++)
385 inode->u.ext_i.i_data[block] = raw_inode->i_zone[block];
386 brelse(bh);
387 inode->i_op = NULL;
388 if (S_ISREG(inode->i_mode))
389 inode->i_op = &ext_file_inode_operations;
390 else if (S_ISDIR(inode->i_mode))
391 inode->i_op = &ext_dir_inode_operations;
392 else if (S_ISLNK(inode->i_mode))
393 inode->i_op = &ext_symlink_inode_operations;
394 else if (S_ISCHR(inode->i_mode))
395 inode->i_op = &chrdev_inode_operations;
396 else if (S_ISBLK(inode->i_mode))
397 inode->i_op = &blkdev_inode_operations;
398 else if (S_ISFIFO(inode->i_mode))
399 init_fifo(inode);
400 }
401
402 static struct buffer_head * ext_update_inode(struct inode * inode)
403 {
404 struct buffer_head * bh;
405 struct ext_inode * raw_inode;
406 int block;
407
408 block = 2 + (inode->i_ino-1)/EXT_INODES_PER_BLOCK;
409 if (!(bh=bread(inode->i_dev, block, BLOCK_SIZE)))
410 panic("unable to read i-node block");
411 raw_inode = ((struct ext_inode *)bh->b_data) +
412 (inode->i_ino-1)%EXT_INODES_PER_BLOCK;
413 raw_inode->i_mode = inode->i_mode;
414 raw_inode->i_uid = inode->i_uid;
415 raw_inode->i_gid = inode->i_gid;
416 raw_inode->i_nlinks = inode->i_nlink;
417 raw_inode->i_size = inode->i_size;
418 raw_inode->i_time = inode->i_mtime;
419 if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
420 raw_inode->i_zone[0] = inode->i_rdev;
421 else for (block = 0; block < 12; block++)
422 raw_inode->i_zone[block] = inode->u.ext_i.i_data[block];
423 mark_buffer_dirty(bh, 1);
424 inode->i_dirt=0;
425 return bh;
426 }
427
428 void ext_write_inode(struct inode * inode)
429 {
430 struct buffer_head *bh;
431 bh = ext_update_inode (inode);
432 brelse(bh);
433 }
434
435 int ext_sync_inode (struct inode *inode)
436 {
437 int err = 0;
438 struct buffer_head *bh;
439
440 bh = ext_update_inode(inode);
441 if (bh && bh->b_dirt)
442 {
443 ll_rw_block(WRITE, 1, &bh);
444 wait_on_buffer(bh);
445 if (bh->b_req && !bh->b_uptodate)
446 {
447 printk ("IO error syncing ext inode [%04x:%08lx]\n",
448 inode->i_dev, inode->i_ino);
449 err = -1;
450 }
451 }
452 else if (!bh)
453 err = -1;
454 brelse (bh);
455 return err;
456 }
457
458 #ifdef MODULE
459
460 char kernel_version[] = UTS_RELEASE;
461
462 static struct file_system_type ext_fs_type = {
463 ext_read_super, "ext", 1, NULL
464 };
465
466 int init_module(void)
467 {
468 register_filesystem(&ext_fs_type);
469 return 0;
470 }
471
472 void cleanup_module(void)
473 {
474 unregister_filesystem(&ext_fs_type);
475 }
476
477 #endif