3 * BFS superblock and inode operations.
4 * Copyright (C) 1999 Tigran Aivazian <tigran@ocston.org>
5 * From fs/minix, Copyright (C) 1991, 1992 Linus Torvalds.
8 #include <linux/module.h>
10 #include <linux/slab.h>
11 #include <linux/init.h>
12 #include <linux/locks.h>
13 #include <linux/bfs_fs.h>
15 #include <asm/uaccess.h>
19 MODULE_AUTHOR("Tigran A. Aivazian");
20 MODULE_DESCRIPTION("SCO UnixWare BFS filesystem for Linux");
26 #define dprintf(x...) printf(x)
31 void dump_imap(const char *prefix
, struct super_block
* s
);
33 static void bfs_read_inode(struct inode
* inode
)
35 unsigned long ino
= inode
->i_ino
;
36 kdev_t dev
= inode
->i_dev
;
37 struct bfs_inode
* di
;
38 struct buffer_head
* bh
;
41 if (ino
< BFS_ROOT_INO
|| ino
> inode
->i_sb
->su_lasti
) {
42 printf("Bad inode number %s:%08lx\n", bdevname(dev
), ino
);
43 make_bad_inode(inode
);
47 block
= (ino
- BFS_ROOT_INO
)/BFS_INODES_PER_BLOCK
+ 1;
48 bh
= bread(dev
, block
, BFS_BSIZE
);
50 printf("Unable to read inode %s:%08lx\n", bdevname(dev
), ino
);
51 make_bad_inode(inode
);
55 off
= (ino
- BFS_ROOT_INO
) % BFS_INODES_PER_BLOCK
;
56 di
= (struct bfs_inode
*)bh
->b_data
+ off
;
58 inode
->i_mode
= 0x0000FFFF & di
->i_mode
;
59 if (di
->i_vtype
== BFS_VDIR
) {
60 inode
->i_mode
|= S_IFDIR
;
61 inode
->i_op
= &bfs_dir_inops
;
62 inode
->i_fop
= &bfs_dir_operations
;
63 } else if (di
->i_vtype
== BFS_VREG
) {
64 inode
->i_mode
|= S_IFREG
;
65 inode
->i_op
= &bfs_file_inops
;
66 inode
->i_fop
= &bfs_file_operations
;
67 inode
->i_mapping
->a_ops
= &bfs_aops
;
70 inode
->i_uid
= di
->i_uid
;
71 inode
->i_gid
= di
->i_gid
;
72 inode
->i_nlink
= di
->i_nlink
;
73 inode
->i_size
= BFS_FILESIZE(di
);
74 inode
->i_blocks
= BFS_FILEBLOCKS(di
);
75 inode
->i_blksize
= PAGE_SIZE
;
76 inode
->i_atime
= di
->i_atime
;
77 inode
->i_mtime
= di
->i_mtime
;
78 inode
->i_ctime
= di
->i_ctime
;
79 inode
->i_rdev
= 0; /* BFS doesn't have special nodes */
80 inode
->iu_dsk_ino
= di
->i_ino
; /* can be 0 so we store a copy */
81 inode
->iu_sblock
= di
->i_sblock
;
82 inode
->iu_eblock
= di
->i_eblock
;
87 static void bfs_write_inode(struct inode
* inode
)
89 unsigned long ino
= inode
->i_ino
;
90 kdev_t dev
= inode
->i_dev
;
91 struct bfs_inode
* di
;
92 struct buffer_head
* bh
;
95 if (ino
< BFS_ROOT_INO
|| ino
> inode
->i_sb
->su_lasti
) {
96 printf("Bad inode number %s:%08lx\n", bdevname(dev
), ino
);
100 block
= (ino
- BFS_ROOT_INO
)/BFS_INODES_PER_BLOCK
+ 1;
101 bh
= bread(dev
, block
, BFS_BSIZE
);
103 printf("Unable to read inode %s:%08lx\n", bdevname(dev
), ino
);
107 off
= (ino
- BFS_ROOT_INO
)%BFS_INODES_PER_BLOCK
;
108 di
= (struct bfs_inode
*)bh
->b_data
+ off
;
110 if (inode
->i_ino
== BFS_ROOT_INO
)
111 di
->i_vtype
= BFS_VDIR
;
113 di
->i_vtype
= BFS_VREG
;
115 di
->i_ino
= inode
->i_ino
;
116 di
->i_mode
= inode
->i_mode
;
117 di
->i_uid
= inode
->i_uid
;
118 di
->i_gid
= inode
->i_gid
;
119 di
->i_nlink
= inode
->i_nlink
;
120 di
->i_atime
= inode
->i_atime
;
121 di
->i_mtime
= inode
->i_mtime
;
122 di
->i_ctime
= inode
->i_ctime
;
123 di
->i_sblock
= inode
->iu_sblock
;
124 di
->i_eblock
= inode
->iu_eblock
;
125 di
->i_eoffset
= di
->i_sblock
* BFS_BSIZE
+ inode
->i_size
- 1;
127 mark_buffer_dirty(bh
, 0);
131 static void bfs_delete_inode(struct inode
* inode
)
133 unsigned long ino
= inode
->i_ino
;
134 kdev_t dev
= inode
->i_dev
;
135 struct bfs_inode
* di
;
136 struct buffer_head
* bh
;
138 struct super_block
* s
= inode
->i_sb
;
140 dprintf("ino=%08lx\n", inode
->i_ino
);
142 if (!inode
|| !inode
->i_dev
|| inode
->i_count
> 1 || inode
->i_nlink
|| !s
)
144 if (inode
->i_ino
< BFS_ROOT_INO
|| inode
->i_ino
> inode
->i_sb
->su_lasti
) {
145 printf("invalid ino=%08lx\n", inode
->i_ino
);
150 inode
->i_atime
= inode
->i_mtime
= inode
->i_ctime
= CURRENT_TIME
;
151 mark_inode_dirty(inode
);
152 block
= (ino
- BFS_ROOT_INO
)/BFS_INODES_PER_BLOCK
+ 1;
153 bh
= bread(dev
, block
, BFS_BSIZE
);
155 printf("Unable to read inode %s:%08lx\n", bdevname(dev
), ino
);
158 off
= (ino
- BFS_ROOT_INO
)%BFS_INODES_PER_BLOCK
;
159 di
= (struct bfs_inode
*)bh
->b_data
+ off
;
161 s
->su_freeb
+= BFS_FILEBLOCKS(di
);
163 clear_bit(di
->i_ino
, s
->su_imap
);
164 dump_imap("delete_inode", s
);
168 mark_buffer_dirty(bh
, 0);
171 /* if this was the last file, make the previous
172 block "last files last block" even if there is no real file there,
174 if (s
->su_lf_eblk
== inode
->iu_eblock
) {
175 s
->su_lf_eblk
= inode
->iu_sblock
- 1;
176 mark_buffer_dirty(s
->su_sbh
, 1);
181 static void bfs_put_super(struct super_block
*s
)
187 static int bfs_statfs(struct super_block
*s
, struct statfs
*buf
)
189 buf
->f_type
= BFS_MAGIC
;
190 buf
->f_bsize
= s
->s_blocksize
;
191 buf
->f_blocks
= s
->su_blocks
;
192 buf
->f_bfree
= buf
->f_bavail
= s
->su_freeb
;
193 buf
->f_files
= s
->su_lasti
+ 1 - BFS_ROOT_INO
;
194 buf
->f_ffree
= s
->su_freei
;
195 buf
->f_fsid
.val
[0] = s
->s_dev
;
196 buf
->f_namelen
= BFS_NAMELEN
;
200 static void bfs_write_super(struct super_block
*s
)
202 if (!(s
->s_flags
& MS_RDONLY
))
203 mark_buffer_dirty(s
->su_sbh
, 1);
207 static struct super_operations bfs_sops
= {
208 read_inode
: bfs_read_inode
,
209 write_inode
: bfs_write_inode
,
210 delete_inode
: bfs_delete_inode
,
211 put_super
: bfs_put_super
,
212 write_super
: bfs_write_super
,
216 void dump_imap(const char *prefix
, struct super_block
* s
)
220 char *tmpbuf
= (char *)get_free_page(GFP_KERNEL
);
224 for (i
=s
->su_lasti
; i
>=0; i
--) {
225 if (i
>PAGE_SIZE
-100) break;
226 if (test_bit(i
, s
->su_imap
))
231 printk(KERN_ERR
"BFS-fs: %s: lasti=%08lx <%s>\n", prefix
, s
->su_lasti
, tmpbuf
);
232 free_page((unsigned long)tmpbuf
);
236 static struct super_block
* bfs_read_super(struct super_block
* s
,
237 void * data
, int silent
)
240 struct buffer_head
* bh
;
241 struct bfs_super_block
* bfs_sb
;
242 struct inode
* inode
;
246 set_blocksize(dev
, BFS_BSIZE
);
247 s
->s_blocksize
= BFS_BSIZE
;
248 s
->s_blocksize_bits
= BFS_BSIZE_BITS
;
250 bh
= bread(dev
, 0, BFS_BSIZE
);
253 bfs_sb
= (struct bfs_super_block
*)bh
->b_data
;
254 if (bfs_sb
->s_magic
!= BFS_MAGIC
) {
256 printf("No BFS filesystem on %s (magic=%08x)\n",
257 bdevname(dev
), bfs_sb
->s_magic
);
260 if (BFS_UNCLEAN(bfs_sb
, s
) && !silent
)
261 printf("%s is unclean, continuing\n", bdevname(dev
));
263 s
->s_magic
= BFS_MAGIC
;
264 s
->su_bfs_sb
= bfs_sb
;
266 s
->su_lasti
= (bfs_sb
->s_start
- BFS_BSIZE
)/sizeof(struct bfs_inode
)
269 imap_len
= s
->su_lasti
/8 + 1;
270 s
->su_imap
= kmalloc(imap_len
, GFP_KERNEL
);
273 memset(s
->su_imap
, 0, imap_len
);
274 for (i
=0; i
<BFS_ROOT_INO
; i
++)
275 set_bit(i
, s
->su_imap
);
278 inode
= iget(s
, BFS_ROOT_INO
);
283 s
->s_root
= d_alloc_root(inode
);
290 s
->su_blocks
= (bfs_sb
->s_end
+ 1)>>BFS_BSIZE_BITS
; /* for statfs(2) */
291 s
->su_freeb
= (bfs_sb
->s_end
+ 1 - bfs_sb
->s_start
)>>BFS_BSIZE_BITS
;
296 for (i
=BFS_ROOT_INO
; i
<=s
->su_lasti
; i
++) {
298 if (inode
->iu_dsk_ino
== 0)
301 set_bit(i
, s
->su_imap
);
302 s
->su_freeb
-= inode
->i_blocks
;
303 if (inode
->iu_eblock
> s
->su_lf_eblk
) {
304 s
->su_lf_eblk
= inode
->iu_eblock
;
305 s
->su_lf_sblk
= inode
->iu_sblock
;
306 s
->su_lf_ioff
= BFS_INO2OFF(i
);
311 if (!(s
->s_flags
& MS_RDONLY
)) {
312 mark_buffer_dirty(bh
, 1);
315 dump_imap("read_super", s
);
323 static DECLARE_FSTYPE_DEV( bfs_fs_type
, "bfs", bfs_read_super
);
325 static int __init
init_bfs_fs(void)
327 return register_filesystem(&bfs_fs_type
);
330 static void __exit
exit_bfs_fs(void)
332 unregister_filesystem(&bfs_fs_type
);
335 module_init(init_bfs_fs
)
336 module_exit(exit_bfs_fs
)