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/io.h> 37 #include <asm/semaphore.h> 38 #include <asm/spu.h> 39 #include <asm/uaccess.h> 40 41 #include "spufs.h" 42 43 static kmem_cache_t *spufs_inode_cache; 44 45 static struct inode * 46 spufs_alloc_inode(struct super_block *sb) 47 { 48 struct spufs_inode_info *ei; 49 50 ei = kmem_cache_alloc(spufs_inode_cache, SLAB_KERNEL); 51 if (!ei) 52 return NULL; 53 return &ei->vfs_inode; 54 } 55 56 static void 57 spufs_destroy_inode(struct inode *inode) 58 { 59 kmem_cache_free(spufs_inode_cache, SPUFS_I(inode)); 60 } 61 62 static void 63 spufs_init_once(void *p, kmem_cache_t * cachep, unsigned long flags) 64 { 65 struct spufs_inode_info *ei = p; 66 67 if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == 68 SLAB_CTOR_CONSTRUCTOR) { 69 inode_init_once(&ei->vfs_inode); 70 } 71 } 72 73 static struct inode * 74 spufs_new_inode(struct super_block *sb, int mode) 75 { 76 struct inode *inode; 77 78 inode = new_inode(sb); 79 if (!inode) 80 goto out; 81 82 inode->i_mode = mode; 83 inode->i_uid = current->fsuid; 84 inode->i_gid = current->fsgid; 85 inode->i_blksize = PAGE_CACHE_SIZE; 86 inode->i_blocks = 0; 87 inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; 88 out: 89 return inode; 90 } 91 92 static int 93 spufs_setattr(struct dentry *dentry, struct iattr *attr) 94 { 95 struct inode *inode = dentry->d_inode; 96 97 if ((attr->ia_valid & ATTR_SIZE) && 98 (attr->ia_size != inode->i_size)) 99 return -EINVAL; 100 return inode_setattr(inode, attr); 101 } 102 103 104 static int 105 spufs_new_file(struct super_block *sb, struct dentry *dentry, 106 const struct file_operations *fops, int mode, 107 struct spu_context *ctx) 108 { 109 static struct inode_operations spufs_file_iops = { 110 .setattr = spufs_setattr, 111 }; 112 struct inode *inode; 113 int ret; 114 115 ret = -ENOSPC; 116 inode = spufs_new_inode(sb, S_IFREG | mode); 117 if (!inode) 118 goto out; 119 120 ret = 0; 121 inode->i_op = &spufs_file_iops; 122 inode->i_fop = fops; 123 inode->u.generic_ip = SPUFS_I(inode)->i_ctx = get_spu_context(ctx); 124 d_add(dentry, inode); 125 out: 126 return ret; 127 } 128 129 static void 130 spufs_delete_inode(struct inode *inode) 131 { 132 if (SPUFS_I(inode)->i_ctx) 133 put_spu_context(SPUFS_I(inode)->i_ctx); 134 clear_inode(inode); 135 } 136 137 static void spufs_prune_dir(struct dentry *dir) 138 { 139 struct dentry *dentry, *tmp; 140 mutex_lock(&dir->d_inode->i_mutex); 141 list_for_each_entry_safe(dentry, tmp, &dir->d_subdirs, d_u.d_child) { 142 spin_lock(&dcache_lock); 143 spin_lock(&dentry->d_lock); 144 if (!(d_unhashed(dentry)) && dentry->d_inode) { 145 dget_locked(dentry); 146 __d_drop(dentry); 147 spin_unlock(&dentry->d_lock); 148 simple_unlink(dir->d_inode, dentry); 149 spin_unlock(&dcache_lock); 150 dput(dentry); 151 } else { 152 spin_unlock(&dentry->d_lock); 153 spin_unlock(&dcache_lock); 154 } 155 } 156 shrink_dcache_parent(dir); 157 mutex_unlock(&dir->d_inode->i_mutex); 158 } 159 160 /* Caller must hold root->i_mutex */ 161 static int spufs_rmdir(struct inode *root, struct dentry *dir_dentry) 162 { 163 /* remove all entries */ 164 spufs_prune_dir(dir_dentry); 165 166 return simple_rmdir(root, dir_dentry); 167 } 168 169 static int spufs_fill_dir(struct dentry *dir, struct tree_descr *files, 170 int mode, struct spu_context *ctx) 171 { 172 struct dentry *dentry; 173 int ret; 174 175 while (files->name && files->name[0]) { 176 ret = -ENOMEM; 177 dentry = d_alloc_name(dir, files->name); 178 if (!dentry) 179 goto out; 180 ret = spufs_new_file(dir->d_sb, dentry, files->ops, 181 files->mode & mode, ctx); 182 if (ret) 183 goto out; 184 files++; 185 } 186 return 0; 187 out: 188 spufs_prune_dir(dir); 189 return ret; 190 } 191 192 static int spufs_dir_close(struct inode *inode, struct file *file) 193 { 194 struct spu_context *ctx; 195 struct inode *dir; 196 struct dentry *dentry; 197 int ret; 198 199 dentry = file->f_dentry; 200 dir = dentry->d_parent->d_inode; 201 ctx = SPUFS_I(dentry->d_inode)->i_ctx; 202 203 mutex_lock(&dir->i_mutex); 204 ret = spufs_rmdir(dir, dentry); 205 mutex_unlock(&dir->i_mutex); 206 WARN_ON(ret); 207 208 /* We have to give up the mm_struct */ 209 spu_forget(ctx); 210 211 return dcache_dir_close(inode, file); 212 } 213 214 struct inode_operations spufs_dir_inode_operations = { 215 .lookup = simple_lookup, 216 }; 217 218 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 .readdir = dcache_readdir, 224 .fsync = simple_sync_file, 225 }; 226 227 static int 228 spufs_mkdir(struct inode *dir, struct dentry *dentry, int mode) 229 { 230 int ret; 231 struct inode *inode; 232 struct spu_context *ctx; 233 234 ret = -ENOSPC; 235 inode = spufs_new_inode(dir->i_sb, mode | S_IFDIR); 236 if (!inode) 237 goto out; 238 239 if (dir->i_mode & S_ISGID) { 240 inode->i_gid = dir->i_gid; 241 inode->i_mode &= S_ISGID; 242 } 243 ctx = alloc_spu_context(); 244 SPUFS_I(inode)->i_ctx = ctx; 245 if (!ctx) 246 goto out_iput; 247 248 inode->i_op = &spufs_dir_inode_operations; 249 inode->i_fop = &simple_dir_operations; 250 ret = spufs_fill_dir(dentry, spufs_dir_contents, mode, ctx); 251 if (ret) 252 goto out_free_ctx; 253 254 d_instantiate(dentry, inode); 255 dget(dentry); 256 dir->i_nlink++; 257 dentry->d_inode->i_nlink++; 258 goto out; 259 260 out_free_ctx: 261 put_spu_context(ctx); 262 out_iput: 263 iput(inode); 264 out: 265 return ret; 266 } 267 268 static int spufs_context_open(struct dentry *dentry, struct vfsmount *mnt) 269 { 270 int ret; 271 struct file *filp; 272 273 ret = get_unused_fd(); 274 if (ret < 0) { 275 dput(dentry); 276 mntput(mnt); 277 goto out; 278 } 279 280 filp = dentry_open(dentry, mnt, O_RDONLY); 281 if (IS_ERR(filp)) { 282 put_unused_fd(ret); 283 ret = PTR_ERR(filp); 284 goto out; 285 } 286 287 filp->f_op = &spufs_context_fops; 288 fd_install(ret, filp); 289 out: 290 return ret; 291 } 292 293 static struct file_system_type spufs_type; 294 295 long spufs_create_thread(struct nameidata *nd, 296 unsigned int flags, mode_t mode) 297 { 298 struct dentry *dentry; 299 int ret; 300 301 /* need to be at the root of spufs */ 302 ret = -EINVAL; 303 if (nd->dentry->d_sb->s_type != &spufs_type || 304 nd->dentry != nd->dentry->d_sb->s_root) 305 goto out; 306 307 /* all flags are reserved */ 308 if (flags) 309 goto out; 310 311 dentry = lookup_create(nd, 1); 312 ret = PTR_ERR(dentry); 313 if (IS_ERR(dentry)) 314 goto out_dir; 315 316 ret = -EEXIST; 317 if (dentry->d_inode) 318 goto out_dput; 319 320 mode &= ~current->fs->umask; 321 ret = spufs_mkdir(nd->dentry->d_inode, dentry, mode & S_IRWXUGO); 322 if (ret) 323 goto out_dput; 324 325 /* 326 * get references for dget and mntget, will be released 327 * in error path of *_open(). 328 */ 329 ret = spufs_context_open(dget(dentry), mntget(nd->mnt)); 330 if (ret < 0) { 331 WARN_ON(spufs_rmdir(nd->dentry->d_inode, dentry)); 332 mutex_unlock(&nd->dentry->d_inode->i_mutex); 333 spu_forget(SPUFS_I(dentry->d_inode)->i_ctx); 334 dput(dentry); 335 goto out; 336 } 337 338 out_dput: 339 dput(dentry); 340 out_dir: 341 mutex_unlock(&nd->dentry->d_inode->i_mutex); 342 out: 343 return ret; 344 } 345 346 /* File system initialization */ 347 enum { 348 Opt_uid, Opt_gid, Opt_err, 349 }; 350 351 static match_table_t spufs_tokens = { 352 { Opt_uid, "uid=%d" }, 353 { Opt_gid, "gid=%d" }, 354 { Opt_err, NULL }, 355 }; 356 357 static int 358 spufs_parse_options(char *options, struct inode *root) 359 { 360 char *p; 361 substring_t args[MAX_OPT_ARGS]; 362 363 while ((p = strsep(&options, ",")) != NULL) { 364 int token, option; 365 366 if (!*p) 367 continue; 368 369 token = match_token(p, spufs_tokens, args); 370 switch (token) { 371 case Opt_uid: 372 if (match_int(&args[0], &option)) 373 return 0; 374 root->i_uid = option; 375 break; 376 case Opt_gid: 377 if (match_int(&args[0], &option)) 378 return 0; 379 root->i_gid = option; 380 break; 381 default: 382 return 0; 383 } 384 } 385 return 1; 386 } 387 388 static int 389 spufs_create_root(struct super_block *sb, void *data) 390 { 391 struct inode *inode; 392 int ret; 393 394 ret = -ENOMEM; 395 inode = spufs_new_inode(sb, S_IFDIR | 0775); 396 if (!inode) 397 goto out; 398 399 inode->i_op = &spufs_dir_inode_operations; 400 inode->i_fop = &simple_dir_operations; 401 SPUFS_I(inode)->i_ctx = NULL; 402 403 ret = -EINVAL; 404 if (!spufs_parse_options(data, inode)) 405 goto out_iput; 406 407 ret = -ENOMEM; 408 sb->s_root = d_alloc_root(inode); 409 if (!sb->s_root) 410 goto out_iput; 411 412 return 0; 413 out_iput: 414 iput(inode); 415 out: 416 return ret; 417 } 418 419 static int 420 spufs_fill_super(struct super_block *sb, void *data, int silent) 421 { 422 static struct super_operations s_ops = { 423 .alloc_inode = spufs_alloc_inode, 424 .destroy_inode = spufs_destroy_inode, 425 .statfs = simple_statfs, 426 .delete_inode = spufs_delete_inode, 427 .drop_inode = generic_delete_inode, 428 }; 429 430 sb->s_maxbytes = MAX_LFS_FILESIZE; 431 sb->s_blocksize = PAGE_CACHE_SIZE; 432 sb->s_blocksize_bits = PAGE_CACHE_SHIFT; 433 sb->s_magic = SPUFS_MAGIC; 434 sb->s_op = &s_ops; 435 436 return spufs_create_root(sb, data); 437 } 438 439 static int 440 spufs_get_sb(struct file_system_type *fstype, int flags, 441 const char *name, void *data, struct vfsmount *mnt) 442 { 443 return get_sb_single(fstype, flags, data, spufs_fill_super, mnt); 444 } 445 446 static struct file_system_type spufs_type = { 447 .owner = THIS_MODULE, 448 .name = "spufs", 449 .get_sb = spufs_get_sb, 450 .kill_sb = kill_litter_super, 451 }; 452 453 static int __init spufs_init(void) 454 { 455 int ret; 456 ret = -ENOMEM; 457 spufs_inode_cache = kmem_cache_create("spufs_inode_cache", 458 sizeof(struct spufs_inode_info), 0, 459 SLAB_HWCACHE_ALIGN, spufs_init_once, NULL); 460 461 if (!spufs_inode_cache) 462 goto out; 463 if (spu_sched_init() != 0) { 464 kmem_cache_destroy(spufs_inode_cache); 465 goto out; 466 } 467 ret = register_filesystem(&spufs_type); 468 if (ret) 469 goto out_cache; 470 ret = register_spu_syscalls(&spufs_calls); 471 if (ret) 472 goto out_fs; 473 return 0; 474 out_fs: 475 unregister_filesystem(&spufs_type); 476 out_cache: 477 kmem_cache_destroy(spufs_inode_cache); 478 out: 479 return ret; 480 } 481 module_init(spufs_init); 482 483 static void __exit spufs_exit(void) 484 { 485 spu_sched_exit(); 486 unregister_spu_syscalls(&spufs_calls); 487 unregister_filesystem(&spufs_type); 488 kmem_cache_destroy(spufs_inode_cache); 489 } 490 module_exit(spufs_exit); 491 492 MODULE_LICENSE("GPL"); 493 MODULE_AUTHOR("Arnd Bergmann <arndb@de.ibm.com>"); 494 495