linux/arch/powerpc/platforms/cell/spufs/inode.c
<<
>>
Prefs
   1
   2/*
   3 * SPU file system
   4 *
   5 * (C) Copyright IBM Deutschland Entwicklung GmbH 2005
   6 *
   7 * Author: Arnd Bergmann <arndb@de.ibm.com>
   8 *
   9 * This program is free software; you can redistribute it and/or modify
  10 * it under the terms of the GNU General Public License as published by
  11 * the Free Software Foundation; either version 2, or (at your option)
  12 * any later version.
  13 *
  14 * This program is distributed in the hope that it will be useful,
  15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17 * GNU General Public License for more details.
  18 *
  19 * You should have received a copy of the GNU General Public License
  20 * along with this program; if not, write to the Free Software
  21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  22 */
  23
  24#include <linux/file.h>
  25#include <linux/fs.h>
  26#include <linux/fsnotify.h>
  27#include <linux/backing-dev.h>
  28#include <linux/init.h>
  29#include <linux/ioctl.h>
  30#include <linux/module.h>
  31#include <linux/mount.h>
  32#include <linux/namei.h>
  33#include <linux/pagemap.h>
  34#include <linux/poll.h>
  35#include <linux/slab.h>
  36#include <linux/parser.h>
  37
  38#include <asm/prom.h>
  39#include <asm/spu.h>
  40#include <asm/spu_priv1.h>
  41#include <asm/uaccess.h>
  42
  43#include "spufs.h"
  44
  45struct spufs_sb_info {
  46        int debug;
  47};
  48
  49static struct kmem_cache *spufs_inode_cache;
  50char *isolated_loader;
  51static int isolated_loader_size;
  52
  53static struct spufs_sb_info *spufs_get_sb_info(struct super_block *sb)
  54{
  55        return sb->s_fs_info;
  56}
  57
  58static struct inode *
  59spufs_alloc_inode(struct super_block *sb)
  60{
  61        struct spufs_inode_info *ei;
  62
  63        ei = kmem_cache_alloc(spufs_inode_cache, GFP_KERNEL);
  64        if (!ei)
  65                return NULL;
  66
  67        ei->i_gang = NULL;
  68        ei->i_ctx = NULL;
  69        ei->i_openers = 0;
  70
  71        return &ei->vfs_inode;
  72}
  73
  74static void spufs_i_callback(struct rcu_head *head)
  75{
  76        struct inode *inode = container_of(head, struct inode, i_rcu);
  77        INIT_LIST_HEAD(&inode->i_dentry);
  78        kmem_cache_free(spufs_inode_cache, SPUFS_I(inode));
  79}
  80
  81static void spufs_destroy_inode(struct inode *inode)
  82{
  83        call_rcu(&inode->i_rcu, spufs_i_callback);
  84}
  85
  86static void
  87spufs_init_once(void *p)
  88{
  89        struct spufs_inode_info *ei = p;
  90
  91        inode_init_once(&ei->vfs_inode);
  92}
  93
  94static struct inode *
  95spufs_new_inode(struct super_block *sb, int mode)
  96{
  97        struct inode *inode;
  98
  99        inode = new_inode(sb);
 100        if (!inode)
 101                goto out;
 102
 103        inode->i_mode = mode;
 104        inode->i_uid = current_fsuid();
 105        inode->i_gid = current_fsgid();
 106        inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
 107out:
 108        return inode;
 109}
 110
 111static int
 112spufs_setattr(struct dentry *dentry, struct iattr *attr)
 113{
 114        struct inode *inode = dentry->d_inode;
 115
 116        if ((attr->ia_valid & ATTR_SIZE) &&
 117            (attr->ia_size != inode->i_size))
 118                return -EINVAL;
 119        setattr_copy(inode, attr);
 120        mark_inode_dirty(inode);
 121        return 0;
 122}
 123
 124
 125static int
 126spufs_new_file(struct super_block *sb, struct dentry *dentry,
 127                const struct file_operations *fops, int mode,
 128                size_t size, struct spu_context *ctx)
 129{
 130        static const struct inode_operations spufs_file_iops = {
 131                .setattr = spufs_setattr,
 132        };
 133        struct inode *inode;
 134        int ret;
 135
 136        ret = -ENOSPC;
 137        inode = spufs_new_inode(sb, S_IFREG | mode);
 138        if (!inode)
 139                goto out;
 140
 141        ret = 0;
 142        inode->i_op = &spufs_file_iops;
 143        inode->i_fop = fops;
 144        inode->i_size = size;
 145        inode->i_private = SPUFS_I(inode)->i_ctx = get_spu_context(ctx);
 146        d_add(dentry, inode);
 147out:
 148        return ret;
 149}
 150
 151static void
 152spufs_evict_inode(struct inode *inode)
 153{
 154        struct spufs_inode_info *ei = SPUFS_I(inode);
 155        end_writeback(inode);
 156        if (ei->i_ctx)
 157                put_spu_context(ei->i_ctx);
 158        if (ei->i_gang)
 159                put_spu_gang(ei->i_gang);
 160}
 161
 162static void spufs_prune_dir(struct dentry *dir)
 163{
 164        struct dentry *dentry, *tmp;
 165
 166        mutex_lock(&dir->d_inode->i_mutex);
 167        list_for_each_entry_safe(dentry, tmp, &dir->d_subdirs, d_u.d_child) {
 168                spin_lock(&dentry->d_lock);
 169                if (!(d_unhashed(dentry)) && dentry->d_inode) {
 170                        dget_dlock(dentry);
 171                        __d_drop(dentry);
 172                        spin_unlock(&dentry->d_lock);
 173                        simple_unlink(dir->d_inode, dentry);
 174                        /* XXX: what was dcache_lock protecting here? Other
 175                         * filesystems (IB, configfs) release dcache_lock
 176                         * before unlink */
 177                        dput(dentry);
 178                } else {
 179                        spin_unlock(&dentry->d_lock);
 180                }
 181        }
 182        shrink_dcache_parent(dir);
 183        mutex_unlock(&dir->d_inode->i_mutex);
 184}
 185
 186/* Caller must hold parent->i_mutex */
 187static int spufs_rmdir(struct inode *parent, struct dentry *dir)
 188{
 189        /* remove all entries */
 190        spufs_prune_dir(dir);
 191        d_drop(dir);
 192
 193        return simple_rmdir(parent, dir);
 194}
 195
 196static int spufs_fill_dir(struct dentry *dir,
 197                const struct spufs_tree_descr *files, int mode,
 198                struct spu_context *ctx)
 199{
 200        struct dentry *dentry, *tmp;
 201        int ret;
 202
 203        while (files->name && files->name[0]) {
 204                ret = -ENOMEM;
 205                dentry = d_alloc_name(dir, files->name);
 206                if (!dentry)
 207                        goto out;
 208                ret = spufs_new_file(dir->d_sb, dentry, files->ops,
 209                                        files->mode & mode, files->size, ctx);
 210                if (ret)
 211                        goto out;
 212                files++;
 213        }
 214        return 0;
 215out:
 216        /*
 217         * remove all children from dir. dir->inode is not set so don't
 218         * just simply use spufs_prune_dir() and panic afterwards :)
 219         * dput() looks like it will do the right thing:
 220         * - dec parent's ref counter
 221         * - remove child from parent's child list
 222         * - free child's inode if possible
 223         * - free child
 224         */
 225        list_for_each_entry_safe(dentry, tmp, &dir->d_subdirs, d_u.d_child) {
 226                dput(dentry);
 227        }
 228
 229        shrink_dcache_parent(dir);
 230        return ret;
 231}
 232
 233static int spufs_dir_close(struct inode *inode, struct file *file)
 234{
 235        struct spu_context *ctx;
 236        struct inode *parent;
 237        struct dentry *dir;
 238        int ret;
 239
 240        dir = file->f_path.dentry;
 241        parent = dir->d_parent->d_inode;
 242        ctx = SPUFS_I(dir->d_inode)->i_ctx;
 243
 244        mutex_lock_nested(&parent->i_mutex, I_MUTEX_PARENT);
 245        ret = spufs_rmdir(parent, dir);
 246        mutex_unlock(&parent->i_mutex);
 247        WARN_ON(ret);
 248
 249        /* We have to give up the mm_struct */
 250        spu_forget(ctx);
 251
 252        return dcache_dir_close(inode, file);
 253}
 254
 255const struct file_operations spufs_context_fops = {
 256        .open           = dcache_dir_open,
 257        .release        = spufs_dir_close,
 258        .llseek         = dcache_dir_lseek,
 259        .read           = generic_read_dir,
 260        .readdir        = dcache_readdir,
 261        .fsync          = noop_fsync,
 262};
 263EXPORT_SYMBOL_GPL(spufs_context_fops);
 264
 265static int
 266spufs_mkdir(struct inode *dir, struct dentry *dentry, unsigned int flags,
 267                int mode)
 268{
 269        int ret;
 270        struct inode *inode;
 271        struct spu_context *ctx;
 272
 273        ret = -ENOSPC;
 274        inode = spufs_new_inode(dir->i_sb, mode | S_IFDIR);
 275        if (!inode)
 276                goto out;
 277
 278        if (dir->i_mode & S_ISGID) {
 279                inode->i_gid = dir->i_gid;
 280                inode->i_mode &= S_ISGID;
 281        }
 282        ctx = alloc_spu_context(SPUFS_I(dir)->i_gang); /* XXX gang */
 283        SPUFS_I(inode)->i_ctx = ctx;
 284        if (!ctx)
 285                goto out_iput;
 286
 287        ctx->flags = flags;
 288        inode->i_op = &simple_dir_inode_operations;
 289        inode->i_fop = &simple_dir_operations;
 290        if (flags & SPU_CREATE_NOSCHED)
 291                ret = spufs_fill_dir(dentry, spufs_dir_nosched_contents,
 292                                         mode, ctx);
 293        else
 294                ret = spufs_fill_dir(dentry, spufs_dir_contents, mode, ctx);
 295
 296        if (ret)
 297                goto out_free_ctx;
 298
 299        if (spufs_get_sb_info(dir->i_sb)->debug)
 300                ret = spufs_fill_dir(dentry, spufs_dir_debug_contents,
 301                                mode, ctx);
 302
 303        if (ret)
 304                goto out_free_ctx;
 305
 306        d_instantiate(dentry, inode);
 307        dget(dentry);
 308        inc_nlink(dir);
 309        inc_nlink(dentry->d_inode);
 310        goto out;
 311
 312out_free_ctx:
 313        spu_forget(ctx);
 314        put_spu_context(ctx);
 315out_iput:
 316        iput(inode);
 317out:
 318        return ret;
 319}
 320
 321static int spufs_context_open(struct dentry *dentry, struct vfsmount *mnt)
 322{
 323        int ret;
 324        struct file *filp;
 325
 326        ret = get_unused_fd();
 327        if (ret < 0) {
 328                dput(dentry);
 329                mntput(mnt);
 330                goto out;
 331        }
 332
 333        filp = dentry_open(dentry, mnt, O_RDONLY, current_cred());
 334        if (IS_ERR(filp)) {
 335                put_unused_fd(ret);
 336                ret = PTR_ERR(filp);
 337                goto out;
 338        }
 339
 340        filp->f_op = &spufs_context_fops;
 341        fd_install(ret, filp);
 342out:
 343        return ret;
 344}
 345
 346static struct spu_context *
 347spufs_assert_affinity(unsigned int flags, struct spu_gang *gang,
 348                                                struct file *filp)
 349{
 350        struct spu_context *tmp, *neighbor, *err;
 351        int count, node;
 352        int aff_supp;
 353
 354        aff_supp = !list_empty(&(list_entry(cbe_spu_info[0].spus.next,
 355                                        struct spu, cbe_list))->aff_list);
 356
 357        if (!aff_supp)
 358                return ERR_PTR(-EINVAL);
 359
 360        if (flags & SPU_CREATE_GANG)
 361                return ERR_PTR(-EINVAL);
 362
 363        if (flags & SPU_CREATE_AFFINITY_MEM &&
 364            gang->aff_ref_ctx &&
 365            gang->aff_ref_ctx->flags & SPU_CREATE_AFFINITY_MEM)
 366                return ERR_PTR(-EEXIST);
 367
 368        if (gang->aff_flags & AFF_MERGED)
 369                return ERR_PTR(-EBUSY);
 370
 371        neighbor = NULL;
 372        if (flags & SPU_CREATE_AFFINITY_SPU) {
 373                if (!filp || filp->f_op != &spufs_context_fops)
 374                        return ERR_PTR(-EINVAL);
 375
 376                neighbor = get_spu_context(
 377                                SPUFS_I(filp->f_dentry->d_inode)->i_ctx);
 378
 379                if (!list_empty(&neighbor->aff_list) && !(neighbor->aff_head) &&
 380                    !list_is_last(&neighbor->aff_list, &gang->aff_list_head) &&
 381                    !list_entry(neighbor->aff_list.next, struct spu_context,
 382                    aff_list)->aff_head) {
 383                        err = ERR_PTR(-EEXIST);
 384                        goto out_put_neighbor;
 385                }
 386
 387                if (gang != neighbor->gang) {
 388                        err = ERR_PTR(-EINVAL);
 389                        goto out_put_neighbor;
 390                }
 391
 392                count = 1;
 393                list_for_each_entry(tmp, &gang->aff_list_head, aff_list)
 394                        count++;
 395                if (list_empty(&neighbor->aff_list))
 396                        count++;
 397
 398                for (node = 0; node < MAX_NUMNODES; node++) {
 399                        if ((cbe_spu_info[node].n_spus - atomic_read(
 400                                &cbe_spu_info[node].reserved_spus)) >= count)
 401                                break;
 402                }
 403
 404                if (node == MAX_NUMNODES) {
 405                        err = ERR_PTR(-EEXIST);
 406                        goto out_put_neighbor;
 407                }
 408        }
 409
 410        return neighbor;
 411
 412out_put_neighbor:
 413        put_spu_context(neighbor);
 414        return err;
 415}
 416
 417static void
 418spufs_set_affinity(unsigned int flags, struct spu_context *ctx,
 419                                        struct spu_context *neighbor)
 420{
 421        if (flags & SPU_CREATE_AFFINITY_MEM)
 422                ctx->gang->aff_ref_ctx = ctx;
 423
 424        if (flags & SPU_CREATE_AFFINITY_SPU) {
 425                if (list_empty(&neighbor->aff_list)) {
 426                        list_add_tail(&neighbor->aff_list,
 427                                &ctx->gang->aff_list_head);
 428                        neighbor->aff_head = 1;
 429                }
 430
 431                if (list_is_last(&neighbor->aff_list, &ctx->gang->aff_list_head)
 432                    || list_entry(neighbor->aff_list.next, struct spu_context,
 433                                                        aff_list)->aff_head) {
 434                        list_add(&ctx->aff_list, &neighbor->aff_list);
 435                } else  {
 436                        list_add_tail(&ctx->aff_list, &neighbor->aff_list);
 437                        if (neighbor->aff_head) {
 438                                neighbor->aff_head = 0;
 439                                ctx->aff_head = 1;
 440                        }
 441                }
 442
 443                if (!ctx->gang->aff_ref_ctx)
 444                        ctx->gang->aff_ref_ctx = ctx;
 445        }
 446}
 447
 448static int
 449spufs_create_context(struct inode *inode, struct dentry *dentry,
 450                        struct vfsmount *mnt, int flags, int mode,
 451                        struct file *aff_filp)
 452{
 453        int ret;
 454        int affinity;
 455        struct spu_gang *gang;
 456        struct spu_context *neighbor;
 457
 458        ret = -EPERM;
 459        if ((flags & SPU_CREATE_NOSCHED) &&
 460            !capable(CAP_SYS_NICE))
 461                goto out_unlock;
 462
 463        ret = -EINVAL;
 464        if ((flags & (SPU_CREATE_NOSCHED | SPU_CREATE_ISOLATE))
 465            == SPU_CREATE_ISOLATE)
 466                goto out_unlock;
 467
 468        ret = -ENODEV;
 469        if ((flags & SPU_CREATE_ISOLATE) && !isolated_loader)
 470                goto out_unlock;
 471
 472        gang = NULL;
 473        neighbor = NULL;
 474        affinity = flags & (SPU_CREATE_AFFINITY_MEM | SPU_CREATE_AFFINITY_SPU);
 475        if (affinity) {
 476                gang = SPUFS_I(inode)->i_gang;
 477                ret = -EINVAL;
 478                if (!gang)
 479                        goto out_unlock;
 480                mutex_lock(&gang->aff_mutex);
 481                neighbor = spufs_assert_affinity(flags, gang, aff_filp);
 482                if (IS_ERR(neighbor)) {
 483                        ret = PTR_ERR(neighbor);
 484                        goto out_aff_unlock;
 485                }
 486        }
 487
 488        ret = spufs_mkdir(inode, dentry, flags, mode & S_IRWXUGO);
 489        if (ret)
 490                goto out_aff_unlock;
 491
 492        if (affinity) {
 493                spufs_set_affinity(flags, SPUFS_I(dentry->d_inode)->i_ctx,
 494                                                                neighbor);
 495                if (neighbor)
 496                        put_spu_context(neighbor);
 497        }
 498
 499        /*
 500         * get references for dget and mntget, will be released
 501         * in error path of *_open().
 502         */
 503        ret = spufs_context_open(dget(dentry), mntget(mnt));
 504        if (ret < 0) {
 505                WARN_ON(spufs_rmdir(inode, dentry));
 506                if (affinity)
 507                        mutex_unlock(&gang->aff_mutex);
 508                mutex_unlock(&inode->i_mutex);
 509                spu_forget(SPUFS_I(dentry->d_inode)->i_ctx);
 510                goto out;
 511        }
 512
 513out_aff_unlock:
 514        if (affinity)
 515                mutex_unlock(&gang->aff_mutex);
 516out_unlock:
 517        mutex_unlock(&inode->i_mutex);
 518out:
 519        dput(dentry);
 520        return ret;
 521}
 522
 523static int
 524spufs_mkgang(struct inode *dir, struct dentry *dentry, int mode)
 525{
 526        int ret;
 527        struct inode *inode;
 528        struct spu_gang *gang;
 529
 530        ret = -ENOSPC;
 531        inode = spufs_new_inode(dir->i_sb, mode | S_IFDIR);
 532        if (!inode)
 533                goto out;
 534
 535        ret = 0;
 536        if (dir->i_mode & S_ISGID) {
 537                inode->i_gid = dir->i_gid;
 538                inode->i_mode &= S_ISGID;
 539        }
 540        gang = alloc_spu_gang();
 541        SPUFS_I(inode)->i_ctx = NULL;
 542        SPUFS_I(inode)->i_gang = gang;
 543        if (!gang)
 544                goto out_iput;
 545
 546        inode->i_op = &simple_dir_inode_operations;
 547        inode->i_fop = &simple_dir_operations;
 548
 549        d_instantiate(dentry, inode);
 550        inc_nlink(dir);
 551        inc_nlink(dentry->d_inode);
 552        return ret;
 553
 554out_iput:
 555        iput(inode);
 556out:
 557        return ret;
 558}
 559
 560static int spufs_gang_open(struct dentry *dentry, struct vfsmount *mnt)
 561{
 562        int ret;
 563        struct file *filp;
 564
 565        ret = get_unused_fd();
 566        if (ret < 0) {
 567                dput(dentry);
 568                mntput(mnt);
 569                goto out;
 570        }
 571
 572        filp = dentry_open(dentry, mnt, O_RDONLY, current_cred());
 573        if (IS_ERR(filp)) {
 574                put_unused_fd(ret);
 575                ret = PTR_ERR(filp);
 576                goto out;
 577        }
 578
 579        filp->f_op = &simple_dir_operations;
 580        fd_install(ret, filp);
 581out:
 582        return ret;
 583}
 584
 585static int spufs_create_gang(struct inode *inode,
 586                        struct dentry *dentry,
 587                        struct vfsmount *mnt, int mode)
 588{
 589        int ret;
 590
 591        ret = spufs_mkgang(inode, dentry, mode & S_IRWXUGO);
 592        if (ret)
 593                goto out;
 594
 595        /*
 596         * get references for dget and mntget, will be released
 597         * in error path of *_open().
 598         */
 599        ret = spufs_gang_open(dget(dentry), mntget(mnt));
 600        if (ret < 0) {
 601                int err = simple_rmdir(inode, dentry);
 602                WARN_ON(err);
 603        }
 604
 605out:
 606        mutex_unlock(&inode->i_mutex);
 607        dput(dentry);
 608        return ret;
 609}
 610
 611
 612static struct file_system_type spufs_type;
 613
 614long spufs_create(struct nameidata *nd, unsigned int flags, mode_t mode,
 615                                                        struct file *filp)
 616{
 617        struct dentry *dentry;
 618        int ret;
 619
 620        ret = -EINVAL;
 621        /* check if we are on spufs */
 622        if (nd->path.dentry->d_sb->s_type != &spufs_type)
 623                goto out;
 624
 625        /* don't accept undefined flags */
 626        if (flags & (~SPU_CREATE_FLAG_ALL))
 627                goto out;
 628
 629        /* only threads can be underneath a gang */
 630        if (nd->path.dentry != nd->path.dentry->d_sb->s_root) {
 631                if ((flags & SPU_CREATE_GANG) ||
 632                    !SPUFS_I(nd->path.dentry->d_inode)->i_gang)
 633                        goto out;
 634        }
 635
 636        dentry = lookup_create(nd, 1);
 637        ret = PTR_ERR(dentry);
 638        if (IS_ERR(dentry))
 639                goto out_dir;
 640
 641        mode &= ~current_umask();
 642
 643        if (flags & SPU_CREATE_GANG)
 644                ret = spufs_create_gang(nd->path.dentry->d_inode,
 645                                         dentry, nd->path.mnt, mode);
 646        else
 647                ret = spufs_create_context(nd->path.dentry->d_inode,
 648                                            dentry, nd->path.mnt, flags, mode,
 649                                            filp);
 650        if (ret >= 0)
 651                fsnotify_mkdir(nd->path.dentry->d_inode, dentry);
 652        return ret;
 653
 654out_dir:
 655        mutex_unlock(&nd->path.dentry->d_inode->i_mutex);
 656out:
 657        return ret;
 658}
 659
 660/* File system initialization */
 661enum {
 662        Opt_uid, Opt_gid, Opt_mode, Opt_debug, Opt_err,
 663};
 664
 665static const match_table_t spufs_tokens = {
 666        { Opt_uid,   "uid=%d" },
 667        { Opt_gid,   "gid=%d" },
 668        { Opt_mode,  "mode=%o" },
 669        { Opt_debug, "debug" },
 670        { Opt_err,    NULL  },
 671};
 672
 673static int
 674spufs_parse_options(struct super_block *sb, char *options, struct inode *root)
 675{
 676        char *p;
 677        substring_t args[MAX_OPT_ARGS];
 678
 679        while ((p = strsep(&options, ",")) != NULL) {
 680                int token, option;
 681
 682                if (!*p)
 683                        continue;
 684
 685                token = match_token(p, spufs_tokens, args);
 686                switch (token) {
 687                case Opt_uid:
 688                        if (match_int(&args[0], &option))
 689                                return 0;
 690                        root->i_uid = option;
 691                        break;
 692                case Opt_gid:
 693                        if (match_int(&args[0], &option))
 694                                return 0;
 695                        root->i_gid = option;
 696                        break;
 697                case Opt_mode:
 698                        if (match_octal(&args[0], &option))
 699                                return 0;
 700                        root->i_mode = option | S_IFDIR;
 701                        break;
 702                case Opt_debug:
 703                        spufs_get_sb_info(sb)->debug = 1;
 704                        break;
 705                default:
 706                        return 0;
 707                }
 708        }
 709        return 1;
 710}
 711
 712static void spufs_exit_isolated_loader(void)
 713{
 714        free_pages((unsigned long) isolated_loader,
 715                        get_order(isolated_loader_size));
 716}
 717
 718static void
 719spufs_init_isolated_loader(void)
 720{
 721        struct device_node *dn;
 722        const char *loader;
 723        int size;
 724
 725        dn = of_find_node_by_path("/spu-isolation");
 726        if (!dn)
 727                return;
 728
 729        loader = of_get_property(dn, "loader", &size);
 730        if (!loader)
 731                return;
 732
 733        /* the loader must be align on a 16 byte boundary */
 734        isolated_loader = (char *)__get_free_pages(GFP_KERNEL, get_order(size));
 735        if (!isolated_loader)
 736                return;
 737
 738        isolated_loader_size = size;
 739        memcpy(isolated_loader, loader, size);
 740        printk(KERN_INFO "spufs: SPU isolation mode enabled\n");
 741}
 742
 743static int
 744spufs_create_root(struct super_block *sb, void *data)
 745{
 746        struct inode *inode;
 747        int ret;
 748
 749        ret = -ENODEV;
 750        if (!spu_management_ops)
 751                goto out;
 752
 753        ret = -ENOMEM;
 754        inode = spufs_new_inode(sb, S_IFDIR | 0775);
 755        if (!inode)
 756                goto out;
 757
 758        inode->i_op = &simple_dir_inode_operations;
 759        inode->i_fop = &simple_dir_operations;
 760        SPUFS_I(inode)->i_ctx = NULL;
 761        inc_nlink(inode);
 762
 763        ret = -EINVAL;
 764        if (!spufs_parse_options(sb, data, inode))
 765                goto out_iput;
 766
 767        ret = -ENOMEM;
 768        sb->s_root = d_alloc_root(inode);
 769        if (!sb->s_root)
 770                goto out_iput;
 771
 772        return 0;
 773out_iput:
 774        iput(inode);
 775out:
 776        return ret;
 777}
 778
 779static int
 780spufs_fill_super(struct super_block *sb, void *data, int silent)
 781{
 782        struct spufs_sb_info *info;
 783        static const struct super_operations s_ops = {
 784                .alloc_inode = spufs_alloc_inode,
 785                .destroy_inode = spufs_destroy_inode,
 786                .statfs = simple_statfs,
 787                .evict_inode = spufs_evict_inode,
 788                .show_options = generic_show_options,
 789        };
 790
 791        save_mount_options(sb, data);
 792
 793        info = kzalloc(sizeof(*info), GFP_KERNEL);
 794        if (!info)
 795                return -ENOMEM;
 796
 797        sb->s_maxbytes = MAX_LFS_FILESIZE;
 798        sb->s_blocksize = PAGE_CACHE_SIZE;
 799        sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
 800        sb->s_magic = SPUFS_MAGIC;
 801        sb->s_op = &s_ops;
 802        sb->s_fs_info = info;
 803
 804        return spufs_create_root(sb, data);
 805}
 806
 807static struct dentry *
 808spufs_mount(struct file_system_type *fstype, int flags,
 809                const char *name, void *data)
 810{
 811        return mount_single(fstype, flags, data, spufs_fill_super);
 812}
 813
 814static struct file_system_type spufs_type = {
 815        .owner = THIS_MODULE,
 816        .name = "spufs",
 817        .mount = spufs_mount,
 818        .kill_sb = kill_litter_super,
 819};
 820
 821static int __init spufs_init(void)
 822{
 823        int ret;
 824
 825        ret = -ENODEV;
 826        if (!spu_management_ops)
 827                goto out;
 828
 829        ret = -ENOMEM;
 830        spufs_inode_cache = kmem_cache_create("spufs_inode_cache",
 831                        sizeof(struct spufs_inode_info), 0,
 832                        SLAB_HWCACHE_ALIGN, spufs_init_once);
 833
 834        if (!spufs_inode_cache)
 835                goto out;
 836        ret = spu_sched_init();
 837        if (ret)
 838                goto out_cache;
 839        ret = register_filesystem(&spufs_type);
 840        if (ret)
 841                goto out_sched;
 842        ret = register_spu_syscalls(&spufs_calls);
 843        if (ret)
 844                goto out_fs;
 845
 846        spufs_init_isolated_loader();
 847
 848        return 0;
 849
 850out_fs:
 851        unregister_filesystem(&spufs_type);
 852out_sched:
 853        spu_sched_exit();
 854out_cache:
 855        kmem_cache_destroy(spufs_inode_cache);
 856out:
 857        return ret;
 858}
 859module_init(spufs_init);
 860
 861static void __exit spufs_exit(void)
 862{
 863        spu_sched_exit();
 864        spufs_exit_isolated_loader();
 865        unregister_spu_syscalls(&spufs_calls);
 866        unregister_filesystem(&spufs_type);
 867        kmem_cache_destroy(spufs_inode_cache);
 868}
 869module_exit(spufs_exit);
 870
 871MODULE_LICENSE("GPL");
 872MODULE_AUTHOR("Arnd Bergmann <arndb@de.ibm.com>");
 873
 874