⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 inode.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
		switch (mode & S_IFMT) {		default:			init_special_inode(inode, mode, dev);			break;		case S_IFREG:			inode->i_op = &hugetlbfs_inode_operations;			inode->i_fop = &hugetlbfs_file_operations;			break;		case S_IFDIR:			inode->i_op = &hugetlbfs_dir_inode_operations;			inode->i_fop = &simple_dir_operations;			/* directory inodes start off with i_nlink == 2 (for "." entry) */			inc_nlink(inode);			break;		case S_IFLNK:			inode->i_op = &page_symlink_inode_operations;			break;		}	}	return inode;}/* * File creation. Allocate an inode, and we're done.. */static int hugetlbfs_mknod(struct inode *dir,			struct dentry *dentry, int mode, dev_t dev){	struct inode *inode;	int error = -ENOSPC;	gid_t gid;	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)		inc_nlink(dir);	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;}/* * mark the head page dirty */static int hugetlbfs_set_page_dirty(struct page *page){	struct page *head = compound_head(page);	SetPageDirty(head);	return 0;}static int hugetlbfs_statfs(struct dentry *dentry, struct kstatfs *buf){	struct hugetlbfs_sb_info *sbinfo = HUGETLBFS_SB(dentry->d_sb);	buf->f_type = HUGETLBFS_MAGIC;	buf->f_bsize = HPAGE_SIZE;	if (sbinfo) {		spin_lock(&sbinfo->stat_lock);		/* If no limits set, just report 0 for max/free/used		 * blocks, like simple_statfs() */		if (sbinfo->max_blocks >= 0) {			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 inline int hugetlbfs_dec_free_inodes(struct hugetlbfs_sb_info *sbinfo){	if (sbinfo->free_inodes >= 0) {		spin_lock(&sbinfo->stat_lock);		if (unlikely(!sbinfo->free_inodes)) {			spin_unlock(&sbinfo->stat_lock);			return 0;		}		sbinfo->free_inodes--;		spin_unlock(&sbinfo->stat_lock);	}	return 1;}static void hugetlbfs_inc_free_inodes(struct hugetlbfs_sb_info *sbinfo){	if (sbinfo->free_inodes >= 0) {		spin_lock(&sbinfo->stat_lock);		sbinfo->free_inodes++;		spin_unlock(&sbinfo->stat_lock);	}}static struct kmem_cache *hugetlbfs_inode_cachep;static struct inode *hugetlbfs_alloc_inode(struct super_block *sb){	struct hugetlbfs_sb_info *sbinfo = HUGETLBFS_SB(sb);	struct hugetlbfs_inode_info *p;	if (unlikely(!hugetlbfs_dec_free_inodes(sbinfo)))		return NULL;	p = kmem_cache_alloc(hugetlbfs_inode_cachep, GFP_KERNEL);	if (unlikely(!p)) {		hugetlbfs_inc_free_inodes(sbinfo);		return NULL;	}	return &p->vfs_inode;}static void hugetlbfs_destroy_inode(struct inode *inode){	hugetlbfs_inc_free_inodes(HUGETLBFS_SB(inode->i_sb));	mpol_free_shared_policy(&HUGETLBFS_I(inode)->policy);	kmem_cache_free(hugetlbfs_inode_cachep, HUGETLBFS_I(inode));}static const struct address_space_operations hugetlbfs_aops = {	.readpage	= hugetlbfs_readpage,	.write_begin	= hugetlbfs_write_begin,	.write_end	= hugetlbfs_write_end,	.set_page_dirty	= hugetlbfs_set_page_dirty,};static void init_once(struct kmem_cache *cachep, void *foo){	struct hugetlbfs_inode_info *ei = (struct hugetlbfs_inode_info *)foo;	inode_init_once(&ei->vfs_inode);}const struct file_operations hugetlbfs_file_operations = {	.read			= hugetlbfs_read,	.mmap			= hugetlbfs_file_mmap,	.fsync			= simple_sync_file,	.get_unmapped_area	= hugetlb_get_unmapped_area,};static const 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 const struct inode_operations hugetlbfs_inode_operations = {	.setattr	= hugetlbfs_setattr,};static const struct super_operations hugetlbfs_ops = {	.alloc_inode    = hugetlbfs_alloc_inode,	.destroy_inode  = hugetlbfs_destroy_inode,	.statfs		= hugetlbfs_statfs,	.delete_inode	= hugetlbfs_delete_inode,	.drop_inode	= hugetlbfs_drop_inode,	.put_super	= hugetlbfs_put_super,};static inthugetlbfs_parse_options(char *options, struct hugetlbfs_config *pconfig){	char *p, *rest;	substring_t args[MAX_OPT_ARGS];	int option;	if (!options)		return 0;	while ((p = strsep(&options, ",")) != NULL) {		int token;		if (!*p)			continue;		token = match_token(p, tokens, args);		switch (token) {		case Opt_uid:			if (match_int(&args[0], &option)) 				goto bad_val;			pconfig->uid = option;			break;		case Opt_gid:			if (match_int(&args[0], &option)) 				goto bad_val;			pconfig->gid = option;			break;		case Opt_mode:			if (match_octal(&args[0], &option)) 				goto bad_val;			pconfig->mode = option & 0777U;			break;		case Opt_size: { 			unsigned long long size;			/* memparse() will accept a K/M/G without a digit */			if (!isdigit(*args[0].from))				goto bad_val;			size = memparse(args[0].from, &rest);			if (*rest == '%') {				size <<= HPAGE_SHIFT;				size *= max_huge_pages;				do_div(size, 100);			}			pconfig->nr_blocks = (size >> HPAGE_SHIFT);			break;		}		case Opt_nr_inodes:			/* memparse() will accept a K/M/G without a digit */			if (!isdigit(*args[0].from))				goto bad_val;			pconfig->nr_inodes = memparse(args[0].from, &rest);			break;		default:			printk(KERN_ERR "hugetlbfs: Bad mount option: \"%s\"\n",				 p);			return -EINVAL;			break;		}	}	return 0;bad_val: 	printk(KERN_ERR "hugetlbfs: Bad value '%s' for mount option '%s'\n",	       args[0].from, p); 	return 1;}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;	sb->s_time_gran = 1;	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, long delta){	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 - delta >= 0)			sbinfo->free_blocks -= delta;		else			ret = -ENOMEM;		spin_unlock(&sbinfo->stat_lock);	}	return ret;}void hugetlb_put_quota(struct address_space *mapping, long delta){	struct hugetlbfs_sb_info *sbinfo = HUGETLBFS_SB(mapping->host->i_sb);	if (sbinfo->free_blocks > -1) {		spin_lock(&sbinfo->stat_lock);		sbinfo->free_blocks += delta;		spin_unlock(&sbinfo->stat_lock);	}}static int hugetlbfs_get_sb(struct file_system_type *fs_type,	int flags, const char *dev_name, void *data, struct vfsmount *mnt){	return get_sb_nodev(fs_type, flags, data, hugetlbfs_fill_super, mnt);}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;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_file_setup(const char *name, size_t size){	int error = -ENOMEM;	struct file *file;	struct inode *inode;	struct dentry *dentry, *root;	struct qstr quick_string;	if (!hugetlbfs_vfsmount)		return ERR_PTR(-ENOENT);	if (!can_do_hugetlb_shm())		return ERR_PTR(-EPERM);	if (!user_shm_lock(size, current->user))		return ERR_PTR(-ENOMEM);	root = hugetlbfs_vfsmount->mnt_root;	quick_string.name = name;	quick_string.len = strlen(quick_string.name);	quick_string.hash = 0;	dentry = d_alloc(root, &quick_string);	if (!dentry)		goto out_shm_unlock;	error = -ENOSPC;	inode = hugetlbfs_get_inode(root->d_sb, current->fsuid,				current->fsgid, S_IFREG | S_IRWXUGO, 0);	if (!inode)		goto out_dentry;	error = -ENOMEM;	if (hugetlb_reserve_pages(inode, 0, size >> HPAGE_SHIFT))		goto out_inode;	d_instantiate(dentry, inode);	inode->i_size = size;	inode->i_nlink = 0;	error = -ENFILE;	file = alloc_file(hugetlbfs_vfsmount, dentry,			FMODE_WRITE | FMODE_READ,			&hugetlbfs_file_operations);	if (!file)		goto out_inode;	return file;out_inode:	iput(inode);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;	error = bdi_init(&hugetlbfs_backing_dev_info);	if (error)		return error;	hugetlbfs_inode_cachep = kmem_cache_create("hugetlbfs_inode_cache",					sizeof(struct hugetlbfs_inode_info),					0, 0, init_once);	if (hugetlbfs_inode_cachep == NULL)		goto out2;	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); out2:	bdi_destroy(&hugetlbfs_backing_dev_info);	return error;}static void __exit exit_hugetlbfs_fs(void){	kmem_cache_destroy(hugetlbfs_inode_cachep);	unregister_filesystem(&hugetlbfs_fs_type);	bdi_destroy(&hugetlbfs_backing_dev_info);}module_init(init_hugetlbfs_fs)module_exit(exit_hugetlbfs_fs)MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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