inode.c
来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 650 行 · 第 1/2 页
C
650 行
} stored++; offset = nextfh & ROMFH_MASK; }out: unlock_kernel(); return stored;}static struct dentry *romfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd){ unsigned long offset, maxoff; int fslen, res; struct inode *inode; char fsname[ROMFS_MAXFN]; /* XXX dynamic? */ struct romfs_inode ri; const char *name; /* got from dentry */ int len; res = -EACCES; /* placeholder for "no data here" */ offset = dir->i_ino & ROMFH_MASK; lock_kernel(); if (romfs_copyfrom(dir, &ri, offset, ROMFH_SIZE) <= 0) goto out; maxoff = romfs_maxsize(dir->i_sb); offset = be32_to_cpu(ri.spec) & ROMFH_MASK; /* OK, now find the file whose name is in "dentry" in the * directory specified by "dir". */ name = dentry->d_name.name; len = dentry->d_name.len; for(;;) { if (!offset || offset >= maxoff) goto out0; if (romfs_copyfrom(dir, &ri, offset, ROMFH_SIZE) <= 0) goto out; /* try to match the first 16 bytes of name */ fslen = romfs_strnlen(dir, offset+ROMFH_SIZE, ROMFH_SIZE); if (len < ROMFH_SIZE) { if (len == fslen) { /* both are shorter, and same size */ romfs_copyfrom(dir, fsname, offset+ROMFH_SIZE, len+1); if (strncmp (name, fsname, len) == 0) break; } } else if (fslen >= ROMFH_SIZE) { /* both are longer; XXX optimize max size */ fslen = romfs_strnlen(dir, offset+ROMFH_SIZE, sizeof(fsname)-1); if (len == fslen) { romfs_copyfrom(dir, fsname, offset+ROMFH_SIZE, len+1); if (strncmp(name, fsname, len) == 0) break; } } /* next entry */ offset = be32_to_cpu(ri.next) & ROMFH_MASK; } /* Hard link handling */ if ((be32_to_cpu(ri.next) & ROMFH_TYPE) == ROMFH_HRD) offset = be32_to_cpu(ri.spec) & ROMFH_MASK; if ((inode = iget(dir->i_sb, offset))) goto outi; /* * it's a bit funky, _lookup needs to return an error code * (negative) or a NULL, both as a dentry. ENOENT should not * be returned, instead we need to create a negative dentry by * d_add(dentry, NULL); and return 0 as no error. * (Although as I see, it only matters on writable file * systems). */out0: inode = NULL;outi: res = 0; d_add (dentry, inode);out: unlock_kernel(); return ERR_PTR(res);}/* * Ok, we do readpage, to be able to execute programs. Unfortunately, * we can't use bmap, since we may have looser alignments. */static intromfs_readpage(struct file *file, struct page * page){ struct inode *inode = page->mapping->host; unsigned long offset, avail, readlen; void *buf; int result = -EIO; page_cache_get(page); lock_kernel(); buf = kmap(page); if (!buf) goto err_out; /* 32 bit warning -- but not for us :) */ offset = page->index << PAGE_CACHE_SHIFT; if (offset < inode->i_size) { avail = inode->i_size-offset; readlen = min_t(unsigned long, avail, PAGE_SIZE); if (romfs_copyfrom(inode, buf, ROMFS_I(inode)->i_dataoffset+offset, readlen) == readlen) { if (readlen < PAGE_SIZE) { memset(buf + readlen,0,PAGE_SIZE-readlen); } SetPageUptodate(page); result = 0; } } if (result) { memset(buf, 0, PAGE_SIZE); SetPageError(page); } flush_dcache_page(page); unlock_page(page); kunmap(page);err_out: page_cache_release(page); unlock_kernel(); return result;}/* Mapping from our types to the kernel */static struct address_space_operations romfs_aops = { .readpage = romfs_readpage};static struct file_operations romfs_dir_operations = { .read = generic_read_dir, .readdir = romfs_readdir,};static struct inode_operations romfs_dir_inode_operations = { .lookup = romfs_lookup,};static mode_t romfs_modemap[] ={ 0, S_IFDIR+0644, S_IFREG+0644, S_IFLNK+0777, S_IFBLK+0600, S_IFCHR+0600, S_IFSOCK+0644, S_IFIFO+0644};static voidromfs_read_inode(struct inode *i){ int nextfh, ino; struct romfs_inode ri; ino = i->i_ino & ROMFH_MASK; i->i_mode = 0; /* Loop for finding the real hard link */ for(;;) { if (romfs_copyfrom(i, &ri, ino, ROMFH_SIZE) <= 0) { printk("romfs: read error for inode 0x%x\n", ino); return; } /* XXX: do romfs_checksum here too (with name) */ nextfh = be32_to_cpu(ri.next); if ((nextfh & ROMFH_TYPE) != ROMFH_HRD) break; ino = be32_to_cpu(ri.spec) & ROMFH_MASK; } i->i_nlink = 1; /* Hard to decide.. */ i->i_size = be32_to_cpu(ri.size); i->i_mtime.tv_sec = i->i_atime.tv_sec = i->i_ctime.tv_sec = 0; i->i_mtime.tv_nsec = i->i_atime.tv_nsec = i->i_ctime.tv_nsec = 0; i->i_uid = i->i_gid = 0; /* Precalculate the data offset */ ino = romfs_strnlen(i, ino+ROMFH_SIZE, ROMFS_MAXFN); if (ino >= 0) ino = ((ROMFH_SIZE+ino+1+ROMFH_PAD)&ROMFH_MASK); else ino = 0; ROMFS_I(i)->i_metasize = ino; ROMFS_I(i)->i_dataoffset = ino+(i->i_ino&ROMFH_MASK); /* Compute permissions */ ino = romfs_modemap[nextfh & ROMFH_TYPE]; /* only "normal" files have ops */ switch (nextfh & ROMFH_TYPE) { case 1: i->i_size = ROMFS_I(i)->i_metasize; i->i_op = &romfs_dir_inode_operations; i->i_fop = &romfs_dir_operations; if (nextfh & ROMFH_EXEC) ino |= S_IXUGO; i->i_mode = ino; break; case 2: i->i_fop = &generic_ro_fops; i->i_data.a_ops = &romfs_aops; if (nextfh & ROMFH_EXEC) ino |= S_IXUGO; i->i_mode = ino; break; case 3: i->i_op = &page_symlink_inode_operations; i->i_data.a_ops = &romfs_aops; i->i_mode = ino | S_IRWXUGO; break; default: /* depending on MBZ for sock/fifos */ nextfh = be32_to_cpu(ri.spec); init_special_inode(i, ino, MKDEV(nextfh>>16,nextfh&0xffff)); }}static kmem_cache_t * romfs_inode_cachep;static struct inode *romfs_alloc_inode(struct super_block *sb){ struct romfs_inode_info *ei; ei = (struct romfs_inode_info *)kmem_cache_alloc(romfs_inode_cachep, SLAB_KERNEL); if (!ei) return NULL; return &ei->vfs_inode;}static void romfs_destroy_inode(struct inode *inode){ kmem_cache_free(romfs_inode_cachep, ROMFS_I(inode));}static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags){ struct romfs_inode_info *ei = (struct romfs_inode_info *) foo; if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == SLAB_CTOR_CONSTRUCTOR) inode_init_once(&ei->vfs_inode);} static int init_inodecache(void){ romfs_inode_cachep = kmem_cache_create("romfs_inode_cache", sizeof(struct romfs_inode_info), 0, SLAB_RECLAIM_ACCOUNT, init_once, NULL); if (romfs_inode_cachep == NULL) return -ENOMEM; return 0;}static void destroy_inodecache(void){ if (kmem_cache_destroy(romfs_inode_cachep)) printk(KERN_INFO "romfs_inode_cache: not all structures were freed\n");}static int romfs_remount(struct super_block *sb, int *flags, char *data){ *flags |= MS_RDONLY; return 0;}static struct super_operations romfs_ops = { .alloc_inode = romfs_alloc_inode, .destroy_inode = romfs_destroy_inode, .read_inode = romfs_read_inode, .statfs = romfs_statfs, .remount_fs = romfs_remount,};static struct super_block *romfs_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *data){ return get_sb_bdev(fs_type, flags, dev_name, data, romfs_fill_super);}static struct file_system_type romfs_fs_type = { .owner = THIS_MODULE, .name = "romfs", .get_sb = romfs_get_sb, .kill_sb = kill_block_super, .fs_flags = FS_REQUIRES_DEV,};static int __init init_romfs_fs(void){ int err = init_inodecache(); if (err) goto out1; err = register_filesystem(&romfs_fs_type); if (err) goto out; return 0;out: destroy_inodecache();out1: return err;}static void __exit exit_romfs_fs(void){ unregister_filesystem(&romfs_fs_type); destroy_inodecache();}/* Yes, works even as a module... :) */module_init(init_romfs_fs)module_exit(exit_romfs_fs)MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?