📄 inode.c
字号:
static intspufs_create_context(struct inode *inode, struct dentry *dentry, struct vfsmount *mnt, int flags, int mode, struct file *aff_filp){ int ret; int affinity; struct spu_gang *gang; struct spu_context *neighbor; ret = -EPERM; if ((flags & SPU_CREATE_NOSCHED) && !capable(CAP_SYS_NICE)) goto out_unlock; ret = -EINVAL; if ((flags & (SPU_CREATE_NOSCHED | SPU_CREATE_ISOLATE)) == SPU_CREATE_ISOLATE) goto out_unlock; ret = -ENODEV; if ((flags & SPU_CREATE_ISOLATE) && !isolated_loader) goto out_unlock; gang = NULL; neighbor = NULL; affinity = flags & (SPU_CREATE_AFFINITY_MEM | SPU_CREATE_AFFINITY_SPU); if (affinity) { gang = SPUFS_I(inode)->i_gang; ret = -EINVAL; if (!gang) goto out_unlock; mutex_lock(&gang->aff_mutex); neighbor = spufs_assert_affinity(flags, gang, aff_filp); if (IS_ERR(neighbor)) { ret = PTR_ERR(neighbor); goto out_aff_unlock; } } ret = spufs_mkdir(inode, dentry, flags, mode & S_IRWXUGO); if (ret) goto out_aff_unlock; if (affinity) spufs_set_affinity(flags, SPUFS_I(dentry->d_inode)->i_ctx, neighbor); /* * get references for dget and mntget, will be released * in error path of *_open(). */ ret = spufs_context_open(dget(dentry), mntget(mnt)); if (ret < 0) { WARN_ON(spufs_rmdir(inode, dentry)); mutex_unlock(&inode->i_mutex); spu_forget(SPUFS_I(dentry->d_inode)->i_ctx); goto out; }out_aff_unlock: if (affinity) mutex_unlock(&gang->aff_mutex);out_unlock: mutex_unlock(&inode->i_mutex);out: dput(dentry); return ret;}static intspufs_mkgang(struct inode *dir, struct dentry *dentry, int mode){ int ret; struct inode *inode; struct spu_gang *gang; ret = -ENOSPC; inode = spufs_new_inode(dir->i_sb, mode | S_IFDIR); if (!inode) goto out; ret = 0; if (dir->i_mode & S_ISGID) { inode->i_gid = dir->i_gid; inode->i_mode &= S_ISGID; } gang = alloc_spu_gang(); SPUFS_I(inode)->i_ctx = NULL; SPUFS_I(inode)->i_gang = gang; if (!gang) goto out_iput; inode->i_op = &simple_dir_inode_operations; inode->i_fop = &simple_dir_operations; d_instantiate(dentry, inode); dir->i_nlink++; dentry->d_inode->i_nlink++; return ret;out_iput: iput(inode);out: return ret;}static int spufs_gang_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 = &simple_dir_operations; fd_install(ret, filp);out: return ret;}static int spufs_create_gang(struct inode *inode, struct dentry *dentry, struct vfsmount *mnt, int mode){ int ret; ret = spufs_mkgang(inode, dentry, mode & S_IRWXUGO); if (ret) goto out; /* * get references for dget and mntget, will be released * in error path of *_open(). */ ret = spufs_gang_open(dget(dentry), mntget(mnt)); if (ret < 0) { int err = simple_rmdir(inode, dentry); WARN_ON(err); }out: mutex_unlock(&inode->i_mutex); dput(dentry); return ret;}static struct file_system_type spufs_type;long spufs_create(struct nameidata *nd, unsigned int flags, mode_t mode, struct file *filp){ struct dentry *dentry; int ret; ret = -EINVAL; /* check if we are on spufs */ if (nd->dentry->d_sb->s_type != &spufs_type) goto out; /* don't accept undefined flags */ if (flags & (~SPU_CREATE_FLAG_ALL)) goto out; /* only threads can be underneath a gang */ if (nd->dentry != nd->dentry->d_sb->s_root) { if ((flags & SPU_CREATE_GANG) || !SPUFS_I(nd->dentry->d_inode)->i_gang) goto out; } dentry = lookup_create(nd, 1); ret = PTR_ERR(dentry); if (IS_ERR(dentry)) goto out_dir; ret = -EEXIST; if (dentry->d_inode) goto out_dput; mode &= ~current->fs->umask; if (flags & SPU_CREATE_GANG) return spufs_create_gang(nd->dentry->d_inode, dentry, nd->mnt, mode); else return spufs_create_context(nd->dentry->d_inode, dentry, nd->mnt, flags, mode, filp);out_dput: dput(dentry);out_dir: mutex_unlock(&nd->dentry->d_inode->i_mutex);out: return ret;}/* File system initialization */enum { Opt_uid, Opt_gid, Opt_mode, Opt_err,};static match_table_t spufs_tokens = { { Opt_uid, "uid=%d" }, { Opt_gid, "gid=%d" }, { Opt_mode, "mode=%o" }, { Opt_err, NULL },};static intspufs_parse_options(char *options, struct inode *root){ char *p; substring_t args[MAX_OPT_ARGS]; while ((p = strsep(&options, ",")) != NULL) { int token, option; if (!*p) continue; token = match_token(p, spufs_tokens, args); switch (token) { case Opt_uid: if (match_int(&args[0], &option)) return 0; root->i_uid = option; break; case Opt_gid: if (match_int(&args[0], &option)) return 0; root->i_gid = option; break; case Opt_mode: if (match_octal(&args[0], &option)) return 0; root->i_mode = option | S_IFDIR; break; default: return 0; } } return 1;}static void spufs_exit_isolated_loader(void){ free_pages((unsigned long) isolated_loader, get_order(isolated_loader_size));}static voidspufs_init_isolated_loader(void){ struct device_node *dn; const char *loader; int size; dn = of_find_node_by_path("/spu-isolation"); if (!dn) return; loader = of_get_property(dn, "loader", &size); if (!loader) return; /* the loader must be align on a 16 byte boundary */ isolated_loader = (char *)__get_free_pages(GFP_KERNEL, get_order(size)); if (!isolated_loader) return; isolated_loader_size = size; memcpy(isolated_loader, loader, size); printk(KERN_INFO "spufs: SPU isolation mode enabled\n");}static intspufs_create_root(struct super_block *sb, void *data){ struct inode *inode; int ret; ret = -ENODEV; if (!spu_management_ops) goto out; ret = -ENOMEM; inode = spufs_new_inode(sb, S_IFDIR | 0775); if (!inode) goto out; inode->i_op = &simple_dir_inode_operations; inode->i_fop = &simple_dir_operations; SPUFS_I(inode)->i_ctx = NULL; ret = -EINVAL; if (!spufs_parse_options(data, inode)) goto out_iput; ret = -ENOMEM; sb->s_root = d_alloc_root(inode); if (!sb->s_root) goto out_iput; return 0;out_iput: iput(inode);out: return ret;}static intspufs_fill_super(struct super_block *sb, void *data, int silent){ static struct super_operations s_ops = { .alloc_inode = spufs_alloc_inode, .destroy_inode = spufs_destroy_inode, .statfs = simple_statfs, .delete_inode = spufs_delete_inode, .drop_inode = generic_delete_inode, }; sb->s_maxbytes = MAX_LFS_FILESIZE; sb->s_blocksize = PAGE_CACHE_SIZE; sb->s_blocksize_bits = PAGE_CACHE_SHIFT; sb->s_magic = SPUFS_MAGIC; sb->s_op = &s_ops; return spufs_create_root(sb, data);}static intspufs_get_sb(struct file_system_type *fstype, int flags, const char *name, void *data, struct vfsmount *mnt){ return get_sb_single(fstype, flags, data, spufs_fill_super, mnt);}static struct file_system_type spufs_type = { .owner = THIS_MODULE, .name = "spufs", .get_sb = spufs_get_sb, .kill_sb = kill_litter_super,};static int __init spufs_init(void){ int ret; ret = -ENODEV; if (!spu_management_ops) goto out; ret = -ENOMEM; spufs_inode_cache = kmem_cache_create("spufs_inode_cache", sizeof(struct spufs_inode_info), 0, SLAB_HWCACHE_ALIGN, spufs_init_once); if (!spufs_inode_cache) goto out; ret = spu_sched_init(); if (ret) goto out_cache; ret = register_filesystem(&spufs_type); if (ret) goto out_sched; ret = register_spu_syscalls(&spufs_calls); if (ret) goto out_fs; spufs_init_isolated_loader(); return 0;out_fs: unregister_filesystem(&spufs_type);out_sched: spu_sched_exit();out_cache: kmem_cache_destroy(spufs_inode_cache);out: return ret;}module_init(spufs_init);static void __exit spufs_exit(void){ spu_sched_exit(); spufs_exit_isolated_loader(); unregister_spu_syscalls(&spufs_calls); unregister_filesystem(&spufs_type); kmem_cache_destroy(spufs_inode_cache);}module_exit(spufs_exit);MODULE_LICENSE("GPL");MODULE_AUTHOR("Arnd Bergmann <arndb@de.ibm.com>");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -