root/arch/powerpc/platforms/cell/spufs/inode.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. spufs_get_sb_info
  2. spufs_alloc_inode
  3. spufs_free_inode
  4. spufs_init_once
  5. spufs_new_inode
  6. spufs_setattr
  7. spufs_new_file
  8. spufs_evict_inode
  9. spufs_prune_dir
  10. spufs_rmdir
  11. spufs_fill_dir
  12. spufs_dir_close
  13. spufs_mkdir
  14. spufs_context_open
  15. spufs_assert_affinity
  16. spufs_set_affinity
  17. spufs_create_context
  18. spufs_mkgang
  19. spufs_gang_open
  20. spufs_create_gang
  21. spufs_create
  22. spufs_show_options
  23. spufs_parse_param
  24. spufs_exit_isolated_loader
  25. spufs_init_isolated_loader
  26. spufs_create_root
  27. spufs_fill_super
  28. spufs_get_tree
  29. spufs_free_fc
  30. spufs_init_fs_context
  31. spufs_init
  32. spufs_exit

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

/* [<][>][^][v][top][bottom][index][help] */