📄 super.c
字号:
/* Read the superblock */ if (pram_calc_checksum((u32*)super, PRAM_SB_SIZE>>2)) { pram_err("checksum error in super block!\n"); goto out; }#ifdef CONFIG_PRAMFS_VNVRAM if (sbi->vnvram && super->s_size > sbi->vnvram->size) { pram_err("pramfs image size 0x%x too large, vnvram only 0x%x", super->s_size, sbi->vnvram->size); goto out; }#endif /* CONFIG_PRAMFS_VNVRAM */ /* get feature flags first */ // FIXME: implement fs features?#if 0 if (super->s_features & ~PRAM_SUPPORTED_FLAGS) { pram_err("unsupported filesystem features\n"); goto out; }#endif blocksize = super->s_blocksize; pram_set_blocksize(sb, blocksize); maxsize = super->s_size; pram_info("pramfs image appears to be %lu KB in size\n", maxsize>>10); pram_info("blocksize %lu\n", blocksize); /* Read the root inode */ root_i = pram_get_inode(sb, PRAM_ROOT_INO); if (pram_calc_checksum((u32*)root_i, PRAM_INODE_SIZE>>2)) { pram_err("checksum error in root inode!\n"); goto out; } /* Check that the root inode is in a sane state */ if (root_i->i_d.d_next) { pram_err("root->next not NULL??!!\n"); goto out; } if (!S_ISDIR(root_i->i_mode)) { pram_err("root is not a directory!\n"); goto out; } root_offset = root_i->i_type.dir.head; if (root_offset == 0) pram_info("empty filesystem\n"); /* Remap the whole filesystem now */ pram_iounmap(sbi, sbi->virt_addr); sbi->virt_addr = pram_ioremap(sbi, sbi->phys_addr, maxsize); if (!sbi->virt_addr) { pram_err("ioremap of the pramfs image failed\n"); goto out; } super = pram_get_super(sb); root_i = pram_get_inode(sb, PRAM_ROOT_INO); pram_do_powerfail_restore(sb, super); *superp = super; *root_ip = root_i; retval = 0;out: return retval;}#ifdef CONFIG_PRAMFS_VNVRAMstatic inline void pram_parse_time_param (struct super_block * sb, const char *data){ /* default is not update time */ if (!strstr(data, "notime") && strstr(data, "time")) { return; } sb->s_flags |= MS_NOTIME;}static inline void pram_parse_data_param (struct super_block * sb, const char *data){ /* default is not data failsafe */ if (strstr(data, "data_failsafe")) sb->s_flags |= MS_DATA_FAILSAFE;}#else#define pram_parse_time_param(sb, data) do {} while (0)#define pram_parse_data_param(sb, data) do {} while (0)#endif /* CONFIG_PRAMFS_VNVRAM */static int pram_fill_super (struct super_block * sb, void * data, int silent){ char *p; struct pram_super_block * super = NULL; struct pram_inode * root_i = NULL; struct pram_sb_info * sbi = NULL; unsigned long maxsize; int retval = -EINVAL; sbi = kzalloc(sizeof(*sbi), GFP_KERNEL); if (!sbi) return -ENOMEM; sb->s_fs_info = sbi; sbi->sb = sb;#ifdef CONFIG_PRAMFS_FAILSAFE mutex_init(&sbi->failsafe_mutex);#endif if (!data) { pram_err("no parameter for mount pramfs\n"); goto out; }#ifdef CONFIG_PRAMFS_VNVRAM if (!(strstr((char *)data, "physaddr="))) { /* no physaddr, assume use vnvram */ int err; sbi->vnvram = kzalloc(sizeof(struct vnvram_info), GFP_KERNEL); if (!sbi->vnvram) { pram_err("alloc vnvram failed\n"); retval = -ENOMEM; goto out; } err = vnvram_get_info_pram(sbi->vnvram); if (err) { retval = err; goto out; } sbi->phys_addr = sbi->vnvram->phys_addr; } if (!sbi->vnvram)#endif /* CONFIG_PRAMFS_VNVRAM */ { /* * The physical location of the pram image is specified as * a mount parameter. This parameter is mandatory for obvious * reasons. Some validation is made on the phys address but this * is not exhaustive and we count on the fact that someone using * this feature is supposed to know what he/she's doing. */ if (!data || !(p = strstr((char *)data, "physaddr="))) { pram_err("unknown physical address for pramfs image\n"); goto out; } sbi->phys_addr = simple_strtoul(p + 9, NULL, 0); if (sbi->phys_addr & (PAGE_SIZE-1)) { pram_err("physical address 0x%lx for pramfs isn't " "aligned to a page boundary\n", sbi->phys_addr); goto out; } if (sbi->phys_addr == 0) { pram_err("physical address for pramfs image can't be 0\n"); goto out; } } pram_parse_time_param (sb, data); pram_parse_data_param (sb, data); if ((p = strstr((char *)data, "init="))) { maxsize = simple_strtoul(p + 5, NULL, 0);#ifdef CONFIG_PRAMFS_VNVRAM if (!maxsize && sbi->vnvram) maxsize = sbi->vnvram->size; /* init=0, use default */#endif pram_info("creating an empty pramfs of size %lu\n", maxsize); retval = init_super(sb, data, maxsize, sbi, &super, &root_i); } else { retval = fill_super(sb, data, sbi, &super, &root_i); } if (retval) goto out; /* Set it all up.. */ sb->s_magic = super->s_magic; sb->s_op = &pram_sops; sb->s_root = d_alloc_root(pram_fill_new_inode(sb, root_i)); retval = 0; out: if (retval) { if (sbi->virt_addr) pram_iounmap(sbi, sbi->virt_addr); kfree(sbi); sb->s_fs_info = NULL;#ifdef CONFIG_PRAMFS_VNVRAM kfree(sbi->vnvram);#endif } return retval;}//static void pram_write_super (struct super_block * sb)//{//}int pram_statfs (struct dentry * dentry, struct kstatfs * buf){ struct super_block * sb = dentry->d_sb; struct pram_super_block * ps = pram_get_super(sb); buf->f_type = PRAM_SUPER_MAGIC; buf->f_bsize = sb->s_blocksize; buf->f_blocks = ps->s_blocks_count; buf->f_bfree = buf->f_bavail = pram_get_free_blocks_count(sb); buf->f_files = ps->s_inodes_count; buf->f_ffree = pram_get_free_inodes_count(sb); buf->f_namelen = PRAM_NAME_LEN; return 0;}int pram_remount (struct super_block * sb, int * mntflags, char * data){ /* mtime is unused at all, avoid calling pram_sync_super * no update super when failsafe is enabled. */#ifndef CONFIG_PRAMFS_FAILSAFE struct pram_super_block * ps; if ((*mntflags & MS_RDONLY) != (sb->s_flags & MS_RDONLY)) { ps = pram_get_super(sb); pram_lock_super(sb); /* no need backup */ ps->s_mtime = get_seconds(); // update mount time pram_unlock_super(sb); }#endif return 0;}static void pram_put_super (struct super_block * sb){ struct pram_sb_info * sbi = (struct pram_sb_info *)sb->s_fs_info; /* It's unmount time, so unmap the pramfs memory */ if (sbi->virt_addr) { pram_iounmap(sbi, sbi->virt_addr); sbi->virt_addr = NULL; }#ifdef CONFIG_PRAMFS_VNVRAM if (sbi->vnvram) { vnvram_sync_range_pram(sbi->vnvram->virt_addr, sbi->vnvram->size); kfree(sbi->vnvram); }#endif sb->s_fs_info = NULL; kfree(sbi);}/* * the super block writes are all done "on the fly", so the * super block is never in a "dirty" state, so there's no need * for write_super. */static struct super_operations pram_sops = { .read_inode = pram_read_inode, .write_inode = pram_write_inode, .dirty_inode = pram_dirty_inode, .put_inode = pram_put_inode, .delete_inode = pram_delete_inode, .put_super = pram_put_super,// .write_super = pram_write_super, .statfs = pram_statfs, .remount_fs = pram_remount,};static int pram_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *data, struct vfsmount *mnt){ return get_sb_single(fs_type, flags, data, pram_fill_super, mnt);}static struct file_system_type pram_fs_type = { .owner = THIS_MODULE, .name = "pramfs", .get_sb = pram_get_sb, .kill_sb = kill_anon_super,};static int __init init_pram_fs(void){ printk(KERN_INFO "PRAMFS"#ifdef CONFIG_PRAMFS_VNVRAM " (VNVRAM)"#endif#ifdef CONFIG_PRAMFS_FAILSAFE " (FAILSAFE)"#endif "\n"); return register_filesystem(&pram_fs_type);}static void __exit exit_pram_fs(void){ unregister_filesystem(&pram_fs_type);}module_init(init_pram_fs)module_exit(exit_pram_fs)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -