Linux 2.2.0
[davej-history.git] / fs / qnx4 / inode.c
blob6261670444a9723cfaebe93dc82994ec09628f11
1 /*
2 * QNX4 file system, Linux implementation.
3 *
4 * Version : 0.1
5 *
6 * Using parts of the xiafs filesystem.
7 *
8 * History :
9 *
10 * 01-06-1998 by Richard Frowijn : first release.
11 * 20-06-1998 by Frank Denis : Linux 2.1.99+ support, boot signature, misc.
12 * 30-06-1998 by Frank Denis : first step to write inodes.
15 #include <linux/config.h>
16 #include <linux/module.h>
17 #include <linux/types.h>
18 #include <linux/errno.h>
19 #include <linux/malloc.h>
20 #include <linux/qnx4_fs.h>
21 #include <linux/fs.h>
22 #include <linux/locks.h>
23 #include <linux/init.h>
25 #include <asm/uaccess.h>
27 #define QNX4_VERSION 4
28 #define QNX4_BMNAME ".bitmap"
29 #define CHECK_BOOT_SIGNATURE 0
31 static struct super_operations qnx4_sops;
33 #ifdef CONFIG_QNX4FS_RW
35 int qnx4_sync_inode(struct inode *inode)
37 int err = 0;
38 # if 0
39 struct buffer_head *bh;
41 bh = qnx4_update_inode(inode);
42 if (bh && buffer_dirty(bh))
44 ll_rw_block(WRITE, 1, &bh);
45 wait_on_buffer(bh);
46 if (buffer_req(bh) && !buffer_uptodate(bh))
48 printk ("IO error syncing qnx4 inode [%s:%08lx]\n",
49 kdevname(inode->i_dev), inode->i_ino);
50 err = -1;
52 brelse (bh);
53 } else if (!bh) {
54 err = -1;
56 # endif
58 return err;
61 static void qnx4_delete_inode(struct inode *inode)
63 QNX4DEBUG(("qnx4: deleting inode [%lu]\n", (unsigned long) inode->i_ino));
64 inode->i_size = 0;
65 qnx4_truncate(inode);
66 qnx4_free_inode(inode);
69 static void qnx4_write_super(struct super_block *sb)
71 QNX4DEBUG(("qnx4: write_super\n"));
72 sb->s_dirt = 0;
75 static void qnx4_put_inode(struct inode *inode)
77 if (inode->i_nlink != 0) {
78 return;
80 inode->i_size = 0;
83 static void qnx4_write_inode(struct inode *inode)
85 struct qnx4_inode_entry *raw_inode;
86 int block, ino;
87 struct buffer_head *bh;
88 ino = inode->i_ino;
90 QNX4DEBUG(("qnx4: write inode 1.\n"));
91 if (inode->i_nlink == 0) {
92 return;
94 if (!ino) {
95 printk("qnx4: bad inode number on dev %s: %d is out of range\n",
96 kdevname(inode->i_dev), ino);
97 return;
99 QNX4DEBUG(("qnx4: write inode 2.\n"));
100 block = ino / QNX4_INODES_PER_BLOCK;
101 if (!(bh = bread(inode->i_dev, block, QNX4_BLOCK_SIZE))) {
102 printk("qnx4: major problem: unable to read inode from dev "
103 "%s\n", kdevname(inode->i_dev));
104 return;
106 raw_inode = ((struct qnx4_inode_entry *) bh->b_data) +
107 (ino % QNX4_INODES_PER_BLOCK);
108 raw_inode->di_mode = inode->i_mode;
109 raw_inode->di_uid = inode->i_uid;
110 raw_inode->di_gid = inode->i_gid;
111 raw_inode->di_nlink = inode->i_nlink;
112 raw_inode->di_size = inode->i_size;
113 raw_inode->di_mtime = inode->i_mtime;
114 raw_inode->di_atime = inode->i_atime;
115 raw_inode->di_ctime = inode->i_ctime;
116 raw_inode->di_first_xtnt.xtnt_size = inode->i_blocks;
117 mark_buffer_dirty(bh, 1);
118 brelse(bh);
121 #endif
123 static struct super_block *qnx4_read_super(struct super_block *, void *, int);
124 static void qnx4_put_super(struct super_block *sb);
125 static void qnx4_read_inode(struct inode *);
126 static int qnx4_remount(struct super_block *sb, int *flags, char *data);
127 static int qnx4_statfs(struct super_block *, struct statfs *, int);
129 static struct super_operations qnx4_sops =
131 qnx4_read_inode,
132 #ifdef CONFIG_QNX4FS_RW
133 qnx4_write_inode,
134 #else
135 NULL,
136 #endif
137 #ifdef CONFIG_QNX4FS_RW
138 qnx4_put_inode,
139 qnx4_delete_inode,
140 NULL, /* notify_change */
141 #else
142 NULL, /* put_inode */
143 NULL, /* delete_inode */
144 NULL, /* notify_change */
145 #endif
146 qnx4_put_super,
147 #ifdef CONFIG_QNX4FS_RW
148 qnx4_write_super,
149 #else
150 NULL,
151 #endif
152 qnx4_statfs,
153 qnx4_remount,
154 NULL /* clear_inode */
157 static int qnx4_remount(struct super_block *sb, int *flags, char *data)
159 struct qnx4_sb_info *qs;
161 qs = &sb->u.qnx4_sb;
162 qs->Version = QNX4_VERSION;
163 if (*flags & MS_RDONLY) {
164 return 0;
166 mark_buffer_dirty(qs->sb_buf, 1);
168 return 0;
171 struct buffer_head *inode_getblk(struct inode *inode, int nr,
172 int create)
174 int tmp;
175 int tst;
176 struct buffer_head *result = NULL;
178 tst = nr;
179 repeat:
180 tmp = tst;
181 if (tmp) {
182 result = getblk(inode->i_dev, tmp, QNX4_BLOCK_SIZE);
183 if (tmp == tst) {
184 return result;
186 brelse(result);
187 goto repeat;
189 if (!create) {
190 return NULL;
192 #if 0
193 tmp = qnx4_new_block(inode->i_sb);
194 if (!tmp) {
195 return NULL;
197 result = getblk(inode->i_dev, tmp, QNX4_BLOCK_SIZE);
198 if (tst) {
199 qnx4_free_block(inode->i_sb, tmp);
200 brelse(result);
201 goto repeat;
203 tst = tmp;
204 #endif
205 inode->i_ctime = CURRENT_TIME;
206 mark_inode_dirty(inode);
207 return result;
210 struct buffer_head *qnx4_bread(struct inode *inode, int block, int create)
212 struct buffer_head *bh;
214 bh = inode_getblk(inode, block, create);
215 if (!bh || buffer_uptodate(bh)) {
216 return bh;
218 ll_rw_block(READ, 1, &bh);
219 wait_on_buffer(bh);
220 if (buffer_uptodate(bh)) {
221 return bh;
223 brelse(bh);
225 return NULL;
228 static int qnx4_statfs(struct super_block *sb,
229 struct statfs *buf, int bufsize)
231 struct statfs tmp;
233 memset(&tmp, 0, sizeof tmp);
234 tmp.f_type = sb->s_magic;
235 tmp.f_bsize = sb->s_blocksize;
236 tmp.f_blocks = le32_to_cpu(sb->u.qnx4_sb.BitMap->di_size) * 8;
237 tmp.f_bfree = qnx4_count_free_blocks(sb);
238 tmp.f_bavail = tmp.f_bfree;
239 tmp.f_files = 0x00; /* change this !!! */
240 tmp.f_ffree = qnx4_count_free_inodes(sb);
241 tmp.f_namelen = QNX4_NAME_MAX;
243 return copy_to_user(buf, &tmp, bufsize) ? -EFAULT : 0;
247 * Check the root directory of the filesystem to make sure
248 * it really _is_ a qnx4 filesystem, and to check the size
249 * of the directory entry.
251 static const char *qnx4_checkroot(struct super_block *s)
253 struct buffer_head *bh;
254 struct qnx4_inode_entry *rootdir;
255 int rd, rl;
256 int i, j;
257 int found = 0;
259 if (s == NULL) {
260 return "no qnx4 filesystem (null superblock).";
262 if (*(s->u.qnx4_sb.sb->RootDir.di_fname) != '/') {
263 return "no qnx4 filesystem (no root dir).";
264 } else {
265 QNX4DEBUG(("QNX4 filesystem found on dev %s.\n", kdevname(s->s_dev)));
266 rd = s->u.qnx4_sb.sb->RootDir.di_first_xtnt.xtnt_blk - 1;
267 rl = s->u.qnx4_sb.sb->RootDir.di_first_xtnt.xtnt_size;
268 for (j = 0; j < rl; j++) {
269 bh = bread(s->s_dev, rd + j, QNX4_BLOCK_SIZE); /* root dir, first block */
270 if (bh == NULL) {
271 return "unable to read root entry.";
273 for (i = 0; i < QNX4_INODES_PER_BLOCK; i++) {
274 rootdir = (struct qnx4_inode_entry *) (bh->b_data + i * QNX4_DIR_ENTRY_SIZE);
275 if (rootdir->di_fname != NULL) {
276 QNX4DEBUG(("Rootdir entry found : [%s]\n", rootdir->di_fname));
277 if (!strncmp(rootdir->di_fname, QNX4_BMNAME, sizeof QNX4_BMNAME)) {
278 found = 1;
279 s->u.qnx4_sb.BitMap = rootdir; /* keep bitmap inode known */
280 break;
284 brelse(bh);
285 if (found != 0) {
286 break;
289 if (found == 0) {
290 return "bitmap file not found.";
293 return NULL;
296 static struct super_block *qnx4_read_super(struct super_block *s,
297 void *data, int silent)
299 struct buffer_head *bh;
300 kdev_t dev = s->s_dev;
301 #if CHECK_BOOT_SIGNATURE
302 char *tmpc;
303 #endif
304 const char *errmsg;
306 MOD_INC_USE_COUNT;
307 lock_super(s);
308 set_blocksize(dev, QNX4_BLOCK_SIZE);
309 s->s_blocksize = QNX4_BLOCK_SIZE;
310 s->s_blocksize_bits = 9;
311 s->s_dev = dev;
313 #if CHECK_BOOT_SIGNATURE
314 bh = bread(dev, 0, QNX4_BLOCK_SIZE);
315 if (!bh) {
316 printk("qnx4: unable to read the boot sector\n");
317 goto outnobh;
319 tmpc = (char *) bh->b_data;
320 if (tmpc[4] != 'Q' || tmpc[5] != 'N' || tmpc[6] != 'X' ||
321 tmpc[7] != '4' || tmpc[8] != 'F' || tmpc[9] != 'S') {
322 printk("qnx4: wrong fsid in boot sector.\n");
323 goto out;
325 brelse(bh);
326 #endif
327 bh = bread(dev, 1, QNX4_BLOCK_SIZE);
328 if (!bh) {
329 printk("qnx4: unable to read the superblock\n");
330 goto outnobh;
332 s->s_op = &qnx4_sops;
333 s->s_magic = QNX4_SUPER_MAGIC;
334 #ifndef CONFIG_QNX4FS_RW
335 s->s_flags |= MS_RDONLY; /* Yup, read-only yet */
336 #endif
337 s->u.qnx4_sb.sb_buf = bh;
338 s->u.qnx4_sb.sb = (struct qnx4_super_block *) bh->b_data;
339 s->s_root =
340 d_alloc_root(iget(s, QNX4_ROOT_INO * QNX4_INODES_PER_BLOCK), NULL);
341 if (s->s_root == NULL) {
342 printk("qnx4: get inode failed\n");
343 goto out;
345 errmsg = qnx4_checkroot(s);
346 if (errmsg != NULL) {
347 printk("qnx4: %s\n", errmsg);
348 goto out;
350 brelse(bh);
351 unlock_super(s);
352 s->s_dirt = 1;
354 return s;
356 out:
357 brelse(bh);
358 outnobh:
359 s->s_dev = 0;
360 unlock_super(s);
361 MOD_DEC_USE_COUNT;
363 return NULL;
366 static void qnx4_put_super(struct super_block *sb)
368 MOD_DEC_USE_COUNT;
369 return;
372 static void qnx4_read_inode(struct inode *inode)
374 struct buffer_head *bh;
375 struct qnx4_inode_entry *raw_inode;
376 int block, ino;
378 ino = inode->i_ino;
379 inode->i_op = NULL;
380 inode->i_mode = 0;
382 QNX4DEBUG(("Reading inode : [%d]\n", ino));
383 if (!ino) {
384 printk("qnx4: bad inode number on dev %s: %d is out of range\n",
385 kdevname(inode->i_dev), ino);
386 return;
388 block = ino / QNX4_INODES_PER_BLOCK;
390 if (!(bh = bread(inode->i_dev, block, QNX4_BLOCK_SIZE))) {
391 printk("qnx4: major problem: unable to read inode from dev "
392 "%s\n", kdevname(inode->i_dev));
393 return;
395 raw_inode = ((struct qnx4_inode_entry *) bh->b_data) +
396 (ino % QNX4_INODES_PER_BLOCK);
398 inode->i_mode = raw_inode->di_mode;
399 inode->i_uid = raw_inode->di_uid;
400 inode->i_gid = raw_inode->di_gid;
401 inode->i_nlink = raw_inode->di_nlink;
402 inode->i_size = raw_inode->di_size;
403 inode->i_mtime = raw_inode->di_mtime;
404 inode->i_atime = raw_inode->di_atime;
405 inode->i_ctime = raw_inode->di_ctime;
406 inode->i_blocks = raw_inode->di_first_xtnt.xtnt_size;
407 inode->i_blksize = QNX4_DIR_ENTRY_SIZE;
409 memcpy(&inode->u.qnx4_i, (struct qnx4_inode_info *) raw_inode, QNX4_DIR_ENTRY_SIZE);
410 inode->i_op = &qnx4_file_inode_operations;
411 if (S_ISREG(inode->i_mode)) {
412 inode->i_op = &qnx4_file_inode_operations;
413 } else {
414 if (S_ISDIR(inode->i_mode)) {
415 inode->i_op = &qnx4_dir_inode_operations;
416 } else {
417 if (S_ISLNK(inode->i_mode)) {
418 inode->i_op = &qnx4_symlink_inode_operations;
419 } else {
420 if (S_ISCHR(inode->i_mode)) {
421 inode->i_op = &chrdev_inode_operations;
422 } else {
423 if (S_ISBLK(inode->i_mode)) {
424 inode->i_op = &blkdev_inode_operations;
425 } else {
426 if (S_ISFIFO(inode->i_mode)) {
427 init_fifo(inode);
434 brelse(bh);
437 static struct file_system_type qnx4_fs_type =
439 "qnx4",
440 FS_REQUIRES_DEV,
441 qnx4_read_super,
442 NULL
445 __initfunc(int init_qnx4_fs(void))
447 printk("QNX4 filesystem v0.2 registered.\n");
448 return register_filesystem(&qnx4_fs_type);
451 #ifdef MODULE
452 EXPORT_NO_SYMBOLS;
454 int init_module(void)
456 return init_qnx4_fs();
459 void cleanup_module(void)
461 unregister_filesystem(&qnx4_fs_type);
464 #endif