* added 0.99 linux version
[mascara-docs.git] / i386 / linux / linux-0.99 / fs / xiafs / inode.c
blob84e2109ec765cc194032f349f7b09149faaa9c99
1 /*
2 * linux/fs/xiafs/inode.c
4 * Copyright (C) Q. Frank Xia, 1993.
5 *
6 * Based on Linus' minix/inode.c
7 * Copyright (C) Linus Torvalds, 1991, 1992.
9 * This software may be redistributed per Linux Copyright.
12 #include <linux/sched.h>
13 #include <linux/xia_fs.h>
14 #include <linux/kernel.h>
15 #include <linux/mm.h>
16 #include <linux/string.h>
17 #include <linux/stat.h>
18 #include <linux/locks.h>
19 #include <asm/system.h>
20 #include <asm/segment.h>
22 #include "xiafs_mac.h"
24 static u_long random_nr;
26 void xiafs_put_inode(struct inode *inode)
28 if (inode->i_nlink)
29 return;
30 inode->i_size = 0;
31 xiafs_truncate(inode);
32 xiafs_free_inode(inode);
35 void xiafs_put_super(struct super_block *sb)
37 int i;
39 lock_super(sb);
40 sb->s_dev = 0;
41 for(i = 0 ; i < _XIAFS_IMAP_SLOTS ; i++)
42 brelse(sb->u.xiafs_sb.s_imap_buf[i]);
43 for(i = 0 ; i < _XIAFS_ZMAP_SLOTS ; i++)
44 brelse(sb->u.xiafs_sb.s_zmap_buf[i]);
45 unlock_super(sb);
48 static struct super_operations xiafs_sops = {
49 xiafs_read_inode,
50 NULL,
51 xiafs_write_inode,
52 xiafs_put_inode,
53 xiafs_put_super,
54 NULL,
55 xiafs_statfs,
56 NULL
59 struct super_block *xiafs_read_super(struct super_block *s, void *data,
60 int silent)
62 struct buffer_head *bh;
63 struct xiafs_super_block *sp;
64 int i, z, dev;
66 dev=s->s_dev;
67 lock_super(s);
69 set_blocksize(dev, BLOCK_SIZE);
71 if (!(bh = bread(dev, 0, BLOCK_SIZE))) {
72 s->s_dev=0;
73 unlock_super(s);
74 printk("XIA-FS: read super_block failed (%s %d)\n", WHERE_ERR);
75 return NULL;
77 sp = (struct xiafs_super_block *) bh->b_data;
78 s->s_magic = sp->s_magic;
79 if (s->s_magic != _XIAFS_SUPER_MAGIC) {
80 s->s_dev = 0;
81 unlock_super(s);
82 brelse(bh);
83 if (!silent)
84 printk("VFS: Can't find a xiafs filesystem on dev 0x%04x.\n",
85 dev);
86 return NULL;
88 s->s_blocksize = sp->s_zone_size;
89 s->s_blocksize_bits = 10 + sp->s_zone_shift;
90 if (s->s_blocksize != BLOCK_SIZE &&
91 (s->s_blocksize == 1024 || s->s_blocksize == 2048 ||
92 s->s_blocksize == 4096)) {
93 brelse(bh);
94 set_blocksize(dev, s->s_blocksize);
95 bh = bread (dev, 0, s->s_blocksize);
96 if(!bh) return NULL;
97 sp = (struct xiafs_super_block *) (((char *)bh->b_data) + BLOCK_SIZE) ;
99 s->u.xiafs_sb.s_nzones = sp->s_nzones;
100 s->u.xiafs_sb.s_ninodes = sp->s_ninodes;
101 s->u.xiafs_sb.s_ndatazones = sp->s_ndatazones;
102 s->u.xiafs_sb.s_imap_zones = sp->s_imap_zones;
103 s->u.xiafs_sb.s_zmap_zones = sp->s_zmap_zones;
104 s->u.xiafs_sb.s_firstdatazone = sp->s_firstdatazone;
105 s->u.xiafs_sb.s_zone_shift = sp->s_zone_shift;
106 s->u.xiafs_sb.s_max_size = sp->s_max_size;
107 brelse(bh);
108 for (i=0;i < _XIAFS_IMAP_SLOTS;i++) {
109 s->u.xiafs_sb.s_imap_buf[i] = NULL;
110 s->u.xiafs_sb.s_imap_iznr[i] = -1;
112 for (i=0;i < _XIAFS_ZMAP_SLOTS;i++) {
113 s->u.xiafs_sb.s_zmap_buf[i] = NULL;
114 s->u.xiafs_sb.s_zmap_zznr[i] = -1;
116 z=1;
117 if ( s->u.xiafs_sb.s_imap_zones > _XIAFS_IMAP_SLOTS )
118 s->u.xiafs_sb.s_imap_cached=1;
119 else {
120 s->u.xiafs_sb.s_imap_cached=0;
121 for (i=0 ; i < s->u.xiafs_sb.s_imap_zones ; i++) {
122 if (!(s->u.xiafs_sb.s_imap_buf[i]=bread(dev, z++, XIAFS_ZSIZE(s))))
123 goto xiafs_read_super_fail;
124 s->u.xiafs_sb.s_imap_iznr[i]=i;
127 if ( s->u.xiafs_sb.s_zmap_zones > _XIAFS_ZMAP_SLOTS )
128 s->u.xiafs_sb.s_zmap_cached=1;
129 else {
130 s->u.xiafs_sb.s_zmap_cached=0;
131 for (i=0 ; i < s->u.xiafs_sb.s_zmap_zones ; i++) {
132 if (!(s->u.xiafs_sb.s_zmap_buf[i]=bread(dev, z++, XIAFS_ZSIZE(s))))
133 goto xiafs_read_super_fail;
134 s->u.xiafs_sb.s_zmap_zznr[i]=i;
137 /* set up enough so that it can read an inode */
138 s->s_dev = dev;
139 s->s_op = &xiafs_sops;
140 s->s_mounted = iget(s, _XIAFS_ROOT_INO);
141 if (!s->s_mounted)
142 goto xiafs_read_super_fail;
143 unlock_super(s);
144 random_nr=CURRENT_TIME;
145 return s;
147 xiafs_read_super_fail:
148 for(i=0; i < _XIAFS_IMAP_SLOTS; i++)
149 brelse(s->u.xiafs_sb.s_imap_buf[i]);
150 for(i=0; i < _XIAFS_ZMAP_SLOTS; i++)
151 brelse(s->u.xiafs_sb.s_zmap_buf[i]);
152 s->s_dev=0;
153 unlock_super(s);
154 printk("XIA-FS: read bitmaps failed (%s %d)\n", WHERE_ERR);
155 return NULL;
158 void xiafs_statfs(struct super_block *sb, struct statfs *buf)
160 long tmp;
162 put_fs_long(_XIAFS_SUPER_MAGIC, &buf->f_type);
163 put_fs_long(XIAFS_ZSIZE(sb), &buf->f_bsize);
164 put_fs_long(sb->u.xiafs_sb.s_ndatazones, &buf->f_blocks);
165 tmp = xiafs_count_free_zones(sb);
166 put_fs_long(tmp, &buf->f_bfree);
167 put_fs_long(tmp, &buf->f_bavail);
168 put_fs_long(sb->u.xiafs_sb.s_ninodes, &buf->f_files);
169 put_fs_long(xiafs_count_free_inodes(sb), &buf->f_ffree);
170 put_fs_long(_XIAFS_NAME_LEN, &buf->f_namelen);
171 /* don't know what should be put in buf->f_fsid */
174 static int zone_bmap(struct buffer_head * bh, int nr)
176 int tmp;
178 if (!bh)
179 return 0;
180 tmp = ((u_long *) bh->b_data)[nr];
181 brelse(bh);
182 return tmp;
185 int xiafs_bmap(struct inode * inode,int zone)
187 int i;
189 if (zone < 0) {
190 printk("XIA-FS: block < 0 (%s %d)\n", WHERE_ERR);
191 return 0;
193 if (zone >= 8+(1+XIAFS_ADDRS_PER_Z(inode->i_sb))*XIAFS_ADDRS_PER_Z(inode->i_sb)) {
194 printk("XIA-FS: zone > big (%s %d)\n", WHERE_ERR);
195 return 0;
197 if (!IS_RDONLY (inode)) {
198 inode->i_atime = CURRENT_TIME;
199 inode->i_dirt = 1;
201 if (zone < 8)
202 return inode->u.xiafs_i.i_zone[zone];
203 zone -= 8;
204 if (zone < XIAFS_ADDRS_PER_Z(inode->i_sb)) {
205 i = inode->u.xiafs_i.i_ind_zone;
206 if (i)
207 i = zone_bmap(bread(inode->i_dev, i, XIAFS_ZSIZE(inode->i_sb)), zone);
208 return i;
210 zone -= XIAFS_ADDRS_PER_Z(inode->i_sb);
211 i = inode->u.xiafs_i.i_dind_zone;
212 if (i)
213 i = zone_bmap(bread(inode->i_dev, i, XIAFS_ZSIZE(inode->i_sb)),
214 zone >> XIAFS_ADDRS_PER_Z_BITS(inode->i_sb));
215 if (i)
216 i= zone_bmap(bread(inode->i_dev,i, XIAFS_ZSIZE(inode->i_sb)),
217 zone & (XIAFS_ADDRS_PER_Z(inode->i_sb)-1));
218 return i;
221 static u_long get_prev_addr(struct inode * inode, int zone)
223 u_long tmp;
225 if (zone > 0)
226 while (--zone >= 0) /* only files with holes suffer */
227 if ((tmp=xiafs_bmap(inode, zone)))
228 return tmp;
229 random_nr=(random_nr+23)%inode->i_sb->u.xiafs_sb.s_ndatazones;
230 return random_nr + inode->i_sb->u.xiafs_sb.s_firstdatazone;
233 static struct buffer_head *
234 dt_getblk(struct inode * inode, u_long *lp, int create, u_long prev_addr)
236 int tmp;
237 struct buffer_head * result;
239 repeat:
240 if ((tmp=*lp)) {
241 result = getblk(inode->i_dev, tmp, XIAFS_ZSIZE(inode->i_sb));
242 if (tmp == *lp)
243 return result;
244 brelse(result);
245 goto repeat;
247 if (!create)
248 return NULL;
249 tmp = xiafs_new_zone(inode->i_sb, prev_addr);
250 if (!tmp)
251 return NULL;
252 result = getblk(inode->i_dev, tmp, XIAFS_ZSIZE(inode->i_sb));
253 if (*lp) {
254 xiafs_free_zone(inode->i_sb, tmp);
255 brelse(result);
256 goto repeat;
258 *lp = tmp;
259 inode->i_blocks+=2 << XIAFS_ZSHIFT(inode->i_sb);
260 return result;
263 static struct buffer_head *
264 indt_getblk(struct inode * inode, struct buffer_head * bh,
265 int nr, int create, u_long prev_addr)
267 int tmp;
268 u_long *lp;
269 struct buffer_head * result;
271 if (!bh)
272 return NULL;
273 if (!bh->b_uptodate) {
274 ll_rw_block(READ, 1, &bh);
275 wait_on_buffer(bh);
276 if (!bh->b_uptodate) {
277 brelse(bh);
278 return NULL;
281 lp = nr + (u_long *) bh->b_data;
282 repeat:
283 if ((tmp=*lp)) {
284 result = getblk(bh->b_dev, tmp, XIAFS_ZSIZE(inode->i_sb));
285 if (tmp == *lp) {
286 brelse(bh);
287 return result;
289 brelse(result);
290 goto repeat;
292 if (!create) {
293 brelse(bh);
294 return NULL;
296 tmp = xiafs_new_zone(inode->i_sb, prev_addr);
297 if (!tmp) {
298 brelse(bh);
299 return NULL;
301 result = getblk(bh->b_dev, tmp, XIAFS_ZSIZE(inode->i_sb));
302 if (*lp) {
303 xiafs_free_zone(inode->i_sb, tmp);
304 brelse(result);
305 goto repeat;
307 *lp = tmp;
308 inode->i_blocks+=2 << XIAFS_ZSHIFT(inode->i_sb);
309 bh->b_dirt = 1;
310 brelse(bh);
311 return result;
314 struct buffer_head * xiafs_getblk(struct inode * inode, int zone, int create)
316 struct buffer_head * bh;
317 u_long prev_addr=0;
319 if (zone<0) {
320 printk("XIA-FS: zone < 0 (%s %d)\n", WHERE_ERR);
321 return NULL;
323 if (zone >= 8+(1+XIAFS_ADDRS_PER_Z(inode->i_sb))*XIAFS_ADDRS_PER_Z(inode->i_sb)) {
324 if (!create)
325 printk("XIA-FS: zone > big (%s %d)\n", WHERE_ERR);
326 return NULL;
328 if (create)
329 prev_addr=get_prev_addr(inode, zone);
330 if (zone < 8)
331 return dt_getblk(inode, zone+inode->u.xiafs_i.i_zone, create, prev_addr);
332 zone -= 8;
333 if (zone < XIAFS_ADDRS_PER_Z(inode->i_sb)) {
334 bh = dt_getblk(inode, &(inode->u.xiafs_i.i_ind_zone), create, prev_addr);
335 bh = indt_getblk(inode, bh, zone, create, prev_addr);
336 return bh;
338 zone -= XIAFS_ADDRS_PER_Z(inode->i_sb);
339 bh = dt_getblk(inode, &(inode->u.xiafs_i.i_dind_zone), create, prev_addr);
340 bh = indt_getblk(inode, bh, zone>>XIAFS_ADDRS_PER_Z_BITS(inode->i_sb),
341 create, prev_addr);
342 bh = indt_getblk(inode, bh, zone&(XIAFS_ADDRS_PER_Z(inode->i_sb)-1),
343 create, prev_addr);
344 return bh;
347 struct buffer_head * xiafs_bread(struct inode * inode, int zone, int create)
349 struct buffer_head * bh;
351 bh = xiafs_getblk(inode, zone, create);
352 if (!bh || bh->b_uptodate)
353 return bh;
354 ll_rw_block(READ, 1, &bh);
355 wait_on_buffer(bh);
356 if (bh->b_uptodate)
357 return bh;
358 brelse(bh);
359 return NULL;
362 void xiafs_read_inode(struct inode * inode)
364 struct buffer_head * bh;
365 struct xiafs_inode * raw_inode;
366 int zone;
367 ino_t ino;
369 ino = inode->i_ino;
370 inode->i_op = NULL;
371 inode->i_mode=0;
372 if (!ino || ino > inode->i_sb->u.xiafs_sb.s_ninodes) {
373 printk("XIA-FS: bad inode number (%s %d)\n", WHERE_ERR);
374 return;
376 zone = 1 + inode->i_sb->u.xiafs_sb.s_imap_zones +
377 inode->i_sb->u.xiafs_sb.s_zmap_zones +
378 (ino-1)/ XIAFS_INODES_PER_Z(inode->i_sb);
379 if (!(bh=bread(inode->i_dev, zone, XIAFS_ZSIZE(inode->i_sb)))) {
380 printk("XIA-FS: read i-node zone failed (%s %d)\n", WHERE_ERR);
381 return;
383 raw_inode = ((struct xiafs_inode *) bh->b_data) +
384 ((ino-1) & (XIAFS_INODES_PER_Z(inode->i_sb) - 1));
385 inode->i_mode = raw_inode->i_mode;
386 inode->i_uid = raw_inode->i_uid;
387 inode->i_gid = raw_inode->i_gid;
388 inode->i_nlink = raw_inode->i_nlinks;
389 inode->i_size = raw_inode->i_size;
390 inode->i_mtime = raw_inode->i_mtime;
391 inode->i_atime = raw_inode->i_atime;
392 inode->i_ctime = raw_inode->i_ctime;
393 inode->i_blksize = XIAFS_ZSIZE(inode->i_sb);
394 if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) {
395 inode->i_blocks=0;
396 inode->i_rdev = raw_inode->i_zone[0];
397 } else {
398 XIAFS_GET_BLOCKS(raw_inode, inode->i_blocks);
399 for (zone = 0; zone < 8; zone++)
400 inode->u.xiafs_i.i_zone[zone] = raw_inode->i_zone[zone] & 0xffffff;
401 inode->u.xiafs_i.i_ind_zone = raw_inode->i_ind_zone & 0xffffff;
402 inode->u.xiafs_i.i_dind_zone = raw_inode->i_dind_zone & 0xffffff;
404 brelse(bh);
405 if (S_ISREG(inode->i_mode))
406 inode->i_op = &xiafs_file_inode_operations;
407 else if (S_ISDIR(inode->i_mode))
408 inode->i_op = &xiafs_dir_inode_operations;
409 else if (S_ISLNK(inode->i_mode))
410 inode->i_op = &xiafs_symlink_inode_operations;
411 else if (S_ISCHR(inode->i_mode))
412 inode->i_op = &chrdev_inode_operations;
413 else if (S_ISBLK(inode->i_mode))
414 inode->i_op = &blkdev_inode_operations;
415 else if (S_ISFIFO(inode->i_mode))
416 init_fifo(inode);
419 static struct buffer_head * xiafs_update_inode(struct inode * inode)
421 struct buffer_head * bh;
422 struct xiafs_inode * raw_inode;
423 int zone;
424 ino_t ino;
426 if (IS_RDONLY (inode)) {
427 printk("XIA-FS: write_inode on a read-only filesystem (%s %d)\n", WHERE_ERR);
428 inode->i_dirt = 0;
429 return 0;
432 ino = inode->i_ino;
433 if (!ino || ino > inode->i_sb->u.xiafs_sb.s_ninodes) {
434 printk("XIA-FS: bad inode number (%s %d)\n", WHERE_ERR);
435 inode->i_dirt=0;
436 return 0;
438 zone = 1 + inode->i_sb->u.xiafs_sb.s_imap_zones +
439 inode->i_sb->u.xiafs_sb.s_zmap_zones +
440 (ino-1) / XIAFS_INODES_PER_Z(inode->i_sb);
441 if (!(bh=bread(inode->i_dev, zone, XIAFS_ZSIZE(inode->i_sb)))) {
442 printk("XIA-FS: read i-node zone failed (%s %d)\n", WHERE_ERR);
443 inode->i_dirt=0;
444 return 0;
446 raw_inode = ((struct xiafs_inode *)bh->b_data) +
447 ((ino-1) & (XIAFS_INODES_PER_Z(inode->i_sb) -1));
448 raw_inode->i_mode = inode->i_mode;
449 raw_inode->i_uid = inode->i_uid;
450 raw_inode->i_gid = inode->i_gid;
451 raw_inode->i_nlinks = inode->i_nlink;
452 raw_inode->i_size = inode->i_size;
453 raw_inode->i_atime = inode->i_atime;
454 raw_inode->i_ctime = inode->i_ctime;
455 raw_inode->i_mtime = inode->i_mtime;
456 if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
457 raw_inode->i_zone[0] = inode->i_rdev;
458 else {
459 XIAFS_PUT_BLOCKS(raw_inode, inode->i_blocks);
460 for (zone = 0; zone < 8; zone++)
461 raw_inode->i_zone[zone] = (raw_inode->i_zone[zone] & 0xff000000)
462 | (inode->u.xiafs_i.i_zone[zone] & 0xffffff);
463 raw_inode->i_ind_zone = (raw_inode->i_ind_zone & 0xff000000)
464 | (inode->u.xiafs_i.i_ind_zone & 0xffffff);
465 raw_inode->i_dind_zone = (raw_inode->i_dind_zone & 0xff000000)
466 | (inode->u.xiafs_i.i_dind_zone & 0xffffff);
468 inode->i_dirt=0;
469 bh->b_dirt=1;
470 return bh;
474 void xiafs_write_inode(struct inode * inode)
476 struct buffer_head * bh;
477 bh = xiafs_update_inode(inode);
478 brelse (bh);
481 int xiafs_sync_inode (struct inode *inode)
483 int err = 0;
484 struct buffer_head *bh;
486 bh = xiafs_update_inode(inode);
487 if (bh && bh->b_dirt)
489 ll_rw_block(WRITE, 1, &bh);
490 wait_on_buffer(bh);
491 if (bh->b_req && !bh->b_uptodate)
493 printk ("IO error syncing xiafs inode [%04X:%lu]\n",
494 inode->i_dev, inode->i_ino);
495 err = -1;
498 else if (!bh)
499 err = -1;
500 brelse (bh);
501 return err;