linux-old/fs/qnx4/inode.c
<<
>>
Prefs
   1/*
   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/config.h>
  16#include <linux/module.h>
  17#include <linux/types.h>
  18#include <linux/string.h>
  19#include <linux/errno.h>
  20#include <linux/slab.h>
  21#include <linux/qnx4_fs.h>
  22#include <linux/fs.h>
  23#include <linux/locks.h>
  24#include <linux/init.h>
  25#include <linux/highuid.h>
  26#include <linux/smp_lock.h>
  27
  28#include <asm/uaccess.h>
  29
  30#define QNX4_VERSION  4
  31#define QNX4_BMNAME   ".bitmap"
  32
  33static struct super_operations qnx4_sops;
  34
  35#ifdef CONFIG_QNX4FS_RW
  36
  37int 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                ll_rw_block(WRITE, 1, &bh);
  47                wait_on_buffer(bh);
  48                if (buffer_req(bh) && !buffer_uptodate(bh))
  49                {
  50                        printk ("IO error syncing qnx4 inode [%s:%08lx]\n",
  51                                kdevname(inode->i_dev), inode->i_ino);
  52                        err = -1;
  53                }
  54                brelse (bh);
  55        } else if (!bh) {
  56                err = -1;
  57        }
  58# endif
  59
  60        return err;
  61}
  62
  63static void qnx4_delete_inode(struct inode *inode)
  64{
  65        QNX4DEBUG(("qnx4: deleting inode [%lu]\n", (unsigned long) inode->i_ino));
  66        lock_kernel();
  67        inode->i_size = 0;
  68        qnx4_truncate(inode);
  69        qnx4_free_inode(inode);
  70        unlock_kernel();
  71}
  72
  73static void qnx4_write_super(struct super_block *sb)
  74{
  75        QNX4DEBUG(("qnx4: write_super\n"));
  76        sb->s_dirt = 0;
  77}
  78
  79static void qnx4_write_inode(struct inode *inode, int unused)
  80{
  81        struct qnx4_inode_entry *raw_inode;
  82        int block, ino;
  83        struct buffer_head *bh;
  84        ino = inode->i_ino;
  85
  86        QNX4DEBUG(("qnx4: write inode 1.\n"));
  87        if (inode->i_nlink == 0) {
  88                return;
  89        }
  90        if (!ino) {
  91                printk("qnx4: bad inode number on dev %s: %d is out of range\n",
  92                       kdevname(inode->i_dev), ino);
  93                return;
  94        }
  95        QNX4DEBUG(("qnx4: write inode 2.\n"));
  96        block = ino / QNX4_INODES_PER_BLOCK;
  97        lock_kernel();
  98        if (!(bh = sb_bread(inode->i_sb, block))) {
  99                printk("qnx4: major problem: unable to read inode from dev "
 100                       "%s\n", kdevname(inode->i_dev));
 101                unlock_kernel();
 102                return;
 103        }
 104        raw_inode = ((struct qnx4_inode_entry *) bh->b_data) +
 105            (ino % QNX4_INODES_PER_BLOCK);
 106        raw_inode->di_mode  = cpu_to_le16(inode->i_mode);
 107        raw_inode->di_uid   = cpu_to_le16(fs_high2lowuid(inode->i_uid));
 108        raw_inode->di_gid   = cpu_to_le16(fs_high2lowgid(inode->i_gid));
 109        raw_inode->di_nlink = cpu_to_le16(inode->i_nlink);
 110        raw_inode->di_size  = cpu_to_le32(inode->i_size);
 111        raw_inode->di_mtime = cpu_to_le32(inode->i_mtime);
 112        raw_inode->di_atime = cpu_to_le32(inode->i_atime);
 113        raw_inode->di_ctime = cpu_to_le32(inode->i_ctime);
 114        raw_inode->di_first_xtnt.xtnt_size = cpu_to_le32(inode->i_blocks);
 115        mark_buffer_dirty(bh);
 116        brelse(bh);
 117        unlock_kernel();
 118}
 119
 120#endif
 121
 122static struct super_block *qnx4_read_super(struct super_block *, void *, int);
 123static void qnx4_put_super(struct super_block *sb);
 124static void qnx4_read_inode(struct inode *);
 125static int qnx4_remount(struct super_block *sb, int *flags, char *data);
 126static int qnx4_statfs(struct super_block *, struct statfs *);
 127
 128static struct super_operations qnx4_sops =
 129{
 130        read_inode:     qnx4_read_inode,
 131#ifdef CONFIG_QNX4FS_RW
 132        write_inode:    qnx4_write_inode,
 133        delete_inode:   qnx4_delete_inode,
 134#endif
 135        put_super:      qnx4_put_super,
 136#ifdef CONFIG_QNX4FS_RW
 137        write_super:    qnx4_write_super,
 138#endif
 139        statfs:         qnx4_statfs,
 140        remount_fs:     qnx4_remount,
 141};
 142
 143static int qnx4_remount(struct super_block *sb, int *flags, char *data)
 144{
 145        struct qnx4_sb_info *qs;
 146
 147        qs = &sb->u.qnx4_sb;
 148        qs->Version = QNX4_VERSION;
 149        if (*flags & MS_RDONLY) {
 150                return 0;
 151        }
 152        mark_buffer_dirty(qs->sb_buf);
 153
 154        return 0;
 155}
 156
 157struct buffer_head *qnx4_getblk(struct inode *inode, int nr,
 158                                 int create)
 159{
 160        struct buffer_head *result = NULL;
 161
 162        if ( nr >= 0 )
 163                nr = qnx4_block_map( inode, nr );
 164        if (nr) {
 165                result = sb_getblk(inode->i_sb, nr);
 166                return result;
 167        }
 168        if (!create) {
 169                return NULL;
 170        }
 171#if 0
 172        tmp = qnx4_new_block(inode->i_sb);
 173        if (!tmp) {
 174                return NULL;
 175        }
 176        result = sb_getblk(inode->i_sb, tmp);
 177        if (tst) {
 178                qnx4_free_block(inode->i_sb, tmp);
 179                brelse(result);
 180                goto repeat;
 181        }
 182        tst = tmp;
 183#endif
 184        inode->i_ctime = CURRENT_TIME;
 185        mark_inode_dirty(inode);
 186        return result;
 187}
 188
 189struct buffer_head *qnx4_bread(struct inode *inode, int block, int create)
 190{
 191        struct buffer_head *bh;
 192
 193        bh = qnx4_getblk(inode, block, create);
 194        if (!bh || buffer_uptodate(bh)) {
 195                return bh;
 196        }
 197        ll_rw_block(READ, 1, &bh);
 198        wait_on_buffer(bh);
 199        if (buffer_uptodate(bh)) {
 200                return bh;
 201        }
 202        brelse(bh);
 203
 204        return NULL;
 205}
 206
 207int qnx4_get_block( struct inode *inode, long iblock, struct buffer_head *bh, int create )
 208{
 209        unsigned long phys;
 210
 211        QNX4DEBUG(("qnx4: qnx4_get_block inode=[%ld] iblock=[%ld]\n",inode->i_ino,iblock));
 212
 213        phys = qnx4_block_map( inode, iblock );
 214        if ( phys ) {
 215                // logical block is before EOF
 216                bh->b_dev     = inode->i_dev;
 217                bh->b_blocknr = phys;
 218                bh->b_state  |= (1UL << BH_Mapped);
 219        } else if ( create ) {
 220                // to be done.
 221        }
 222        return 0;
 223}
 224
 225unsigned long qnx4_block_map( struct inode *inode, long iblock )
 226{
 227        int ix;
 228        long offset, i_xblk;
 229        unsigned long block = 0;
 230        struct buffer_head *bh = 0;
 231        struct qnx4_xblk *xblk = 0;
 232        struct qnx4_inode_info *qnx4_inode = &inode->u.qnx4_i;
 233        qnx4_nxtnt_t nxtnt = le16_to_cpu(qnx4_inode->i_num_xtnts);
 234
 235        if ( iblock < le32_to_cpu(qnx4_inode->i_first_xtnt.xtnt_size) ) {
 236                // iblock is in the first extent. This is easy.
 237                block = le32_to_cpu(qnx4_inode->i_first_xtnt.xtnt_blk) + iblock - 1;
 238        } else {
 239                // iblock is beyond first extent. We have to follow the extent chain.
 240                i_xblk = le32_to_cpu(qnx4_inode->i_xblk);
 241                offset = iblock - le32_to_cpu(qnx4_inode->i_first_xtnt.xtnt_size);
 242                ix = 0;
 243                while ( --nxtnt > 0 ) {
 244                        if ( ix == 0 ) {
 245                                // read next xtnt block.
 246                                bh = sb_bread(inode->i_sb, i_xblk - 1);
 247                                if ( !bh ) {
 248                                        QNX4DEBUG(("qnx4: I/O error reading xtnt block [%ld])\n", i_xblk - 1));
 249                                        return -EIO;
 250                                }
 251                                xblk = (struct qnx4_xblk*)bh->b_data;
 252                                if ( memcmp( xblk->xblk_signature, "IamXblk", 7 ) ) {
 253                                        QNX4DEBUG(("qnx4: block at %ld is not a valid xtnt\n", qnx4_inode->i_xblk));
 254                                        return -EIO;
 255                                }
 256                        }
 257                        if ( offset < le32_to_cpu(xblk->xblk_xtnts[ix].xtnt_size) ) {
 258                                // got it!
 259                                block = le32_to_cpu(xblk->xblk_xtnts[ix].xtnt_blk) + offset - 1;
 260                                break;
 261                        }
 262                        offset -= le32_to_cpu(xblk->xblk_xtnts[ix].xtnt_size);
 263                        if ( ++ix >= xblk->xblk_num_xtnts ) {
 264                                i_xblk = le32_to_cpu(xblk->xblk_next_xblk);
 265                                ix = 0;
 266                                brelse( bh );
 267                                bh = 0;
 268                        }
 269                }
 270                if ( bh )
 271                        brelse( bh );
 272        }
 273
 274        QNX4DEBUG(("qnx4: mapping block %ld of inode %ld = %ld\n",iblock,inode->i_ino,block));
 275        return block;
 276}
 277
 278static int qnx4_statfs(struct super_block *sb, struct statfs *buf)
 279{
 280        buf->f_type    = sb->s_magic;
 281        buf->f_bsize   = sb->s_blocksize;
 282        buf->f_blocks  = le32_to_cpu(sb->u.qnx4_sb.BitMap->di_size) * 8;
 283        buf->f_bfree   = qnx4_count_free_blocks(sb);
 284        buf->f_bavail  = buf->f_bfree;
 285        buf->f_namelen = QNX4_NAME_MAX;
 286
 287        return 0;
 288}
 289
 290/*
 291 * Check the root directory of the filesystem to make sure
 292 * it really _is_ a qnx4 filesystem, and to check the size
 293 * of the directory entry.
 294 */
 295static const char *qnx4_checkroot(struct super_block *sb)
 296{
 297        struct buffer_head *bh;
 298        struct qnx4_inode_entry *rootdir;
 299        int rd, rl;
 300        int i, j;
 301        int found = 0;
 302
 303        if (*(sb->u.qnx4_sb.sb->RootDir.di_fname) != '/') {
 304                return "no qnx4 filesystem (no root dir).";
 305        } else {
 306                QNX4DEBUG(("QNX4 filesystem found on dev %s.\n", kdevname(sb->s_dev)));
 307                rd = le32_to_cpu(sb->u.qnx4_sb.sb->RootDir.di_first_xtnt.xtnt_blk) - 1;
 308                rl = le32_to_cpu(sb->u.qnx4_sb.sb->RootDir.di_first_xtnt.xtnt_size);
 309                for (j = 0; j < rl; j++) {
 310                        bh = sb_bread(sb, rd + j);      /* root dir, first block */
 311                        if (bh == NULL) {
 312                                return "unable to read root entry.";
 313                        }
 314                        for (i = 0; i < QNX4_INODES_PER_BLOCK; i++) {
 315                                rootdir = (struct qnx4_inode_entry *) (bh->b_data + i * QNX4_DIR_ENTRY_SIZE);
 316                                if (rootdir->di_fname != NULL) {
 317                                        QNX4DEBUG(("Rootdir entry found : [%s]\n", rootdir->di_fname));
 318                                        if (!strncmp(rootdir->di_fname, QNX4_BMNAME, sizeof QNX4_BMNAME)) {
 319                                                found = 1;
 320                                                sb->u.qnx4_sb.BitMap = kmalloc( sizeof( struct qnx4_inode_entry ), GFP_KERNEL );
 321                                                if (!sb->u.qnx4_sb.BitMap) {
 322                                                        brelse (bh);
 323                                                        return "not enough memory for bitmap inode";
 324                                                }
 325                                                memcpy( sb->u.qnx4_sb.BitMap, rootdir, sizeof( struct qnx4_inode_entry ) );     /* keep bitmap inode known */
 326                                                break;
 327                                        }
 328                                }
 329                        }
 330                        brelse(bh);
 331                        if (found != 0) {
 332                                break;
 333                        }
 334                }
 335                if (found == 0) {
 336                        return "bitmap file not found.";
 337                }
 338        }
 339        return NULL;
 340}
 341
 342static struct super_block *qnx4_read_super(struct super_block *s,
 343                                           void *data, int silent)
 344{
 345        struct buffer_head *bh;
 346        kdev_t dev = s->s_dev;
 347        struct inode *root;
 348        const char *errmsg;
 349
 350        set_blocksize(dev, QNX4_BLOCK_SIZE);
 351        s->s_blocksize = QNX4_BLOCK_SIZE;
 352        s->s_blocksize_bits = QNX4_BLOCK_SIZE_BITS;
 353
 354        /* Check the superblock signature. Since the qnx4 code is
 355           dangerous, we should leave as quickly as possible
 356           if we don't belong here... */
 357        bh = sb_bread(s, 1);
 358        if (!bh) {
 359                printk("qnx4: unable to read the superblock\n");
 360                goto outnobh;
 361        }
 362        if ( le32_to_cpu( *(__u32*)bh->b_data ) != QNX4_SUPER_MAGIC ) {
 363                if (!silent)
 364                        printk("qnx4: wrong fsid in superblock sector.\n");
 365                goto out;
 366        }
 367        s->s_op = &qnx4_sops;
 368        s->s_magic = QNX4_SUPER_MAGIC;
 369#ifndef CONFIG_QNX4FS_RW
 370        s->s_flags |= MS_RDONLY;        /* Yup, read-only yet */
 371#endif
 372        s->u.qnx4_sb.sb_buf = bh;
 373        s->u.qnx4_sb.sb = (struct qnx4_super_block *) bh->b_data;
 374
 375
 376        /* check before allocating dentries, inodes, .. */
 377        errmsg = qnx4_checkroot(s);
 378        if (errmsg != NULL) {
 379                if (!silent)
 380                        printk("qnx4: %s\n", errmsg);
 381                goto out;
 382        }
 383
 384        /* does root not have inode number QNX4_ROOT_INO ?? */
 385        root = iget(s, QNX4_ROOT_INO * QNX4_INODES_PER_BLOCK);
 386        if (!root) {
 387                printk("qnx4: get inode failed\n");
 388                goto out;
 389        }
 390
 391        s->s_root = d_alloc_root(root);
 392        if (s->s_root == NULL)
 393                goto outi;
 394
 395        brelse(bh);
 396
 397        return s;
 398
 399      outi:
 400        iput(root);
 401      out:
 402        brelse(bh);
 403      outnobh:
 404
 405        return NULL;
 406}
 407
 408static void qnx4_put_super(struct super_block *sb)
 409{
 410        kfree( sb->u.qnx4_sb.BitMap );
 411        return;
 412}
 413
 414static int qnx4_writepage(struct page *page)
 415{
 416        return block_write_full_page(page,qnx4_get_block);
 417}
 418static int qnx4_readpage(struct file *file, struct page *page)
 419{
 420        return block_read_full_page(page,qnx4_get_block);
 421}
 422static int qnx4_prepare_write(struct file *file, struct page *page, unsigned from, unsigned to)
 423{
 424        return cont_prepare_write(page,from,to,qnx4_get_block,
 425                &page->mapping->host->u.qnx4_i.mmu_private);
 426}
 427static int qnx4_bmap(struct address_space *mapping, long block)
 428{
 429        return generic_block_bmap(mapping,block,qnx4_get_block);
 430}
 431struct address_space_operations qnx4_aops = {
 432        readpage: qnx4_readpage,
 433        writepage: qnx4_writepage,
 434        sync_page: block_sync_page,
 435        prepare_write: qnx4_prepare_write,
 436        commit_write: generic_commit_write,
 437        bmap: qnx4_bmap
 438};
 439
 440static void qnx4_read_inode(struct inode *inode)
 441{
 442        struct buffer_head *bh;
 443        struct qnx4_inode_entry *raw_inode;
 444        int block, ino;
 445
 446        ino = inode->i_ino;
 447        inode->i_mode = 0;
 448
 449        QNX4DEBUG(("Reading inode : [%d]\n", ino));
 450        if (!ino) {
 451                printk("qnx4: bad inode number on dev %s: %d is out of range\n",
 452                       kdevname(inode->i_dev), ino);
 453                return;
 454        }
 455        block = ino / QNX4_INODES_PER_BLOCK;
 456
 457        if (!(bh = sb_bread(inode->i_sb, block))) {
 458                printk("qnx4: major problem: unable to read inode from dev "
 459                       "%s\n", kdevname(inode->i_dev));
 460                return;
 461        }
 462        raw_inode = ((struct qnx4_inode_entry *) bh->b_data) +
 463            (ino % QNX4_INODES_PER_BLOCK);
 464
 465        inode->i_mode    = le16_to_cpu(raw_inode->di_mode);
 466        inode->i_uid     = (uid_t)le16_to_cpu(raw_inode->di_uid);
 467        inode->i_gid     = (gid_t)le16_to_cpu(raw_inode->di_gid);
 468        inode->i_nlink   = le16_to_cpu(raw_inode->di_nlink);
 469        inode->i_size    = le32_to_cpu(raw_inode->di_size);
 470        inode->i_mtime   = le32_to_cpu(raw_inode->di_mtime);
 471        inode->i_atime   = le32_to_cpu(raw_inode->di_atime);
 472        inode->i_ctime   = le32_to_cpu(raw_inode->di_ctime);
 473        inode->i_blocks  = le32_to_cpu(raw_inode->di_first_xtnt.xtnt_size);
 474        inode->i_blksize = QNX4_DIR_ENTRY_SIZE;
 475
 476        memcpy(&inode->u.qnx4_i, (struct qnx4_inode_info *) raw_inode, QNX4_DIR_ENTRY_SIZE);
 477        if (S_ISREG(inode->i_mode)) {
 478                inode->i_op = &qnx4_file_inode_operations;
 479                inode->i_fop = &qnx4_file_operations;
 480                inode->i_mapping->a_ops = &qnx4_aops;
 481                inode->u.qnx4_i.mmu_private = inode->i_size;
 482        } else if (S_ISDIR(inode->i_mode)) {
 483                inode->i_op = &qnx4_dir_inode_operations;
 484                inode->i_fop = &qnx4_dir_operations;
 485        } else if (S_ISLNK(inode->i_mode)) {
 486                inode->i_op = &page_symlink_inode_operations;
 487                inode->i_mapping->a_ops = &qnx4_aops;
 488                inode->u.qnx4_i.mmu_private = inode->i_size;
 489        } else
 490                printk("qnx4: bad inode %d on dev %s\n",ino,kdevname(inode->i_dev));
 491        brelse(bh);
 492}
 493
 494static DECLARE_FSTYPE_DEV(qnx4_fs_type, "qnx4", qnx4_read_super);
 495
 496static int __init init_qnx4_fs(void)
 497{
 498        printk("QNX4 filesystem 0.2.2 registered.\n");
 499        return register_filesystem(&qnx4_fs_type);
 500}
 501
 502static void __exit exit_qnx4_fs(void)
 503{
 504        unregister_filesystem(&qnx4_fs_type);
 505}
 506
 507EXPORT_NO_SYMBOLS;
 508
 509module_init(init_qnx4_fs)
 510module_exit(exit_qnx4_fs)
 511MODULE_LICENSE("GPL");
 512
 513
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.