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

📄 inode.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * SPU file system * * (C) Copyright IBM Deutschland Entwicklung GmbH 2005 * * Author: Arnd Bergmann <arndb@de.ibm.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */#include <linux/file.h>#include <linux/fs.h>#include <linux/backing-dev.h>#include <linux/init.h>#include <linux/ioctl.h>#include <linux/module.h>#include <linux/mount.h>#include <linux/namei.h>#include <linux/pagemap.h>#include <linux/poll.h>#include <linux/slab.h>#include <linux/parser.h>#include <asm/prom.h>#include <asm/semaphore.h>#include <asm/spu.h>#include <asm/spu_priv1.h>#include <asm/uaccess.h>#include "spufs.h"static struct kmem_cache *spufs_inode_cache;char *isolated_loader;static int isolated_loader_size;static struct inode *spufs_alloc_inode(struct super_block *sb){	struct spufs_inode_info *ei;	ei = kmem_cache_alloc(spufs_inode_cache, GFP_KERNEL);	if (!ei)		return NULL;	ei->i_gang = NULL;	ei->i_ctx = NULL;	ei->i_openers = 0;	return &ei->vfs_inode;}static voidspufs_destroy_inode(struct inode *inode){	kmem_cache_free(spufs_inode_cache, SPUFS_I(inode));}static voidspufs_init_once(struct kmem_cache *cachep, void *p){	struct spufs_inode_info *ei = p;	inode_init_once(&ei->vfs_inode);}static struct inode *spufs_new_inode(struct super_block *sb, int mode){	struct inode *inode;	inode = new_inode(sb);	if (!inode)		goto out;	inode->i_mode = mode;	inode->i_uid = current->fsuid;	inode->i_gid = current->fsgid;	inode->i_blocks = 0;	inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;out:	return inode;}static intspufs_setattr(struct dentry *dentry, struct iattr *attr){	struct inode *inode = dentry->d_inode;	if ((attr->ia_valid & ATTR_SIZE) &&	    (attr->ia_size != inode->i_size))		return -EINVAL;	return inode_setattr(inode, attr);}static intspufs_new_file(struct super_block *sb, struct dentry *dentry,		const struct file_operations *fops, int mode,		struct spu_context *ctx){	static struct inode_operations spufs_file_iops = {		.setattr = spufs_setattr,	};	struct inode *inode;	int ret;	ret = -ENOSPC;	inode = spufs_new_inode(sb, S_IFREG | mode);	if (!inode)		goto out;	ret = 0;	inode->i_op = &spufs_file_iops;	inode->i_fop = fops;	inode->i_private = SPUFS_I(inode)->i_ctx = get_spu_context(ctx);	d_add(dentry, inode);out:	return ret;}static voidspufs_delete_inode(struct inode *inode){	struct spufs_inode_info *ei = SPUFS_I(inode);	if (ei->i_ctx)		put_spu_context(ei->i_ctx);	if (ei->i_gang)		put_spu_gang(ei->i_gang);	clear_inode(inode);}static void spufs_prune_dir(struct dentry *dir){	struct dentry *dentry, *tmp;	mutex_lock(&dir->d_inode->i_mutex);	list_for_each_entry_safe(dentry, tmp, &dir->d_subdirs, d_u.d_child) {		spin_lock(&dcache_lock);		spin_lock(&dentry->d_lock);		if (!(d_unhashed(dentry)) && dentry->d_inode) {			dget_locked(dentry);			__d_drop(dentry);			spin_unlock(&dentry->d_lock);			simple_unlink(dir->d_inode, dentry);			spin_unlock(&dcache_lock);			dput(dentry);		} else {			spin_unlock(&dentry->d_lock);			spin_unlock(&dcache_lock);		}	}	shrink_dcache_parent(dir);	mutex_unlock(&dir->d_inode->i_mutex);}/* Caller must hold parent->i_mutex */static int spufs_rmdir(struct inode *parent, struct dentry *dir){	/* remove all entries */	spufs_prune_dir(dir);	d_drop(dir);	return simple_rmdir(parent, dir);}static int spufs_fill_dir(struct dentry *dir, struct tree_descr *files,			  int mode, struct spu_context *ctx){	struct dentry *dentry, *tmp;	int ret;	while (files->name && files->name[0]) {		ret = -ENOMEM;		dentry = d_alloc_name(dir, files->name);		if (!dentry)			goto out;		ret = spufs_new_file(dir->d_sb, dentry, files->ops,					files->mode & mode, ctx);		if (ret)			goto out;		files++;	}	return 0;out:	/*	 * remove all children from dir. dir->inode is not set so don't	 * just simply use spufs_prune_dir() and panic afterwards :)	 * dput() looks like it will do the right thing:	 * - dec parent's ref counter	 * - remove child from parent's child list	 * - free child's inode if possible	 * - free child	 */	list_for_each_entry_safe(dentry, tmp, &dir->d_subdirs, d_u.d_child) {		dput(dentry);	}	shrink_dcache_parent(dir);	return ret;}static int spufs_dir_close(struct inode *inode, struct file *file){	struct spu_context *ctx;	struct inode *parent;	struct dentry *dir;	int ret;	dir = file->f_path.dentry;	parent = dir->d_parent->d_inode;	ctx = SPUFS_I(dir->d_inode)->i_ctx;	mutex_lock(&parent->i_mutex);	ret = spufs_rmdir(parent, dir);	mutex_unlock(&parent->i_mutex);	WARN_ON(ret);	/* We have to give up the mm_struct */	spu_forget(ctx);	return dcache_dir_close(inode, file);}const struct file_operations spufs_context_fops = {	.open		= dcache_dir_open,	.release	= spufs_dir_close,	.llseek		= dcache_dir_lseek,	.read		= generic_read_dir,	.readdir	= dcache_readdir,	.fsync		= simple_sync_file,};EXPORT_SYMBOL_GPL(spufs_context_fops);static intspufs_mkdir(struct inode *dir, struct dentry *dentry, unsigned int flags,		int mode){	int ret;	struct inode *inode;	struct spu_context *ctx;	ret = -ENOSPC;	inode = spufs_new_inode(dir->i_sb, mode | S_IFDIR);	if (!inode)		goto out;	if (dir->i_mode & S_ISGID) {		inode->i_gid = dir->i_gid;		inode->i_mode &= S_ISGID;	}	ctx = alloc_spu_context(SPUFS_I(dir)->i_gang); /* XXX gang */	SPUFS_I(inode)->i_ctx = ctx;	if (!ctx)		goto out_iput;	ctx->flags = flags;	inode->i_op = &simple_dir_inode_operations;	inode->i_fop = &simple_dir_operations;	if (flags & SPU_CREATE_NOSCHED)		ret = spufs_fill_dir(dentry, spufs_dir_nosched_contents,					 mode, ctx);	else		ret = spufs_fill_dir(dentry, spufs_dir_contents, mode, ctx);	if (ret)		goto out_free_ctx;	d_instantiate(dentry, inode);	dget(dentry);	dir->i_nlink++;	dentry->d_inode->i_nlink++;	goto out;out_free_ctx:	spu_forget(ctx);	put_spu_context(ctx);out_iput:	iput(inode);out:	return ret;}static int spufs_context_open(struct dentry *dentry, struct vfsmount *mnt){	int ret;	struct file *filp;	ret = get_unused_fd();	if (ret < 0) {		dput(dentry);		mntput(mnt);		goto out;	}	filp = dentry_open(dentry, mnt, O_RDONLY);	if (IS_ERR(filp)) {		put_unused_fd(ret);		ret = PTR_ERR(filp);		goto out;	}	filp->f_op = &spufs_context_fops;	fd_install(ret, filp);out:	return ret;}static struct spu_context *spufs_assert_affinity(unsigned int flags, struct spu_gang *gang,						struct file *filp){	struct spu_context *tmp, *neighbor;	int count, node;	int aff_supp;	aff_supp = !list_empty(&(list_entry(cbe_spu_info[0].spus.next,					struct spu, cbe_list))->aff_list);	if (!aff_supp)		return ERR_PTR(-EINVAL);	if (flags & SPU_CREATE_GANG)		return ERR_PTR(-EINVAL);	if (flags & SPU_CREATE_AFFINITY_MEM &&	    gang->aff_ref_ctx &&	    gang->aff_ref_ctx->flags & SPU_CREATE_AFFINITY_MEM)		return ERR_PTR(-EEXIST);	if (gang->aff_flags & AFF_MERGED)		return ERR_PTR(-EBUSY);	neighbor = NULL;	if (flags & SPU_CREATE_AFFINITY_SPU) {		if (!filp || filp->f_op != &spufs_context_fops)			return ERR_PTR(-EINVAL);		neighbor = get_spu_context(				SPUFS_I(filp->f_dentry->d_inode)->i_ctx);		if (!list_empty(&neighbor->aff_list) && !(neighbor->aff_head) &&		    !list_is_last(&neighbor->aff_list, &gang->aff_list_head) &&		    !list_entry(neighbor->aff_list.next, struct spu_context,		    aff_list)->aff_head)			return ERR_PTR(-EEXIST);		if (gang != neighbor->gang)			return ERR_PTR(-EINVAL);		count = 1;		list_for_each_entry(tmp, &gang->aff_list_head, aff_list)			count++;		if (list_empty(&neighbor->aff_list))			count++;		for (node = 0; node < MAX_NUMNODES; node++) {			if ((cbe_spu_info[node].n_spus - atomic_read(				&cbe_spu_info[node].reserved_spus)) >= count)				break;		}		if (node == MAX_NUMNODES)			return ERR_PTR(-EEXIST);	}	return neighbor;}static voidspufs_set_affinity(unsigned int flags, struct spu_context *ctx,					struct spu_context *neighbor){	if (flags & SPU_CREATE_AFFINITY_MEM)		ctx->gang->aff_ref_ctx = ctx;	if (flags & SPU_CREATE_AFFINITY_SPU) {		if (list_empty(&neighbor->aff_list)) {			list_add_tail(&neighbor->aff_list,				&ctx->gang->aff_list_head);			neighbor->aff_head = 1;		}		if (list_is_last(&neighbor->aff_list, &ctx->gang->aff_list_head)		    || list_entry(neighbor->aff_list.next, struct spu_context,							aff_list)->aff_head) {			list_add(&ctx->aff_list, &neighbor->aff_list);		} else  {			list_add_tail(&ctx->aff_list, &neighbor->aff_list);			if (neighbor->aff_head) {				neighbor->aff_head = 0;				ctx->aff_head = 1;			}		}		if (!ctx->gang->aff_ref_ctx)			ctx->gang->aff_ref_ctx = ctx;	}}

⌨️ 快捷键说明

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