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