cregit-Linux how code gets into the kernel

Release 4.11 fs/qnx4/inode.c

Directory: fs/qnx4
/*
 * QNX4 file system, Linux implementation.
 *
 * Version : 0.2.1
 *
 * Using parts of the xiafs filesystem.
 *
 * History :
 *
 * 01-06-1998 by Richard Frowijn : first release.
 * 20-06-1998 by Frank Denis : Linux 2.1.99+ support, boot signature, misc.
 * 30-06-1998 by Frank Denis : first step to write inodes.
 */

#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/highuid.h>
#include <linux/pagemap.h>
#include <linux/buffer_head.h>
#include <linux/writeback.h>
#include <linux/statfs.h>
#include "qnx4.h"


#define QNX4_VERSION  4

#define QNX4_BMNAME   ".bitmap"


static const struct super_operations qnx4_sops;

static struct inode *qnx4_alloc_inode(struct super_block *sb);
static void qnx4_destroy_inode(struct inode *inode);
static int qnx4_remount(struct super_block *sb, int *flags, char *data);
static int qnx4_statfs(struct dentry *, struct kstatfs *);


static const struct super_operations qnx4_sops =
{
	.alloc_inode	= qnx4_alloc_inode,
	.destroy_inode	= qnx4_destroy_inode,
	.statfs		= qnx4_statfs,
	.remount_fs	= qnx4_remount,
};


static int qnx4_remount(struct super_block *sb, int *flags, char *data) { struct qnx4_sb_info *qs; sync_filesystem(sb); qs = qnx4_sb(sb); qs->Version = QNX4_VERSION; *flags |= MS_RDONLY; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)3774.00%125.00%
Al Viro510.00%125.00%
Theodore Y. Ts'o510.00%125.00%
Brian Gerst36.00%125.00%
Total50100.00%4100.00%


static int qnx4_get_block( struct inode *inode, sector_t iblock, struct buffer_head *bh, int create ) { unsigned long phys; QNX4DEBUG((KERN_INFO "qnx4: qnx4_get_block inode=[%ld] iblock=[%ld]\n",inode->i_ino,iblock)); phys = qnx4_block_map( inode, iblock ); if ( phys ) { // logical block is before EOF map_bh(bh, inode->i_sb, phys); } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)6187.14%120.00%
Linus Torvalds710.00%240.00%
Anders Larsen11.43%120.00%
Adrian Bunk11.43%120.00%
Total70100.00%5100.00%


static inline u32 try_extent(qnx4_xtnt_t *extent, u32 *offset) { u32 size = le32_to_cpu(extent->xtnt_size); if (*offset < size) return le32_to_cpu(extent->xtnt_blk) + *offset - 1; *offset -= size; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Al Viro53100.00%1100.00%
Total53100.00%1100.00%


unsigned long qnx4_block_map( struct inode *inode, long iblock ) { int ix; long i_xblk; struct buffer_head *bh = NULL; struct qnx4_xblk *xblk = NULL; struct qnx4_inode_entry *qnx4_inode = qnx4_raw_inode(inode); u16 nxtnt = le16_to_cpu(qnx4_inode->di_num_xtnts); u32 offset = iblock; u32 block = try_extent(&qnx4_inode->di_first_xtnt, &offset); if (block) { // iblock is in the first extent. This is easy. } else { // iblock is beyond first extent. We have to follow the extent chain. i_xblk = le32_to_cpu(qnx4_inode->di_xblk); ix = 0; while ( --nxtnt > 0 ) { if ( ix == 0 ) { // read next xtnt block. bh = sb_bread(inode->i_sb, i_xblk - 1); if ( !bh ) { QNX4DEBUG((KERN_ERR "qnx4: I/O error reading xtnt block [%ld])\n", i_xblk - 1)); return -EIO; } xblk = (struct qnx4_xblk*)bh->b_data; if ( memcmp( xblk->xblk_signature, "IamXblk", 7 ) ) { QNX4DEBUG((KERN_ERR "qnx4: block at %ld is not a valid xtnt\n", qnx4_inode->i_xblk)); return -EIO; } } block = try_extent(&xblk->xblk_xtnts[ix], &offset); if (block) { // got it! break; } if ( ++ix >= xblk->xblk_num_xtnts ) { i_xblk = le32_to_cpu(xblk->xblk_next_xblk); ix = 0; brelse( bh ); bh = NULL; } } if ( bh ) brelse( bh ); } QNX4DEBUG((KERN_INFO "qnx4: mapping block %ld of inode %ld = %ld\n",iblock,inode->i_ino,block)); return block; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)23584.53%440.00%
Al Viro3010.79%220.00%
Linus Torvalds93.24%220.00%
Anders Larsen31.08%110.00%
Alexey Dobriyan10.36%110.00%
Total278100.00%10100.00%


static int qnx4_statfs(struct dentry *dentry, struct kstatfs *buf) { struct super_block *sb = dentry->d_sb; u64 id = huge_encode_dev(sb->s_bdev->bd_dev); buf->f_type = sb->s_magic; buf->f_bsize = sb->s_blocksize; buf->f_blocks = le32_to_cpu(qnx4_sb(sb)->BitMap->di_size) * 8; buf->f_bfree = qnx4_count_free_blocks(sb); buf->f_bavail = buf->f_bfree; buf->f_namelen = QNX4_NAME_MAX; buf->f_fsid.val[0] = (u32)id; buf->f_fsid.val[1] = (u32)(id >> 32); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)7054.26%233.33%
Coly Li4434.11%116.67%
David Howells118.53%116.67%
Brian Gerst32.33%116.67%
Andrew Morton10.78%116.67%
Total129100.00%6100.00%

/* * Check the root directory of the filesystem to make sure * it really _is_ a qnx4 filesystem, and to check the size * of the directory entry. */
static const char *qnx4_checkroot(struct super_block *sb, struct qnx4_super_block *s) { struct buffer_head *bh; struct qnx4_inode_entry *rootdir; int rd, rl; int i, j; if (s->RootDir.di_fname[0] != '/' || s->RootDir.di_fname[1] != '\0') return "no qnx4 filesystem (no root dir)."; QNX4DEBUG((KERN_NOTICE "QNX4 filesystem found on dev %s.\n", sb->s_id)); rd = le32_to_cpu(s->RootDir.di_first_xtnt.xtnt_blk) - 1; rl = le32_to_cpu(s->RootDir.di_first_xtnt.xtnt_size); for (j = 0; j < rl; j++) { bh = sb_bread(sb, rd + j); /* root dir, first block */ if (bh == NULL) return "unable to read root entry."; rootdir = (struct qnx4_inode_entry *) bh->b_data; for (i = 0; i < QNX4_INODES_PER_BLOCK; i++, rootdir++) { QNX4DEBUG((KERN_INFO "rootdir entry found : [%s]\n", rootdir->di_fname)); if (strcmp(rootdir->di_fname, QNX4_BMNAME) != 0) continue; qnx4_sb(sb)->BitMap = kmemdup(rootdir, sizeof(struct qnx4_inode_entry), GFP_KERNEL); brelse(bh); if (!qnx4_sb(sb)->BitMap) return "not enough memory for bitmap inode"; /* keep bitmap inode known */ return NULL; } brelse(bh); } return "bitmap file not found."; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)17470.73%325.00%
Al Viro4719.11%216.67%
Dave Jones135.28%18.33%
Brian Gerst31.22%18.33%
Thomas Meyer31.22%18.33%
Anders Larsen31.22%18.33%
Linus Torvalds20.81%216.67%
Julia Lawall10.41%18.33%
Total246100.00%12100.00%


static int qnx4_fill_super(struct super_block *s, void *data, int silent) { struct buffer_head *bh; struct inode *root; const char *errmsg; struct qnx4_sb_info *qs; qs = kzalloc(sizeof(struct qnx4_sb_info), GFP_KERNEL); if (!qs) return -ENOMEM; s->s_fs_info = qs; sb_set_blocksize(s, QNX4_BLOCK_SIZE); s->s_op = &qnx4_sops; s->s_magic = QNX4_SUPER_MAGIC; s->s_flags |= MS_RDONLY; /* Yup, read-only yet */ /* Check the superblock signature. Since the qnx4 code is dangerous, we should leave as quickly as possible if we don't belong here... */ bh = sb_bread(s, 1); if (!bh) { printk(KERN_ERR "qnx4: unable to read the superblock\n"); return -EINVAL; } /* check before allocating dentries, inodes, .. */ errmsg = qnx4_checkroot(s, (struct qnx4_super_block *) bh->b_data); brelse(bh); if (errmsg != NULL) { if (!silent) printk(KERN_ERR "qnx4: %s\n", errmsg); return -EINVAL; } /* does root not have inode number QNX4_ROOT_INO ?? */ root = qnx4_iget(s, QNX4_ROOT_INO * QNX4_INODES_PER_BLOCK); if (IS_ERR(root)) { printk(KERN_ERR "qnx4: get inode failed\n"); return PTR_ERR(root); } s->s_root = d_make_root(root); if (s->s_root == NULL) return -ENOMEM; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)13359.38%218.18%
Al Viro4218.75%327.27%
Brian Gerst3616.07%218.18%
David Howells83.57%19.09%
Anders Larsen20.89%19.09%
Linus Torvalds20.89%19.09%
Panagiotis Issaris10.45%19.09%
Total224100.00%11100.00%


static void qnx4_kill_sb(struct super_block *sb) { struct qnx4_sb_info *qs = qnx4_sb(sb); kill_block_super(sb); if (qs) { kfree(qs->BitMap); kfree(qs); } }

Contributors

PersonTokensPropCommitsCommitProp
Brian Gerst2045.45%120.00%
Linus Torvalds (pre-git)1227.27%360.00%
Al Viro1227.27%120.00%
Total44100.00%5100.00%


static int qnx4_readpage(struct file *file, struct page *page) { return block_read_full_page(page,qnx4_get_block); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)24100.00%2100.00%
Total24100.00%2100.00%


static sector_t qnx4_bmap(struct address_space *mapping, sector_t block) { return generic_block_bmap(mapping,block,qnx4_get_block); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)2291.67%150.00%
Andrew Morton28.33%150.00%
Total24100.00%2100.00%

static const struct address_space_operations qnx4_aops = { .readpage = qnx4_readpage, .bmap = qnx4_bmap };
struct inode *qnx4_iget(struct super_block *sb, unsigned long ino) { struct buffer_head *bh; struct qnx4_inode_entry *raw_inode; int block; struct qnx4_inode_entry *qnx4_inode; struct inode *inode; inode = iget_locked(sb, ino); if (!inode) return ERR_PTR(-ENOMEM); if (!(inode->i_state & I_NEW)) return inode; qnx4_inode = qnx4_raw_inode(inode); inode->i_mode = 0; QNX4DEBUG((KERN_INFO "reading inode : [%d]\n", ino)); if (!ino) { printk(KERN_ERR "qnx4: bad inode number on dev %s: %lu is " "out of range\n", sb->s_id, ino); iget_failed(inode); return ERR_PTR(-EIO); } block = ino / QNX4_INODES_PER_BLOCK; if (!(bh = sb_bread(sb, block))) { printk(KERN_ERR "qnx4: major problem: unable to read inode from dev " "%s\n", sb->s_id); iget_failed(inode); return ERR_PTR(-EIO); } raw_inode = ((struct qnx4_inode_entry *) bh->b_data) + (ino % QNX4_INODES_PER_BLOCK); inode->i_mode = le16_to_cpu(raw_inode->di_mode); i_uid_write(inode, (uid_t)le16_to_cpu(raw_inode->di_uid)); i_gid_write(inode, (gid_t)le16_to_cpu(raw_inode->di_gid)); set_nlink(inode, le16_to_cpu(raw_inode->di_nlink)); inode->i_size = le32_to_cpu(raw_inode->di_size); inode->i_mtime.tv_sec = le32_to_cpu(raw_inode->di_mtime); inode->i_mtime.tv_nsec = 0; inode->i_atime.tv_sec = le32_to_cpu(raw_inode->di_atime); inode->i_atime.tv_nsec = 0; inode->i_ctime.tv_sec = le32_to_cpu(raw_inode->di_ctime); inode->i_ctime.tv_nsec = 0; inode->i_blocks = le32_to_cpu(raw_inode->di_first_xtnt.xtnt_size); memcpy(qnx4_inode, raw_inode, QNX4_DIR_ENTRY_SIZE); if (S_ISREG(inode->i_mode)) { inode->i_fop = &generic_ro_fops; inode->i_mapping->a_ops = &qnx4_aops; qnx4_i(inode)->mmu_private = inode->i_size; } else if (S_ISDIR(inode->i_mode)) { inode->i_op = &qnx4_dir_inode_operations; inode->i_fop = &qnx4_dir_operations; } else if (S_ISLNK(inode->i_mode)) { inode->i_op = &page_symlink_inode_operations; inode_nohighmem(inode); inode->i_mapping->a_ops = &qnx4_aops; qnx4_i(inode)->mmu_private = inode->i_size; } else { printk(KERN_ERR "qnx4: bad inode %lu on dev %s\n", ino, sb->s_id); iget_failed(inode); brelse(bh); return ERR_PTR(-EIO); } brelse(bh); unlock_new_inode(inode); return inode; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)31563.64%637.50%
David Howells10721.62%16.25%
Andi Kleen306.06%16.25%
Linus Torvalds224.44%318.75%
Eric W. Biedermann81.62%16.25%
Al Viro51.01%16.25%
Miklos Szeredi40.81%16.25%
Anders Larsen30.61%16.25%
Christoph Hellwig10.20%16.25%
Total495100.00%16100.00%

static struct kmem_cache *qnx4_inode_cachep;
static struct inode *qnx4_alloc_inode(struct super_block *sb) { struct qnx4_inode_info *ei; ei = kmem_cache_alloc(qnx4_inode_cachep, GFP_KERNEL); if (!ei) return NULL; return &ei->vfs_inode; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds4097.56%150.00%
Christoph Lameter12.44%150.00%
Total41100.00%2100.00%


static void qnx4_i_callback(struct rcu_head *head) { struct inode *inode = container_of(head, struct inode, i_rcu); kmem_cache_free(qnx4_inode_cachep, qnx4_i(inode)); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds1850.00%150.00%
Nicholas Piggin1850.00%150.00%
Total36100.00%2100.00%


static void qnx4_destroy_inode(struct inode *inode) { call_rcu(&inode->i_rcu, qnx4_i_callback); }

Contributors

PersonTokensPropCommitsCommitProp
Nicholas Piggin21100.00%1100.00%
Total21100.00%1100.00%


static void init_once(void *foo) { struct qnx4_inode_info *ei = (struct qnx4_inode_info *) foo; inode_init_once(&ei->vfs_inode); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds2790.00%150.00%
Christoph Lameter310.00%150.00%
Total30100.00%2100.00%


static int init_inodecache(void) { qnx4_inode_cachep = kmem_cache_create("qnx4_inode_cache", sizeof(struct qnx4_inode_info), 0, (SLAB_RECLAIM_ACCOUNT| SLAB_MEM_SPREAD|SLAB_ACCOUNT), init_once); if (qnx4_inode_cachep == NULL) return -ENOMEM; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds3984.78%120.00%
Paul Jackson48.70%240.00%
Vladimir Davydov24.35%120.00%
Andrew Morton12.17%120.00%
Total46100.00%5100.00%


static void destroy_inodecache(void) { /* * Make sure all delayed rcu free inodes are flushed before we * destroy cache. */ rcu_barrier(); kmem_cache_destroy(qnx4_inode_cachep); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds1376.47%150.00%
Kirill A. Shutemov423.53%150.00%
Total17100.00%2100.00%


static struct dentry *qnx4_mount(struct file_system_type *fs_type, int flags, const char *dev_name, void *data) { return mount_bdev(fs_type, flags, dev_name, data, qnx4_fill_super); }

Contributors

PersonTokensPropCommitsCommitProp
Al Viro3384.62%240.00%
Linus Torvalds (pre-git)512.82%240.00%
Andries E. Brouwer12.56%120.00%
Total39100.00%5100.00%

static struct file_system_type qnx4_fs_type = { .owner = THIS_MODULE, .name = "qnx4", .mount = qnx4_mount, .kill_sb = qnx4_kill_sb, .fs_flags = FS_REQUIRES_DEV, }; MODULE_ALIAS_FS("qnx4");
static int __init init_qnx4_fs(void) { int err; err = init_inodecache(); if (err) return err; err = register_filesystem(&qnx4_fs_type); if (err) { destroy_inodecache(); return err; } printk(KERN_INFO "QNX4 filesystem 0.2.3 registered.\n"); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds3464.15%116.67%
Linus Torvalds (pre-git)1732.08%350.00%
Anders Larsen11.89%116.67%
Alan Cox11.89%116.67%
Total53100.00%6100.00%


static void __exit exit_qnx4_fs(void) { unregister_filesystem(&qnx4_fs_type); destroy_inodecache(); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)1583.33%266.67%
Linus Torvalds316.67%133.33%
Total18100.00%3100.00%

module_init(init_qnx4_fs) module_exit(exit_qnx4_fs) MODULE_LICENSE("GPL");

Overall Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)120456.37%1622.54%
Al Viro25511.94%1216.90%
Linus Torvalds25411.89%79.86%
David Howells1275.95%22.82%
Brian Gerst653.04%22.82%
Coly Li442.06%11.41%
Nicholas Piggin391.83%11.41%
Andi Kleen301.40%11.41%
Alan Cox281.31%11.41%
Eric W. Biedermann130.61%22.82%
Dave Jones130.61%11.41%
Anders Larsen130.61%11.41%
Christoph Hellwig100.47%57.04%
Christoph Lameter60.28%34.23%
Theodore Y. Ts'o50.23%11.41%
Andrew Morton50.23%34.23%
Miklos Szeredi40.19%11.41%
Kirill A. Shutemov40.19%11.41%
Paul Jackson40.19%22.82%
Thomas Meyer30.14%11.41%
Adrian Bunk20.09%11.41%
Josef 'Jeff' Sipek20.09%11.41%
Vladimir Davydov20.09%11.41%
Alexey Dobriyan10.05%11.41%
Julia Lawall10.05%11.41%
Panagiotis Issaris10.05%11.41%
Andries E. Brouwer10.05%11.41%
Total2136100.00%71100.00%
Directory: fs/qnx4
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.