2 * linux/fs/xiafs/inode.c
4 * Copyright (C) Q. Frank Xia, 1993.
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>
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
)
31 xiafs_truncate(inode
);
32 xiafs_free_inode(inode
);
35 void xiafs_put_super(struct super_block
*sb
)
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
]);
48 static struct super_operations xiafs_sops
= {
59 struct super_block
*xiafs_read_super(struct super_block
*s
, void *data
,
62 struct buffer_head
*bh
;
63 struct xiafs_super_block
*sp
;
69 set_blocksize(dev
, BLOCK_SIZE
);
71 if (!(bh
= bread(dev
, 0, BLOCK_SIZE
))) {
74 printk("XIA-FS: read super_block failed (%s %d)\n", WHERE_ERR
);
77 sp
= (struct xiafs_super_block
*) bh
->b_data
;
78 s
->s_magic
= sp
->s_magic
;
79 if (s
->s_magic
!= _XIAFS_SUPER_MAGIC
) {
84 printk("VFS: Can't find a xiafs filesystem on dev 0x%04x.\n",
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)) {
94 set_blocksize(dev
, s
->s_blocksize
);
95 bh
= bread (dev
, 0, s
->s_blocksize
);
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
;
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;
117 if ( s
->u
.xiafs_sb
.s_imap_zones
> _XIAFS_IMAP_SLOTS
)
118 s
->u
.xiafs_sb
.s_imap_cached
=1;
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;
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 */
139 s
->s_op
= &xiafs_sops
;
140 s
->s_mounted
= iget(s
, _XIAFS_ROOT_INO
);
142 goto xiafs_read_super_fail
;
144 random_nr
=CURRENT_TIME
;
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
]);
154 printk("XIA-FS: read bitmaps failed (%s %d)\n", WHERE_ERR
);
158 void xiafs_statfs(struct super_block
*sb
, struct statfs
*buf
)
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
)
180 tmp
= ((u_long
*) bh
->b_data
)[nr
];
185 int xiafs_bmap(struct inode
* inode
,int zone
)
190 printk("XIA-FS: block < 0 (%s %d)\n", WHERE_ERR
);
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
);
197 if (!IS_RDONLY (inode
)) {
198 inode
->i_atime
= CURRENT_TIME
;
202 return inode
->u
.xiafs_i
.i_zone
[zone
];
204 if (zone
< XIAFS_ADDRS_PER_Z(inode
->i_sb
)) {
205 i
= inode
->u
.xiafs_i
.i_ind_zone
;
207 i
= zone_bmap(bread(inode
->i_dev
, i
, XIAFS_ZSIZE(inode
->i_sb
)), zone
);
210 zone
-= XIAFS_ADDRS_PER_Z(inode
->i_sb
);
211 i
= inode
->u
.xiafs_i
.i_dind_zone
;
213 i
= zone_bmap(bread(inode
->i_dev
, i
, XIAFS_ZSIZE(inode
->i_sb
)),
214 zone
>> XIAFS_ADDRS_PER_Z_BITS(inode
->i_sb
));
216 i
= zone_bmap(bread(inode
->i_dev
,i
, XIAFS_ZSIZE(inode
->i_sb
)),
217 zone
& (XIAFS_ADDRS_PER_Z(inode
->i_sb
)-1));
221 static u_long
get_prev_addr(struct inode
* inode
, int zone
)
226 while (--zone
>= 0) /* only files with holes suffer */
227 if ((tmp
=xiafs_bmap(inode
, zone
)))
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
)
237 struct buffer_head
* result
;
241 result
= getblk(inode
->i_dev
, tmp
, XIAFS_ZSIZE(inode
->i_sb
));
249 tmp
= xiafs_new_zone(inode
->i_sb
, prev_addr
);
252 result
= getblk(inode
->i_dev
, tmp
, XIAFS_ZSIZE(inode
->i_sb
));
254 xiafs_free_zone(inode
->i_sb
, tmp
);
259 inode
->i_blocks
+=2 << XIAFS_ZSHIFT(inode
->i_sb
);
263 static struct buffer_head
*
264 indt_getblk(struct inode
* inode
, struct buffer_head
* bh
,
265 int nr
, int create
, u_long prev_addr
)
269 struct buffer_head
* result
;
273 if (!bh
->b_uptodate
) {
274 ll_rw_block(READ
, 1, &bh
);
276 if (!bh
->b_uptodate
) {
281 lp
= nr
+ (u_long
*) bh
->b_data
;
284 result
= getblk(bh
->b_dev
, tmp
, XIAFS_ZSIZE(inode
->i_sb
));
296 tmp
= xiafs_new_zone(inode
->i_sb
, prev_addr
);
301 result
= getblk(bh
->b_dev
, tmp
, XIAFS_ZSIZE(inode
->i_sb
));
303 xiafs_free_zone(inode
->i_sb
, tmp
);
308 inode
->i_blocks
+=2 << XIAFS_ZSHIFT(inode
->i_sb
);
314 struct buffer_head
* xiafs_getblk(struct inode
* inode
, int zone
, int create
)
316 struct buffer_head
* bh
;
320 printk("XIA-FS: zone < 0 (%s %d)\n", WHERE_ERR
);
323 if (zone
>= 8+(1+XIAFS_ADDRS_PER_Z(inode
->i_sb
))*XIAFS_ADDRS_PER_Z(inode
->i_sb
)) {
325 printk("XIA-FS: zone > big (%s %d)\n", WHERE_ERR
);
329 prev_addr
=get_prev_addr(inode
, zone
);
331 return dt_getblk(inode
, zone
+inode
->u
.xiafs_i
.i_zone
, create
, prev_addr
);
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
);
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
),
342 bh
= indt_getblk(inode
, bh
, zone
&(XIAFS_ADDRS_PER_Z(inode
->i_sb
)-1),
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
)
354 ll_rw_block(READ
, 1, &bh
);
362 void xiafs_read_inode(struct inode
* inode
)
364 struct buffer_head
* bh
;
365 struct xiafs_inode
* raw_inode
;
372 if (!ino
|| ino
> inode
->i_sb
->u
.xiafs_sb
.s_ninodes
) {
373 printk("XIA-FS: bad inode number (%s %d)\n", WHERE_ERR
);
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
);
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
)) {
396 inode
->i_rdev
= raw_inode
->i_zone
[0];
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;
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
))
419 static struct buffer_head
* xiafs_update_inode(struct inode
* inode
)
421 struct buffer_head
* bh
;
422 struct xiafs_inode
* raw_inode
;
426 if (IS_RDONLY (inode
)) {
427 printk("XIA-FS: write_inode on a read-only filesystem (%s %d)\n", WHERE_ERR
);
433 if (!ino
|| ino
> inode
->i_sb
->u
.xiafs_sb
.s_ninodes
) {
434 printk("XIA-FS: bad inode number (%s %d)\n", WHERE_ERR
);
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
);
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
;
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);
474 void xiafs_write_inode(struct inode
* inode
)
476 struct buffer_head
* bh
;
477 bh
= xiafs_update_inode(inode
);
481 int xiafs_sync_inode (struct inode
*inode
)
484 struct buffer_head
*bh
;
486 bh
= xiafs_update_inode(inode
);
487 if (bh
&& bh
->b_dirt
)
489 ll_rw_block(WRITE
, 1, &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
);