OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [fs/] [qnx4/] [inode.c] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
2
 * QNX4 file system, Linux implementation.
3
 *
4
 * Version : 0.2.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.
13
 */
14
 
15
#include <linux/module.h>
16
#include <linux/types.h>
17
#include <linux/string.h>
18
#include <linux/errno.h>
19
#include <linux/slab.h>
20
#include <linux/fs.h>
21
#include <linux/qnx4_fs.h>
22
#include <linux/init.h>
23
#include <linux/highuid.h>
24
#include <linux/smp_lock.h>
25
#include <linux/pagemap.h>
26
#include <linux/buffer_head.h>
27
#include <linux/vfs.h>
28
#include <asm/uaccess.h>
29
 
30
#define QNX4_VERSION  4
31
#define QNX4_BMNAME   ".bitmap"
32
 
33
static const struct super_operations qnx4_sops;
34
 
35
#ifdef CONFIG_QNX4FS_RW
36
 
37
int qnx4_sync_inode(struct inode *inode)
38
{
39
        int err = 0;
40
# if 0
41
        struct buffer_head *bh;
42
 
43
        bh = qnx4_update_inode(inode);
44
        if (bh && buffer_dirty(bh))
45
        {
46
                sync_dirty_buffer(bh);
47
                if (buffer_req(bh) && !buffer_uptodate(bh))
48
                {
49
                        printk ("IO error syncing qnx4 inode [%s:%08lx]\n",
50
                                inode->i_sb->s_id, inode->i_ino);
51
                        err = -1;
52
                }
53
                brelse (bh);
54
        } else if (!bh) {
55
                err = -1;
56
        }
57
# endif
58
 
59
        return err;
60
}
61
 
62
static void qnx4_delete_inode(struct inode *inode)
63
{
64
        QNX4DEBUG(("qnx4: deleting inode [%lu]\n", (unsigned long) inode->i_ino));
65
        truncate_inode_pages(&inode->i_data, 0);
66
        inode->i_size = 0;
67
        qnx4_truncate(inode);
68
        lock_kernel();
69
        qnx4_free_inode(inode);
70
        unlock_kernel();
71
}
72
 
73
static void qnx4_write_super(struct super_block *sb)
74
{
75
        lock_kernel();
76
        QNX4DEBUG(("qnx4: write_super\n"));
77
        sb->s_dirt = 0;
78
        unlock_kernel();
79
}
80
 
81
static int qnx4_write_inode(struct inode *inode, int unused)
82
{
83
        struct qnx4_inode_entry *raw_inode;
84
        int block, ino;
85
        struct buffer_head *bh;
86
        ino = inode->i_ino;
87
 
88
        QNX4DEBUG(("qnx4: write inode 1.\n"));
89
        if (inode->i_nlink == 0) {
90
                return 0;
91
        }
92
        if (!ino) {
93
                printk("qnx4: bad inode number on dev %s: %d is out of range\n",
94
                       inode->i_sb->s_id, ino);
95
                return -EIO;
96
        }
97
        QNX4DEBUG(("qnx4: write inode 2.\n"));
98
        block = ino / QNX4_INODES_PER_BLOCK;
99
        lock_kernel();
100
        if (!(bh = sb_bread(inode->i_sb, block))) {
101
                printk("qnx4: major problem: unable to read inode from dev "
102
                       "%s\n", inode->i_sb->s_id);
103
                unlock_kernel();
104
                return -EIO;
105
        }
106
        raw_inode = ((struct qnx4_inode_entry *) bh->b_data) +
107
            (ino % QNX4_INODES_PER_BLOCK);
108
        raw_inode->di_mode  = cpu_to_le16(inode->i_mode);
109
        raw_inode->di_uid   = cpu_to_le16(fs_high2lowuid(inode->i_uid));
110
        raw_inode->di_gid   = cpu_to_le16(fs_high2lowgid(inode->i_gid));
111
        raw_inode->di_nlink = cpu_to_le16(inode->i_nlink);
112
        raw_inode->di_size  = cpu_to_le32(inode->i_size);
113
        raw_inode->di_mtime = cpu_to_le32(inode->i_mtime.tv_sec);
114
        raw_inode->di_atime = cpu_to_le32(inode->i_atime.tv_sec);
115
        raw_inode->di_ctime = cpu_to_le32(inode->i_ctime.tv_sec);
116
        raw_inode->di_first_xtnt.xtnt_size = cpu_to_le32(inode->i_blocks);
117
        mark_buffer_dirty(bh);
118
        brelse(bh);
119
        unlock_kernel();
120
        return 0;
121
}
122
 
123
#endif
124
 
125
static void qnx4_put_super(struct super_block *sb);
126
static struct inode *qnx4_alloc_inode(struct super_block *sb);
127
static void qnx4_destroy_inode(struct inode *inode);
128
static void qnx4_read_inode(struct inode *);
129
static int qnx4_remount(struct super_block *sb, int *flags, char *data);
130
static int qnx4_statfs(struct dentry *, struct kstatfs *);
131
 
132
static const struct super_operations qnx4_sops =
133
{
134
        .alloc_inode    = qnx4_alloc_inode,
135
        .destroy_inode  = qnx4_destroy_inode,
136
        .read_inode     = qnx4_read_inode,
137
        .put_super      = qnx4_put_super,
138
        .statfs         = qnx4_statfs,
139
        .remount_fs     = qnx4_remount,
140
#ifdef CONFIG_QNX4FS_RW
141
        .write_inode    = qnx4_write_inode,
142
        .delete_inode   = qnx4_delete_inode,
143
        .write_super    = qnx4_write_super,
144
#endif
145
};
146
 
147
static int qnx4_remount(struct super_block *sb, int *flags, char *data)
148
{
149
        struct qnx4_sb_info *qs;
150
 
151
        qs = qnx4_sb(sb);
152
        qs->Version = QNX4_VERSION;
153
#ifndef CONFIG_QNX4FS_RW
154
        *flags |= MS_RDONLY;
155
#endif
156
        if (*flags & MS_RDONLY) {
157
                return 0;
158
        }
159
 
160
        mark_buffer_dirty(qs->sb_buf);
161
 
162
        return 0;
163
}
164
 
165
static struct buffer_head *qnx4_getblk(struct inode *inode, int nr,
166
                                       int create)
167
{
168
        struct buffer_head *result = NULL;
169
 
170
        if ( nr >= 0 )
171
                nr = qnx4_block_map( inode, nr );
172
        if (nr) {
173
                result = sb_getblk(inode->i_sb, nr);
174
                return result;
175
        }
176
        if (!create) {
177
                return NULL;
178
        }
179
#if 0
180
        tmp = qnx4_new_block(inode->i_sb);
181
        if (!tmp) {
182
                return NULL;
183
        }
184
        result = sb_getblk(inode->i_sb, tmp);
185
        if (tst) {
186
                qnx4_free_block(inode->i_sb, tmp);
187
                brelse(result);
188
                goto repeat;
189
        }
190
        tst = tmp;
191
#endif
192
        inode->i_ctime = CURRENT_TIME_SEC;
193
        mark_inode_dirty(inode);
194
        return result;
195
}
196
 
197
struct buffer_head *qnx4_bread(struct inode *inode, int block, int create)
198
{
199
        struct buffer_head *bh;
200
 
201
        bh = qnx4_getblk(inode, block, create);
202
        if (!bh || buffer_uptodate(bh)) {
203
                return bh;
204
        }
205
        ll_rw_block(READ, 1, &bh);
206
        wait_on_buffer(bh);
207
        if (buffer_uptodate(bh)) {
208
                return bh;
209
        }
210
        brelse(bh);
211
 
212
        return NULL;
213
}
214
 
215
static int qnx4_get_block( struct inode *inode, sector_t iblock, struct buffer_head *bh, int create )
216
{
217
        unsigned long phys;
218
 
219
        QNX4DEBUG(("qnx4: qnx4_get_block inode=[%ld] iblock=[%ld]\n",inode->i_ino,iblock));
220
 
221
        phys = qnx4_block_map( inode, iblock );
222
        if ( phys ) {
223
                // logical block is before EOF
224
                map_bh(bh, inode->i_sb, phys);
225
        } else if ( create ) {
226
                // to be done.
227
        }
228
        return 0;
229
}
230
 
231
unsigned long qnx4_block_map( struct inode *inode, long iblock )
232
{
233
        int ix;
234
        long offset, i_xblk;
235
        unsigned long block = 0;
236
        struct buffer_head *bh = NULL;
237
        struct qnx4_xblk *xblk = NULL;
238
        struct qnx4_inode_entry *qnx4_inode = qnx4_raw_inode(inode);
239
        u16 nxtnt = le16_to_cpu(qnx4_inode->di_num_xtnts);
240
 
241
        if ( iblock < le32_to_cpu(qnx4_inode->di_first_xtnt.xtnt_size) ) {
242
                // iblock is in the first extent. This is easy.
243
                block = le32_to_cpu(qnx4_inode->di_first_xtnt.xtnt_blk) + iblock - 1;
244
        } else {
245
                // iblock is beyond first extent. We have to follow the extent chain.
246
                i_xblk = le32_to_cpu(qnx4_inode->di_xblk);
247
                offset = iblock - le32_to_cpu(qnx4_inode->di_first_xtnt.xtnt_size);
248
                ix = 0;
249
                while ( --nxtnt > 0 ) {
250
                        if ( ix == 0 ) {
251
                                // read next xtnt block.
252
                                bh = sb_bread(inode->i_sb, i_xblk - 1);
253
                                if ( !bh ) {
254
                                        QNX4DEBUG(("qnx4: I/O error reading xtnt block [%ld])\n", i_xblk - 1));
255
                                        return -EIO;
256
                                }
257
                                xblk = (struct qnx4_xblk*)bh->b_data;
258
                                if ( memcmp( xblk->xblk_signature, "IamXblk", 7 ) ) {
259
                                        QNX4DEBUG(("qnx4: block at %ld is not a valid xtnt\n", qnx4_inode->i_xblk));
260
                                        return -EIO;
261
                                }
262
                        }
263
                        if ( offset < le32_to_cpu(xblk->xblk_xtnts[ix].xtnt_size) ) {
264
                                // got it!
265
                                block = le32_to_cpu(xblk->xblk_xtnts[ix].xtnt_blk) + offset - 1;
266
                                break;
267
                        }
268
                        offset -= le32_to_cpu(xblk->xblk_xtnts[ix].xtnt_size);
269
                        if ( ++ix >= xblk->xblk_num_xtnts ) {
270
                                i_xblk = le32_to_cpu(xblk->xblk_next_xblk);
271
                                ix = 0;
272
                                brelse( bh );
273
                                bh = NULL;
274
                        }
275
                }
276
                if ( bh )
277
                        brelse( bh );
278
        }
279
 
280
        QNX4DEBUG(("qnx4: mapping block %ld of inode %ld = %ld\n",iblock,inode->i_ino,block));
281
        return block;
282
}
283
 
284
static int qnx4_statfs(struct dentry *dentry, struct kstatfs *buf)
285
{
286
        struct super_block *sb = dentry->d_sb;
287
 
288
        lock_kernel();
289
 
290
        buf->f_type    = sb->s_magic;
291
        buf->f_bsize   = sb->s_blocksize;
292
        buf->f_blocks  = le32_to_cpu(qnx4_sb(sb)->BitMap->di_size) * 8;
293
        buf->f_bfree   = qnx4_count_free_blocks(sb);
294
        buf->f_bavail  = buf->f_bfree;
295
        buf->f_namelen = QNX4_NAME_MAX;
296
 
297
        unlock_kernel();
298
 
299
        return 0;
300
}
301
 
302
/*
303
 * Check the root directory of the filesystem to make sure
304
 * it really _is_ a qnx4 filesystem, and to check the size
305
 * of the directory entry.
306
 */
307
static const char *qnx4_checkroot(struct super_block *sb)
308
{
309
        struct buffer_head *bh;
310
        struct qnx4_inode_entry *rootdir;
311
        int rd, rl;
312
        int i, j;
313
        int found = 0;
314
 
315
        if (*(qnx4_sb(sb)->sb->RootDir.di_fname) != '/') {
316
                return "no qnx4 filesystem (no root dir).";
317
        } else {
318
                QNX4DEBUG(("QNX4 filesystem found on dev %s.\n", sb->s_id));
319
                rd = le32_to_cpu(qnx4_sb(sb)->sb->RootDir.di_first_xtnt.xtnt_blk) - 1;
320
                rl = le32_to_cpu(qnx4_sb(sb)->sb->RootDir.di_first_xtnt.xtnt_size);
321
                for (j = 0; j < rl; j++) {
322
                        bh = sb_bread(sb, rd + j);      /* root dir, first block */
323
                        if (bh == NULL) {
324
                                return "unable to read root entry.";
325
                        }
326
                        for (i = 0; i < QNX4_INODES_PER_BLOCK; i++) {
327
                                rootdir = (struct qnx4_inode_entry *) (bh->b_data + i * QNX4_DIR_ENTRY_SIZE);
328
                                if (rootdir->di_fname != NULL) {
329
                                        QNX4DEBUG(("Rootdir entry found : [%s]\n", rootdir->di_fname));
330
                                        if (!strncmp(rootdir->di_fname, QNX4_BMNAME, sizeof QNX4_BMNAME)) {
331
                                                found = 1;
332
                                                qnx4_sb(sb)->BitMap = kmalloc( sizeof( struct qnx4_inode_entry ), GFP_KERNEL );
333
                                                if (!qnx4_sb(sb)->BitMap) {
334
                                                        brelse (bh);
335
                                                        return "not enough memory for bitmap inode";
336
                                                }
337
                                                memcpy( qnx4_sb(sb)->BitMap, rootdir, sizeof( struct qnx4_inode_entry ) );      /* keep bitmap inode known */
338
                                                break;
339
                                        }
340
                                }
341
                        }
342
                        brelse(bh);
343
                        if (found != 0) {
344
                                break;
345
                        }
346
                }
347
                if (found == 0) {
348
                        return "bitmap file not found.";
349
                }
350
        }
351
        return NULL;
352
}
353
 
354
static int qnx4_fill_super(struct super_block *s, void *data, int silent)
355
{
356
        struct buffer_head *bh;
357
        struct inode *root;
358
        const char *errmsg;
359
        struct qnx4_sb_info *qs;
360
 
361
        qs = kzalloc(sizeof(struct qnx4_sb_info), GFP_KERNEL);
362
        if (!qs)
363
                return -ENOMEM;
364
        s->s_fs_info = qs;
365
 
366
        sb_set_blocksize(s, QNX4_BLOCK_SIZE);
367
 
368
        /* Check the superblock signature. Since the qnx4 code is
369
           dangerous, we should leave as quickly as possible
370
           if we don't belong here... */
371
        bh = sb_bread(s, 1);
372
        if (!bh) {
373
                printk("qnx4: unable to read the superblock\n");
374
                goto outnobh;
375
        }
376
        if ( le32_to_cpup((__le32*) bh->b_data) != QNX4_SUPER_MAGIC ) {
377
                if (!silent)
378
                        printk("qnx4: wrong fsid in superblock.\n");
379
                goto out;
380
        }
381
        s->s_op = &qnx4_sops;
382
        s->s_magic = QNX4_SUPER_MAGIC;
383
#ifndef CONFIG_QNX4FS_RW
384
        s->s_flags |= MS_RDONLY;        /* Yup, read-only yet */
385
#endif
386
        qnx4_sb(s)->sb_buf = bh;
387
        qnx4_sb(s)->sb = (struct qnx4_super_block *) bh->b_data;
388
 
389
 
390
        /* check before allocating dentries, inodes, .. */
391
        errmsg = qnx4_checkroot(s);
392
        if (errmsg != NULL) {
393
                if (!silent)
394
                        printk("qnx4: %s\n", errmsg);
395
                goto out;
396
        }
397
 
398
        /* does root not have inode number QNX4_ROOT_INO ?? */
399
        root = iget(s, QNX4_ROOT_INO * QNX4_INODES_PER_BLOCK);
400
        if (!root) {
401
                printk("qnx4: get inode failed\n");
402
                goto out;
403
        }
404
 
405
        s->s_root = d_alloc_root(root);
406
        if (s->s_root == NULL)
407
                goto outi;
408
 
409
        brelse(bh);
410
 
411
        return 0;
412
 
413
      outi:
414
        iput(root);
415
      out:
416
        brelse(bh);
417
      outnobh:
418
        kfree(qs);
419
        s->s_fs_info = NULL;
420
        return -EINVAL;
421
}
422
 
423
static void qnx4_put_super(struct super_block *sb)
424
{
425
        struct qnx4_sb_info *qs = qnx4_sb(sb);
426
        kfree( qs->BitMap );
427
        kfree( qs );
428
        sb->s_fs_info = NULL;
429
        return;
430
}
431
 
432
static int qnx4_writepage(struct page *page, struct writeback_control *wbc)
433
{
434
        return block_write_full_page(page,qnx4_get_block, wbc);
435
}
436
 
437
static int qnx4_readpage(struct file *file, struct page *page)
438
{
439
        return block_read_full_page(page,qnx4_get_block);
440
}
441
 
442
static int qnx4_write_begin(struct file *file, struct address_space *mapping,
443
                        loff_t pos, unsigned len, unsigned flags,
444
                        struct page **pagep, void **fsdata)
445
{
446
        struct qnx4_inode_info *qnx4_inode = qnx4_i(mapping->host);
447
        *pagep = NULL;
448
        return cont_write_begin(file, mapping, pos, len, flags, pagep, fsdata,
449
                                qnx4_get_block,
450
                                &qnx4_inode->mmu_private);
451
}
452
static sector_t qnx4_bmap(struct address_space *mapping, sector_t block)
453
{
454
        return generic_block_bmap(mapping,block,qnx4_get_block);
455
}
456
static const struct address_space_operations qnx4_aops = {
457
        .readpage       = qnx4_readpage,
458
        .writepage      = qnx4_writepage,
459
        .sync_page      = block_sync_page,
460
        .write_begin    = qnx4_write_begin,
461
        .write_end      = generic_write_end,
462
        .bmap           = qnx4_bmap
463
};
464
 
465
static void qnx4_read_inode(struct inode *inode)
466
{
467
        struct buffer_head *bh;
468
        struct qnx4_inode_entry *raw_inode;
469
        int block, ino;
470
        struct super_block *sb = inode->i_sb;
471
        struct qnx4_inode_entry *qnx4_inode = qnx4_raw_inode(inode);
472
 
473
        ino = inode->i_ino;
474
        inode->i_mode = 0;
475
 
476
        QNX4DEBUG(("Reading inode : [%d]\n", ino));
477
        if (!ino) {
478
                printk("qnx4: bad inode number on dev %s: %d is out of range\n",
479
                       sb->s_id, ino);
480
                return;
481
        }
482
        block = ino / QNX4_INODES_PER_BLOCK;
483
 
484
        if (!(bh = sb_bread(sb, block))) {
485
                printk("qnx4: major problem: unable to read inode from dev "
486
                       "%s\n", sb->s_id);
487
                return;
488
        }
489
        raw_inode = ((struct qnx4_inode_entry *) bh->b_data) +
490
            (ino % QNX4_INODES_PER_BLOCK);
491
 
492
        inode->i_mode    = le16_to_cpu(raw_inode->di_mode);
493
        inode->i_uid     = (uid_t)le16_to_cpu(raw_inode->di_uid);
494
        inode->i_gid     = (gid_t)le16_to_cpu(raw_inode->di_gid);
495
        inode->i_nlink   = le16_to_cpu(raw_inode->di_nlink);
496
        inode->i_size    = le32_to_cpu(raw_inode->di_size);
497
        inode->i_mtime.tv_sec   = le32_to_cpu(raw_inode->di_mtime);
498
        inode->i_mtime.tv_nsec = 0;
499
        inode->i_atime.tv_sec   = le32_to_cpu(raw_inode->di_atime);
500
        inode->i_atime.tv_nsec = 0;
501
        inode->i_ctime.tv_sec   = le32_to_cpu(raw_inode->di_ctime);
502
        inode->i_ctime.tv_nsec = 0;
503
        inode->i_blocks  = le32_to_cpu(raw_inode->di_first_xtnt.xtnt_size);
504
 
505
        memcpy(qnx4_inode, raw_inode, QNX4_DIR_ENTRY_SIZE);
506
        if (S_ISREG(inode->i_mode)) {
507
                inode->i_op = &qnx4_file_inode_operations;
508
                inode->i_fop = &qnx4_file_operations;
509
                inode->i_mapping->a_ops = &qnx4_aops;
510
                qnx4_i(inode)->mmu_private = inode->i_size;
511
        } else if (S_ISDIR(inode->i_mode)) {
512
                inode->i_op = &qnx4_dir_inode_operations;
513
                inode->i_fop = &qnx4_dir_operations;
514
        } else if (S_ISLNK(inode->i_mode)) {
515
                inode->i_op = &page_symlink_inode_operations;
516
                inode->i_mapping->a_ops = &qnx4_aops;
517
                qnx4_i(inode)->mmu_private = inode->i_size;
518
        } else
519
                printk("qnx4: bad inode %d on dev %s\n",ino,sb->s_id);
520
        brelse(bh);
521
}
522
 
523
static struct kmem_cache *qnx4_inode_cachep;
524
 
525
static struct inode *qnx4_alloc_inode(struct super_block *sb)
526
{
527
        struct qnx4_inode_info *ei;
528
        ei = kmem_cache_alloc(qnx4_inode_cachep, GFP_KERNEL);
529
        if (!ei)
530
                return NULL;
531
        return &ei->vfs_inode;
532
}
533
 
534
static void qnx4_destroy_inode(struct inode *inode)
535
{
536
        kmem_cache_free(qnx4_inode_cachep, qnx4_i(inode));
537
}
538
 
539
static void init_once(struct kmem_cache *cachep, void *foo)
540
{
541
        struct qnx4_inode_info *ei = (struct qnx4_inode_info *) foo;
542
 
543
        inode_init_once(&ei->vfs_inode);
544
}
545
 
546
static int init_inodecache(void)
547
{
548
        qnx4_inode_cachep = kmem_cache_create("qnx4_inode_cache",
549
                                             sizeof(struct qnx4_inode_info),
550
                                             0, (SLAB_RECLAIM_ACCOUNT|
551
                                                SLAB_MEM_SPREAD),
552
                                             init_once);
553
        if (qnx4_inode_cachep == NULL)
554
                return -ENOMEM;
555
        return 0;
556
}
557
 
558
static void destroy_inodecache(void)
559
{
560
        kmem_cache_destroy(qnx4_inode_cachep);
561
}
562
 
563
static int qnx4_get_sb(struct file_system_type *fs_type,
564
        int flags, const char *dev_name, void *data, struct vfsmount *mnt)
565
{
566
        return get_sb_bdev(fs_type, flags, dev_name, data, qnx4_fill_super,
567
                           mnt);
568
}
569
 
570
static struct file_system_type qnx4_fs_type = {
571
        .owner          = THIS_MODULE,
572
        .name           = "qnx4",
573
        .get_sb         = qnx4_get_sb,
574
        .kill_sb        = kill_block_super,
575
        .fs_flags       = FS_REQUIRES_DEV,
576
};
577
 
578
static int __init init_qnx4_fs(void)
579
{
580
        int err;
581
 
582
        err = init_inodecache();
583
        if (err)
584
                return err;
585
 
586
        err = register_filesystem(&qnx4_fs_type);
587
        if (err) {
588
                destroy_inodecache();
589
                return err;
590
        }
591
 
592
        printk("QNX4 filesystem 0.2.3 registered.\n");
593
        return 0;
594
}
595
 
596
static void __exit exit_qnx4_fs(void)
597
{
598
        unregister_filesystem(&qnx4_fs_type);
599
        destroy_inodecache();
600
}
601
 
602
module_init(init_qnx4_fs)
603
module_exit(exit_qnx4_fs)
604
MODULE_LICENSE("GPL");
605
 

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.