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