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

📄 shmem.c

📁 最新最稳定的Linux内存管理模块源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
}static const struct inode_operations shmem_symlink_inline_operations = {	.readlink	= generic_readlink,	.follow_link	= shmem_follow_link_inline,};static const struct inode_operations shmem_symlink_inode_operations = {	.truncate	= shmem_truncate,	.readlink	= generic_readlink,	.follow_link	= shmem_follow_link,	.put_link	= shmem_put_link,};#ifdef CONFIG_TMPFS_POSIX_ACL/* * Superblocks without xattr inode operations will get security.* xattr * support from the VFS "for free". As soon as we have any other xattrs * like ACLs, we also need to implement the security.* handlers at * filesystem level, though. */static size_t shmem_xattr_security_list(struct inode *inode, char *list,					size_t list_len, const char *name,					size_t name_len){	return security_inode_listsecurity(inode, list, list_len);}static int shmem_xattr_security_get(struct inode *inode, const char *name,				    void *buffer, size_t size){	if (strcmp(name, "") == 0)		return -EINVAL;	return xattr_getsecurity(inode, name, buffer, size);}static int shmem_xattr_security_set(struct inode *inode, const char *name,				    const void *value, size_t size, int flags){	if (strcmp(name, "") == 0)		return -EINVAL;	return security_inode_setsecurity(inode, name, value, size, flags);}static struct xattr_handler shmem_xattr_security_handler = {	.prefix = XATTR_SECURITY_PREFIX,	.list   = shmem_xattr_security_list,	.get    = shmem_xattr_security_get,	.set    = shmem_xattr_security_set,};static struct xattr_handler *shmem_xattr_handlers[] = {	&shmem_xattr_acl_access_handler,	&shmem_xattr_acl_default_handler,	&shmem_xattr_security_handler,	NULL};#endifstatic struct dentry *shmem_get_parent(struct dentry *child){	return ERR_PTR(-ESTALE);}static int shmem_match(struct inode *ino, void *vfh){	__u32 *fh = vfh;	__u64 inum = fh[2];	inum = (inum << 32) | fh[1];	return ino->i_ino == inum && fh[0] == ino->i_generation;}static struct dentry *shmem_fh_to_dentry(struct super_block *sb,		struct fid *fid, int fh_len, int fh_type){	struct inode *inode;	struct dentry *dentry = NULL;	u64 inum = fid->raw[2];	inum = (inum << 32) | fid->raw[1];	if (fh_len < 3)		return NULL;	inode = ilookup5(sb, (unsigned long)(inum + fid->raw[0]),			shmem_match, fid->raw);	if (inode) {		dentry = d_find_alias(inode);		iput(inode);	}	return dentry;}static int shmem_encode_fh(struct dentry *dentry, __u32 *fh, int *len,				int connectable){	struct inode *inode = dentry->d_inode;	if (*len < 3)		return 255;	if (hlist_unhashed(&inode->i_hash)) {		/* Unfortunately insert_inode_hash is not idempotent,		 * so as we hash inodes here rather than at creation		 * time, we need a lock to ensure we only try		 * to do it once		 */		static DEFINE_SPINLOCK(lock);		spin_lock(&lock);		if (hlist_unhashed(&inode->i_hash))			__insert_inode_hash(inode,					    inode->i_ino + inode->i_generation);		spin_unlock(&lock);	}	fh[0] = inode->i_generation;	fh[1] = inode->i_ino;	fh[2] = ((__u64)inode->i_ino) >> 32;	*len = 3;	return 1;}static const struct export_operations shmem_export_ops = {	.get_parent     = shmem_get_parent,	.encode_fh      = shmem_encode_fh,	.fh_to_dentry	= shmem_fh_to_dentry,};static int shmem_parse_options(char *options, struct shmem_sb_info *sbinfo,			       bool remount){	char *this_char, *value, *rest;	while (options != NULL) {		this_char = options;		for (;;) {			/*			 * NUL-terminate this option: unfortunately,			 * mount options form a comma-separated list,			 * but mpol's nodelist may also contain commas.			 */			options = strchr(options, ',');			if (options == NULL)				break;			options++;			if (!isdigit(*options)) {				options[-1] = '\0';				break;			}		}		if (!*this_char)			continue;		if ((value = strchr(this_char,'=')) != NULL) {			*value++ = 0;		} else {			printk(KERN_ERR			    "tmpfs: No value for mount option '%s'\n",			    this_char);			return 1;		}		if (!strcmp(this_char,"size")) {			unsigned long long size;			size = memparse(value,&rest);			if (*rest == '%') {				size <<= PAGE_SHIFT;				size *= totalram_pages;				do_div(size, 100);				rest++;			}			if (*rest)				goto bad_val;			sbinfo->max_blocks =				DIV_ROUND_UP(size, PAGE_CACHE_SIZE);		} else if (!strcmp(this_char,"nr_blocks")) {			sbinfo->max_blocks = memparse(value, &rest);			if (*rest)				goto bad_val;		} else if (!strcmp(this_char,"nr_inodes")) {			sbinfo->max_inodes = memparse(value, &rest);			if (*rest)				goto bad_val;		} else if (!strcmp(this_char,"mode")) {			if (remount)				continue;			sbinfo->mode = simple_strtoul(value, &rest, 8) & 07777;			if (*rest)				goto bad_val;		} else if (!strcmp(this_char,"uid")) {			if (remount)				continue;			sbinfo->uid = simple_strtoul(value, &rest, 0);			if (*rest)				goto bad_val;		} else if (!strcmp(this_char,"gid")) {			if (remount)				continue;			sbinfo->gid = simple_strtoul(value, &rest, 0);			if (*rest)				goto bad_val;		} else if (!strcmp(this_char,"mpol")) {			if (mpol_parse_str(value, &sbinfo->mpol, 1))				goto bad_val;		} else {			printk(KERN_ERR "tmpfs: Bad mount option %s\n",			       this_char);			return 1;		}	}	return 0;bad_val:	printk(KERN_ERR "tmpfs: Bad value '%s' for mount option '%s'\n",	       value, this_char);	return 1;}static int shmem_remount_fs(struct super_block *sb, int *flags, char *data){	struct shmem_sb_info *sbinfo = SHMEM_SB(sb);	struct shmem_sb_info config = *sbinfo;	unsigned long blocks;	unsigned long inodes;	int error = -EINVAL;	if (shmem_parse_options(data, &config, true))		return error;	spin_lock(&sbinfo->stat_lock);	blocks = sbinfo->max_blocks - sbinfo->free_blocks;	inodes = sbinfo->max_inodes - sbinfo->free_inodes;	if (config.max_blocks < blocks)		goto out;	if (config.max_inodes < inodes)		goto out;	/*	 * Those tests also disallow limited->unlimited while any are in	 * use, so i_blocks will always be zero when max_blocks is zero;	 * but we must separately disallow unlimited->limited, because	 * in that case we have no record of how much is already in use.	 */	if (config.max_blocks && !sbinfo->max_blocks)		goto out;	if (config.max_inodes && !sbinfo->max_inodes)		goto out;	error = 0;	sbinfo->max_blocks  = config.max_blocks;	sbinfo->free_blocks = config.max_blocks - blocks;	sbinfo->max_inodes  = config.max_inodes;	sbinfo->free_inodes = config.max_inodes - inodes;	mpol_put(sbinfo->mpol);	sbinfo->mpol        = config.mpol;	/* transfers initial ref */out:	spin_unlock(&sbinfo->stat_lock);	return error;}static int shmem_show_options(struct seq_file *seq, struct vfsmount *vfs){	struct shmem_sb_info *sbinfo = SHMEM_SB(vfs->mnt_sb);	if (sbinfo->max_blocks != shmem_default_max_blocks())		seq_printf(seq, ",size=%luk",			sbinfo->max_blocks << (PAGE_CACHE_SHIFT - 10));	if (sbinfo->max_inodes != shmem_default_max_inodes())		seq_printf(seq, ",nr_inodes=%lu", sbinfo->max_inodes);	if (sbinfo->mode != (S_IRWXUGO | S_ISVTX))		seq_printf(seq, ",mode=%03o", sbinfo->mode);	if (sbinfo->uid != 0)		seq_printf(seq, ",uid=%u", sbinfo->uid);	if (sbinfo->gid != 0)		seq_printf(seq, ",gid=%u", sbinfo->gid);	shmem_show_mpol(seq, sbinfo->mpol);	return 0;}#endif /* CONFIG_TMPFS */static void shmem_put_super(struct super_block *sb){	kfree(sb->s_fs_info);	sb->s_fs_info = NULL;}static int shmem_fill_super(struct super_block *sb,			    void *data, int silent){	struct inode *inode;	struct dentry *root;	struct shmem_sb_info *sbinfo;	int err = -ENOMEM;	/* Round up to L1_CACHE_BYTES to resist false sharing */	sbinfo = kmalloc(max((int)sizeof(struct shmem_sb_info),				L1_CACHE_BYTES), GFP_KERNEL);	if (!sbinfo)		return -ENOMEM;	sbinfo->max_blocks = 0;	sbinfo->max_inodes = 0;	sbinfo->mode = S_IRWXUGO | S_ISVTX;	sbinfo->uid = current_fsuid();	sbinfo->gid = current_fsgid();	sbinfo->mpol = NULL;	sb->s_fs_info = sbinfo;#ifdef CONFIG_TMPFS	/*	 * Per default we only allow half of the physical ram per	 * tmpfs instance, limiting inodes to one per page of lowmem;	 * but the internal instance is left unlimited.	 */	if (!(sb->s_flags & MS_NOUSER)) {		sbinfo->max_blocks = shmem_default_max_blocks();		sbinfo->max_inodes = shmem_default_max_inodes();		if (shmem_parse_options(data, sbinfo, false)) {			err = -EINVAL;			goto failed;		}	}	sb->s_export_op = &shmem_export_ops;#else	sb->s_flags |= MS_NOUSER;#endif	spin_lock_init(&sbinfo->stat_lock);	sbinfo->free_blocks = sbinfo->max_blocks;	sbinfo->free_inodes = sbinfo->max_inodes;	sb->s_maxbytes = SHMEM_MAX_BYTES;	sb->s_blocksize = PAGE_CACHE_SIZE;	sb->s_blocksize_bits = PAGE_CACHE_SHIFT;	sb->s_magic = TMPFS_MAGIC;	sb->s_op = &shmem_ops;	sb->s_time_gran = 1;#ifdef CONFIG_TMPFS_POSIX_ACL	sb->s_xattr = shmem_xattr_handlers;	sb->s_flags |= MS_POSIXACL;#endif	inode = shmem_get_inode(sb, S_IFDIR | sbinfo->mode, 0, VM_NORESERVE);	if (!inode)		goto failed;	inode->i_uid = sbinfo->uid;	inode->i_gid = sbinfo->gid;	root = d_alloc_root(inode);	if (!root)		goto failed_iput;	sb->s_root = root;	return 0;failed_iput:	iput(inode);failed:	shmem_put_super(sb);	return err;}static struct kmem_cache *shmem_inode_cachep;static struct inode *shmem_alloc_inode(struct super_block *sb){	struct shmem_inode_info *p;	p = (struct shmem_inode_info *)kmem_cache_alloc(shmem_inode_cachep, GFP_KERNEL);	if (!p)		return NULL;	return &p->vfs_inode;}static void shmem_destroy_inode(struct inode *inode){	if ((inode->i_mode & S_IFMT) == S_IFREG) {		/* only struct inode is valid if it's an inline symlink */		mpol_free_shared_policy(&SHMEM_I(inode)->policy);	}	shmem_acl_destroy_inode(inode);	kmem_cache_free(shmem_inode_cachep, SHMEM_I(inode));}static void init_once(void *foo){	struct shmem_inode_info *p = (struct shmem_inode_info *) foo;	inode_init_once(&p->vfs_inode);#ifdef CONFIG_TMPFS_POSIX_ACL	p->i_acl = NULL;	p->i_default_acl = NULL;#endif}static int init_inodecache(void){	shmem_inode_cachep = kmem_cache_create("shmem_inode_cache",				sizeof(struct shmem_inode_info),				0, SLAB_PANIC, init_once);	return 0;}static void destroy_inodecache(void){	kmem_cache_destroy(shmem_inode_cachep);}static const struct address_space_operations shmem_aops = {	.writepage	= shmem_writepage,	.set_page_dirty	= __set_page_dirty_no_writeback,#ifdef CONFIG_TMPFS	.readpage	= shmem_readpage,	.write_begin	= shmem_write_begin,	.write_end	= shmem_write_end,#endif	.migratepage	= migrate_page,};static const struct file_operations shmem_file_operations = {	.mmap		= shmem_mmap,#ifdef CONFIG_TMPFS	.llseek		= generic_file_llseek,	.read		= do_sync_read,	.write		= do_sync_write,	.aio_read	= shmem_file_aio_read,	.aio_write	= generic_file_aio_write,	.fsync		= simple_sync_file,	.splice_read	= generic_file_splice_read,	.splice_write	= generic_file_splice_write,#endif};static const struct inode_operations shmem_inode_operations = {	.truncate	= shmem_truncate,	.setattr	= shmem_notify_change,	.truncate_range	= shmem_truncate_range,#ifdef CONFIG_TMPFS_POSIX_ACL	.setxattr	= generic_setxattr,	.getxattr	= generic_getxattr,	.listxattr	= generic_listxattr,	.removexattr	= generic_removexattr,	.permission	= shmem_permission,#endif};static const struct inode_operations shmem_dir_inode_operations = {#ifdef CONFIG_TMPFS	.create		= shmem_create,	.lookup		= simple_lookup,	.link		= shmem_link,	.unlink		= shmem_unlink,	.symlink	= shmem_symlink,	.mkdir		= shmem_mkdir,	.rmdir		= shmem_rmdir,	.mknod		= shmem_mknod,	.rename		= shmem_rename,#endif#ifdef CONFIG_TMPFS_POSIX_ACL	.setattr	= shmem_notify_change,	.setxattr	= generic_setxattr,	.getxattr	= generic_getxattr,	.listxattr	= generic_listxattr,	.removexattr	= generic_removexattr,	.permission	= shmem_permission,#endif};static const struct inode_operations shmem_special_inode_operations = {#ifdef CONFIG_TMPFS_POSIX_ACL	.setattr	= shmem_notify_change,	.setxattr	= generic_setxattr,	.getxattr	= generic_getxattr,	.listxattr	= generic_listxattr,	.removexattr	= generic_removexattr,	.permission	= shmem_permission,#endif};static const struct super_operations shmem_ops = {	.alloc_inode	= shmem_alloc_inode,	.destroy_inode	= shmem_destroy_inode,#ifdef CONFIG_TMPFS	.statfs		= shmem_statfs,	.remount_fs	= shmem_remount_fs,	.show_options	= shmem_show_options,#endif	.delete_inode	= shmem_delete_inode,	.drop_inode	= generic_delete_inode,	.put_super	= shmem_put_super,};static struct vm_operations_struct shmem_vm_ops = {	.fault		= shmem_fault,#ifdef CONFIG_NUMA	.set_policy 

⌨️ 快捷键说明

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