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