Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 
0003 /*
0004  * SPU file system
0005  *
0006  * (C) Copyright IBM Deutschland Entwicklung GmbH 2005
0007  *
0008  * Author: Arnd Bergmann <arndb@de.ibm.com>
0009  */
0010 
0011 #include <linux/file.h>
0012 #include <linux/fs.h>
0013 #include <linux/fs_context.h>
0014 #include <linux/fs_parser.h>
0015 #include <linux/fsnotify.h>
0016 #include <linux/backing-dev.h>
0017 #include <linux/init.h>
0018 #include <linux/ioctl.h>
0019 #include <linux/module.h>
0020 #include <linux/mount.h>
0021 #include <linux/namei.h>
0022 #include <linux/pagemap.h>
0023 #include <linux/poll.h>
0024 #include <linux/of.h>
0025 #include <linux/seq_file.h>
0026 #include <linux/slab.h>
0027 
0028 #include <asm/spu.h>
0029 #include <asm/spu_priv1.h>
0030 #include <linux/uaccess.h>
0031 
0032 #include "spufs.h"
0033 
0034 struct spufs_sb_info {
0035     bool debug;
0036 };
0037 
0038 static struct kmem_cache *spufs_inode_cache;
0039 char *isolated_loader;
0040 static int isolated_loader_size;
0041 
0042 static struct spufs_sb_info *spufs_get_sb_info(struct super_block *sb)
0043 {
0044     return sb->s_fs_info;
0045 }
0046 
0047 static struct inode *
0048 spufs_alloc_inode(struct super_block *sb)
0049 {
0050     struct spufs_inode_info *ei;
0051 
0052     ei = kmem_cache_alloc(spufs_inode_cache, GFP_KERNEL);
0053     if (!ei)
0054         return NULL;
0055 
0056     ei->i_gang = NULL;
0057     ei->i_ctx = NULL;
0058     ei->i_openers = 0;
0059 
0060     return &ei->vfs_inode;
0061 }
0062 
0063 static void spufs_free_inode(struct inode *inode)
0064 {
0065     kmem_cache_free(spufs_inode_cache, SPUFS_I(inode));
0066 }
0067 
0068 static void
0069 spufs_init_once(void *p)
0070 {
0071     struct spufs_inode_info *ei = p;
0072 
0073     inode_init_once(&ei->vfs_inode);
0074 }
0075 
0076 static struct inode *
0077 spufs_new_inode(struct super_block *sb, umode_t mode)
0078 {
0079     struct inode *inode;
0080 
0081     inode = new_inode(sb);
0082     if (!inode)
0083         goto out;
0084 
0085     inode->i_ino = get_next_ino();
0086     inode->i_mode = mode;
0087     inode->i_uid = current_fsuid();
0088     inode->i_gid = current_fsgid();
0089     inode->i_atime = inode->i_mtime = inode->i_ctime = current_time(inode);
0090 out:
0091     return inode;
0092 }
0093 
0094 static int
0095 spufs_setattr(struct user_namespace *mnt_userns, struct dentry *dentry,
0096           struct iattr *attr)
0097 {
0098     struct inode *inode = d_inode(dentry);
0099 
0100     if ((attr->ia_valid & ATTR_SIZE) &&
0101         (attr->ia_size != inode->i_size))
0102         return -EINVAL;
0103     setattr_copy(&init_user_ns, inode, attr);
0104     mark_inode_dirty(inode);
0105     return 0;
0106 }
0107 
0108 
0109 static int
0110 spufs_new_file(struct super_block *sb, struct dentry *dentry,
0111         const struct file_operations *fops, umode_t mode,
0112         size_t size, struct spu_context *ctx)
0113 {
0114     static const struct inode_operations spufs_file_iops = {
0115         .setattr = spufs_setattr,
0116     };
0117     struct inode *inode;
0118     int ret;
0119 
0120     ret = -ENOSPC;
0121     inode = spufs_new_inode(sb, S_IFREG | mode);
0122     if (!inode)
0123         goto out;
0124 
0125     ret = 0;
0126     inode->i_op = &spufs_file_iops;
0127     inode->i_fop = fops;
0128     inode->i_size = size;
0129     inode->i_private = SPUFS_I(inode)->i_ctx = get_spu_context(ctx);
0130     d_add(dentry, inode);
0131 out:
0132     return ret;
0133 }
0134 
0135 static void
0136 spufs_evict_inode(struct inode *inode)
0137 {
0138     struct spufs_inode_info *ei = SPUFS_I(inode);
0139     clear_inode(inode);
0140     if (ei->i_ctx)
0141         put_spu_context(ei->i_ctx);
0142     if (ei->i_gang)
0143         put_spu_gang(ei->i_gang);
0144 }
0145 
0146 static void spufs_prune_dir(struct dentry *dir)
0147 {
0148     struct dentry *dentry, *tmp;
0149 
0150     inode_lock(d_inode(dir));
0151     list_for_each_entry_safe(dentry, tmp, &dir->d_subdirs, d_child) {
0152         spin_lock(&dentry->d_lock);
0153         if (simple_positive(dentry)) {
0154             dget_dlock(dentry);
0155             __d_drop(dentry);
0156             spin_unlock(&dentry->d_lock);
0157             simple_unlink(d_inode(dir), dentry);
0158             /* XXX: what was dcache_lock protecting here? Other
0159              * filesystems (IB, configfs) release dcache_lock
0160              * before unlink */
0161             dput(dentry);
0162         } else {
0163             spin_unlock(&dentry->d_lock);
0164         }
0165     }
0166     shrink_dcache_parent(dir);
0167     inode_unlock(d_inode(dir));
0168 }
0169 
0170 /* Caller must hold parent->i_mutex */
0171 static int spufs_rmdir(struct inode *parent, struct dentry *dir)
0172 {
0173     /* remove all entries */
0174     int res;
0175     spufs_prune_dir(dir);
0176     d_drop(dir);
0177     res = simple_rmdir(parent, dir);
0178     /* We have to give up the mm_struct */
0179     spu_forget(SPUFS_I(d_inode(dir))->i_ctx);
0180     return res;
0181 }
0182 
0183 static int spufs_fill_dir(struct dentry *dir,
0184         const struct spufs_tree_descr *files, umode_t mode,
0185         struct spu_context *ctx)
0186 {
0187     while (files->name && files->name[0]) {
0188         int ret;
0189         struct dentry *dentry = d_alloc_name(dir, files->name);
0190         if (!dentry)
0191             return -ENOMEM;
0192         ret = spufs_new_file(dir->d_sb, dentry, files->ops,
0193                     files->mode & mode, files->size, ctx);
0194         if (ret)
0195             return ret;
0196         files++;
0197     }
0198     return 0;
0199 }
0200 
0201 static int spufs_dir_close(struct inode *inode, struct file *file)
0202 {
0203     struct inode *parent;
0204     struct dentry *dir;
0205     int ret;
0206 
0207     dir = file->f_path.dentry;
0208     parent = d_inode(dir->d_parent);
0209 
0210     inode_lock_nested(parent, I_MUTEX_PARENT);
0211     ret = spufs_rmdir(parent, dir);
0212     inode_unlock(parent);
0213     WARN_ON(ret);
0214 
0215     return dcache_dir_close(inode, file);
0216 }
0217 
0218 const struct file_operations spufs_context_fops = {
0219     .open       = dcache_dir_open,
0220     .release    = spufs_dir_close,
0221     .llseek     = dcache_dir_lseek,
0222     .read       = generic_read_dir,
0223     .iterate_shared = dcache_readdir,
0224     .fsync      = noop_fsync,
0225 };
0226 EXPORT_SYMBOL_GPL(spufs_context_fops);
0227 
0228 static int
0229 spufs_mkdir(struct inode *dir, struct dentry *dentry, unsigned int flags,
0230         umode_t mode)
0231 {
0232     int ret;
0233     struct inode *inode;
0234     struct spu_context *ctx;
0235 
0236     inode = spufs_new_inode(dir->i_sb, mode | S_IFDIR);
0237     if (!inode)
0238         return -ENOSPC;
0239 
0240     inode_init_owner(&init_user_ns, inode, dir, mode | S_IFDIR);
0241     ctx = alloc_spu_context(SPUFS_I(dir)->i_gang); /* XXX gang */
0242     SPUFS_I(inode)->i_ctx = ctx;
0243     if (!ctx) {
0244         iput(inode);
0245         return -ENOSPC;
0246     }
0247 
0248     ctx->flags = flags;
0249     inode->i_op = &simple_dir_inode_operations;
0250     inode->i_fop = &simple_dir_operations;
0251 
0252     inode_lock(inode);
0253 
0254     dget(dentry);
0255     inc_nlink(dir);
0256     inc_nlink(inode);
0257 
0258     d_instantiate(dentry, inode);
0259 
0260     if (flags & SPU_CREATE_NOSCHED)
0261         ret = spufs_fill_dir(dentry, spufs_dir_nosched_contents,
0262                      mode, ctx);
0263     else
0264         ret = spufs_fill_dir(dentry, spufs_dir_contents, mode, ctx);
0265 
0266     if (!ret && spufs_get_sb_info(dir->i_sb)->debug)
0267         ret = spufs_fill_dir(dentry, spufs_dir_debug_contents,
0268                 mode, ctx);
0269 
0270     if (ret)
0271         spufs_rmdir(dir, dentry);
0272 
0273     inode_unlock(inode);
0274 
0275     return ret;
0276 }
0277 
0278 static int spufs_context_open(struct path *path)
0279 {
0280     int ret;
0281     struct file *filp;
0282 
0283     ret = get_unused_fd_flags(0);
0284     if (ret < 0)
0285         return ret;
0286 
0287     filp = dentry_open(path, O_RDONLY, current_cred());
0288     if (IS_ERR(filp)) {
0289         put_unused_fd(ret);
0290         return PTR_ERR(filp);
0291     }
0292 
0293     filp->f_op = &spufs_context_fops;
0294     fd_install(ret, filp);
0295     return ret;
0296 }
0297 
0298 static struct spu_context *
0299 spufs_assert_affinity(unsigned int flags, struct spu_gang *gang,
0300                         struct file *filp)
0301 {
0302     struct spu_context *tmp, *neighbor, *err;
0303     int count, node;
0304     int aff_supp;
0305 
0306     aff_supp = !list_empty(&(list_entry(cbe_spu_info[0].spus.next,
0307                     struct spu, cbe_list))->aff_list);
0308 
0309     if (!aff_supp)
0310         return ERR_PTR(-EINVAL);
0311 
0312     if (flags & SPU_CREATE_GANG)
0313         return ERR_PTR(-EINVAL);
0314 
0315     if (flags & SPU_CREATE_AFFINITY_MEM &&
0316         gang->aff_ref_ctx &&
0317         gang->aff_ref_ctx->flags & SPU_CREATE_AFFINITY_MEM)
0318         return ERR_PTR(-EEXIST);
0319 
0320     if (gang->aff_flags & AFF_MERGED)
0321         return ERR_PTR(-EBUSY);
0322 
0323     neighbor = NULL;
0324     if (flags & SPU_CREATE_AFFINITY_SPU) {
0325         if (!filp || filp->f_op != &spufs_context_fops)
0326             return ERR_PTR(-EINVAL);
0327 
0328         neighbor = get_spu_context(
0329                 SPUFS_I(file_inode(filp))->i_ctx);
0330 
0331         if (!list_empty(&neighbor->aff_list) && !(neighbor->aff_head) &&
0332             !list_is_last(&neighbor->aff_list, &gang->aff_list_head) &&
0333             !list_entry(neighbor->aff_list.next, struct spu_context,
0334             aff_list)->aff_head) {
0335             err = ERR_PTR(-EEXIST);
0336             goto out_put_neighbor;
0337         }
0338 
0339         if (gang != neighbor->gang) {
0340             err = ERR_PTR(-EINVAL);
0341             goto out_put_neighbor;
0342         }
0343 
0344         count = 1;
0345         list_for_each_entry(tmp, &gang->aff_list_head, aff_list)
0346             count++;
0347         if (list_empty(&neighbor->aff_list))
0348             count++;
0349 
0350         for (node = 0; node < MAX_NUMNODES; node++) {
0351             if ((cbe_spu_info[node].n_spus - atomic_read(
0352                 &cbe_spu_info[node].reserved_spus)) >= count)
0353                 break;
0354         }
0355 
0356         if (node == MAX_NUMNODES) {
0357             err = ERR_PTR(-EEXIST);
0358             goto out_put_neighbor;
0359         }
0360     }
0361 
0362     return neighbor;
0363 
0364 out_put_neighbor:
0365     put_spu_context(neighbor);
0366     return err;
0367 }
0368 
0369 static void
0370 spufs_set_affinity(unsigned int flags, struct spu_context *ctx,
0371                     struct spu_context *neighbor)
0372 {
0373     if (flags & SPU_CREATE_AFFINITY_MEM)
0374         ctx->gang->aff_ref_ctx = ctx;
0375 
0376     if (flags & SPU_CREATE_AFFINITY_SPU) {
0377         if (list_empty(&neighbor->aff_list)) {
0378             list_add_tail(&neighbor->aff_list,
0379                 &ctx->gang->aff_list_head);
0380             neighbor->aff_head = 1;
0381         }
0382 
0383         if (list_is_last(&neighbor->aff_list, &ctx->gang->aff_list_head)
0384             || list_entry(neighbor->aff_list.next, struct spu_context,
0385                             aff_list)->aff_head) {
0386             list_add(&ctx->aff_list, &neighbor->aff_list);
0387         } else  {
0388             list_add_tail(&ctx->aff_list, &neighbor->aff_list);
0389             if (neighbor->aff_head) {
0390                 neighbor->aff_head = 0;
0391                 ctx->aff_head = 1;
0392             }
0393         }
0394 
0395         if (!ctx->gang->aff_ref_ctx)
0396             ctx->gang->aff_ref_ctx = ctx;
0397     }
0398 }
0399 
0400 static int
0401 spufs_create_context(struct inode *inode, struct dentry *dentry,
0402             struct vfsmount *mnt, int flags, umode_t mode,
0403             struct file *aff_filp)
0404 {
0405     int ret;
0406     int affinity;
0407     struct spu_gang *gang;
0408     struct spu_context *neighbor;
0409     struct path path = {.mnt = mnt, .dentry = dentry};
0410 
0411     if ((flags & SPU_CREATE_NOSCHED) &&
0412         !capable(CAP_SYS_NICE))
0413         return -EPERM;
0414 
0415     if ((flags & (SPU_CREATE_NOSCHED | SPU_CREATE_ISOLATE))
0416         == SPU_CREATE_ISOLATE)
0417         return -EINVAL;
0418 
0419     if ((flags & SPU_CREATE_ISOLATE) && !isolated_loader)
0420         return -ENODEV;
0421 
0422     gang = NULL;
0423     neighbor = NULL;
0424     affinity = flags & (SPU_CREATE_AFFINITY_MEM | SPU_CREATE_AFFINITY_SPU);
0425     if (affinity) {
0426         gang = SPUFS_I(inode)->i_gang;
0427         if (!gang)
0428             return -EINVAL;
0429         mutex_lock(&gang->aff_mutex);
0430         neighbor = spufs_assert_affinity(flags, gang, aff_filp);
0431         if (IS_ERR(neighbor)) {
0432             ret = PTR_ERR(neighbor);
0433             goto out_aff_unlock;
0434         }
0435     }
0436 
0437     ret = spufs_mkdir(inode, dentry, flags, mode & 0777);
0438     if (ret)
0439         goto out_aff_unlock;
0440 
0441     if (affinity) {
0442         spufs_set_affinity(flags, SPUFS_I(d_inode(dentry))->i_ctx,
0443                                 neighbor);
0444         if (neighbor)
0445             put_spu_context(neighbor);
0446     }
0447 
0448     ret = spufs_context_open(&path);
0449     if (ret < 0)
0450         WARN_ON(spufs_rmdir(inode, dentry));
0451 
0452 out_aff_unlock:
0453     if (affinity)
0454         mutex_unlock(&gang->aff_mutex);
0455     return ret;
0456 }
0457 
0458 static int
0459 spufs_mkgang(struct inode *dir, struct dentry *dentry, umode_t mode)
0460 {
0461     int ret;
0462     struct inode *inode;
0463     struct spu_gang *gang;
0464 
0465     ret = -ENOSPC;
0466     inode = spufs_new_inode(dir->i_sb, mode | S_IFDIR);
0467     if (!inode)
0468         goto out;
0469 
0470     ret = 0;
0471     inode_init_owner(&init_user_ns, inode, dir, mode | S_IFDIR);
0472     gang = alloc_spu_gang();
0473     SPUFS_I(inode)->i_ctx = NULL;
0474     SPUFS_I(inode)->i_gang = gang;
0475     if (!gang) {
0476         ret = -ENOMEM;
0477         goto out_iput;
0478     }
0479 
0480     inode->i_op = &simple_dir_inode_operations;
0481     inode->i_fop = &simple_dir_operations;
0482 
0483     d_instantiate(dentry, inode);
0484     inc_nlink(dir);
0485     inc_nlink(d_inode(dentry));
0486     return ret;
0487 
0488 out_iput:
0489     iput(inode);
0490 out:
0491     return ret;
0492 }
0493 
0494 static int spufs_gang_open(struct path *path)
0495 {
0496     int ret;
0497     struct file *filp;
0498 
0499     ret = get_unused_fd_flags(0);
0500     if (ret < 0)
0501         return ret;
0502 
0503     /*
0504      * get references for dget and mntget, will be released
0505      * in error path of *_open().
0506      */
0507     filp = dentry_open(path, O_RDONLY, current_cred());
0508     if (IS_ERR(filp)) {
0509         put_unused_fd(ret);
0510         return PTR_ERR(filp);
0511     }
0512 
0513     filp->f_op = &simple_dir_operations;
0514     fd_install(ret, filp);
0515     return ret;
0516 }
0517 
0518 static int spufs_create_gang(struct inode *inode,
0519             struct dentry *dentry,
0520             struct vfsmount *mnt, umode_t mode)
0521 {
0522     struct path path = {.mnt = mnt, .dentry = dentry};
0523     int ret;
0524 
0525     ret = spufs_mkgang(inode, dentry, mode & 0777);
0526     if (!ret) {
0527         ret = spufs_gang_open(&path);
0528         if (ret < 0) {
0529             int err = simple_rmdir(inode, dentry);
0530             WARN_ON(err);
0531         }
0532     }
0533     return ret;
0534 }
0535 
0536 
0537 static struct file_system_type spufs_type;
0538 
0539 long spufs_create(struct path *path, struct dentry *dentry,
0540         unsigned int flags, umode_t mode, struct file *filp)
0541 {
0542     struct inode *dir = d_inode(path->dentry);
0543     int ret;
0544 
0545     /* check if we are on spufs */
0546     if (path->dentry->d_sb->s_type != &spufs_type)
0547         return -EINVAL;
0548 
0549     /* don't accept undefined flags */
0550     if (flags & (~SPU_CREATE_FLAG_ALL))
0551         return -EINVAL;
0552 
0553     /* only threads can be underneath a gang */
0554     if (path->dentry != path->dentry->d_sb->s_root)
0555         if ((flags & SPU_CREATE_GANG) || !SPUFS_I(dir)->i_gang)
0556             return -EINVAL;
0557 
0558     mode &= ~current_umask();
0559 
0560     if (flags & SPU_CREATE_GANG)
0561         ret = spufs_create_gang(dir, dentry, path->mnt, mode);
0562     else
0563         ret = spufs_create_context(dir, dentry, path->mnt, flags, mode,
0564                         filp);
0565     if (ret >= 0)
0566         fsnotify_mkdir(dir, dentry);
0567 
0568     return ret;
0569 }
0570 
0571 /* File system initialization */
0572 struct spufs_fs_context {
0573     kuid_t  uid;
0574     kgid_t  gid;
0575     umode_t mode;
0576 };
0577 
0578 enum {
0579     Opt_uid, Opt_gid, Opt_mode, Opt_debug,
0580 };
0581 
0582 static const struct fs_parameter_spec spufs_fs_parameters[] = {
0583     fsparam_u32 ("gid",             Opt_gid),
0584     fsparam_u32oct  ("mode",            Opt_mode),
0585     fsparam_u32 ("uid",             Opt_uid),
0586     fsparam_flag    ("debug",           Opt_debug),
0587     {}
0588 };
0589 
0590 static int spufs_show_options(struct seq_file *m, struct dentry *root)
0591 {
0592     struct spufs_sb_info *sbi = spufs_get_sb_info(root->d_sb);
0593     struct inode *inode = root->d_inode;
0594 
0595     if (!uid_eq(inode->i_uid, GLOBAL_ROOT_UID))
0596         seq_printf(m, ",uid=%u",
0597                from_kuid_munged(&init_user_ns, inode->i_uid));
0598     if (!gid_eq(inode->i_gid, GLOBAL_ROOT_GID))
0599         seq_printf(m, ",gid=%u",
0600                from_kgid_munged(&init_user_ns, inode->i_gid));
0601     if ((inode->i_mode & S_IALLUGO) != 0775)
0602         seq_printf(m, ",mode=%o", inode->i_mode);
0603     if (sbi->debug)
0604         seq_puts(m, ",debug");
0605     return 0;
0606 }
0607 
0608 static int spufs_parse_param(struct fs_context *fc, struct fs_parameter *param)
0609 {
0610     struct spufs_fs_context *ctx = fc->fs_private;
0611     struct spufs_sb_info *sbi = fc->s_fs_info;
0612     struct fs_parse_result result;
0613     kuid_t uid;
0614     kgid_t gid;
0615     int opt;
0616 
0617     opt = fs_parse(fc, spufs_fs_parameters, param, &result);
0618     if (opt < 0)
0619         return opt;
0620 
0621     switch (opt) {
0622     case Opt_uid:
0623         uid = make_kuid(current_user_ns(), result.uint_32);
0624         if (!uid_valid(uid))
0625             return invalf(fc, "Unknown uid");
0626         ctx->uid = uid;
0627         break;
0628     case Opt_gid:
0629         gid = make_kgid(current_user_ns(), result.uint_32);
0630         if (!gid_valid(gid))
0631             return invalf(fc, "Unknown gid");
0632         ctx->gid = gid;
0633         break;
0634     case Opt_mode:
0635         ctx->mode = result.uint_32 & S_IALLUGO;
0636         break;
0637     case Opt_debug:
0638         sbi->debug = true;
0639         break;
0640     }
0641 
0642     return 0;
0643 }
0644 
0645 static void spufs_exit_isolated_loader(void)
0646 {
0647     free_pages((unsigned long) isolated_loader,
0648             get_order(isolated_loader_size));
0649 }
0650 
0651 static void __init
0652 spufs_init_isolated_loader(void)
0653 {
0654     struct device_node *dn;
0655     const char *loader;
0656     int size;
0657 
0658     dn = of_find_node_by_path("/spu-isolation");
0659     if (!dn)
0660         return;
0661 
0662     loader = of_get_property(dn, "loader", &size);
0663     of_node_put(dn);
0664     if (!loader)
0665         return;
0666 
0667     /* the loader must be align on a 16 byte boundary */
0668     isolated_loader = (char *)__get_free_pages(GFP_KERNEL, get_order(size));
0669     if (!isolated_loader)
0670         return;
0671 
0672     isolated_loader_size = size;
0673     memcpy(isolated_loader, loader, size);
0674     printk(KERN_INFO "spufs: SPU isolation mode enabled\n");
0675 }
0676 
0677 static int spufs_create_root(struct super_block *sb, struct fs_context *fc)
0678 {
0679     struct spufs_fs_context *ctx = fc->fs_private;
0680     struct inode *inode;
0681 
0682     if (!spu_management_ops)
0683         return -ENODEV;
0684 
0685     inode = spufs_new_inode(sb, S_IFDIR | ctx->mode);
0686     if (!inode)
0687         return -ENOMEM;
0688 
0689     inode->i_uid = ctx->uid;
0690     inode->i_gid = ctx->gid;
0691     inode->i_op = &simple_dir_inode_operations;
0692     inode->i_fop = &simple_dir_operations;
0693     SPUFS_I(inode)->i_ctx = NULL;
0694     inc_nlink(inode);
0695 
0696     sb->s_root = d_make_root(inode);
0697     if (!sb->s_root)
0698         return -ENOMEM;
0699     return 0;
0700 }
0701 
0702 static const struct super_operations spufs_ops = {
0703     .alloc_inode    = spufs_alloc_inode,
0704     .free_inode = spufs_free_inode,
0705     .statfs     = simple_statfs,
0706     .evict_inode    = spufs_evict_inode,
0707     .show_options   = spufs_show_options,
0708 };
0709 
0710 static int spufs_fill_super(struct super_block *sb, struct fs_context *fc)
0711 {
0712     sb->s_maxbytes = MAX_LFS_FILESIZE;
0713     sb->s_blocksize = PAGE_SIZE;
0714     sb->s_blocksize_bits = PAGE_SHIFT;
0715     sb->s_magic = SPUFS_MAGIC;
0716     sb->s_op = &spufs_ops;
0717 
0718     return spufs_create_root(sb, fc);
0719 }
0720 
0721 static int spufs_get_tree(struct fs_context *fc)
0722 {
0723     return get_tree_single(fc, spufs_fill_super);
0724 }
0725 
0726 static void spufs_free_fc(struct fs_context *fc)
0727 {
0728     kfree(fc->s_fs_info);
0729 }
0730 
0731 static const struct fs_context_operations spufs_context_ops = {
0732     .free       = spufs_free_fc,
0733     .parse_param    = spufs_parse_param,
0734     .get_tree   = spufs_get_tree,
0735 };
0736 
0737 static int spufs_init_fs_context(struct fs_context *fc)
0738 {
0739     struct spufs_fs_context *ctx;
0740     struct spufs_sb_info *sbi;
0741 
0742     ctx = kzalloc(sizeof(struct spufs_fs_context), GFP_KERNEL);
0743     if (!ctx)
0744         goto nomem;
0745 
0746     sbi = kzalloc(sizeof(struct spufs_sb_info), GFP_KERNEL);
0747     if (!sbi)
0748         goto nomem_ctx;
0749 
0750     ctx->uid = current_uid();
0751     ctx->gid = current_gid();
0752     ctx->mode = 0755;
0753 
0754     fc->fs_private = ctx;
0755     fc->s_fs_info = sbi;
0756     fc->ops = &spufs_context_ops;
0757     return 0;
0758 
0759 nomem_ctx:
0760     kfree(ctx);
0761 nomem:
0762     return -ENOMEM;
0763 }
0764 
0765 static struct file_system_type spufs_type = {
0766     .owner = THIS_MODULE,
0767     .name = "spufs",
0768     .init_fs_context = spufs_init_fs_context,
0769     .parameters = spufs_fs_parameters,
0770     .kill_sb = kill_litter_super,
0771 };
0772 MODULE_ALIAS_FS("spufs");
0773 
0774 static int __init spufs_init(void)
0775 {
0776     int ret;
0777 
0778     ret = -ENODEV;
0779     if (!spu_management_ops)
0780         goto out;
0781 
0782     ret = -ENOMEM;
0783     spufs_inode_cache = kmem_cache_create("spufs_inode_cache",
0784             sizeof(struct spufs_inode_info), 0,
0785             SLAB_HWCACHE_ALIGN|SLAB_ACCOUNT, spufs_init_once);
0786 
0787     if (!spufs_inode_cache)
0788         goto out;
0789     ret = spu_sched_init();
0790     if (ret)
0791         goto out_cache;
0792     ret = register_spu_syscalls(&spufs_calls);
0793     if (ret)
0794         goto out_sched;
0795     ret = register_filesystem(&spufs_type);
0796     if (ret)
0797         goto out_syscalls;
0798 
0799     spufs_init_isolated_loader();
0800 
0801     return 0;
0802 
0803 out_syscalls:
0804     unregister_spu_syscalls(&spufs_calls);
0805 out_sched:
0806     spu_sched_exit();
0807 out_cache:
0808     kmem_cache_destroy(spufs_inode_cache);
0809 out:
0810     return ret;
0811 }
0812 module_init(spufs_init);
0813 
0814 static void __exit spufs_exit(void)
0815 {
0816     spu_sched_exit();
0817     spufs_exit_isolated_loader();
0818     unregister_spu_syscalls(&spufs_calls);
0819     unregister_filesystem(&spufs_type);
0820     kmem_cache_destroy(spufs_inode_cache);
0821 }
0822 module_exit(spufs_exit);
0823 
0824 MODULE_LICENSE("GPL");
0825 MODULE_AUTHOR("Arnd Bergmann <arndb@de.ibm.com>");
0826