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