inode.c

来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 837 行 · 第 1/2 页

C
837
字号
	if (dir->i_mode & S_ISGID) {		gid = dir->i_gid;		if (S_ISDIR(mode))			mode |= S_ISGID;	} else {		gid = current->fsgid;	}	inode = hugetlbfs_get_inode(dir->i_sb, current->fsuid, gid, mode, dev);	if (inode) {		dir->i_ctime = dir->i_mtime = CURRENT_TIME;		d_instantiate(dentry, inode);		dget(dentry);	/* Extra count - pin the dentry in core */		error = 0;	}	return error;}static int hugetlbfs_mkdir(struct inode *dir, struct dentry *dentry, int mode){	int retval = hugetlbfs_mknod(dir, dentry, mode | S_IFDIR, 0);	if (!retval)		dir->i_nlink++;	return retval;}static int hugetlbfs_create(struct inode *dir, struct dentry *dentry, int mode, struct nameidata *nd){	return hugetlbfs_mknod(dir, dentry, mode | S_IFREG, 0);}static int hugetlbfs_symlink(struct inode *dir,			struct dentry *dentry, const char *symname){	struct inode *inode;	int error = -ENOSPC;	gid_t gid;	if (dir->i_mode & S_ISGID)		gid = dir->i_gid;	else		gid = current->fsgid;	inode = hugetlbfs_get_inode(dir->i_sb, current->fsuid,					gid, S_IFLNK|S_IRWXUGO, 0);	if (inode) {		int l = strlen(symname)+1;		error = page_symlink(inode, symname, l);		if (!error) {			d_instantiate(dentry, inode);			dget(dentry);		} else			iput(inode);	}	dir->i_ctime = dir->i_mtime = CURRENT_TIME;	return error;}/* * For direct-IO reads into hugetlb pages */int hugetlbfs_set_page_dirty(struct page *page){	return 0;}static int hugetlbfs_statfs(struct super_block *sb, struct kstatfs *buf){	struct hugetlbfs_sb_info *sbinfo = HUGETLBFS_SB(sb);	buf->f_type = HUGETLBFS_MAGIC;	buf->f_bsize = HPAGE_SIZE;	if (sbinfo) {		spin_lock(&sbinfo->stat_lock);		buf->f_blocks = sbinfo->max_blocks;		buf->f_bavail = buf->f_bfree = sbinfo->free_blocks;		buf->f_files = sbinfo->max_inodes;		buf->f_ffree = sbinfo->free_inodes;		spin_unlock(&sbinfo->stat_lock);	}	buf->f_namelen = NAME_MAX;	return 0;}static void hugetlbfs_put_super(struct super_block *sb){	struct hugetlbfs_sb_info *sbi = HUGETLBFS_SB(sb);	if (sbi) {		sb->s_fs_info = NULL;		kfree(sbi);	}}static kmem_cache_t *hugetlbfs_inode_cachep;static struct inode *hugetlbfs_alloc_inode(struct super_block *sb){	struct hugetlbfs_inode_info *p;	p = kmem_cache_alloc(hugetlbfs_inode_cachep, SLAB_KERNEL);	if (!p)		return NULL;	return &p->vfs_inode;}static void init_once(void *foo, kmem_cache_t *cachep, unsigned long flags){	struct hugetlbfs_inode_info *ei = (struct hugetlbfs_inode_info *)foo;	if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==	    SLAB_CTOR_CONSTRUCTOR)		inode_init_once(&ei->vfs_inode);}static void hugetlbfs_destroy_inode(struct inode *inode){	mpol_free_shared_policy(&HUGETLBFS_I(inode)->policy);	kmem_cache_free(hugetlbfs_inode_cachep, HUGETLBFS_I(inode));}static struct address_space_operations hugetlbfs_aops = {	.readpage	= hugetlbfs_readpage,	.prepare_write	= hugetlbfs_prepare_write,	.commit_write	= hugetlbfs_commit_write,	.set_page_dirty	= hugetlbfs_set_page_dirty,};struct file_operations hugetlbfs_file_operations = {	.mmap			= hugetlbfs_file_mmap,	.fsync			= simple_sync_file,	.get_unmapped_area	= hugetlb_get_unmapped_area,};static struct inode_operations hugetlbfs_dir_inode_operations = {	.create		= hugetlbfs_create,	.lookup		= simple_lookup,	.link		= simple_link,	.unlink		= simple_unlink,	.symlink	= hugetlbfs_symlink,	.mkdir		= hugetlbfs_mkdir,	.rmdir		= simple_rmdir,	.mknod		= hugetlbfs_mknod,	.rename		= simple_rename,	.setattr	= hugetlbfs_setattr,};static struct inode_operations hugetlbfs_inode_operations = {	.setattr	= hugetlbfs_setattr,};static struct super_operations hugetlbfs_ops = {	.alloc_inode    = hugetlbfs_alloc_inode,	.destroy_inode  = hugetlbfs_destroy_inode,	.statfs		= hugetlbfs_statfs,	.drop_inode	= hugetlbfs_drop_inode,	.put_super	= hugetlbfs_put_super,};static inthugetlbfs_parse_options(char *options, struct hugetlbfs_config *pconfig){	char *opt, *value, *rest;	if (!options)		return 0;	while ((opt = strsep(&options, ",")) != NULL) {		if (!*opt)			continue;		value = strchr(opt, '=');		if (!value || !*value)			return -EINVAL;		else			*value++ = '\0';		if (!strcmp(opt, "uid"))			pconfig->uid = simple_strtoul(value, &value, 0);		else if (!strcmp(opt, "gid"))			pconfig->gid = simple_strtoul(value, &value, 0);		else if (!strcmp(opt, "mode"))			pconfig->mode = simple_strtoul(value,&value,0) & 0777U;		else if (!strcmp(opt, "size")) {			unsigned long long size = memparse(value, &rest);			if (*rest == '%') {				size <<= HPAGE_SHIFT;				size *= max_huge_pages;				do_div(size, 100);				rest++;			}			size &= HPAGE_MASK;			pconfig->nr_blocks = (size >> HPAGE_SHIFT);			value = rest;		} else if (!strcmp(opt,"nr_inodes")) {			pconfig->nr_inodes = memparse(value, &rest);			value = rest;		} else			return -EINVAL;		if (*value)			return -EINVAL;	}	return 0;}static inthugetlbfs_fill_super(struct super_block *sb, void *data, int silent){	struct inode * inode;	struct dentry * root;	int ret;	struct hugetlbfs_config config;	struct hugetlbfs_sb_info *sbinfo;	config.nr_blocks = -1; /* No limit on size by default */	config.nr_inodes = -1; /* No limit on number of inodes by default */	config.uid = current->fsuid;	config.gid = current->fsgid;	config.mode = 0755;	ret = hugetlbfs_parse_options(data, &config);	if (ret)		return ret;	sbinfo = kmalloc(sizeof(struct hugetlbfs_sb_info), GFP_KERNEL);	if (!sbinfo)		return -ENOMEM;	sb->s_fs_info = sbinfo;	spin_lock_init(&sbinfo->stat_lock);	sbinfo->max_blocks = config.nr_blocks;	sbinfo->free_blocks = config.nr_blocks;	sbinfo->max_inodes = config.nr_inodes;	sbinfo->free_inodes = config.nr_inodes;	sb->s_maxbytes = MAX_LFS_FILESIZE;	sb->s_blocksize = HPAGE_SIZE;	sb->s_blocksize_bits = HPAGE_SHIFT;	sb->s_magic = HUGETLBFS_MAGIC;	sb->s_op = &hugetlbfs_ops;	inode = hugetlbfs_get_inode(sb, config.uid, config.gid,					S_IFDIR | config.mode, 0);	if (!inode)		goto out_free;	root = d_alloc_root(inode);	if (!root) {		iput(inode);		goto out_free;	}	sb->s_root = root;	return 0;out_free:	kfree(sbinfo);	return -ENOMEM;}int hugetlb_get_quota(struct address_space *mapping){	int ret = 0;	struct hugetlbfs_sb_info *sbinfo = HUGETLBFS_SB(mapping->host->i_sb);	if (sbinfo->free_blocks > -1) {		spin_lock(&sbinfo->stat_lock);		if (sbinfo->free_blocks > 0)			sbinfo->free_blocks--;		else			ret = -ENOMEM;		spin_unlock(&sbinfo->stat_lock);	}	return ret;}void hugetlb_put_quota(struct address_space *mapping){	struct hugetlbfs_sb_info *sbinfo = HUGETLBFS_SB(mapping->host->i_sb);	if (sbinfo->free_blocks > -1) {		spin_lock(&sbinfo->stat_lock);		sbinfo->free_blocks++;		spin_unlock(&sbinfo->stat_lock);	}}static struct super_block *hugetlbfs_get_sb(struct file_system_type *fs_type,	int flags, const char *dev_name, void *data){	return get_sb_nodev(fs_type, flags, data, hugetlbfs_fill_super);}static struct file_system_type hugetlbfs_fs_type = {	.name		= "hugetlbfs",	.get_sb		= hugetlbfs_get_sb,	.kill_sb	= kill_litter_super,};static struct vfsmount *hugetlbfs_vfsmount;/* * Return the next identifier for a shm file */static unsigned long hugetlbfs_counter(void){	static spinlock_t lock = SPIN_LOCK_UNLOCKED;	static unsigned long counter;	unsigned long ret;	spin_lock(&lock);	ret = ++counter;	spin_unlock(&lock);	return ret;}static int can_do_hugetlb_shm(void){	return likely(capable(CAP_IPC_LOCK) ||			in_group_p(sysctl_hugetlb_shm_group) ||			can_do_mlock());}struct file *hugetlb_zero_setup(size_t size){	int error = -ENOMEM;	struct file *file;	struct inode *inode;	struct dentry *dentry, *root;	struct qstr quick_string;	char buf[16];	if (!can_do_hugetlb_shm())		return ERR_PTR(-EPERM);	if (!is_hugepage_mem_enough(size))		return ERR_PTR(-ENOMEM);	if (!user_shm_lock(size, current->user))		return ERR_PTR(-ENOMEM);	root = hugetlbfs_vfsmount->mnt_root;	snprintf(buf, 16, "%lu", hugetlbfs_counter());	quick_string.name = buf;	quick_string.len = strlen(quick_string.name);	quick_string.hash = 0;	dentry = d_alloc(root, &quick_string);	if (!dentry)		goto out_shm_unlock;	error = -ENFILE;	file = get_empty_filp();	if (!file)		goto out_dentry;	error = -ENOSPC;	inode = hugetlbfs_get_inode(root->d_sb, current->fsuid,				current->fsgid, S_IFREG | S_IRWXUGO, 0);	if (!inode)		goto out_file;	d_instantiate(dentry, inode);	inode->i_size = size;	inode->i_nlink = 0;	file->f_vfsmnt = mntget(hugetlbfs_vfsmount);	file->f_dentry = dentry;	file->f_mapping = inode->i_mapping;	file->f_op = &hugetlbfs_file_operations;	file->f_mode = FMODE_WRITE | FMODE_READ;	return file;out_file:	put_filp(file);out_dentry:	dput(dentry);out_shm_unlock:	user_shm_unlock(size, current->user);	return ERR_PTR(error);}static int __init init_hugetlbfs_fs(void){	int error;	struct vfsmount *vfsmount;	hugetlbfs_inode_cachep = kmem_cache_create("hugetlbfs_inode_cache",					sizeof(struct hugetlbfs_inode_info),					0, 0, init_once, NULL);	if (hugetlbfs_inode_cachep == NULL)		return -ENOMEM;	error = register_filesystem(&hugetlbfs_fs_type);	if (error)		goto out;	vfsmount = kern_mount(&hugetlbfs_fs_type);	if (!IS_ERR(vfsmount)) {		hugetlbfs_vfsmount = vfsmount;		return 0;	}	error = PTR_ERR(vfsmount); out:	if (error)		kmem_cache_destroy(hugetlbfs_inode_cachep);	return error;}static void __exit exit_hugetlbfs_fs(void){	kmem_cache_destroy(hugetlbfs_inode_cachep);	unregister_filesystem(&hugetlbfs_fs_type);}module_init(init_hugetlbfs_fs)module_exit(exit_hugetlbfs_fs)MODULE_LICENSE("GPL");

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?