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